Skip to content

Commit 13187d9

Browse files
BenWibkingpre-commit-ci[bot]chongchonghe
authored
Fix ComputeSoundSpeed for particles with MHD (quokka-astro#1481)
### Description Modifies ComputeSoundSpeed in the particle creation machinery to correctly subtract magnetic energy. ### Related issues Fixes quokka-astro#1467. ### Checklist _Before this pull request can be reviewed, all of these tasks should be completed. Denote completed tasks with an `x` inside the square brackets `[ ]` in the Markdown source below:_ - [x] I have added a description (see above). - [x] I have added a link to any related issues (if applicable; see above). - [x] I have read the [Contributing Guide](https://github.com/quokka-astro/quokka/blob/development/CONTRIBUTING.md). - [ ] I have added tests for any new physics that this PR adds to the code. - [ ] *(For quokka-astro org members)* I have manually triggered the GPU tests with the magic comment `/azp run`. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: ChongChong He <chongchonghe99@gmail.com>
1 parent 6058d91 commit 13187d9

12 files changed

Lines changed: 371 additions & 143 deletions

File tree

inputs/ParticleCreationAMR.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ amr.v = 1 # verbosity in Amr
1515
# *****************************************************************
1616
amr.n_cell = 32 32 32
1717
amr.max_level = 1 # number of levels = max_level + 1
18-
amr.blocking_factor = 8 # grid size must be divisible by this
19-
amr.max_grid_size = 8 # at least 128 for GPUs
18+
amr.blocking_factor = 16 # needs to be >= ceil(nghost/ref_ratio)*ref_ratio for proper nesting
19+
amr.max_grid_size = 16 # at least 128 for GPUs
2020
amr.n_error_buf = 2 # minimum 2 cell buffer around tagged cells
2121
amr.grid_eff = 1.0
2222

src/hydro/EOS.hpp

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,14 @@ AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE auto EOS<problem_t>::ComputePressure(am
321321
{
322322
// return pressure for an ideal gas
323323
amrex::Real P = NAN;
324+
325+
if constexpr (gamma_ == 1.0) {
326+
static_assert(EOS_Traits<problem_t>::cs_isothermal > 0.0, "EOS_Traits<problem_t>::cs_isothermal must be set when gamma=1.");
327+
amrex::ignore_unused(Eint);
328+
amrex::ignore_unused(massScalars);
329+
P = rho * EOS_Traits<problem_t>::cs_isothermal * EOS_Traits<problem_t>::cs_isothermal;
330+
return P;
331+
}
324332
#ifdef CHEMISTRY
325333
eos_t chemstate;
326334
chemstate.rho = rho;
@@ -342,19 +350,17 @@ AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE auto EOS<problem_t>::ComputePressure(am
342350
#else
343351
amrex::ignore_unused(massScalars);
344352

345-
if constexpr (gamma_ != 1.0) {
346-
chem_eos_t estate;
347-
estate.rho = rho;
348-
// if rho is 0, pass 0 to state.e
349-
if (rho == 0.0) {
350-
estate.e = 0;
351-
} else {
352-
estate.e = Eint / rho;
353-
}
354-
estate.mu = mean_molecular_weight_ / C::m_u;
355-
eos(eos_input_re, estate);
356-
P = estate.p;
353+
chem_eos_t estate;
354+
estate.rho = rho;
355+
// if rho is 0, pass 0 to state.e
356+
if (rho == 0.0) {
357+
estate.e = 0;
358+
} else {
359+
estate.e = Eint / rho;
357360
}
361+
estate.mu = mean_molecular_weight_ / C::m_u;
362+
eos(eos_input_re, estate);
363+
P = estate.p;
358364
#endif
359365
return P;
360366
}
@@ -367,6 +373,15 @@ AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE auto EOS<problem_t>::ComputeSoundSpeed(
367373
// return sound speed for an ideal gas
368374
amrex::Real cs = NAN;
369375

376+
if constexpr (gamma_ == 1.0) {
377+
static_assert(EOS_Traits<problem_t>::cs_isothermal > 0.0, "EOS_Traits<problem_t>::cs_isothermal must be set when gamma=1.");
378+
amrex::ignore_unused(rho);
379+
amrex::ignore_unused(Pressure);
380+
amrex::ignore_unused(massScalars);
381+
cs = EOS_Traits<problem_t>::cs_isothermal;
382+
return cs;
383+
}
384+
370385
#ifdef CHEMISTRY
371386
eos_t chemstate;
372387
chemstate.rho = rho;
@@ -388,14 +403,12 @@ AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE auto EOS<problem_t>::ComputeSoundSpeed(
388403
#else
389404
amrex::ignore_unused(massScalars);
390405

391-
if constexpr (gamma_ != 1.0) {
392-
chem_eos_t estate;
393-
estate.rho = rho;
394-
estate.p = Pressure;
395-
estate.mu = mean_molecular_weight_ / C::m_u;
396-
eos(eos_input_rp, estate);
397-
cs = estate.cs;
398-
}
406+
chem_eos_t estate;
407+
estate.rho = rho;
408+
estate.p = Pressure;
409+
estate.mu = mean_molecular_weight_ / C::m_u;
410+
eos(eos_input_rp, estate);
411+
cs = estate.cs;
399412
#endif
400413
return cs;
401414
}

src/particles/PhysicsParticles.hpp

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#ifndef PHYSICS_PARTICLES_HPP_
22
#define PHYSICS_PARTICLES_HPP_
33

4+
#include <array>
45
#include <cstdint>
56
#include <map>
67
#include <memory>
8+
#include <ranges>
79
#include <string>
810

911
#include <fmt/format.h>
@@ -136,18 +138,27 @@ class PhysicsParticleDescriptorBase
136138

137139
//----- Methods that are implemented for some but not all particle types, so they cannot be pure virtual -----
138140

139-
virtual auto depositSN(amrex::MultiFab & /*state*/, int /*lev*/, amrex::Real /*time*/, amrex::Real /*dt*/) -> amrex::Real { return 0.0_rt; }
141+
virtual auto depositSN(amrex::MultiFab & /*state*/, std::array<amrex::MultiFab, AMREX_SPACEDIM> const * /*state_fc*/, int /*lev*/, amrex::Real /*time*/,
142+
amrex::Real /*dt*/) -> amrex::Real
143+
{
144+
return 0.0_rt;
145+
}
140146

141-
virtual void computeSinkAccretion(amrex::MultiFab &state, amrex::MultiFab &state_accretion_rate, int lev, amrex::Real time, amrex::Real dt)
142-
{ /* Default empty implementation */ }
147+
virtual void computeSinkAccretion(amrex::MultiFab &state, amrex::MultiFab &state_accretion_rate,
148+
std::array<amrex::MultiFab, AMREX_SPACEDIM> const *state_fc, int lev, amrex::Real time, amrex::Real dt)
149+
{ /* Default empty implementation */
150+
}
143151

144152
// Create particles from hydro state at the finest level
145153
// Note: particles are not allowed to spawn outside of real cells. If they do, we will need a redistribution immediately after this call in order to
146154
// make particle-mesh interaction work.
147-
virtual void createParticlesFromState(amrex::MultiFab &state, amrex::MultiFab &accretion_rate, int lev, amrex::Real current_time, amrex::Real dt)
148-
{ /* Default empty implementation */ }
155+
virtual void createParticlesFromState(amrex::MultiFab &state, amrex::MultiFab &accretion_rate, int lev, amrex::Real current_time, amrex::Real dt,
156+
std::array<amrex::MultiFab, AMREX_SPACEDIM> const *state_fc)
157+
{ /* Default empty implementation */
158+
}
149159

150-
virtual void applySinkAccretion(amrex::MultiFab &state, amrex::MultiFab &state_accretion_rate, const amrex::Geometry &geom, int lev, amrex::Real time,
160+
virtual void applySinkAccretion(amrex::MultiFab &state, amrex::MultiFab &state_accretion_rate,
161+
std::array<amrex::MultiFab, AMREX_SPACEDIM> const *state_fc, const amrex::Geometry &geom, int lev, amrex::Real time,
151162
amrex::Real dt)
152163
{ /* Default empty implementation */
153164
}
@@ -562,7 +573,8 @@ template <typename ContainerType, typename problem_t, ParticleType particleType>
562573
}
563574

564575
// Implementation of supernova energy and momentum deposition from particles to grid
565-
auto depositSN(amrex::MultiFab &state, int lev, amrex::Real time, amrex::Real dt) -> amrex::Real override
576+
auto depositSN(amrex::MultiFab &state, std::array<amrex::MultiFab, AMREX_SPACEDIM> const *state_fc, int lev, amrex::Real time, amrex::Real dt)
577+
-> amrex::Real override
566578
{
567579
amrex::Real max_velocity = 0.0;
568580

@@ -573,7 +585,7 @@ template <typename ContainerType, typename problem_t, ParticleType particleType>
573585
"UnitSystem must be CGS for particleMeshInteraction");
574586

575587
// Deposit supernova energy and momentum from all particles. This also updates the evolution stage of the particles.
576-
max_velocity = SNDeposition<ContainerType, problem_t>(this->container_, state, lev, time, dt, this->getMassIndex(),
588+
max_velocity = SNDeposition<ContainerType, problem_t>(this->container_, state, state_fc, lev, time, dt, this->getMassIndex(),
577589
this->getEvolutionStageIndex(), this->getBirthTimeIndex());
578590
} else {
579591
// Only update evolution stage but not deposit energy/momentum
@@ -586,26 +598,28 @@ template <typename ContainerType, typename problem_t, ParticleType particleType>
586598
}
587599

588600
// compute accretion rate
589-
void computeSinkAccretion(amrex::MultiFab &state, amrex::MultiFab &state_accretion_rate, int lev, amrex::Real time, amrex::Real dt) override
601+
void computeSinkAccretion(amrex::MultiFab &state, amrex::MultiFab &state_accretion_rate, std::array<amrex::MultiFab, AMREX_SPACEDIM> const *state_fc,
602+
int lev, amrex::Real time, amrex::Real dt) override
590603
{
591-
SinkAccretionUtils::computeAccretion<ContainerType, problem_t>(this->container_, state, state_accretion_rate, lev, time, dt,
604+
SinkAccretionUtils::computeAccretion<ContainerType, problem_t>(this->container_, state, state_accretion_rate, state_fc, lev, time, dt,
592605
this->getMassIndex());
593606
}
594607

595608
// apply accretion
596-
void applySinkAccretion(amrex::MultiFab &state, amrex::MultiFab &state_accretion_rate, const amrex::Geometry &geom, int lev, amrex::Real time,
597-
amrex::Real dt) override
609+
void applySinkAccretion(amrex::MultiFab &state, amrex::MultiFab &state_accretion_rate, std::array<amrex::MultiFab, AMREX_SPACEDIM> const *state_fc,
610+
const amrex::Geometry &geom, int lev, amrex::Real time, amrex::Real dt) override
598611
{
599-
SinkAccretionUtils::applyAccretion<ContainerType, problem_t>(this->container_, state, state_accretion_rate, geom, lev, time, dt,
612+
SinkAccretionUtils::applyAccretion<ContainerType, problem_t>(this->container_, state, state_accretion_rate, state_fc, geom, lev, time, dt,
600613
this->getMassIndex());
601614
}
602615

603-
void createParticlesFromState(amrex::MultiFab &state, amrex::MultiFab &accretion_rate, int lev, amrex::Real current_time, amrex::Real dt) override
616+
void createParticlesFromState(amrex::MultiFab &state, amrex::MultiFab &accretion_rate, int lev, amrex::Real current_time, amrex::Real dt,
617+
std::array<amrex::MultiFab, AMREX_SPACEDIM> const *state_fc) override
604618
{
605619
// Use the traits class to implement the specialized behavior
606620
ParticleCreationTraits<particleType>::template createParticles<problem_t, ContainerType>(
607621
this->container_, this->getMassIndex(), state, accretion_rate, lev, current_time, dt, this->getEvolutionStageIndex(),
608-
this->getBirthTimeIndex());
622+
this->getBirthTimeIndex(), state_fc);
609623
}
610624
#endif // AMREX_SPACEDIM == 3
611625
};
@@ -756,37 +770,39 @@ template <typename problem_t> class PhysicsParticleRegister
756770
}
757771

758772
// Deposit supernova energy and momentum from all particles
759-
auto depositSN(amrex::MultiFab &state, int lev, amrex::Real time, amrex::Real dt) -> amrex::Real
773+
auto depositSN(amrex::MultiFab &state, std::array<amrex::MultiFab, AMREX_SPACEDIM> const *state_fc, int lev, amrex::Real time, amrex::Real dt)
774+
-> amrex::Real
760775
{
761776
const BL_PROFILE("PhysicsParticleRegister::depositSN()");
762777
amrex::Real max_velocity = 0.0;
763778
// Each particle type handles its own buffer creation and roundoff independently
764779
for (const auto &[type, descriptor] : particleRegistry_) {
765-
const amrex::Real max_velocity_ = descriptor->depositSN(state, lev, time, dt);
780+
const amrex::Real max_velocity_ = descriptor->depositSN(state, state_fc, lev, time, dt);
766781
max_velocity = std::max(max_velocity, max_velocity_);
767782
}
768783
return max_velocity;
769784
}
770785

771786
// Implementation of computeSinkAccretion
772-
void computeSinkAccretion(amrex::MultiFab &state, amrex::MultiFab &state_accretion_rate, int lev, amrex::Real time, amrex::Real dt)
787+
void computeSinkAccretion(amrex::MultiFab &state, amrex::MultiFab &state_accretion_rate, std::array<amrex::MultiFab, AMREX_SPACEDIM> const *state_fc,
788+
int lev, amrex::Real time, amrex::Real dt)
773789
{
774790
const BL_PROFILE("PhysicsParticleRegister::computeSinkAccretion()");
775791
for (const auto &[type, descriptor] : particleRegistry_) {
776792
if (descriptor->getAllowsAccretion()) {
777-
descriptor->computeSinkAccretion(state, state_accretion_rate, lev, time, dt);
793+
descriptor->computeSinkAccretion(state, state_accretion_rate, state_fc, lev, time, dt);
778794
}
779795
}
780796
}
781797

782798
// Implementation of applySinkAccretion
783-
void applySinkAccretion(amrex::MultiFab &state, amrex::MultiFab &state_accretion_rate, const amrex::Geometry &geom, int lev, amrex::Real time,
784-
amrex::Real dt)
799+
void applySinkAccretion(amrex::MultiFab &state, amrex::MultiFab &state_accretion_rate, std::array<amrex::MultiFab, AMREX_SPACEDIM> const *state_fc,
800+
const amrex::Geometry &geom, int lev, amrex::Real time, amrex::Real dt)
785801
{
786802
const BL_PROFILE("PhysicsParticleRegister::applySinkAccretion()");
787803
for (const auto &[type, descriptor] : particleRegistry_) {
788804
if (descriptor->getAllowsAccretion()) {
789-
descriptor->applySinkAccretion(state, state_accretion_rate, geom, lev, time, dt);
805+
descriptor->applySinkAccretion(state, state_accretion_rate, state_fc, geom, lev, time, dt);
790806
}
791807
}
792808
}
@@ -830,7 +846,7 @@ template <typename problem_t> class PhysicsParticleRegister
830846
const std::string typeName = getParticleTypeName(type);
831847

832848
// Check if this particle type is in the requested list
833-
if (std::find(particleTypeNames.begin(), particleTypeNames.end(), typeName) != particleTypeNames.end()) {
849+
if (std::ranges::find(particleTypeNames, typeName) != particleTypeNames.end()) {
834850
descriptor->writePlotFile(plotfilename, typeName);
835851
descriptor->writeUnitsFile(plotfilename, typeName);
836852
}
@@ -887,14 +903,15 @@ template <typename problem_t> class PhysicsParticleRegister
887903
}
888904

889905
// Create particles based on particle type
890-
void createParticlesFromState(amrex::MultiFab &state, amrex::MultiFab &accretion_rate, int lev, amrex::Real current_time, amrex::Real dt)
906+
void createParticlesFromState(amrex::MultiFab &state, amrex::MultiFab &accretion_rate, int lev, amrex::Real current_time, amrex::Real dt,
907+
std::array<amrex::MultiFab, AMREX_SPACEDIM> const *state_fc = nullptr)
891908
{
892909
const BL_PROFILE("PhysicsParticleRegister::createParticlesFromState()");
893910
for (const auto &[type, descriptor] : particleRegistry_) {
894911
// Only create particles if the descriptor allows creation
895912
if (descriptor->getAllowsCreation()) {
896913
// Call the appropriate particle creation method based on the particle type
897-
descriptor->createParticlesFromState(state, accretion_rate, lev, current_time, dt);
914+
descriptor->createParticlesFromState(state, accretion_rate, lev, current_time, dt, state_fc);
898915

899916
// redistribute particles
900917
// descriptor->redistribute(lev);

0 commit comments

Comments
 (0)