sandbox/Antoonvh/my_sphere.c
Vortex shedding behind a sphere at Reynolds \in [200, 2000]
This setup is a slight modification of the flow past a sphere example. These modifications are concerned with generating this movie:
Flow past a sphere with increasing Reynolds number (Re). The visualization shows a volumetric rendering of the stagnant fluid (red) in the wake, upto the fluid with 90% of the mean velocity (blue), with increasing transparancy.
This visualization can be compared to the visualization of the \lambda_2 citerion
Vortex detection (\lambda_2) isosurface rendering
We solve the Navier–Stokes equations on an adaptive octree and use embedded boundaries to define the sphere.
#include "grid/octree.h"
#include "embed.h"
#include "navier-stokes/centered.h"
#include "view.h"
// a bwatch movie...
#include "bwatch.h"We will use the \lambda_2 criterion of Jeong and Hussain, 1995 for vortex detection.
#include "lambda2.h"This is the maximum level of refinement i.e. an equivalent maximum resolution of 1024^3.
int maxlevel = 10;We need a new field to define the viscosity.
face vector muv[];The domain size is 16^3. We move the origin so that the center of the unit sphere is not too close to boundaries.
double D = 1. [1];
int main()
{
init_grid (64);
size (16.*D);
origin (- 3.*D, -L0/2., -L0/2.);
mu = muv;
run();
}The viscosity is given by the Reynolds number, the sphere diameter, the inflow velocity, and fluid fraction.
double U0 = 1., Re = 200.;
event properties (i++)
{
foreach_face()
muv.x[] = fm.x[]*D*U0/Re;
}The boundary conditions are inflow with unit velocity on the left-hand-side and outflow on the right-hand-side.
u.n[left] = dirichlet(U0);
u.t[left] = dirichlet (0);
u.r[left] = dirichlet (0);
p[left] = neumann(0.);
pf[left] = neumann(0.);
u.n[right] = neumann(0.);
p[right] = dirichlet(0.);
pf[right] = dirichlet(0.);The boundary condition is no slip on the embedded boundary.
Re is increased from 200 to 2000.
We initially refine only in a sphere, slightly larger than the solid sphere. The sphere is displace a bit, to make text rendering in the movie more convenient.
refine (x*x + sq(y + D) + z*z < sq(1.2*D/2.) && level < maxlevel);We define the unit sphere.
solid (cs, fs, x*x + sq(y + D) + z*z - sq(D/2.));We set the initially horizontal velocity to the inflow velocity everywhere (outside the sphere).
foreach()
u.x[] = cs[] ? U0 : 0.;
}We log the number of iterations of the multigrid solver for pressure and viscosity.
We use Basilisk view to create the animated isosurface of \lambda_2.
event movies (t += 0.125; t <= 240)
{Here we compute two new fields, \lambda_2 and the vorticity component in the y-z plane.
scalar l2[], vyz[];
foreach()
vyz[] = ((u.y[0,0,1] - u.y[0,0,-1]) - (u.z[0,1] - u.z[0,-1]))/(2.*Delta);
lambda2 (u, l2);
view (fov = 11.44, quat = {0.072072,0.245086,0.303106,0.918076},
tx = -0.307321, ty = 0.22653, bg = {1,1,1},
width = 802, height = 634);
draw_vof ("cs", "fs");
isosurface ("l2", -0.01, color = "vyz", min = -1, max = 1,
linear = true, map = cool_warm);
save ("movie.mp4");Here we compute the a flow speed related field, for volumetric
rendering with bwatch.
scalar U[];
foreach() {
U[] = 0;
foreach_dimension()
U[] += sq(u.x[]);
U[] = 0.9*U0 - sqrt(U[]);
}
static FILE * fp = popen ("ppm2mp4 sphere.mp4", "w");
double angle = 1.2*cos(2.*pi*t/240.);
char capt[99];
sprintf (capt, "Re = %d ", (int)Re);
watch (fov = 10, O = {1.5*L0*cos(angle), 2*D, 1.5*L0*sin(angle + 1e-6)}, poi = {X0 + L0/2., -D, 1e-3}, nx = 1500, ny = 600);
// Sketching an exact sphere is cheaper compared to rendering its fov facets
sphere (D/2.,{1e-6, -D, 0} , mat = {.col = {100, 100, 100}, .R = 0.1});
// Encapsulating sphere as background
sphere (4*L0, mat = {.dull = true});
// Fix me: Is removing these "not exist" files needed?
system ("rm 3not9exist6.ppm");
system ("rm 2not8exist5.ppm");
// Note $Re$ in movie
sketch_text (capt, ops = "-font Bookman-DemiItalic -rotate 90", res = 2000,
pos = "center", tc = {23, 23, 23}, fs = 40, alpha = 0.01, n = {1, 0, 0});
// Volumetric rendering
volume (U, cols = true, sc = 0.25, mval = 0.001, shading = 1);
store (fp);
// Fit me: Should image data be handled better (is it even freed?)
plain();
// Remainder from Testing
//store (fopen ("test.ppm", "w"));
}We set an adaptation criterion with an error threshold of 0.02 on all velocity components and 10^{-2} on the geometry.
