Introduction
The second example shows the the rising of a warm bubble, which to some extent, resembles the mushroom cloud of an atomic bomb. This test case was proposed by [1]. The original setting was is 2D and we extended it to 3D. The size of the domain is 1 km \(\times\) 1 km \(\times\) 2.5km. The model resolution is uniformlly 5 m in each dimension. The bubble is initially centered at \(x_0 = y_0 = 500 \text{m}, z_0 = 260 \text{m}\) with a Gaussian-shaped potential temperature anomaly as:
\begin{eqnarray*} \Delta \theta &=& 0.5\;\text{K}, \qquad\quad\quad r \leq a \\ &=& 0.5e^{-(r-a)^2/s^2}\;\text{K}, \quad r > a \end{eqnarray*}
where \(r\) is the distance to the center, \(a=50\) m and \(s=100\) m. The background atmosphere is isentropic with surface pressure being 1 bar and surface temperature 303.15 K. The bubble is then released and evolve to 1200 s.
The commented program
Include files
These input files are just like those in the Example #1 : The straka Problem, so additional comments are not required.
#include <athena/athena.hpp>
#include <athena/athena_arrays.hpp>
#include <athena/coordinates/coordinates.hpp>
#include <athena/eos/eos.hpp>
#include <athena/field/field.hpp>
#include <athena/hydro/hydro.hpp>
#include <athena/mesh/mesh.hpp>
#include <athena/parameter_input.hpp>
#include <athena/stride_iterator.hpp>
canoe
snap
Preamble
We only need one global variables here, the surface pressure
Same as that in Example #1 : The straka Problem, make outputs of temperature and potential temperature.
void MeshBlock::InitUserMeshBlockData(ParameterInput *pin) {
AllocateUserOutputVariables(2);
SetUserOutputVariableName(0, "temp");
SetUserOutputVariableName(1, "theta");
}
Set temperature and potential temperature.
void MeshBlock::UserWorkBeforeOutput(ParameterInput *pin) {
Real gamma = peos->GetGamma();
for (int k = ks; k <= ke; ++k)
for (
int j = js;
j <= je; ++
j)
for (int i = is; i <= ie; ++i) {
user_out_var(0, k,
j, i) = pthermo->GetTemp(
this, k,
j, i);
user_out_var(1, k,
j, i) = pthermo->PotentialTemp(
this,
p0, k,
j, i);
}
}
static Thermodynamics const * GetInstance()
Return a pointer to the one and only instance of Thermodynamics.
Initialize surface pressure from input file.
void Mesh::InitUserMeshData(ParameterInput *pin) {
p0 = pin->GetReal(
"problem",
"p0");
}
Initial condition
We do not need forcings other than gravity in this problem, so we go directly to the initial condition.
void MeshBlock::ProblemGenerator(ParameterInput *pin) {
Similar to Example #1 : The straka Problem, read variables in the input file
Real gamma = pin->GetReal("hydro", "gamma");
Real grav = -phydro->hsrc.GetG1();
Real
Ts = pin->GetReal(
"problem",
"Ts");
Real
Rd = pin->GetReal(
"thermodynamics",
"Rd");
Real
cp = gamma / (gamma - 1.) *
Rd;
Real xc = pin->GetReal("problem", "xc");
Real yc = pin->GetReal("problem", "yc");
Real zc = pin->GetReal("problem", "zc");
Real s = pin->GetReal("problem", "s");
Real
a = pin->GetReal(
"problem",
"a");
Real dT = pin->GetReal("problem", "dT");
Whether to do a uniform bubble or not.
bool uniform_bubble =
pin->GetOrAddBoolean("problem", "uniform_bubble", false);
Loop over the grids and set initial condition
for (int k = ks; k <= ke; ++k)
for (
int j = js;
j <= je; ++
j)
for (int i = is; i <= ie; ++i) {
Real
x1 = pcoord->x1v(i);
Real
x2 = pcoord->x2v(
j);
Real x3 = pcoord->x3v(k);
Real
r = sqrt((x3 - yc) * (x3 - yc) + (
x2 - xc) * (
x2 - xc) +
temp += dT * pow(phydro->w(IPR, k,
j, i) /
p0,
Rd /
cp);
else if (!uniform_bubble)
temp += dT * exp(-(
r -
a) * (
r -
a) / (s * s)) *
pow(phydro->w(IPR, k,
j, i) /
p0,
Rd /
cp);
phydro->w(IDN, k,
j, i) = phydro->w(IPR, k,
j, i) / (
Rd *
temp);
phydro->w(IVX, k,
j, i) = phydro->w(IVY, k,
j, i) = 0.;
}
Change primitive variables to conserved variables
peos->PrimitiveToConserved(phydro->w, pfield->bcc, phydro->u, pcoord, is, ie,
js, je, ks, ke);
}
Results
Here we show the animation of the rising bubble
The temperature anomaly of the bubble is colored in blue/red with blue being colder and red being warmer. Initially, the warm part of the bubble is hiden at its center and you only see the colder outer part. Multiple convective overturnings develop seen during the rising motion to deliver the warm gas upward and outward. Unlike the 2D solution shown in [1], the 3D evolution of the bubble features a vortex ring surounding the core of the rising center and the head of the rising bubble is minimum compared to the ring.
The plain program
#include <athena/athena.hpp>
#include <athena/athena_arrays.hpp>
#include <athena/coordinates/coordinates.hpp>
#include <athena/eos/eos.hpp>
#include <athena/field/field.hpp>
#include <athena/hydro/hydro.hpp>
#include <athena/mesh/mesh.hpp>
#include <athena/parameter_input.hpp>
#include <athena/stride_iterator.hpp>
void MeshBlock::InitUserMeshBlockData(ParameterInput *pin) {
AllocateUserOutputVariables(2);
SetUserOutputVariableName(0, "temp");
SetUserOutputVariableName(1, "theta");
}
void MeshBlock::UserWorkBeforeOutput(ParameterInput *pin) {
Real gamma = peos->GetGamma();
for (int k = ks; k <= ke; ++k)
for (
int j = js;
j <= je; ++
j)
for (int i = is; i <= ie; ++i) {
user_out_var(0, k,
j, i) = pthermo->GetTemp(
this, k,
j, i);
user_out_var(1, k,
j, i) = pthermo->PotentialTemp(
this,
p0, k,
j, i);
}
}
void Mesh::InitUserMeshData(ParameterInput *pin) {
p0 = pin->GetReal(
"problem",
"p0");
}
void MeshBlock::ProblemGenerator(ParameterInput *pin) {
Real gamma = pin->GetReal("hydro", "gamma");
Real grav = -phydro->hsrc.GetG1();
Real
Ts = pin->GetReal(
"problem",
"Ts");
Real
Rd = pin->GetReal(
"thermodynamics",
"Rd");
Real
cp = gamma / (gamma - 1.) *
Rd;
Real xc = pin->GetReal("problem", "xc");
Real yc = pin->GetReal("problem", "yc");
Real zc = pin->GetReal("problem", "zc");
Real s = pin->GetReal("problem", "s");
Real
a = pin->GetReal(
"problem",
"a");
Real dT = pin->GetReal("problem", "dT");
bool uniform_bubble =
pin->GetOrAddBoolean("problem", "uniform_bubble", false);
for (int k = ks; k <= ke; ++k)
for (
int j = js;
j <= je; ++
j)
for (int i = is; i <= ie; ++i) {
Real
x1 = pcoord->x1v(i);
Real
x2 = pcoord->x2v(
j);
Real x3 = pcoord->x3v(k);
Real
r = sqrt((x3 - yc) * (x3 - yc) + (
x2 - xc) * (
x2 - xc) +
temp += dT * pow(phydro->w(IPR, k,
j, i) /
p0,
Rd /
cp);
else if (!uniform_bubble)
temp += dT * exp(-(
r -
a) * (
r -
a) / (s * s)) *
pow(phydro->w(IPR, k,
j, i) /
p0,
Rd /
cp);
phydro->w(IDN, k,
j, i) = phydro->w(IPR, k,
j, i) / (
Rd *
temp);
phydro->w(IVX, k,
j, i) = phydro->w(IVY, k,
j, i) = 0.;
}
peos->PrimitiveToConserved(phydro->w, pfield->bcc, phydro->u, pcoord, is, ie,
js, je, ks, ke);
}