sandbox/hugoj/lib/diffusionH.h
Vertical diffusion
This code builds upon diffusion.h to implement a Neumann condition at the top and the bottom of the domain.
See the test case here
void vertical_diffusion2 (Point point, scalar h, scalar s, double dt, double D,
double dst, double dsb)
{
double a[nl], b[nl], c[nl], rhs[nl];The rhs of the tridiagonal system is h_l s_l.
foreach_layer()
rhs[point.l] = s[]*h[];The lower, principal and upper diagonals a, b and c are given by a_{l > 0} = - \left( \frac{D \Delta t}{h_{l - 1 / 2}} \right)^{n + 1} c_{l < \mathrm{nl} - 1} = - \left( \frac{D \Delta t}{h_{l + 1 / 2}} \right)^{n + 1} b_{0 < l < \mathrm{nl} - 1} = h_l^{n + 1} - a_l - c_l
for (int l = 1; l < nl - 1; l++) {
a[l] = - 2.*D*dt/(h[0,0,l-1] + h[0,0,l]);
c[l] = - 2.*D*dt/(h[0,0,l] + h[0,0,l+1]);
b[l] = h[0,0,l] - a[l] - c[l];
}For the top layer the boundary conditions give the (ghost) boundary value s_{\mathrm{nl}} = s_{\mathrm{nl} - 1} + \dot{s}_t h_{\mathrm{nl} - 1}, which gives the diagonal coefficient and right-hand-side b_{\mathrm{nl} - 1} = h_{\mathrm{nl} - 1}^{n + 1} - a_{\mathrm{nl} - 1} \mathrm{rhs}_{\mathrm{nl} - 1} = (hs)_{\mathrm{nl} - 1}^{\star} + D \Delta t \dot{s}_t
a[nl-1] = - 2.*D*dt/(h[0,0,nl-2] + h[0,0,nl-1]);
b[nl-1] = h[0,0,nl-1] - a[nl-1];
rhs[nl-1] += D*dt*dst;For the bottom layer we use the same logic as for the top
b[0] = h[] + 2.*dt*D*(1./(h[] + h[0,0,1]));
c[0] = - 2.*dt*D*(1./(h[] + h[0,0,1]));
rhs[0] -= D*dt*dsb;
if (nl == 1) {
b[0] += c[0];
rhs[0] += (- c[0]*h[] - D*dt) * dst; //Todo: add flux condition dst_b for case nl=1
}We can now solve the tridiagonal system using the Thomas algorithm.
for (int l = 1; l < nl; l++) {
b[l] -= a[l]*c[l-1]/b[l-1];
rhs[l] -= a[l]*rhs[l-1]/b[l-1];
}
a[nl-1] = rhs[nl-1]/b[nl-1];
s[0,0,nl-1] = a[nl-1];
for (int l = nl - 2; l >= 0; l--)
s[0,0,l] = a[l] = (rhs[l] - c[l]*a[l+1])/b[l];
}
/* # TODO
- fix the case nl=1
**/