Skip to content

Commit 411599d

Browse files
committed
Add prolongate prim for hydro
1 parent 094d362 commit 411599d

File tree

7 files changed

+143
-12
lines changed

7 files changed

+143
-12
lines changed

src/eos/adiabatic_glmmhd.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
// Athena headers
1616
#include "../main.hpp"
1717
#include "eos.hpp"
18+
#include "utils/error_checking.hpp"
1819

1920
using parthenon::MeshBlock;
2021
using parthenon::MeshBlockData;
@@ -30,6 +31,9 @@ class AdiabaticGLMMHDEOS : public EquationOfState {
3031
gamma_{gamma} {}
3132

3233
void ConservedToPrimitive(MeshData<Real> *md) const override;
34+
void PrimitiveToConserved(MeshData<Real> *md) const override {
35+
PARTHENON_FAIL("needs impl.");
36+
}
3337

3438
KOKKOS_INLINE_FUNCTION
3539
Real GetGamma() const { return gamma_; }

src/eos/adiabatic_hydro.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,35 @@ void AdiabaticHydroEOS::ConservedToPrimitive(MeshData<Real> *md) const {
6969
pkg->UpdateParam<std::int64_t>("fixed_num_cells_floor_temp",
7070
floor_temp_pkg + floor_temp);
7171
}
72+
73+
//----------------------------------------------------------------------------------------
74+
// \!fn void EquationOfState::PrimitiveToConserved(
75+
// Container<Real> &rc,
76+
// int il, int iu, int jl, int ju, int kl, int ku)
77+
// \brief Converts primitive to conserved variables in adiabatic hydro.
78+
// Not using any floors here and failing loudly because those fixes
79+
// are applied in ConsToPrim call. Should discss advantags and disadvantages of this
80+
// approach.
81+
void AdiabaticHydroEOS::PrimitiveToConserved(MeshData<Real> *md) const {
82+
auto cons_pack = md->PackVariables(std::vector<std::string>{"cons"});
83+
auto const prim_pack = md->PackVariables(std::vector<std::string>{"prim"});
84+
auto ib = md->GetBlockData(0)->GetBoundsI(IndexDomain::entire);
85+
auto jb = md->GetBlockData(0)->GetBoundsJ(IndexDomain::entire);
86+
auto kb = md->GetBlockData(0)->GetBoundsK(IndexDomain::entire);
87+
88+
auto pkg = md->GetBlockData(0)->GetBlockPointer()->packages.Get("Hydro");
89+
const auto nhydro = pkg->Param<int>("nhydro");
90+
const auto nscalars = pkg->Param<int>("nscalars");
91+
92+
auto this_on_device = (*this);
93+
94+
parthenon::par_for(
95+
DEFAULT_LOOP_PATTERN, "PrimitiveToConserved", parthenon::DevExecSpace(), 0,
96+
cons_pack.GetDim(5) - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e,
97+
KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) {
98+
auto &cons = cons_pack(b);
99+
const auto &prim = prim_pack(b);
100+
101+
this_on_device.PrimToCons(cons, prim, nhydro, nscalars, k, j, i);
102+
});
103+
}

