From dd6d9f83a882cca5e7a48ebc66c93de4eda1d5b2 Mon Sep 17 00:00:00 2001 From: Adam Dempsey Date: Sun, 12 Jan 2025 09:30:29 -0700 Subject: [PATCH 1/9] Update singularity --- external/singularity-eos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/singularity-eos b/external/singularity-eos index f7df74f9..3f78b830 160000 --- a/external/singularity-eos +++ b/external/singularity-eos @@ -1 +1 @@ -Subproject commit f7df74f90d53e97d048cd230eec1d6203d7c37d2 +Subproject commit 3f78b8306701c8265eb54e4572a3d382a7a727e4 From d37154fd56267075df985521217a1d736bfd8fad Mon Sep 17 00:00:00 2001 From: Adam Dempsey Date: Mon, 13 Jan 2025 07:53:51 -0700 Subject: [PATCH 2/9] Convert stopping time models to class. Add new model that is not just Stokes --- src/artemis.cpp | 2 +- src/drag/drag.cpp | 8 ++- src/drag/drag.hpp | 155 +++++++++++++++++++++++++++++++++++++++------- 3 files changed, 141 insertions(+), 24 deletions(-) diff --git a/src/artemis.cpp b/src/artemis.cpp index 782a6863..15361539 100644 --- a/src/artemis.cpp +++ b/src/artemis.cpp @@ -104,7 +104,7 @@ Packages_t ProcessPackages(std::unique_ptr &pin) { if (do_dust) packages.Add(Dust::Initialize(pin.get())); if (do_rotating_frame) packages.Add(RotatingFrame::Initialize(pin.get())); if (do_cooling) packages.Add(Gas::Cooling::Initialize(pin.get())); - if (do_drag) packages.Add(Drag::Initialize(pin.get())); + if (do_drag) packages.Add(Drag::Initialize(pin.get(), constants, units)); if (do_radiation) { auto eos_h = packages.Get("gas")->Param("eos_h"); auto opacity_h = packages.Get("gas")->Param("opacity_h"); diff --git a/src/drag/drag.cpp b/src/drag/drag.cpp index 39f8a57d..78a77867 100644 --- a/src/drag/drag.cpp +++ b/src/drag/drag.cpp @@ -16,13 +16,16 @@ #include "artemis.hpp" #include "geometry/geometry.hpp" #include "utils/eos/eos.hpp" +#include "utils/units.hpp" using ArtemisUtils::EOS; namespace Drag { //---------------------------------------------------------------------------------------- //! \fn StateDescriptor Drag::Initialize //! \brief Adds intialization function for damping package -std::shared_ptr Initialize(ParameterInput *pin) { +std::shared_ptr Initialize(ParameterInput *pin, + ArtemisUtils::Constants &constants, + ArtemisUtils::Units &units) { auto drag = std::make_shared("drag"); Params ¶ms = drag->AllParams(); @@ -82,7 +85,8 @@ std::shared_ptr Initialize(ParameterInput *pin) { // Enforce 1 gas species - params.Add("stopping_time_params", StoppingTimeParams("dust/stopping_time", pin)); + params.Add("stopping_time_params", + StoppingTimeParams("dust/stopping_time", pin, constants, units)); } return drag; diff --git a/src/drag/drag.hpp b/src/drag/drag.hpp index 3f9adf86..0fbd1fb5 100644 --- a/src/drag/drag.hpp +++ b/src/drag/drag.hpp @@ -22,6 +22,7 @@ #include "utils/artemis_utils.hpp" #include "utils/diffusion/diffusion_coeff.hpp" #include "utils/eos/eos.hpp" +#include "utils/units.hpp" using namespace parthenon::package::prelude; using ArtemisUtils::EOS; @@ -54,7 +55,7 @@ namespace Drag { */ enum class Coupling { simple_dust, self, null }; -enum class DragModel { constant, stokes, null }; +enum class DragModel { constant, stokes, dp15, null }; inline Coupling ChooseDrag(const std::string choice) { if (choice == "self") { @@ -111,10 +112,11 @@ struct SelfDragParams { struct StoppingTimeParams { - Real scale; + Real scale, dh, mass_scale, p1, p2, p3; DragModel model; ParArray1D tau; - StoppingTimeParams(std::string block_name, ParameterInput *pin) { + StoppingTimeParams(std::string block_name, ParameterInput *pin, + ArtemisUtils::Constants &constants, ArtemisUtils::Units &units) { const std::string choice = pin->GetString(block_name, "type"); const int nd = pin->GetOrAddInteger("dust", "nspecies", 1); tau = ParArray1D("tau", nd); @@ -137,13 +139,124 @@ struct StoppingTimeParams { h_tau(n) = scale; } tau.DeepCopy(h_tau); + } else if (choice == "dp15") { + model = DragModel::dp15; + scale = pin->GetOrAddReal(block_name, "scale", 1.0); + auto h_tau = tau.GetHostMirror(); + for (int n = 0; n < nd; n++) { + h_tau(n) = scale; + } + tau.DeepCopy(h_tau); + dh = units.GetLengthPhysicalToCode() * + pin->GetOrAddReal(block_name, "gas_diameter", 2.71e-8 /* cm */); + p1 = pin->GetOrAddReal(block_name, "p1", 3.07); + p2 = pin->GetOrAddReal(block_name, "p2", 0.6688); + p3 = pin->GetOrAddReal(block_name, "p3", 0.681); + // save this so that we don't have to pass units struct to the Get() routines + mass_scale = units.GetMassPhysicalToCode(); + } else { PARTHENON_FAIL("bad type for stopping time model"); } } }; -std::shared_ptr Initialize(ParameterInput *pin); +template +class DragCoeff { + public: + KOKKOS_INLINE_FUNCTION Real Get(const StoppingTimeParams &dp, const int id, + const Real dg, const Real Tg, const Real u, + const Real grain_density, const Real size, + const EOS &eos) const { + PARTHENON_FAIL("No default implementation for drag coefficient"); + } +}; + +// null +template <> +class DragCoeff { + public: + KOKKOS_INLINE_FUNCTION Real Get(const StoppingTimeParams &dp, const int id, + const Real dg, const Real Tg, const Real u, + const Real grain_density, const Real size, + const EOS &eos) const { + return Big(); + } +}; + +template <> +class DragCoeff { + public: + KOKKOS_INLINE_FUNCTION Real Get(const StoppingTimeParams &dp, const int id, + const Real dg, const Real Tg, const Real u, + const Real grain_density, const Real size, + const EOS &eos) const { + return dp.tau(id); + } +}; + +template <> +class DragCoeff { + public: + KOKKOS_INLINE_FUNCTION Real Get(const StoppingTimeParams &dp, const int id, + const Real dg, const Real Tg, const Real u, + const Real grain_density, const Real size, + const EOS &eos) const { + const Real cv = eos.SpecificHeatFromDensityTemperature(dg, Tg); + const Real gm1 = eos.GruneisenParamFromDensityTemperature(dg, Tg); + // kb T/ mu = cv * gm1 * T + const Real vth = std::sqrt(8.0 / M_PI * gm1 * cv * Tg); + return dp.tau(id) * grain_density / dg * size / vth; + } +}; + +template <> +class DragCoeff { + public: + KOKKOS_INLINE_FUNCTION Real Get(const StoppingTimeParams &dp, const int id, + const Real dg, const Real Tg, const Real u, + const Real grain_density, const Real size, + const EOS &eos) const { + const Real cv = eos.SpecificHeatFromDensityTemperature(dg, Tg); + const Real gm1 = eos.GruneisenParamFromDensityTemperature(dg, Tg); + const Real mu = dp.mass_scale * eos.MeanAtomicMass(); + const Real gamma = gm1 + 1.; + const Real sgam = std::sqrt(gamma); + // kb T/ mu = cv * gm1 * T + + const Real vth = std::sqrt(8.0 / M_PI * gm1 * cv * Tg); + // Mach and Reynolds numbers + // Mu is non-zero, M can be zero + const Real Mu = std::sqrt(8. / (M_PI * gamma)) / vth; + const Real M = u * Mu; + const Real K = 5. / (32. * std::sqrt(M_PI)) * mu / SQR(dp.dh) / (dg * size * sgam); + // Ru is non-zero, R can be zero + const Real Ru = Mu / K; + const Real R = Ru * u; + + // CD = 2 + (CS - 2) * exp(-p1 sqrt(g) K * G(R)) + CE * exp(-1/(2*K)) + + // The two coefficients (multiplied by u) + const Real CEu = 1. / (sgam * Mu) * (4.6 / (1. + M) + 1.7 /* srt(Td/Tg) */); + const Real CSu = + 24. / Ru * (1. + 0.15 * std::pow(R, dp.p3)) + 0.407 * R * u / (R + 8710.); + + // weight functions + const Real x = std::pow(R / 312., dp.p2); + const Real G = std::exp(2.5 * x / (1. + x)); + const Real ws = std::exp(-dp.p1 * sgam * K * G); + const Real we = std::exp(-1. / (2. * K)); + + // The final stopping time + const Real CDu = 2 * u * (1. - ws) + CSu * ws + CEu * we; + const Real alpha = 3. / 8 * CDu * dg / (grain_density * size); + return dp.tau(id) / (alpha + Fuzz()); + } +}; + +std::shared_ptr Initialize(ParameterInput *pin, + ArtemisUtils::Constants &constants, + ArtemisUtils::Units &units); template TaskStatus DragSource(MeshData *md, const Real time, const Real dt); @@ -398,13 +511,8 @@ TaskStatus SimpleDragSourceImpl(MeshData *md, const Real time, const Real Real fvd[3] = {0.}; const auto nspecies = vmesh.GetSize(b, dust::cons::density()); - [[maybe_unused]] auto &grain_density_ = grain_density; - [[maybe_unused]] Real vth = Null(); - - if constexpr (DRAG == DragModel::stokes) { - const Real gm1 = eos_d.GruneisenParamFromDensityInternalEnergy(dg, sieg); - vth = std::sqrt(8.0 / M_PI * gm1 * sieg); - } + DragCoeff drag_coeff; + Real Tg = eos_d.TemperatureFromDensityInternalEnergy(dg, sieg); // First pass to collect \sum rho' and \sum rho' v and compute new vg const Real vdt[3] = {0.0}; @@ -415,11 +523,14 @@ TaskStatus SimpleDragSourceImpl(MeshData *md, const Real time, const Real vmesh(b, dust::cons::momentum(VI(n, 0)), k, j, i) / (hx[0] * dens), vmesh(b, dust::cons::momentum(VI(n, 1)), k, j, i) / (hx[1] * dens), vmesh(b, dust::cons::momentum(VI(n, 2)), k, j, i) / (hx[2] * dens)}; - Real tc = tp.tau(id); - [[maybe_unused]] auto &sizes_ = sizes; - if constexpr (DRAG == DragModel::stokes) { - tc = tp.scale * grain_density_ / dg * sizes_(id) / vth; - } + + // relative speed + const Real u = + std::sqrt(SQR(vd[0] - vg[0]) + SQR(vd[1] - vg[1]) + SQR(vd[2] - vg[2])); + + // Get the stopping time + Real tc = drag_coeff.Get(tp, id, dg, Tg, u, grain_density, sizes(id), eos_d); + const Real alpha = dt * ((tc <= 0.0) ? Big() : 1.0 / tc); for (int d = 0; d < 3; d++) { const Real rhop = dens * alpha / (1.0 + alpha + bd[d]); @@ -447,11 +558,13 @@ TaskStatus SimpleDragSourceImpl(MeshData *md, const Real time, const Real vmesh(b, dust::cons::momentum(VI(n, 0)), k, j, i) / (hx[0] * dens), vmesh(b, dust::cons::momentum(VI(n, 1)), k, j, i) / (hx[1] * dens), vmesh(b, dust::cons::momentum(VI(n, 2)), k, j, i) / (hx[2] * dens)}; - Real tc = tp.tau(id); - [[maybe_unused]] auto &sizes_ = sizes; - if constexpr (DRAG == DragModel::stokes) { - tc = tp.scale * grain_density_ / dg * sizes_(id) / vth; - } + // relative speed + const Real u = + std::sqrt(SQR(vd[0] - vg[0]) + SQR(vd[1] - vg[1]) + SQR(vd[2] - vg[2])); + + // Get the stopping time + Real tc = drag_coeff.Get(tp, id, dg, Tg, u, grain_density, sizes(id), eos_d); + const Real alpha = dt * ((tc <= 0.0) ? Big() : 1.0 / tc); for (int d = 0; d < 3; d++) { Real delta_d = 0.; From d7e8084ec53e760ddf19f37c85ba20014ca19300 Mon Sep 17 00:00:00 2001 From: Adam Dempsey Date: Mon, 13 Jan 2025 07:57:46 -0700 Subject: [PATCH 3/9] mmw -> mu --- src/gas/gas.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gas/gas.cpp b/src/gas/gas.cpp index 7d09e9ff..b93d7916 100644 --- a/src/gas/gas.cpp +++ b/src/gas/gas.cpp @@ -104,8 +104,8 @@ std::shared_ptr Initialize(ParameterInput *pin, const Real gamma = pin->GetOrAddReal("gas", "gamma", 1.66666666667); auto cv = Null(); if (pin->DoesParameterExist("gas", "cv")) { - PARTHENON_REQUIRE(!pin->DoesParameterExist("gas", "mmw"), - "Cannot specify both cv and mmw"); + PARTHENON_REQUIRE(!pin->DoesParameterExist("gas", "mu"), + "Cannot specify both cv and mu"); cv = pin->GetReal("gas", "cv"); PARTHENON_REQUIRE(cv > 0, "Only positive cv allowed!"); } else { From 4170211af0e7a827b1f9a7d48aa291cf8df12abb Mon Sep 17 00:00:00 2001 From: Adam Dempsey Date: Mon, 13 Jan 2025 07:58:23 -0700 Subject: [PATCH 4/9] Cleanup includes --- src/artemis.cpp | 9 ++++++--- src/artemis.hpp | 3 --- src/utils/eos/eos.hpp | 3 +++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/artemis.cpp b/src/artemis.cpp index 15361539..ce7a5850 100644 --- a/src/artemis.cpp +++ b/src/artemis.cpp @@ -23,7 +23,9 @@ #include "nbody/nbody.hpp" #include "rotating_frame/rotating_frame.hpp" #include "utils/artemis_utils.hpp" +#include "utils/eos/eos.hpp" #include "utils/history.hpp" +#include "utils/opacity/opacity.hpp" #include "utils/units.hpp" // Jaybenne includes @@ -106,9 +108,10 @@ Packages_t ProcessPackages(std::unique_ptr &pin) { if (do_cooling) packages.Add(Gas::Cooling::Initialize(pin.get())); if (do_drag) packages.Add(Drag::Initialize(pin.get(), constants, units)); if (do_radiation) { - auto eos_h = packages.Get("gas")->Param("eos_h"); - auto opacity_h = packages.Get("gas")->Param("opacity_h"); - auto scattering_h = packages.Get("gas")->Param("scattering_h"); + auto eos_h = packages.Get("gas")->Param("eos_h"); + auto opacity_h = packages.Get("gas")->Param("opacity_h"); + auto scattering_h = + packages.Get("gas")->Param("scattering_h"); packages.Add(jaybenne::Initialize(pin.get(), opacity_h, scattering_h, eos_h)); PARTHENON_REQUIRE(coords == Coordinates::cartesian, "Jaybenne currently supports only Cartesian coordinates!"); diff --git a/src/artemis.hpp b/src/artemis.hpp index 5dc7d4a9..be193e97 100644 --- a/src/artemis.hpp +++ b/src/artemis.hpp @@ -21,9 +21,6 @@ #include #include -// Singularity-eos includes -#include - using namespace parthenon; using namespace parthenon::driver::prelude; using namespace parthenon::package::prelude; diff --git a/src/utils/eos/eos.hpp b/src/utils/eos/eos.hpp index 85f5b8e2..1dd3505d 100644 --- a/src/utils/eos/eos.hpp +++ b/src/utils/eos/eos.hpp @@ -13,8 +13,11 @@ #ifndef UTILS_EOS_HPP_ #define UTILS_EOS_HPP_ +#include + #include "artemis.hpp" + namespace ArtemisUtils { // Maximum size of lambda array for optional extra EOS arguments. From ceb82881f4ec66bf8ee26482535a172774dc46f9 Mon Sep 17 00:00:00 2001 From: Adam Dempsey Date: Mon, 13 Jan 2025 10:56:24 -0700 Subject: [PATCH 5/9] Add new stopping time model to params --- src/dust/params.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dust/params.yaml b/src/dust/params.yaml index e0dedbca..1b5afebe 100644 --- a/src/dust/params.yaml +++ b/src/dust/params.yaml @@ -120,5 +120,8 @@ dust: stokes: _type: opt _description: "Stopping times between the gas and dust fluid are in the Stokes regime" + dp15: + _type: opt + _description: "Stopping times between the gas and dust fluid use the model described in Appendix A of D'Angelo & Podolok (2015)." From 52892a5a4f7fc7f85fc5604b1c1a53e28dc2c89d Mon Sep 17 00:00:00 2001 From: Adam Dempsey Date: Sat, 18 Jan 2025 10:16:37 -0700 Subject: [PATCH 6/9] Add amu to mass_scale --- src/drag/drag.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/drag/drag.hpp b/src/drag/drag.hpp index 0fbd1fb5..c9980e54 100644 --- a/src/drag/drag.hpp +++ b/src/drag/drag.hpp @@ -152,8 +152,9 @@ struct StoppingTimeParams { p1 = pin->GetOrAddReal(block_name, "p1", 3.07); p2 = pin->GetOrAddReal(block_name, "p2", 0.6688); p3 = pin->GetOrAddReal(block_name, "p3", 0.681); - // save this so that we don't have to pass units struct to the Get() routines - mass_scale = units.GetMassPhysicalToCode(); + // save this so that we don't have to pass units and constants struct to the Get() + // routines + mass_scale = units.GetMassPhysicalToCode() * constants.GetAMUCode(); } else { PARTHENON_FAIL("bad type for stopping time model"); From 1b91224ab527cbbaff66e7204a989b8ff811bc8a Mon Sep 17 00:00:00 2001 From: Adam Dempsey Date: Sat, 18 Jan 2025 10:16:50 -0700 Subject: [PATCH 7/9] Initialize abar/zbar in eos --- src/gas/gas.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gas/gas.cpp b/src/gas/gas.cpp index d044aaf1..0038949b 100644 --- a/src/gas/gas.cpp +++ b/src/gas/gas.cpp @@ -103,17 +103,21 @@ std::shared_ptr Initialize(ParameterInput *pin, if (eos_name == "ideal") { const Real gamma = pin->GetOrAddReal("gas", "gamma", 1.66666666667); auto cv = Null(); + auto mu = Null(); + if (pin->DoesParameterExist("gas", "cv")) { PARTHENON_REQUIRE(!pin->DoesParameterExist("gas", "mu"), "Cannot specify both cv and mu"); cv = pin->GetReal("gas", "cv"); PARTHENON_REQUIRE(cv > 0, "Only positive cv allowed!"); + mu = constants.GetKBCode() / ((gamma - 1.) * constants.GetAMUCode() * cv); } else { - const Real mu = pin->GetOrAddReal("gas", "mu", 1.); + mu = pin->GetOrAddReal("gas", "mu", 1.); PARTHENON_REQUIRE(mu > 0, "Only positive mean molecular weight allowed!"); cv = constants.GetKBCode() / ((gamma - 1.) * constants.GetAMUCode() * mu); } - EOS eos_host = singularity::IdealGas(gamma - 1., cv); + auto zbar = pin->GetOrAddReal("gas", "zbar", 1.0); + EOS eos_host = singularity::IdealGas(gamma - 1., cv, {mu, zbar}); EOS eos_device = eos_host.GetOnDevice(); params.Add("eos_h", eos_host); params.Add("eos_d", eos_device); From d93b25e39fc3814f2afa8cd0994a91e91856af91 Mon Sep 17 00:00:00 2001 From: Adam Dempsey Date: Sat, 18 Jan 2025 10:17:41 -0700 Subject: [PATCH 8/9] format --- src/utils/eos/eos.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils/eos/eos.hpp b/src/utils/eos/eos.hpp index 1dd3505d..4dd7fab0 100644 --- a/src/utils/eos/eos.hpp +++ b/src/utils/eos/eos.hpp @@ -17,7 +17,6 @@ #include "artemis.hpp" - namespace ArtemisUtils { // Maximum size of lambda array for optional extra EOS arguments. From 9482ca274a12f9cba9ef36314cc6799f263f7b12 Mon Sep 17 00:00:00 2001 From: Adam Dempsey Date: Tue, 21 Jan 2025 17:41:23 -0700 Subject: [PATCH 9/9] Error if both cv and mu are set. Add cv and mu to params --- src/gas/gas.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/gas/gas.cpp b/src/gas/gas.cpp index 0038949b..81b1717f 100644 --- a/src/gas/gas.cpp +++ b/src/gas/gas.cpp @@ -111,11 +111,18 @@ std::shared_ptr Initialize(ParameterInput *pin, cv = pin->GetReal("gas", "cv"); PARTHENON_REQUIRE(cv > 0, "Only positive cv allowed!"); mu = constants.GetKBCode() / ((gamma - 1.) * constants.GetAMUCode() * cv); + if (pin->DoesParameterExist("gas", "mu")) { + PARTHENON_FAIL("Cannot set both mu and cv in the input file. One is calculated " + "from the other!"); + } } else { mu = pin->GetOrAddReal("gas", "mu", 1.); PARTHENON_REQUIRE(mu > 0, "Only positive mean molecular weight allowed!"); cv = constants.GetKBCode() / ((gamma - 1.) * constants.GetAMUCode() * mu); } + // Store these so they are available in outputs + params.Add("cv", cv); + params.Add("mu", mu); auto zbar = pin->GetOrAddReal("gas", "zbar", 1.0); EOS eos_host = singularity::IdealGas(gamma - 1., cv, {mu, zbar}); EOS eos_device = eos_host.GetOnDevice();