sandbox/Antoonvh/convection_cyl.c

Atmospheric convection on a sphere
Rather than using an exotic mapping to allow a spherical metric, we may embed a sphere in a 3D domain. Here we test the concept by embedding a cylindrical earth into a quadtree.
The case
We take inspiration from Van Heerwaarden and Mellado (2016) and consider a stably stratified atmosphere (BV-freq N) over a warm earth surface with radius R.
The resulting movie
#include "embed.h"
#include "navier-stokes/centered.h"
#include "tracer.h"
#include "diffusion.h"
#include "profile6.h"
#include "view.h"
scalar s[];
scalar * tracers = {s};
double R = .5;
#define RADIUS (sqrt(sq(x) + sq(y) + sq(z)))
.n[embed] = dirichlet (0.);
u.t[embed] = dirichlet (0.);
u#if dimension == 3
.r[embed] = dirichlet (0.);
u#endif
[embed] = dirichlet (RADIUS + 1.);
s[left] = dirichlet (RADIUS);
s[right] = dirichlet (RADIUS);
s[bottom] = dirichlet (RADIUS);
s[top] = dirichlet (RADIUS);
s
face vector muc[], av[];
double nu = 0.0001;
int main() {
= 4;
L0 = Y0 = -L0/2.;
X0 = 256;
N = muc;
mu = av;
a run();
}
event init (t = 0) {
vertex scalar phi[];
foreach_vertex()
[] = RADIUS - R;
phifractions (phi, cs, fs);
foreach()
[] = (RADIUS + 0.005*noise())*cs[];
s}
event properties (i++) {
foreach_face()
.x[] = fm.x[]*nu;
mucboundary ((scalar*){muc});
}
event tracer_diffusion(i++)
(s, dt, mu); diffusion
Gravity
Gravity is oriented in the radial direction.
event acceleration (i++) {
foreach_face() {
= {x, y, z};
coord r .x[] = (s[] + s[-1])*r.x/RADIUS;
av}
}
event movie (t += 0.1) {
draw_vof ("cs", "fs", filled = -1, fc = {0.9, 0.9, 0.9});
squares ("s", min = R, max = R + 1.5, linear = true);
save ("movie.mp4");
}
event prof (t = {0, 10, 50, 100}) {
char fname[99];
sprintf(fname, "prof%g", t);
({s}, RADIUS, fname);
profile }
Here are some radial profiles of the s field.
set yr [0.5:2.2]
set xr [0.4:2.4]
set xlabel 'Buoyancy'
set ylabel 'Radius'
set key top left
set size ratio -1
plot 'prof0' u 2:1 w l lw 2 t 't = 0' ,\
'prof10' u 2:1 w l lw 2 t 't = 10' ,\
'prof50' u 2:1 w l lw 2 t 't = 50',\
'prof100' u 2:1 w l lw 2 t 't = 100'
event adapt (i++)
((scalar*){cs,s, u}, (double[]){0.01, 0.05, 0.02, 0.02}, 9, 5); adapt_wavelet