-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbcg.h
More file actions
97 lines (80 loc) · 2.52 KB
/
bcg.h
File metadata and controls
97 lines (80 loc) · 2.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/**
# Bell-Collela-Glaz advection scheme
The function below implements the 2nd-order, unsplit, upwind scheme of
[Bell-Collela-Glaz, 1989](references.bib#bell89). Given a centered
scalar field *f*, a face vector field *uf* (possibly weighted by a
face metric), a timestep *dt* and a source term field *src*, it fills
the face vector field *flux* with the components of the advection
fluxes of *f*. */
void tracer_fluxes (scalar f,
face vector uf,
face vector flux,
double dt,
(const) scalar src)
{
/**
We first compute the cell-centered gradient of *f* in a locally-allocated
vector field. */
vector g[];
gradients ({f}, {g});
/**
For each face, the flux is composed of two parts... */
foreach_face() {
/**
A normal component... (Note that we cheat a bit here, `un` should
strictly be `dt*(uf.x[i] + uf.x[i+1])/((fm.x[] +
fm.x[i+1])*Delta)` but this causes trouble with boundary
conditions (when using narrow '1 ghost cell' stencils)). */
double un = dt*uf.x[]/(fm.x[]*Delta + SEPS), s = sign(un);
int i = -(s + 1.)/2.;
double f2 = f[i] + (src[] + src[-1])*dt/4. + s*(1. - s*un)*g.x[i]*Delta/2.;
/**
and tangential components... */
#if dimension > 1
if (fm.y[i] && fm.y[i,1]) {
double vn = (uf.y[i] + uf.y[i,1])/(fm.y[i] + fm.y[i,1]);
double fyy = vn < 0. ? f[i,1] - f[i] : f[i] - f[i,-1];
f2 -= dt*vn*fyy/(2.*Delta);
}
#endif
#if dimension > 2
if (fm.z[i] && fm.z[i,0,1]) {
double wn = (uf.z[i] + uf.z[i,0,1])/(fm.z[i] + fm.z[i,0,1]);
double fzz = wn < 0. ? f[i,0,1] - f[i] : f[i] - f[i,0,-1];
f2 -= dt*wn*fzz/(2.*Delta);
}
#endif
flux.x[] = f2*uf.x[];
}
}
/**
The function below uses the *tracer_fluxes* function to integrate the
advection equation, using an explicit scheme with timestep *dt*, for
each tracer in the list. */
void advection (scalar * tracers, face vector u, double dt,
scalar * src = NULL)
{
/**
If *src* is not provided we set all the source terms to zero. */
scalar * psrc = src;
if (!src)
for (scalar s in tracers) {
const scalar zero[] = 0.;
src = list_append (src, zero);
}
assert (list_len (tracers) == list_len (src));
scalar f, source;
for (f,source in tracers,src) {
face vector flux[];
tracer_fluxes (f, u, flux, dt, source);
#if !EMBED
foreach()
foreach_dimension()
f[] += dt*(flux.x[] - flux.x[1])/(Delta*cm[]);
#else // EMBED
update_tracer (f, u, flux, dt);
#endif // EMBED
}
if (!psrc)
free (src);
}