Skip to content

Commit 6c2ff2e

Browse files
committed
add stopping criterion based on overdensity
1 parent e8978c6 commit 6c2ff2e

3 files changed

Lines changed: 80 additions & 0 deletions

File tree

src/main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ int main(int argc, char *argv[]) {
196196
} else if (problem == "precipitator_spherical") {
197197
Hydro::ProblemInitPackageData = precipitator_spherical::ProblemInitPackageData;
198198
pman.app_input->ProblemGenerator = precipitator_spherical::ProblemGenerator;
199+
pman.app_input->PostStepMeshUserWorkInLoop =
200+
precipitator_spherical::PostStepMeshUserWorkInLoop;
199201
pman.app_input->UserMeshWorkBeforeOutput =
200202
precipitator_spherical::UserMeshWorkBeforeOutput;
201203
Hydro::ProblemSourceUnsplit = precipitator_spherical::AddUnsplitSrcTerms;

src/pgen/pgen.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *pkg
127127
void ProblemGenerator(MeshBlock *pmb, parthenon::ParameterInput *pin);
128128
void AddUnsplitSrcTerms(MeshData<Real> *md, const parthenon::SimTime t, const Real dt);
129129
void AddSplitSrcTerms(MeshData<Real> *md, const parthenon::SimTime t, const Real dt);
130+
void PostStepMeshUserWorkInLoop(Mesh *mesh, ParameterInput *pin,
131+
const parthenon::SimTime &tm);
130132
void UserMeshWorkBeforeOutput(Mesh *mesh, ParameterInput *pin,
131133
const parthenon::SimTime &);
132134
} // namespace precipitator_spherical

src/pgen/precipitator_spherical.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,10 @@ void ProblemInitPackageData(ParameterInput *pin, StateDescriptor *pkg) {
741741
pin->GetOrAddReal("precipitator", "source_diag_min_hse_dv_kms",
742742
100.0),
743743
parthenon::Params::Mutability::Restart);
744+
pkg->AddParam<>("density_contrast_stop_threshold",
745+
pin->GetOrAddReal("precipitator",
746+
"density_contrast_stop_threshold", 10.0),
747+
parthenon::Params::Mutability::Restart);
744748

745749
pkg->AddParam<>("outer_sponge_inner_radius",
746750
pin->GetOrAddReal("precipitator", "outer_sponge_inner_radius",
@@ -1331,6 +1335,78 @@ void AddSplitSrcTerms(MeshData<Real> *md, const parthenon::SimTime, const Real d
13311335
});
13321336
}
13331337

1338+
Real MaxDensityContrastOverRadialMean(Mesh *mesh) {
1339+
auto md = mesh->mesh_data.Get();
1340+
auto pmb = md->GetBlockData(0)->GetBlockPointer();
1341+
auto pkg = pmb->packages.Get("Hydro");
1342+
1343+
const int num_bins = pkg->Param<int>("radial_profile_bins");
1344+
const Real rmin = pkg->Param<Real>("radial_profile_min");
1345+
const Real rmax = pkg->Param<Real>("radial_profile_max");
1346+
const Real nominal_outer_radius = pkg->Param<Real>("nominal_outer_radius");
1347+
const Real inv_dr =
1348+
(num_bins > 1 && rmax > rmin) ? static_cast<Real>(num_bins) / (rmax - rmin) : 0.0;
1349+
1350+
parthenon::ParArray1D<Real> rho_bar("rho_bar_stop_check", num_bins);
1351+
auto prim_pack = md->PackVariables(std::vector<std::string>{"prim"});
1352+
ComputeRadialAverageProfile(
1353+
rho_bar, md.get(), rmin, rmax,
1354+
KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, const Real) {
1355+
return prim_pack(b)(IDN, k, j, i);
1356+
});
1357+
1358+
IndexRange ib = md->GetBlockData(0)->GetBoundsI(IndexDomain::interior);
1359+
IndexRange jb = md->GetBlockData(0)->GetBoundsJ(IndexDomain::interior);
1360+
IndexRange kb = md->GetBlockData(0)->GetBoundsK(IndexDomain::interior);
1361+
1362+
Real max_contrast = -std::numeric_limits<Real>::infinity();
1363+
parthenon::par_reduce(
1364+
DEFAULT_LOOP_PATTERN, "SphericalPrecipMaxDensityContrast",
1365+
parthenon::DevExecSpace(), 0, prim_pack.GetDim(5) - 1, kb.s, kb.e, jb.s, jb.e,
1366+
ib.s, ib.e,
1367+
KOKKOS_LAMBDA(const int b, const int k, const int j, const int i,
1368+
Real &local_max) {
1369+
const auto &coords = prim_pack.GetCoords(b);
1370+
const auto &prim = prim_pack(b);
1371+
const Real radius = Radius(coords.Xc<1>(i), coords.Xc<2>(j), coords.Xc<3>(k));
1372+
if (radius > nominal_outer_radius) return;
1373+
const Real rho_avg = SampleRadialProfile(rho_bar, num_bins, radius, rmin, inv_dr);
1374+
const Real contrast =
1375+
(rho_avg > 0.0) ? (prim(IDN, k, j, i) - rho_avg) / rho_avg : 0.0;
1376+
if (contrast > local_max) local_max = contrast;
1377+
},
1378+
Kokkos::Max<Real>(max_contrast));
1379+
1380+
#ifdef MPI_PARALLEL
1381+
PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &max_contrast, 1,
1382+
MPI_PARTHENON_REAL, MPI_MAX, MPI_COMM_WORLD));
1383+
#endif
1384+
1385+
return max_contrast;
1386+
}
1387+
1388+
void PostStepMeshUserWorkInLoop(Mesh *mesh, ParameterInput *,
1389+
const parthenon::SimTime &tm) {
1390+
auto md = mesh->mesh_data.Get();
1391+
auto pmb = md->GetBlockData(0)->GetBlockPointer();
1392+
auto pkg = pmb->packages.Get("Hydro");
1393+
const Real threshold = pkg->Param<Real>("density_contrast_stop_threshold");
1394+
if (!(threshold > 0.0)) return;
1395+
1396+
const Real max_contrast = MaxDensityContrastOverRadialMean(mesh);
1397+
if (max_contrast > threshold) {
1398+
auto &mutable_tm = const_cast<parthenon::SimTime &>(tm);
1399+
mutable_tm.tlim = std::min(mutable_tm.tlim, mutable_tm.time + mutable_tm.dt);
1400+
mutable_tm.nlim = (mutable_tm.nlim < 0) ? mutable_tm.ncycle + 1
1401+
: std::min(mutable_tm.nlim, tm.ncycle + 1);
1402+
if (parthenon::Globals::my_rank == 0) {
1403+
std::cout << "Stopping precipitator_spherical: max "
1404+
"delta_rho_over_rho_bar="
1405+
<< max_contrast << " exceeds " << threshold << std::endl;
1406+
}
1407+
}
1408+
}
1409+
13341410
void UserMeshWorkBeforeOutput(Mesh *mesh, ParameterInput *pin,
13351411
const parthenon::SimTime &) {
13361412
auto md = mesh->mesh_data.Get();

0 commit comments

Comments
 (0)