sandbox/Antoonvh/tree/2cyl2d.c
Flow around two cylinders in 2D
Following Stephane’s setups for the Von Karman-street example and the starting flow around a cylinder test, we also setup a similar scenario, now using two cylinders.
We use automatically scaling refinement near the embedded surface. This is useful when multiple cylinders at various radii are used.
Vorticity and tracer particles
set xlabel 't'
set ylabel 'C_d'
plot 'log10-10' u 2:3
#include "embed.h"
#include "navier-stokes/centered.h"
#include "navier-stokes/double-projection.h"
#include "view.h"
#define BVIEW 1
#include "../particles.h"
#include "treegen.h"
#define CYLINDER (sqrt(sq(x) + sq(y - 0.01*R)) - R)
double R = 1, U = 1, Re = 1000, c = 10., C = 2, ue, nu;
int maxlevel = 10;
.n[left] = dirichlet (U);
u.n[left] = U;
uf.t[left] = dirichlet (0);
u[left] = dirichlet (0.);
p[left] = dirichlet (0.);
pf
.n[right] = neumann (0.);
u[right] = neumann (0.);
p[right] = neumann (0.);
pf
.n[embed] = dirichlet (0.);
u.t[embed] = dirichlet (0.);
u
FILE * fp;
face vector muc[];
scalar J[], res[];
Branch * branches;
int main() {
= U*R/Re;
nu periodic (top);
= 30;
L0 = -L0/3.5;
X0 = Z0 = -L0/2.;
Y0 = muc;
mu = 2;
NITERMIN = 1e-4;
TOLERANCE char logname[99];
= U/c;
ue sprintf (logname, "log%d-%g", maxlevel, c);
= fopen (logname, "w");
fp run();
}
void prolongate_ratio (Point point, scalar s) {
foreach_child() {
if (s[] != nodata)
[] += s[]*Delta;
s}
}
event init (t = 0) {
.prolongation = prolongate_ratio;
res= 2;
nb = malloc (nb*sizeof(Branch));
branches [0].start = (coord){0, 1, -1};
branches[0].end = (coord){0, 1, 1};
branches[0].R = R;
branches[0].parent = 0;
branches[1].start = (coord){1, -2, -1};
branches[1].end = (coord){1, -2, 1};
branches[1].R = 0.35*R;
branches[1].parent = 1;
branches
foreach()
.x[] = U;
udo {
tree_interface (branches, cs, fs, J);
foreach() {
[] = nodata;
resif (cs[] > 0 && cs[] < 1) {
[] = 1/sqrt(branches[(int)(J[] + 0.5)].R/Re);
res}
}
boundary ({res, u});
} while (adapt_wavelet ({res, u}, (double[]){C, ue, ue, ue},
, 4).nf > 10);
maxlevelforeach()
.x[] *= (cs[] > 0);
uinit_particles_2D_square_grid (10, -5, 0.01, 2);
}
In order to omit issues with inconsitent boundary conditions, we use a damping layer near the in and out flow boundaries.
event damp (i++) {
= {U, 0, 0};
coord Uinf foreach() {
if (fabs(x - (X0 + L0/2.)) > 4*L0/10.)
foreach_dimension()
.x[] += dt*(Uinf.x - u.x[])/2.;
u}
boundary ((scalar*){u});
}
event properties (i++) {
foreach_face()
.x[] = fm.x[]*nu;
mucboundary ((scalar*){muc});
}
event adapt (i++) {
foreach() {
[] = nodata;
resif (cs[] > 0 && cs[] < 1) {
[] = U/sqrt(branches[(int)(J[] + 0.5)].R*nu);
res}
}
((scalar*){res, u}, (double[]){C, ue, ue, ue}, maxlevel, 5);
adapt_wavelet unrefine (level > 5 && (x - X0) < L0/10. && (X0 + L0 - x) < L0/10.);
}
event logger (i += 5) {
, Fmu;
coord Fpembed_force (p, u, mu, &Fp, &Fmu);
fprintf (fp, "%d %g %g %g %g %g %ld\n",
, t, Fp.x, Fp.y, Fmu.x, Fmu.y, grid->n);
i}
event movies (t += 0.4) {
view (fov = 6, width = 1200, height = 400, tx = -0.25);
scalar omega[];
vorticity (u, omega);
boundary ({omega});
translate (z = 0.05) {
draw_vof ("cs", "fs", filled = -1, fc = {1,1,1});
draw_vof ("cs", "fs", lw = 2);
}
squares ("omega", min = -2, max = 2, linear = true, map = cool_warm);
cells();
char str[99];
sprintf (str, "Re_R = %g, C = %g, ML = %d", Re, c, maxlevel);
draw_string (str, 1, lw = 3, lc = {1, 0, 1});
scatter (loc);
save ("mov2c.mp4");
}
event stop (t = 150) {
fclose (fp);
free (branches);
}