13#ifndef CD_TRACERPARTICLESTEPPERIMPLEM_H
14#define CD_TRACERPARTICLESTEPPERIMPLEM_H
24#include <CD_NamespaceHeader.H>
31 CH_TIME(
"TracerParticleStepper::TracerParticleStepper");
42 CH_TIME(
"TracerParticleStepper::~TracerParticleStepper");
43 if (m_verbosity > 5) {
44 pout() <<
"TracerParticleStepper::~TracerParticleStepper" << endl;
52 CH_TIME(
"TracerParticleStepper::setupSolvers()");
53 if (m_verbosity > 5) {
54 pout() <<
"TracerParticleStepper::setupSolvers()" << endl;
59 m_solver->setPhase(m_phase);
60 m_solver->setRealm(m_realm);
61 m_solver->parseOptions();
68 CH_TIME(
"TracerParticleStepper::allocate()");
69 if (m_verbosity > 5) {
70 pout() <<
"TracerParticleStepper::allocate()" << endl;
73 m_amr->allocate(m_velocity, m_realm, m_phase, SpaceDim);
81 CH_TIME(
"TracerParticleStepper::initialData()");
82 if (m_verbosity > 5) {
83 pout() <<
"TracerParticleStepper::initialData()" << endl;
87 this->initialParticles();
89 m_solver->setVelocity(m_velocity);
90 m_solver->interpolateVelocities();
97 CH_TIME(
"TracerParticleStepper::registerRealms()");
98 if (m_verbosity > 5) {
99 pout() <<
"TracerParticleStepper::registerRealms()" << endl;
102 m_amr->registerRealm(m_realm);
109 CH_TIME(
"TracerParticleStepper::registerOperators()");
110 if (m_verbosity > 5) {
111 pout() <<
"TracerParticleStepper::registerOperators()" << endl;
114 m_solver->registerOperators();
121 CH_TIME(
"TracerParticleStepper::parseOptions()");
122 if (m_verbosity > 5) {
123 pout() <<
"TracerParticleStepper::parseOptions()" << endl;
126 this->parseIntegrator();
127 this->parseVelocityField();
128 this->parseInitialConditions();
135 CH_TIME(
"TracerParticleStepper::parseRuntimeOptions()");
136 if (m_verbosity > 5) {
137 pout() <<
"TracerParticleStepper::parseRuntimeOptions()" << endl;
140 this->parseIntegrator();
142 m_solver->parseRuntimeOptions();
149 CH_TIME(
"TracerParticleStepper::parseIntegrator()");
150 if (m_verbosity > 5) {
151 pout() <<
"TracerParticleStepper::parseIntegrator()" << endl;
154 ParmParse pp(
"TracerParticleStepper");
158 pp.get(
"verbosity", m_verbosity);
159 pp.get(
"cfl", m_cfl);
160 pp.get(
"integration", str);
161 if (str ==
"euler") {
162 m_algorithm = IntegrationAlgorithm::Euler;
164 else if (str ==
"rk2") {
165 m_algorithm = IntegrationAlgorithm::RK2;
167 else if (str ==
"rk4") {
168 m_algorithm = IntegrationAlgorithm::RK4;
171 MayDay::Error(
"TracerParticleStepper::parseIntegrator -- logic bust");
179 CH_TIME(
"TracerParticleStepper::parseVelocityField()");
180 if (m_verbosity > 5) {
181 pout() <<
"TracerParticleStepper::parseVelocityField()" << endl;
184 ParmParse pp(
"TracerParticleStepper");
187 pp.get(
"velocity_field", v);
190 m_velocityField = VelocityField::Diagonal;
193 m_velocityField = VelocityField::Rotational;
196 MayDay::Error(
"TracerParticleStepper::parseVelocityField -- logic bust");
204 CH_TIME(
"TracerParticleStepper::parseInitialConditions()");
205 if (m_verbosity > 5) {
206 pout() <<
"TracerParticleStepper::parseInitialConditions()" << endl;
209 ParmParse pp(
"TracerParticleStepper");
212 pp.get(
"initial_particles", numParticles);
214 m_numInitialParticles = size_t(std::max(0.0, numParticles));
222 CH_TIME(
"TracerParticleStepper::writeCheckpointData(HDF5Handle, int)");
223 if (m_verbosity > 5) {
224 pout() <<
"TracerParticleStepper::writeCheckpointData(HDF5Handle, int)" << endl;
227 m_solver->writeCheckpointLevel(a_handle, a_lvl);
236 CH_TIME(
"TracerParticleStepper::readCheckpointData(HDF5Handle, int)");
237 if (m_verbosity > 5) {
238 pout() <<
"TracerParticleStepper::readCheckpointData(HDF5Handle, int)" << endl;
241 m_solver->readCheckpointLevel(a_handle, a_lvl);
249 CH_TIME(
"TracerParticleStepper::getNumberOfPlotVariables()");
250 if (m_verbosity > 5) {
251 pout() <<
"TracerParticleStepper::getNumberOfPlotVariables()" << endl;
254 return m_solver->getNumberOfPlotVariables();
258inline Vector<std::string>
261 CH_TIME(
"TracerParticleStepper::getPlotVariableNames()");
262 if (m_verbosity > 5) {
263 pout() <<
"TracerParticleStepper::getPlotVariableNames()" << endl;
266 return m_solver->getPlotVariableNames();
273 const std::string& a_outputRealm,
274 const int a_level)
const
276 CH_TIME(
"TracerParticleStepper::writePlotData(EBAMRCellData, Vector<std::string>, int)");
277 if (m_verbosity > 5) {
278 pout() <<
"TracerParticleStepper::writePlotData(EBAMRCellData, Vector<std::string>, int)" << endl;
281 CH_assert(a_level >= 0);
282 CH_assert(a_level <= m_amr->getFinestLevel());
284 m_solver->writePlotData(a_output, a_icomp, a_outputRealm, a_level);
291 CH_TIME(
"TracerParticleStepper::computeDt()");
292 if (m_verbosity > 5) {
293 pout() <<
"TracerParticleStepper::computeDt()" << endl;
296 return m_cfl * m_solver->computeDt();
303 CH_TIME(
"TracerParticleStepper::advance(Real)");
304 if (m_verbosity > 5) {
305 pout() <<
"TracerParticleStepper::advance(Real)" << endl;
308 switch (m_algorithm) {
309 case IntegrationAlgorithm::Euler: {
310 this->advanceParticlesEuler(a_dt);
314 case IntegrationAlgorithm::RK2: {
315 this->advanceParticlesRK2(a_dt);
319 case IntegrationAlgorithm::RK4: {
320 this->advanceParticlesRK4(a_dt);
325 MayDay::Error(
"TracerParticleStepper::advance -- logic bust");
336 CH_TIME(
"TracerParticleStepper::synchronizeSolverTimes");
337 if (m_verbosity > 5) {
338 pout() <<
"TracerParticleStepper::synchronizeSolverTimes" << endl;
345 m_solver->setTime(a_step, a_time, a_dt);
352 CH_TIME(
"TracerParticleStepper::preRegrid(int, int)");
353 if (m_verbosity > 5) {
354 pout() <<
"TracerParticleStepper::preRegrid(int, int)" << endl;
357 m_solver->preRegrid(a_lmin, a_oldFinestLevel);
364 CH_TIME(
"TracerParticleStepper::regrid(int, int, int)");
365 if (m_verbosity > 5) {
366 pout() <<
"TracerParticleStepper::regrid(int, int, int)" << endl;
370 m_amr->reallocate(m_velocity, m_phase, a_lmin);
374 m_solver->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
381 CH_TIME(
"TracerParticleStepper::postRegrid()");
382 if (m_verbosity > 5) {
383 pout() <<
"TracerParticleStepper::postRegrid()" << endl;
388 m_solver->interpolateVelocities();
395 CH_TIME(
"TracerParticleStepper::setVelocity()");
396 if (m_verbosity > 5) {
397 pout() <<
"TracerParticleStepper::setVelocity()" << endl;
400 std::function<RealVect(
const RealVect a_position)> velFunc;
402 switch (m_velocityField) {
403 case VelocityField::Diagonal: {
404 velFunc = [](
const RealVect& a_position) -> RealVect {
405 return RealVect::Unit;
410 case VelocityField::Rotational: {
411 velFunc = [](
const RealVect pos) -> RealVect {
412 const Real r = pos.vectorLength();
413 const Real theta = atan2(pos[1], pos[0]);
415 return RealVect(D_DECL(-r * sin(theta), r * cos(theta), 0.));
426 m_amr->getMultiCutVofIterator(m_realm, m_phase));
428 m_amr->conservativeAverage(m_velocity, m_realm, m_phase);
429 m_amr->interpGhost(m_velocity, m_realm, m_phase);
436 CH_TIME(
"TracerParticleStepper::initialParticles()");
437 if (m_verbosity > 5) {
438 pout() <<
"TracerParticleStepper::initialParticles()" << endl;
452 const RealVect probLo = m_amr->getProbLo();
453 const RealVect probHi = m_amr->getProbHi();
455 auto uniformDistribution = [probLo, probHi]() -> RealVect {
456 RealVect ret = probLo;
458 for (
int dir = 0; dir < SpaceDim; dir++) {
468 ParticleManagement::drawRandomParticles(drawnParticles, m_numInitialParticles, uniformDistribution);
475 m_amr->removeCoveredParticlesIF(solverParticles, m_phase, 0.0);
482 CH_TIME(
"TracerParticleStepper::advanceParticlesEuler()");
483 if (m_verbosity > 5) {
484 pout() <<
"TracerParticleStepper::advanceParticlesEuler()" << endl;
491 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
492 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
493 const DataIterator& dit = dbl.dataIterator();
495 const int nbox = dit.size();
497#pragma omp parallel for schedule(runtime)
498 for (
int mybox = 0; mybox < nbox; mybox++) {
499 const DataIndex& din = dit[mybox];
505 D_DECL(leaf.template column<&P::v_x>(), leaf.template column<&P::v_y>(), leaf.template column<&P::v_z>())};
508 for (
int dir = 0; dir < SpaceDim; dir++) {
509 pos[dir][i] += vel[dir][i] * a_dt;
515 amrParticles.
remap();
516 m_amr->removeCoveredParticlesIF(amrParticles, m_phase, 0.0);
518 m_solver->interpolateVelocities();
525 CH_TIME(
"TracerParticleStepper::advanceParticlesRK2()");
526 if (m_verbosity > 5) {
527 pout() <<
"TracerParticleStepper::advanceParticlesRK2()" << endl;
535 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
536 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
537 const DataIterator& dit = dbl.dataIterator();
539 const int nbox = dit.size();
541#pragma omp parallel for schedule(runtime)
542 for (
int mybox = 0; mybox < nbox; mybox++) {
543 const DataIndex& din = dit[mybox];
549 D_DECL(leaf.template column<&P::v_x>(), leaf.template column<&P::v_y>(), leaf.template column<&P::v_z>())};
550 double*
const xk[SpaceDim] = {
551 D_DECL(leaf.template column<&P::xk_x>(), leaf.template column<&P::xk_y>(), leaf.template column<&P::xk_z>())};
553 D_DECL(leaf.template column<&P::k1_x>(), leaf.template column<&P::k1_y>(), leaf.template column<&P::k1_z>())};
556 for (
int dir = 0; dir < SpaceDim; dir++) {
557 xk[dir][i] = pos[dir][i];
558 k1[dir][i] = vel[dir][i];
559 pos[dir][i] += vel[dir][i] * a_dt;
566 amrParticles.
remap();
567 m_amr->removeCoveredParticlesIF(amrParticles, m_phase, 0.0);
568 m_solver->interpolateVelocities();
571 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
572 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
573 const DataIterator& dit = dbl.dataIterator();
575 const int nbox = dit.size();
577#pragma omp parallel for schedule(runtime)
578 for (
int mybox = 0; mybox < nbox; mybox++) {
579 const DataIndex& din = dit[mybox];
585 D_DECL(leaf.template column<&P::v_x>(), leaf.template column<&P::v_y>(), leaf.template column<&P::v_z>())};
586 const double*
const xk[SpaceDim] = {
587 D_DECL(leaf.template column<&P::xk_x>(), leaf.template column<&P::xk_y>(), leaf.template column<&P::xk_z>())};
589 D_DECL(leaf.template column<&P::k1_x>(), leaf.template column<&P::k1_y>(), leaf.template column<&P::k1_z>())};
592 for (
int dir = 0; dir < SpaceDim; dir++) {
594 pos[dir][i] = xk[dir][i] + 0.5 * a_dt * (k1[dir][i] + vel[dir][i]);
601 amrParticles.
remap();
602 m_amr->removeCoveredParticlesIF(amrParticles, m_phase, 0.0);
603 m_solver->interpolateVelocities();
610 CH_TIME(
"TracerParticleStepper::advanceParticlesRK4()");
611 if (m_verbosity > 5) {
612 pout() <<
"TracerParticleStepper::advanceParticlesRK4()" << endl;
619 const Real dtHalf = a_dt / 2.0;
620 const Real dtSixth = a_dt / 6.0;
624 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
625 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
626 const DataIterator& dit = dbl.dataIterator();
628 const int nbox = dit.size();
630#pragma omp parallel for schedule(runtime)
631 for (
int mybox = 0; mybox < nbox; mybox++) {
632 const DataIndex& din = dit[mybox];
638 D_DECL(leaf.template column<&P::v_x>(), leaf.template column<&P::v_y>(), leaf.template column<&P::v_z>())};
639 double*
const xk[SpaceDim] = {
640 D_DECL(leaf.template column<&P::xk_x>(), leaf.template column<&P::xk_y>(), leaf.template column<&P::xk_z>())};
642 D_DECL(leaf.template column<&P::k1_x>(), leaf.template column<&P::k1_y>(), leaf.template column<&P::k1_z>())};
645 for (
int dir = 0; dir < SpaceDim; dir++) {
646 xk[dir][i] = pos[dir][i];
647 k1[dir][i] = vel[dir][i];
648 pos[dir][i] = xk[dir][i] + dtHalf * vel[dir][i];
655 amrParticles.
remap();
656 m_solver->interpolateVelocities();
661 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
662 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
663 const DataIterator& dit = dbl.dataIterator();
665 const int nbox = dit.size();
667#pragma omp parallel for schedule(runtime)
668 for (
int mybox = 0; mybox < nbox; mybox++) {
669 const DataIndex& din = dit[mybox];
675 D_DECL(leaf.template column<&P::v_x>(), leaf.template column<&P::v_y>(), leaf.template column<&P::v_z>())};
676 const double*
const xk[SpaceDim] = {
677 D_DECL(leaf.template column<&P::xk_x>(), leaf.template column<&P::xk_y>(), leaf.template column<&P::xk_z>())};
679 D_DECL(leaf.template column<&P::k2_x>(), leaf.template column<&P::k2_y>(), leaf.template column<&P::k2_z>())};
682 for (
int dir = 0; dir < SpaceDim; dir++) {
683 k2[dir][i] = vel[dir][i];
684 pos[dir][i] = xk[dir][i] + dtHalf * vel[dir][i];
691 amrParticles.
remap();
692 m_solver->interpolateVelocities();
697 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
698 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
699 const DataIterator& dit = dbl.dataIterator();
701 const int nbox = dit.size();
703#pragma omp parallel for schedule(runtime)
704 for (
int mybox = 0; mybox < nbox; mybox++) {
705 const DataIndex& din = dit[mybox];
711 D_DECL(leaf.template column<&P::v_x>(), leaf.template column<&P::v_y>(), leaf.template column<&P::v_z>())};
712 const double*
const xk[SpaceDim] = {
713 D_DECL(leaf.template column<&P::xk_x>(), leaf.template column<&P::xk_y>(), leaf.template column<&P::xk_z>())};
715 D_DECL(leaf.template column<&P::k3_x>(), leaf.template column<&P::k3_y>(), leaf.template column<&P::k3_z>())};
718 for (
int dir = 0; dir < SpaceDim; dir++) {
719 k3[dir][i] = vel[dir][i];
720 pos[dir][i] = xk[dir][i] + a_dt * vel[dir][i];
727 amrParticles.
remap();
728 m_solver->interpolateVelocities();
733 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
734 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
735 const DataIterator& dit = dbl.dataIterator();
737 const int nbox = dit.size();
739#pragma omp parallel for schedule(runtime)
740 for (
int mybox = 0; mybox < nbox; mybox++) {
741 const DataIndex& din = dit[mybox];
747 D_DECL(leaf.template column<&P::v_x>(), leaf.template column<&P::v_y>(), leaf.template column<&P::v_z>())};
748 const double*
const xk[SpaceDim] = {
749 D_DECL(leaf.template column<&P::xk_x>(), leaf.template column<&P::xk_y>(), leaf.template column<&P::xk_z>())};
751 D_DECL(leaf.template column<&P::k1_x>(), leaf.template column<&P::k1_y>(), leaf.template column<&P::k1_z>())};
753 D_DECL(leaf.template column<&P::k2_x>(), leaf.template column<&P::k2_y>(), leaf.template column<&P::k2_z>())};
755 D_DECL(leaf.template column<&P::k3_x>(), leaf.template column<&P::k3_y>(), leaf.template column<&P::k3_z>())};
758 for (
int dir = 0; dir < SpaceDim; dir++) {
759 pos[dir][i] = xk[dir][i] + dtSixth * k1[dir][i] + dtHalf * k2[dir][i] + dtHalf * k3[dir][i] +
760 dtSixth * vel[dir][i];
767 amrParticles.
remap();
768 m_solver->interpolateVelocities();
771 m_amr->removeCoveredParticlesIF(amrParticles, m_phase, 0.0);
774#include <CD_NamespaceFooter.H>
Declaration of a namespace for SIMD-decorated loops over SoA particles.
Namespace containing various particle management utilities.
CD_PARTICLE_REAL ParticleReal
Floating-point type a user may use for payload columns.
Definition CD_ParticleSoA.H:156
File containing some useful static methods related to random number generation.
Declaration of the Physics::TracerParticle::TracerParticleStepper TimeStepper.
static void setValue(LevelData< MFInterfaceFAB< T > > &a_lhs, const T &a_value)
Set value in an MFInterfaceFAB data holder.
Definition CD_DataOpsImplem.H:24
AMR-hierarchy container of computational particles, stored per patch in Struct-of-Arrays form.
Definition CD_ParticleContainer.H:123
void clearParticles()
Drop all valid particles on every level (keeps each leaf's arena capacity).
Definition CD_ParticleContainer.H:442
void remap()
Redistribute every valid particle to the patch/level/rank that owns its cell.
Definition CD_ParticleContainerImplem.H:494
void addParticlesDestructive(ParticleSoA< P, Traits > &a_particles)
Add a free-standing buffer of particles to the container, routing each to its owner.
Definition CD_ParticleContainer.H:478
AMRParticlesSoA< P, Traits > & getParticles()
The valid particles on all levels.
Definition CD_ParticleContainer.H:317
Arena-backed Struct-of-Arrays particle container for a single grid patch.
Definition CD_ParticleSoA.H:655
double * positionColumn(const int a_dir) noexcept
Raw position component column dir (double*, for SIMD kernels).
Definition CD_ParticleSoA.H:1137
TimeStepper for advancing tracer particles in a prescribed velocity field on an AMR mesh.
Definition CD_TracerParticleStepper.H:56
void registerRealms() override
Register realms. Primal is the only realm we need.
Definition CD_TracerParticleStepperImplem.H:95
virtual void parseInitialConditions()
Parse initial conditions.
Definition CD_TracerParticleStepperImplem.H:202
void parseRuntimeOptions() override
Parse runtime options.
Definition CD_TracerParticleStepperImplem.H:133
void initialData() override
Fill problem with initial data.
Definition CD_TracerParticleStepperImplem.H:79
void registerOperators() override
Register operators.
Definition CD_TracerParticleStepperImplem.H:107
virtual Real computeDt() override
Compute a time step to be used by Driver.
Definition CD_TracerParticleStepperImplem.H:289
int getNumberOfPlotVariables() const override
Get number of plot variables for this physics module.
Definition CD_TracerParticleStepperImplem.H:247
virtual void advanceParticlesEuler(const Real a_dt)
Advance particles using explicit Euler rule.
Definition CD_TracerParticleStepperImplem.H:480
virtual void preRegrid(const int a_lmin, const int a_oldFinestLevel) override
Perform pre-regrid operations.
Definition CD_TracerParticleStepperImplem.H:350
void allocate() override
Allocate storage for solvers and time stepper.
Definition CD_TracerParticleStepperImplem.H:66
void writePlotData(LevelData< EBCellFAB > &a_output, int &a_icomp, const std::string &a_realm, const int a_level) const override
Write plot data to output holder.
Definition CD_TracerParticleStepperImplem.H:271
virtual void regrid(const int a_lmin, const int a_oldFinestLevel, const int a_newFinestLevel) override
Time stepper regrid method.
Definition CD_TracerParticleStepperImplem.H:362
virtual Real advance(const Real a_dt) override
Advancement method. Swaps between various kernels.
Definition CD_TracerParticleStepperImplem.H:301
void parseOptions()
Parse options.
Definition CD_TracerParticleStepperImplem.H:119
virtual void synchronizeSolverTimes(const int a_step, const Real a_time, const Real a_dt) override
Synchronize solver times and time steps.
Definition CD_TracerParticleStepperImplem.H:334
virtual void advanceParticlesRK2(const Real a_dt)
Advance particles using second order Runge-Kutta.
Definition CD_TracerParticleStepperImplem.H:523
void setupSolvers() override
Instantiate the tracer particle solver.
Definition CD_TracerParticleStepperImplem.H:50
virtual ~TracerParticleStepper()
Destructor.
Definition CD_TracerParticleStepperImplem.H:40
virtual void advanceParticlesRK4(const Real a_dt)
Advance particles using fourth order Runge-Kutta.
Definition CD_TracerParticleStepperImplem.H:608
Vector< std::string > getPlotVariableNames() const override
Get plot variable names.
Definition CD_TracerParticleStepperImplem.H:259
virtual void parseVelocityField()
Parse velocity field.
Definition CD_TracerParticleStepperImplem.H:177
virtual void parseIntegrator()
Parse integration algorithm from input script.
Definition CD_TracerParticleStepperImplem.H:147
virtual void postRegrid() override
Perform post-regrid operations.
Definition CD_TracerParticleStepperImplem.H:379
virtual void initialParticles()
Fill initial particles.
Definition CD_TracerParticleStepperImplem.H:434
TracerParticleStepper()
Constructor. Does nothing.
Definition CD_TracerParticleStepperImplem.H:29
virtual void setVelocity()
Set the velocity on the mesh.
Definition CD_TracerParticleStepperImplem.H:393
static Real getUniformReal01()
Get a uniform real number on the interval [0,1].
Definition CD_RandomImplem.H:156
static const std::string Primal
Identifier for perimal realm.
Definition CD_Realm.H:44
Base class for a tracer particle solver. This solver can advance particles in a pre-defined velocity ...
Definition CD_TracerParticleSolver.H:39
ALWAYS_INLINE void loop(const ParticleSoA< P, Traits > &a_soa, Functor &&a_kernel)
Launch a kernel over every particle in a ParticleSoA, decorating the loop with CD_PRAGMA_SIMD.
Definition CD_ParticleLoops.H:87
Namespace for encapsulating physics code for tracer particles.
Definition CD_TracerParticlePhysics.H:22
@ gas
Gas phase.
Definition CD_MultiFluidIndexSpace.H:39