main.cpp 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // This code simulates a potential flow (subsonic flow) around a horizontal NACA0012 airfoil.
  2. // The problem is nonlinear because the air density depends on the air speed.
  3. #include "sparselizardbase.h"
  4. using namespace mathop;
  5. void sparselizard(void)
  6. {
  7. // The domain regions as defined in 'airfoil2D.geo':
  8. int air = 1, airfoil = 2, downstream = 3, upstream = 4;
  9. // Load the 'airfoil2D' mesh:
  10. mesh mymesh("airfoil2D.msh");
  11. // Define the whole outer boundary:
  12. int gammaouter = regionunion({upstream, downstream});
  13. // Define the velocity potential field 'phi' with standard nodal shape functions ("h1").
  14. // grad(phi) is the fluid velocity. Field x is the x coordinate field.
  15. field phi("h1"), x("x");
  16. // Use interpolation order 1:
  17. phi.setorder(air, 1);
  18. // Specific weight of air under some circumstances:
  19. double gamma = 1.4;
  20. // Define the air density 'rho' and the Mach number:
  21. expression rho = pow(1 + (gamma-1)/2.0 * 0.7 * 0.7 * (1-grad(phi)*grad(phi)), 1.0/(gamma-1));
  22. expression machnumber = sqrt(grad(phi)*grad(phi)) / sqrt(1.0/(0.7*0.7) + 0.5*(gamma-1) * (1-grad(phi)*grad(phi)));
  23. // We suppose outside the air domain a uniform speed of 1 with direction left to right.
  24. // Since grad(phi) is the speed we have that grad(x) indeed gives us what we want.
  25. phi.setconstraint(gammaouter, x);
  26. // Define the potential flow formulation:
  27. formulation pf;
  28. // On the airfoil boundary the default Neumann condition dphi/dnormal = 0
  29. // automatically ensures that there is no fluid entering the airfoil.
  30. // We thus do not need anything else than this:
  31. pf += integral(air, rho * grad(dof(phi)) * grad(tf(phi)) );
  32. // Start the nonlinear iteration with an all zero guess:
  33. vec sol(pf);
  34. double relres = 1;
  35. while (relres > 1e-7)
  36. {
  37. // Generate the formulation:
  38. pf.generate();
  39. // Get A and b to solve Ax = b:
  40. mat A = pf.A();
  41. vec b = pf.b();
  42. // Compute a relative residual:
  43. relres = (b - A*sol).norm() / b.norm();
  44. // Solve Ax = b:
  45. sol = solve(A, b);
  46. // Transfer the data from the solution vector to field 'phi' on the whole 'air' region:
  47. phi.setdata(air, sol);
  48. std::cout << "Current iteration has relative residual: " << relres << std::endl;
  49. }
  50. // Write the fluid speed (i.e. grad(phi)) and the Mach number:
  51. grad(phi).write(air, "flowspeed.pos");
  52. machnumber.write(air, "machnumber.pos");
  53. // Code validation line. Can be removed.
  54. std::cout << (machnumber.integrate(air, 3) < 62.4149 && machnumber.integrate(air, 3) > 62.4145);
  55. }
  56. int main(void)
  57. {
  58. SlepcInitialize(0,{},0,0);
  59. sparselizard();
  60. SlepcFinalize();
  61. return 0;
  62. }