src/eos/adiabatic_hydro.hpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class AdiabaticHydroEOS : public EquationOfState {
3131
gamma_{gamma} {}
3232

3333
void ConservedToPrimitive(MeshData<Real> *md) const override;
34+
void PrimitiveToConserved(MeshData<Real> *md) const override;
3435

3536
KOKKOS_INLINE_FUNCTION
3637
Real GetGamma() const { return gamma_; }
@@ -151,6 +152,55 @@ class AdiabaticHydroEOS : public EquationOfState {
151152
return floors_used;
152153
}
153154

155+
//----------------------------------------------------------------------------------------
156+
// \!fn Real EquationOfState::PrimToCons(View4D cons, View4D prim, const int& k, const
157+
// int& j, const int& i) \brief Fills an array of conservatives given an array of
158+
// primities, currently without floors
159+
template <typename View4D>
160+
KOKKOS_INLINE_FUNCTION void PrimToCons(View4D cons, View4D prim, const int &nhydro,
161+
const int &nscalars, const int &k, const int &j,
162+
const int &i) const {
163+
Real gm1 = GetGamma() - 1.0;
164+
165+
Real &u_d = cons(IDN, k, j, i);
166+
Real &u_m1 = cons(IM1, k, j, i);
167+
Real &u_m2 = cons(IM2, k, j, i);
168+
Real &u_m3 = cons(IM3, k, j, i);
169+
Real &u_e = cons(IEN, k, j, i);
170+
171+
Real &w_d = prim(IDN, k, j, i);
172+
Real &w_vx = prim(IV1, k, j, i);
173+
Real &w_vy = prim(IV2, k, j, i);
174+
Real &w_vz = prim(IV3, k, j, i);
175+
Real &w_p = prim(IPR, k, j, i);
176+
177+
PARTHENON_REQUIRE(w_d != 0.0,
178+
"Densities should never be exactly 0! This points to working with "
179+
"some default initialized and/or uninitialized data.");
180+
PARTHENON_REQUIRE(w_d > 0.0,
181+
"Got negative density. Might need to impl floors here too.");
182+
PARTHENON_REQUIRE(w_p != 0.0,
183+
"Pressure should never be exactly 0! This points to working with "
184+
"some default initialized and/or uninitialized data.");
185+
PARTHENON_REQUIRE(w_p > 0.0,
186+
"Got negative pressure. Might need to impl floors here too.");
187+
// apply density floor, without changing momentum or energy
188+
u_d = w_d;
189+
190+
Real di = 1.0 / u_d;
191+
u_m1 = w_d * w_vx;
192+
u_m2 = w_d * w_vy;
193+
u_m3 = w_d * w_vz;
194+
195+
const Real e_k = 0.5 * w_d * (SQR(w_vx) + SQR(w_vy) + SQR(w_vz));
196+
u_e = e_k + w_p / gm1;
197+
198+
// Convert passive scalars
199+
for (auto n = nhydro; n < nhydro + nscalars; ++n) {
200+
cons(n, k, j, i) = prim(n, k, j, i) * w_d;
201+
}
202+
}
203+
154204
private:
155205
Real gamma_; // ratio of specific heats
156206
};

