sandbox/ghigo/src/test-navier-stokes/naca.c
2D NACA2414 airfoil at Re=1,000
This test case is inspired from the Gerris test case starting.
We solve here the Navier-Stokes equations and add the NACA2414 using an embedded boundary.
#include "embed.h"
#include "navier-stokes/centered.h"
#include "view.h"
double Reynolds = 1000.;
int maxlevel = 8;
face vector muv[];
Reference solution
#define chord (1.) // NACA2414 chord length
#define uref (1.) // Reference velocity, uref
#define tref ((chord)/(uref)) // Reference time, tref
We also define the shape of the domain.
#define naca00xx(x,y,a) (sq (y) - sq (5.*(a)*(0.2969*sqrt ((x)) \
- 0.1260*((x)) \
- 0.3516*sq ((x)) \
+ 0.2843*cube ((x)) \
- 0.1036*pow ((x), 4.)))) // -0.1015 or -0.1036
The domain is four units long, centered vertically.
int main() {
L0 = 4;
origin (-0.5, -L0/2.);
N = 256;
mu = muv;
run();
}
event properties (i++)
{
foreach_face()
muv.x[] = fm.x[]/Reynolds;
}
The fluid is injected on the left boundary with a unit velocity. The tracer is injected in the lower-half of the left boundary. An outflow condition is used on the right boundary.
u.n[left] = dirichlet(1.);
p[left] = neumann(0.);
pf[left] = neumann(0.);
u.n[right] = neumann(0.);
p[right] = dirichlet(0.);
pf[right] = dirichlet(0.);
The airfoil is no-slip.
u.n[embed] = dirichlet(0.);
u.t[embed] = dirichlet(0.);
double naca(double x, double y)
{
// NACA2414 parameters
double mm = 0.02;
double pp = 0.4;
double tt = 0.14;
if (x >= 0. && x <= (chord)) {
// Camber line coordinates, adimensional
double xc = x/(chord), yc = y/(chord), thetac = 0.;
if (xc < pp) {
yc -= mm/sq (pp)*(2.*pp*xc - sq (xc));
thetac = atan (2.*mm/sq (pp)*(pp - xc));
}
else {
yc -= mm/sq (1. - pp)*(1. - 2.*pp + 2.*pp*xc - sq (xc));
thetac = atan (2.*mm/sq (1. - pp)*(pp - xc));
}
return naca00xx (xc, yc, tt*cos (thetac));
}
else
return 1.;
}
event init (t = 0)
{
solid (cs, fs, naca(x,y));
We set the initial velocity field.
foreach()
u.x[] = 1.;
scalar omega[];
vorticity (u, omega);
view (quat = {0.000, 0.000, 0.000, 1.000},
fov = 30, near = 0.01, far = 1000,
tx = -0.211, ty = 0.053, tz = -2.508,
width = 818, height = 768);
box();
squares (color = "omega");
draw_vof(c="cs",lw=2, lc = {1,1,1});
cells();
save("omega-init.png");
}
event logfile (i += 10){
scalar omega[];
vorticity (u,omega);
foreach()
{
if(cs[]< 1.0)
{
omega[]=nodata;
}
else
{
omega[]=fabs(omega[]);
}
}
stats om = statsf(omega);
fprintf (stderr, "%d %g %g %g\n", i, t, om.max, om.stddev);
}
We produce animations of the vorticity field…
event movies (t += 0.1; t <= 4.)
{
scalar omega[];
vorticity (u, omega);
view (quat = {0.000, 0.000, 0.000, 1.000},
fov = 30, near = 0.01, far = 1000,
tx = -0.211, ty = 0.053, tz = -2.508,
width = 818, height = 768);
box();
squares (color = "omega");
draw_vof(c="cs",lw=2, lc = {1,1,1});
cells();
save("omega.mp4");
}
We adapt according to the error on the embedded geometry and velocity fields.
Results
Vorticity