sandbox/hugoj/test_diffusion_with_bott_neumann/diff_test.c
How to use diffusion.h and dr.h together
This 1D case is an example on how to set boundary condition for a scalar T. Temperature is initialized as affine function of z, at the surface a (heat) flux is imposed and at the bottom we impose a that the initial gradient is conserved at all t.
Note: imposing flux = 0 at the bottom could be done using \lambda_b = HUGE but its not clean. A proper Neumann condition would need a modification of diffusion.h. I started that but adding an argument with default value (allowing existing code to continue to run without modification) to the function ‘vertical_diffusion’ raise some error. Working on this modified diffusion.h requires to copy/link nh.h, implicit.h, hydro.h in the directory of diffusion.h. There might be a better way to do this…
#include "grid/multigrid.h"
//#include "grid/multigrid1D.h"
hydro.h: No such file or directory
#include "hydro.h"
#include "nh.h"
#include "layered/remap.h"
#include "layered/perfs.h"
//#include "bderembl/libs/netcdf_bas.h" // read/write netcdf files
double tend = 3600.0;
double smalltime = 1e-10;
// -> stratification related
double strat = 0.000002; // [s-2] N^2 stratification
double Ts = 20.; // [K] Surface temperature (arbitrary)
double qt = -500.; // [W.m-2] Heat flux
double rho0 = 1025.; // [kg.m-3] reference density
double cp = 4.2e3; // [J.kg-1.K-1] heat capacity water
double alphaT = 2e-4; // [K-1] Thermal expansion coeff for water
double Pr = 1.; // Prandtl number = nu/kappa
double kappa = 1.5e-5; // [m2.s-1] Scalar vertical diffusion coeff
double T0 = 20.; // [°C] Reference temperature
double Trand = 0.001; // [°C] Random temperature perturbution
const double g_ = 9.81; // [m.s-2] Gravity
#define drho(T) (alphaT*(T0-T)) // Linear equation of state (Vallis 2.4)
#define Tini(z) strat/(g_*alphaT)*z + Ts
#include "layered/dr.h"
static FILE * fp;
int main(int argc, char *argv[])
{
L0 = 50.;
nu = 0.01;
kappa = nu;
N = 1;
nl = 30;
G = 9.81;
theta_H = 0.51;
CFL_H = 8.;
CFL = 0.8;
origin (-L0/2., -L0/2.);
#if dimension==2
periodic (top);
#endif
periodic (left);
run();
}
event init(i = 0) {
foreach() {
zb[] = -100.;
eta[] = 0.;
double H = - zb[];
double z = zb[];
foreach_layer() {
h[] = H/nl;
z += h[]/2.;
foreach_dimension()
u.x[] = 0.;
w[] = 0.;
T[] = Tini(z) + Trand * noise()*exp(z/100.) ;
z += h[]/2.;
}
}
fp = fopen("T_profile.dat","w"); // reset file
fclose(fp);
}
event viscous_term (i++)
{
foreach() {
vertical_diffusion (point, // point
h, // h
T, // scalar
dt, // dt
kappa, // D
qt/(kappa*rho0*cp), // dst
strat/(g_*alphaT), // dsb
0., // s_b
HUGE, // lambda_b
0., // s_t
HUGE); // lambda_t
// void vertical_diffusion (Point point, scalar h, scalar s, double dt, double D,
// double dst, double dsb,double s_b, double lambda_b, double s_t, double lambda_t)
//vertical_diffusion (point, h, T, dt, kappa, qt/(kappa*rho0*cp), 0., 0. , HUGE); //
}
}
event log (i++){
fp = fopen("T_profile.dat","a");
if (fp == NULL){
fprintf(stderr, "Error opening file T_profile.dat");
return 2;
}
foreach() {
foreach_layer()
fprintf (fp, "%f %d %d %g\n", t, i, point.l, T[]);
}
fprintf(fp,"\n\n");
fclose(fp);
}
event stop (t = tend);import numpy as np
import matplotlib.pyplot as plt
# --- load data ---
data = []
with open("T_profile.dat") as f:
for line in f:
line = line.strip()
if line.startswith("#") or line == "":
continue
t, it, layer, T = line.split()
data.append((float(t), int(it), int(layer), float(T)))
data = np.array(data)
# --- group by iteration ---
iterations = np.unique(data[:, 1].astype(int))
fig, ax = plt.subplots(figsize=(8, 6))
cmap = plt.get_cmap("viridis", len(iterations))
for idx, it in enumerate(iterations):
mask = data[:, 1].astype(int) == it
block = data[mask]
layer = block[:, 2]
T = block[:, 3]
t_val = block[0, 0]
ax.plot(T, layer, color=cmap(idx), marker="+", linestyle="-", label=f"t = {t_val:.1f}")
ax.set_xlabel("T")
ax.set_ylabel("Layer")
ax.set_title("Temperature profiles")
ax.set_xlim([19.875,20.025])
#ax.legend(loc="upper left", bbox_to_anchor=(1, 1))
plt.tight_layout()
plt.savefig("T_profiles.png", dpi=150)
plt.show()