src/eos/eos.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class EquationOfState {
3838
internal_e_floor_(internal_e_floor), velocity_ceiling_(velocity_ceiling),
3939
internal_e_ceiling_(internal_e_ceiling) {}
4040
virtual void ConservedToPrimitive(MeshData<Real> *md) const = 0;
41+
virtual void PrimitiveToConserved(MeshData<Real> *md) const = 0;
4142

4243
KOKKOS_INLINE_FUNCTION
4344
Real GetPressureFloor() const { return pressure_floor_; }

src/hydro/hydro.cpp

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "diffusion/diffusion.hpp"
3333
#include "glmmhd/glmmhd.hpp"
3434
#include "hydro.hpp"
35+
#include "interface/metadata.hpp"
3536
#include "interface/params.hpp"
3637
#include "outputs/outputs.hpp"
3738
#include "prolongation/custom_ops.hpp"
@@ -217,6 +218,12 @@ void ConsToPrim(MeshData<Real> *md) {
217218
md->GetBlockData(0)->GetBlockPointer()->packages.Get("Hydro")->Param<T>("eos");
218219
eos.ConservedToPrimitive(md);
219220
}
221+
template <class T>
222+
void PrimToCons(MeshData<Real> *md) {
223+
const auto &eos =
224+
md->GetBlockData(0)->GetBlockPointer()->packages.Get("Hydro")->Param<T>("eos");
225+
eos.PrimitiveToConserved(md);
226+
}
220227

221228
// Add unsplit sources, i.e., source that are integrated in all stages of the
222229
// explicit integration scheme.
@@ -493,6 +500,9 @@ std::shared_ptr<StateDescriptor> Initialize(ParameterInput *pin) {
493500
Units units(pin, pkg);
494501
}
495502

503+
const auto prolong_prims = pin->GetOrAddBoolean("hydro", "prolongate_prims", false);
504+
pkg->AddParam<>("prolongate_prims", prolong_prims);
505+
496506
auto eos_str = pin->GetString("hydro", "eos");
497507
if (eos_str == "adiabatic") {
498508
Real gamma = pin->GetReal("hydro", "gamma");
@@ -717,7 +727,12 @@ std::shared_ptr<StateDescriptor> Initialize(ParameterInput *pin) {
717727
if (fluid == Fluid::euler) {
718728
AdiabaticHydroEOS eos(pfloor, dfloor, efloor, vceil, eceil, gamma);
719729
pkg->AddParam<>("eos", eos);
720-
pkg->FillDerivedMesh = ConsToPrim<AdiabaticHydroEOS>;
730+
if (prolong_prims) {
731+
pkg->PreCommFillDerivedMesh = ConsToPrim<AdiabaticHydroEOS>;
732+
pkg->FillDerivedMesh = PrimToCons<AdiabaticHydroEOS>;
733+
} else {
734+
pkg->FillDerivedMesh = ConsToPrim<AdiabaticHydroEOS>;
735+
}
721736
pkg->EstimateTimestepMesh = EstimateTimestep<Fluid::euler>;
722737
} else if (fluid == Fluid::glmmhd) {
723738
AdiabaticGLMMHDEOS eos(pfloor, dfloor, efloor, vceil, eceil, gamma);
@@ -787,15 +802,32 @@ std::shared_ptr<StateDescriptor> Initialize(ParameterInput *pin) {
787802
prim_labels.emplace_back("scalar_" + std::to_string(i));
788803
}
789804

790-
Metadata m(
791-
{Metadata::Cell, Metadata::Independent, Metadata::FillGhost, Metadata::WithFluxes},
792-
std::vector<int>({nhydro + nscalars}), cons_labels);
805+
Metadata m;
806+
// In principle, it'd be nicer to work with .Set(), but see
807+
// https://github.com/parthenon-hpc-lab/parthenon/issues/844 so let's
808+
// be safe than sorry.
809+
if (prolong_prims) {
810+
// no FillGhost here
811+
m = Metadata({Metadata::Cell, Metadata::Independent, Metadata::WithFluxes},
812+
std::vector<int>({nhydro + nscalars}), cons_labels);
813+
} else {
814+
m = Metadata({Metadata::Cell, Metadata::Independent, Metadata::FillGhost,
815+
Metadata::WithFluxes},
816+
std::vector<int>({nhydro + nscalars}), cons_labels);
817+
}
793818
m.RegisterRefinementOps<refinement_ops::ProlongateCellMinModMultiD,
794819
parthenon::refinement_ops::RestrictAverage>();
795820
pkg->AddField("cons", m);
796821

797-
m = Metadata({Metadata::Cell, Metadata::Derived}, std::vector<int>({nhydro + nscalars}),
798-
prim_labels);
822+
if (prolong_prims) {
823+
m = Metadata({Metadata::Cell, Metadata::Derived, Metadata::FillGhost},
824+
std::vector<int>({nhydro + nscalars}), prim_labels);
825+
m.RegisterRefinementOps<refinement_ops::ProlongateCellMinModMultiD,
826+
parthenon::refinement_ops::RestrictAverage>();
827+
} else {
828+
m = Metadata({Metadata::Cell, Metadata::Derived},
829+
std::vector<int>({nhydro + nscalars}), prim_labels);
830+
}
799831
pkg->AddField("prim", m);
800832

801833
const auto refine_str = pin->GetOrAddString("refinement", "type", "unset");

src/hydro/hydro_driver.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,10 @@ void AddSTSTasks(TaskCollection *ptask_coll, Mesh *pmesh, BlockList_t &blocks,
260260
auto rkl2_step_first = tl.AddTask(init_MY0, RKL2StepFirst, Y0.get(), base.get(),
261261
Yjm2.get(), MY0.get(), s_rkl, tau);
262262

263+
// if prolongate on prims is done then this is a ConsToPrim call. Otherwise, noop.
264+
auto precomm_fill_derived =
265+
tl.AddTask(rkl2_step_first, parthenon::Update::PreCommFillDerived<MeshData<Real>>,
266+
base.get());
263267
// Update ghost cells of Y1 (as MY1 is calculated for each Y_j).
264268
// Y1 stored in "base", see rkl2_step_first task.
265269
// Update ghost cells (local and non local), prolongate and apply bound cond.
@@ -268,7 +272,7 @@ void AddSTSTasks(TaskCollection *ptask_coll, Mesh *pmesh, BlockList_t &blocks,
268272
// best impl. Go with default call (split local/nonlocal) for now.
269273
// TODO(pgrete) optimize (in parthenon) to only send subset of updated vars
270274
auto bounds_exchange = parthenon::AddBoundaryExchangeTasks(
271-
rkl2_step_first | start_bnd, tl, base, pmesh->multilevel);
275+
precomm_fill_derived | start_bnd, tl, base, pmesh->multilevel);
272276

273277
tl.AddTask(bounds_exchange, parthenon::Update::FillDerived<MeshData<Real>>,
274278
base.get());
@@ -326,14 +330,18 @@ void AddSTSTasks(TaskCollection *ptask_coll, Mesh *pmesh, BlockList_t &blocks,
326330
tl.AddTask(set_flx, RKL2StepOther, Y0.get(), base.get(), Yjm2.get(), MY0.get(),
327331
mu_j, nu_j, mu_tilde_j, gamma_tilde_j, tau);
328332

333+
// if prolongate on prims is done then this is a ConsToPrim call. Otherwise, noop.
334+
auto precomm_fill_derived =
335+
tl.AddTask(rkl2_step_other,
336+
parthenon::Update::PreCommFillDerived<MeshData<Real>>, base.get());
329337
// update ghost cells of base (currently storing Yj)
330338
// Update ghost cells (local and non local), prolongate and apply bound cond.
331339
// TODO(someone) experiment with split (local/nonlocal) comms with respect to
332340
// performance for various tests (static, amr, block sizes) and then decide on the
333341
// best impl. Go with default call (split local/nonlocal) for now.
334342
// TODO(pgrete) optimize (in parthenon) to only send subset of updated vars
335343
auto bounds_exchange = parthenon::AddBoundaryExchangeTasks(
336-
rkl2_step_other | start_bnd, tl, base, pmesh->multilevel);
344+
precomm_fill_derived | start_bnd, tl, base, pmesh->multilevel);
337345

338346
tl.AddTask(bounds_exchange, parthenon::Update::FillDerived<MeshData<Real>>,
339347
base.get());
@@ -561,11 +569,15 @@ TaskCollection HydroDriver::MakeTaskCollection(BlockList_t &blocks, int stage) {
561569
tl.AddTask(source_split_strang_final, AddSplitSourcesFirstOrder, mu0.get(), tm);
562570
}
563571

572+
// if prolongate on prims is done then this is a ConsToPrim call. Otherwise, noop.
573+
auto precomm_fill_derived =
574+
tl.AddTask(source_split_first_order,
575+
parthenon::Update::PreCommFillDerived<MeshData<Real>>, mu0.get());
564576
// Update ghost cells (local and non local), prolongate and apply bound cond.
565577
// TODO(someone) experiment with split (local/nonlocal) comms with respect to
566578
// performance for various tests (static, amr, block sizes) and then decide on the
567579
// best impl. Go with default call (split local/nonlocal) for now.
568-
parthenon::AddBoundaryExchangeTasks(source_split_first_order | start_bnd, tl, mu0,
580+
parthenon::AddBoundaryExchangeTasks(precomm_fill_derived | start_bnd, tl, mu0,
569581
pmesh->multilevel);
570582
}
571583

src/pgen/cloud.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,9 @@ void InitUserMeshData(Mesh *mesh, ParameterInput *pin) {
149149

150150
void ProblemGenerator(MeshBlock *pmb, ParameterInput *pin) {
151151
auto hydro_pkg = pmb->packages.Get("Hydro");
152-
auto ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior);
153-
auto jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior);
154-
auto kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior);
152+
auto ib = pmb->cellbounds.GetBoundsI(IndexDomain::entire);
153+
auto jb = pmb->cellbounds.GetBoundsJ(IndexDomain::entire);
154+
auto kb = pmb->cellbounds.GetBoundsK(IndexDomain::entire);
155155

156156
const auto nhydro = hydro_pkg->Param<int>("nhydro");
157157
const auto nscalars = hydro_pkg->Param<int>("nscalars");

0 commit comments

Comments
 (0)