12 #ifndef CD_ItoKMCStepperImplem_H
13 #define CD_ItoKMCStepperImplem_H
19 #include <ParmParse.H>
30 #include <CD_NamespaceHeader.H>
32 using namespace Physics::ItoKMC;
34 template <
typename I,
typename C,
typename R,
typename F>
37 CH_TIME(
"ItoKMCStepper::ItoKMCStepper");
41 m_name =
"ItoKMCStepper";
42 m_plasmaPhase = phase::gas;
45 m_maxGrowthDt = 1.E99;
46 m_maxShrinkDt = 1.E99;
50 m_redistributeCDR =
true;
51 m_regridSuperparticles =
true;
54 m_minParticleAdvectionCFL = 0.0;
55 m_maxParticleAdvectionCFL = 1.0;
56 m_minParticleDiffusionCFL = 0.0;
60 m_fluidAdvectionDiffusionCFL = 0.5;
66 template <
typename I,
typename C,
typename R,
typename F>
69 CH_TIME(
"ItoKMCStepper::ItoKMCStepper(RefCountrPtr<ItoKMCPhysics>)");
71 m_physics = a_physics;
73 if (m_physics->getNumPlasmaSpecies() == 0) {
74 MayDay::Abort(
"ItoKMCStepper::ItoKMCStepper -- numPlasmaSpecies = 0, there's no problem to solve here!");
78 template <
typename I,
typename C,
typename R,
typename F>
81 CH_TIME(
"ItoKMCStepper::~ItoKMCStepper");
84 template <
typename I,
typename C,
typename R,
typename F>
88 CH_TIME(
"ItoKMCStepper::parseOptions");
89 if (m_verbosity > 5) {
90 pout() << m_name +
"::parseOptions" << endl;
93 this->parseVerbosity();
94 this->parseExitOnFailure();
95 this->parseRedistributeCDR();
96 this->parsePlotVariables();
97 this->parseSuperParticles();
98 this->parseDualGrid();
99 this->parseLoadBalance();
100 this->parseTimeStepRestrictions();
101 this->parseParametersEB();
104 template <
typename I,
typename C,
typename R,
typename F>
108 CH_TIME(
"ItoKMCStepper::parseRuntimeOptions");
109 if (m_verbosity > 5) {
110 pout() << m_name +
"::parseRuntimeOptions" << endl;
113 this->parseVerbosity();
114 this->parseExitOnFailure();
115 this->parseRedistributeCDR();
116 this->parsePlotVariables();
117 this->parseSuperParticles();
118 this->parseLoadBalance();
119 this->parseTimeStepRestrictions();
120 this->parseParametersEB();
122 m_ito->parseRuntimeOptions();
123 m_cdr->parseRuntimeOptions();
124 m_fieldSolver->parseRuntimeOptions();
125 m_rte->parseRuntimeOptions();
126 m_sigmaSolver->parseRuntimeOptions();
128 m_physics->parseRuntimeOptions();
131 template <
typename I,
typename C,
typename R,
typename F>
135 CH_TIME(
"ItoKMCStepper::parseVerbosity");
136 if (m_verbosity > 5) {
137 pout() << m_name +
"::parseVerbosity" << endl;
140 ParmParse pp(m_name.c_str());
142 pp.get(
"verbosity", m_verbosity);
143 pp.get(
"profile", m_profile);
146 template <
typename I,
typename C,
typename R,
typename F>
150 CH_TIME(
"ItoKMCStepper::parseExitOnFailure");
151 if (m_verbosity > 5) {
152 pout() << m_name +
"::parseExitOnFailure" << endl;
155 ParmParse pp(m_name.c_str());
157 pp.get(
"abort_on_failure", m_abortOnFailure);
160 template <
typename I,
typename C,
typename R,
typename F>
164 CH_TIME(
"ItoKMCStepper::parseRedistributeCDR");
165 if (m_verbosity > 5) {
166 pout() << m_name +
"::parseRedistributeCDR" << endl;
169 ParmParse pp(m_name.c_str());
171 pp.get(
"redistribute_cdr", m_redistributeCDR);
174 template <
typename I,
typename C,
typename R,
typename F>
178 CH_TIME(
"ItoKMCStepper::parsePlotVariables");
179 if (m_verbosity > 5) {
180 pout() << m_name +
"::parsePlotVariables" << endl;
183 m_plotConductivity =
false;
184 m_plotCurrentDensity =
false;
185 m_plotParticlesPerPatch =
false;
188 ParmParse pp(m_name.c_str());
189 const int num = pp.countval(
"plt_vars");
192 Vector<std::string> str(num);
193 pp.getarr(
"plt_vars", str, 0, num);
196 for (
int i = 0; i < num; i++) {
197 if (str[i] ==
"conductivity") {
198 m_plotConductivity =
true;
200 else if (str[i] ==
"current_density") {
201 m_plotCurrentDensity =
true;
203 else if (str[i] ==
"particles_per_patch") {
204 m_plotParticlesPerPatch =
true;
210 template <
typename I,
typename C,
typename R,
typename F>
214 CH_TIME(
"ItoKMCStepper::parseSuperParticles");
215 if (m_verbosity > 5) {
216 pout() << m_name +
"::parseSuperParticles" << endl;
219 ParmParse pp(m_name.c_str());
221 m_particlesPerCell.resize(pp.countval(
"particles_per_cell"));
223 pp.get(
"merge_interval", m_mergeInterval);
224 pp.get(
"regrid_superparticles", m_regridSuperparticles);
225 pp.getarr(
"particles_per_cell", m_particlesPerCell, 0, m_particlesPerCell.size());
227 for (
int lvl = 0; lvl < m_particlesPerCell.size(); lvl++) {
228 if (m_particlesPerCell[lvl] <= 0) {
229 MayDay::Error(
"ItoKMCStepper::parseSuperParticles -- must have 'particles_per_cell' > 0");
234 template <
typename I,
typename C,
typename R,
typename F>
238 CH_TIME(
"ItoKMCStepper::parseDualGrid");
239 if (m_verbosity > 5) {
240 pout() << m_name +
"::parseDualGrid" << endl;
243 ParmParse pp(m_name.c_str());
245 pp.get(
"dual_grid", m_dualGrid);
248 m_particleRealm =
"ParticleRealm";
250 CH_assert(m_particleRealm != m_fluidRealm);
253 m_particleRealm = m_fluidRealm;
257 template <
typename I,
typename C,
typename R,
typename F>
261 CH_TIME(
"ItoKMCStepper::parseLoadBalance");
262 if (m_verbosity > 5) {
263 pout() << m_name +
"::parseLoadBalance" << endl;
266 ParmParse pp(m_name.c_str());
270 pp.get(
"load_balance_particles", m_loadBalanceParticles);
271 pp.get(
"load_balance_fluid", m_loadBalanceFluid);
272 pp.get(
"load_per_cell", m_loadPerCell);
275 pp.get(
"box_sorting", str);
277 m_boxSort = BoxSorting::None;
279 else if (str ==
"std") {
280 m_boxSort = BoxSorting::Std;
282 else if (str ==
"shuffle") {
283 m_boxSort = BoxSorting::Shuffle;
285 else if (str ==
"morton") {
286 m_boxSort = BoxSorting::Morton;
289 const std::string err =
"ItoKMCStepper::parseLoadBalance - 'box_sorting = " + str +
"' not recognized";
291 MayDay::Error(err.c_str());
295 const int numIndices = pp.countval(
"load_indices");
297 if (numIndices > 0) {
298 pp.getarr(
"load_indices", m_loadBalanceIndices, 0, numIndices);
301 const std::string err =
"ItoKMCStepper::parseLoadBalance - 'load_indices' argument has zero entries";
303 MayDay::Error(err.c_str());
307 template <
typename I,
typename C,
typename R,
typename F>
311 CH_TIME(
"ItoKMCStepper::parseTimeStepRestrictions");
312 if (m_verbosity > 5) {
313 pout() << m_name +
"::parseTimeStepRestrictions" << endl;
316 ParmParse pp(m_name.c_str());
318 pp.get(
"min_particle_advection_cfl", m_minParticleAdvectionCFL);
319 pp.get(
"max_particle_advection_cfl", m_maxParticleAdvectionCFL);
320 pp.get(
"min_particle_diffusion_cfl", m_minParticleDiffusionCFL);
321 pp.get(
"max_particle_diffusion_cfl", m_maxParticleDiffusionCFL);
322 pp.get(
"min_particle_advection_diffusion_cfl", m_minParticleAdvectionDiffusionCFL);
323 pp.get(
"max_particle_advection_diffusion_cfl", m_maxParticleAdvectionDiffusionCFL);
324 pp.get(
"fluid_advection_diffusion_cfl", m_fluidAdvectionDiffusionCFL);
325 pp.get(
"relax_dt_factor", m_relaxTimeFactor);
326 pp.get(
"min_dt", m_minDt);
327 pp.get(
"max_dt", m_maxDt);
328 pp.get(
"max_growth_dt", m_maxGrowthDt);
329 pp.get(
"max_shrink_dt", m_maxShrinkDt);
331 if (m_maxGrowthDt <= 1.0) {
332 MayDay::Error(
"ItoKMCStepper::parseTimeStepRestrictions() - must have max_growth_dt > 1.0");
335 if (m_maxShrinkDt <= 1.0) {
336 MayDay::Error(
"ItoKMCStepper::parseTimeStepRestrictions() - must have max_shrink_dt > 1.0");
339 if (m_relaxTimeFactor <= 0.0) {
340 MayDay::Error(
"ItoKMCStepper::parseTimeStepRestrictions() - must have relax_dt > 0.0");
344 MayDay::Error(
"ItoKMCStepper::parseTimeStepRestrictions() - must have min_dt >= 0.0");
348 MayDay::Error(
"ItoKMCStepper::parseTimeStepRestrictions() - must have max_dt >= 0.0");
351 if (m_maxParticleAdvectionCFL <= 0.0) {
352 MayDay::Error(
"ItoKMCStepper::parseTimeStepRestrictions() - must have max_particle_advection_cfl > 0.0");
355 if (m_minParticleAdvectionCFL < 0.0) {
356 MayDay::Error(
"ItoKMCStepper::parseTimeStepRestrictions() - must have min_particle_advection_cfl >= 0.0");
359 if (m_maxParticleDiffusionCFL <= 0.0) {
360 MayDay::Error(
"ItoKMCStepper::parseTimeStepRestrictions() - must have particle_diffusion_cfl > 0.0");
363 if (m_minParticleDiffusionCFL < 0.0) {
364 MayDay::Error(
"ItoKMCStepper::parseTimeStepRestrictions() - must have particle_diffusion_cfl >= 0.0");
367 if (m_maxParticleAdvectionDiffusionCFL <= 0.0) {
368 MayDay::Error(
"ItoKMCStepper::parseTimeStepRestrictions() - must have particle_advection_diffusion_cfl > 0.0");
371 if (m_minParticleAdvectionDiffusionCFL < 0.0) {
372 MayDay::Error(
"ItoKMCStepper::parseTimeStepRestrictions() - must have particle_advection_diffusion_cfl >= 0.0");
375 if (m_fluidAdvectionDiffusionCFL <= 0.0) {
376 MayDay::Error(
"ItoKMCStepper::parseTimeStepRestrictions() - must have fluid_advection_diffusion_cfl > 0.0");
380 template <
typename I,
typename C,
typename R,
typename F>
384 CH_TIME(
"ItoKMCStepper::parseTimeStepRestrictions");
385 if (m_verbosity > 5) {
386 pout() << m_name +
"::parseTimeStepRestrictions" << endl;
389 ParmParse pp(m_name.c_str());
393 pp.get(
"eb_tolerance", m_toleranceEB);
396 template <
typename I,
typename C,
typename R,
typename F>
400 CH_TIME(
"ItoKMCStepper::setupSolver");
401 if (m_verbosity > 5) {
402 pout() << m_name +
"::setupSolvers" << endl;
407 this->setupPoisson();
408 this->setupRadiativeTransfer();
412 template <
typename I,
typename C,
typename R,
typename F>
416 CH_TIME(
"ItoKMCStepper::setupIto");
417 if (m_verbosity > 5) {
418 pout() << m_name +
"::setupIto" << endl;
422 m_ito = factory.
newLayout(m_physics->getItoSpecies());
424 m_ito->parseOptions();
425 m_ito->setAmr(m_amr);
426 m_ito->setPhase(m_plasmaPhase);
427 m_ito->setComputationalGeometry(m_computationalGeometry);
428 m_ito->setRealm(m_particleRealm);
431 template <
typename I,
typename C,
typename R,
typename F>
435 CH_TIME(
"ItoKMCStepper::setupCdr");
436 if (m_verbosity > 5) {
437 pout() << m_name +
"::setupCdr" << endl;
441 m_cdr = factory.
newLayout(m_physics->getCdrSpecies());
443 m_cdr->parseOptions();
444 m_cdr->setAmr(m_amr);
445 m_cdr->setPhase(m_plasmaPhase);
446 m_cdr->setComputationalGeometry(m_computationalGeometry);
447 m_cdr->setRealm(m_fluidRealm);
450 template <
typename I,
typename C,
typename R,
typename F>
454 CH_TIME(
"ItoKMCStepper::setupRadiativeTransfer");
455 if (m_verbosity > 5) {
456 pout() << m_name +
"::setupRadiativeTransfer" << endl;
460 m_rte = factory.
newLayout(m_physics->getRtSpecies());
462 m_rte->parseOptions();
463 m_rte->setPhase(m_plasmaPhase);
464 m_rte->setAmr(m_amr);
465 m_rte->setComputationalGeometry(m_computationalGeometry);
466 m_rte->setRealm(m_particleRealm);
467 m_rte->sanityCheck();
470 template <
typename I,
typename C,
typename R,
typename F>
474 CH_TIME(
"ItoKMCStepper::setupPoisson");
475 if (m_verbosity > 5) {
476 pout() << m_name +
"::setupPoisson" << endl;
479 m_fieldSolver = RefCountedPtr<FieldSolver>(
new F());
480 m_fieldSolver->parseOptions();
481 m_fieldSolver->setAmr(m_amr);
482 m_fieldSolver->setComputationalGeometry(m_computationalGeometry);
483 m_fieldSolver->setVoltage(m_voltage);
484 m_fieldSolver->setRealm(m_fluidRealm);
487 template <
typename I,
typename C,
typename R,
typename F>
491 CH_TIME(
"ItoKMCStepper::setupSigma");
492 if (m_verbosity > 5) {
493 pout() << m_name +
"::setupSigma" << endl;
497 m_sigmaSolver->parseOptions();
498 m_sigmaSolver->setRealm(m_fluidRealm);
499 m_sigmaSolver->setPhase(m_plasmaPhase);
500 m_sigmaSolver->setName(
"Surface charge");
501 m_sigmaSolver->setTime(0, 0.0, 0.0);
504 template <
typename I,
typename C,
typename R,
typename F>
508 CH_TIME(
"ItoKMCStepper::allocate");
509 if (m_verbosity > 5) {
510 pout() << m_name +
"::allocate" << endl;
516 m_fieldSolver->allocate();
517 m_sigmaSolver->allocate();
519 this->allocateInternals();
522 template <
typename I,
typename C,
typename R,
typename F>
526 CH_TIME(
"ItoKMCStepper::allocateInternals");
527 if (m_verbosity > 5) {
528 pout() << m_name +
"::allocateInternals" << endl;
531 const int numItoSpecies = m_physics->getNumItoSpecies();
532 const int numCdrSpecies = m_physics->getNumCdrSpecies();
533 const int numPlasmaSpecies = m_physics->getNumPlasmaSpecies();
534 const int numPhotonSpecies = m_physics->getNumPhotonSpecies();
536 CH_assert(numPlasmaSpecies > 0);
539 m_amr->allocate(m_fluidScratch1, m_fluidRealm, m_plasmaPhase, 1);
540 m_amr->allocate(m_fluidScratchD, m_fluidRealm, m_plasmaPhase, SpaceDim);
541 m_amr->allocate(m_fluidScratchEB, m_fluidRealm, m_plasmaPhase, 1);
543 m_amr->allocate(m_particleScratch1, m_particleRealm, m_plasmaPhase, 1);
544 m_amr->allocate(m_particleScratchD, m_particleRealm, m_plasmaPhase, SpaceDim);
545 m_amr->allocate(m_particleScratchEB, m_particleRealm, m_plasmaPhase, 1);
548 m_amr->allocate(m_conductivityCell, m_fluidRealm, m_plasmaPhase, 1);
549 m_amr->allocate(m_conductivityFace, m_fluidRealm, m_plasmaPhase, 1);
550 m_amr->allocate(m_conductivityEB, m_fluidRealm, m_plasmaPhase, 1);
553 m_amr->allocate(m_electricFieldParticle, m_particleRealm, m_plasmaPhase, SpaceDim);
554 m_amr->allocate(m_electricFieldFluid, m_fluidRealm, m_plasmaPhase, SpaceDim);
557 m_cdrMobilities.resize(numCdrSpecies);
558 m_cdrPhotoiProducts.resize(numCdrSpecies);
559 for (
int i = 0; i < numCdrSpecies; i++) {
560 m_amr->allocate(m_cdrMobilities[i], m_fluidRealm, m_plasmaPhase, 1);
561 m_amr->allocate(m_cdrPhotoiProducts[i], m_particleRealm);
565 m_fluidGradPhiIto.resize(numItoSpecies);
566 m_fluidPhiIto.resize(numItoSpecies);
567 m_fluidGradPhiCDR.resize(numCdrSpecies);
568 for (
int i = 0; i < numItoSpecies; i++) {
569 m_amr->allocate(m_fluidGradPhiIto[i], m_fluidRealm, m_plasmaPhase, SpaceDim);
570 m_amr->allocate(m_fluidPhiIto[i], m_fluidRealm, m_plasmaPhase, 1);
572 for (
int i = 0; i < numCdrSpecies; i++) {
573 m_amr->allocate(m_fluidGradPhiCDR[i], m_fluidRealm, m_plasmaPhase, SpaceDim);
577 m_secondaryParticles.resize(numItoSpecies);
578 m_secondaryPhotons.resize(numPhotonSpecies);
580 m_cdrFluxes.resize(numCdrSpecies);
581 m_cdrFluxesExtrap.resize(numCdrSpecies);
583 for (
int i = 0; i < numItoSpecies; i++) {
584 m_amr->allocate(m_secondaryParticles[i], m_particleRealm);
587 for (
int i = 0; i < numPhotonSpecies; i++) {
588 m_amr->allocate(m_secondaryPhotons[i], m_particleRealm);
591 for (
int i = 0; i < numCdrSpecies; i++) {
592 m_amr->allocate(m_cdrFluxes[i], m_particleRealm, m_plasmaPhase, 1);
593 m_amr->allocate(m_cdrFluxesExtrap[i], m_particleRealm, m_plasmaPhase, 1);
597 m_amr->allocate(m_currentDensity, m_fluidRealm, m_plasmaPhase, SpaceDim);
600 m_amr->allocate(m_fluidPPC, m_fluidRealm, m_plasmaPhase, numPlasmaSpecies);
602 if (numItoSpecies > 0) {
603 m_amr->allocate(m_particleItoPPC, m_particleRealm, m_plasmaPhase, numItoSpecies);
604 m_amr->allocate(m_particleOldItoPPC, m_particleRealm, m_plasmaPhase, numItoSpecies);
608 m_amr->allocate(m_particleItoPPC, m_particleRealm, m_plasmaPhase, 1);
609 m_amr->allocate(m_particleOldItoPPC, m_particleRealm, m_plasmaPhase, 1);
612 if (numCdrSpecies > 0) {
613 m_amr->allocate(m_fluidCdrPPC, m_fluidRealm, m_plasmaPhase, numCdrSpecies);
614 m_amr->allocate(m_fluidOldCdrPPC, m_fluidRealm, m_plasmaPhase, numCdrSpecies);
617 m_amr->allocatePointer(m_fluidCdrPPC, m_fluidRealm);
618 m_amr->allocatePointer(m_fluidOldCdrPPC, m_fluidRealm);
621 if (numPhotonSpecies > 0) {
622 m_amr->allocate(m_particleYPC, m_particleRealm, m_plasmaPhase, numPhotonSpecies);
623 m_amr->allocate(m_fluidYPC, m_fluidRealm, m_plasmaPhase, numPhotonSpecies);
627 m_amr->allocate(m_particleYPC, m_particleRealm, m_plasmaPhase, 1);
628 m_amr->allocate(m_fluidYPC, m_fluidRealm, m_plasmaPhase, 1);
632 template <
typename I,
typename C,
typename R,
typename F>
636 CH_TIME(
"ItoKMCStepper::postInitialize");
637 if (m_verbosity > 5) {
638 pout() << m_name +
"::postInitialize" << endl;
642 template <
typename I,
typename C,
typename R,
typename F>
646 CH_TIME(
"ItoKMCStepper::initialData");
647 if (m_verbosity > 5) {
648 pout() << m_name +
"::initialData" << endl;
651 CH_assert(!(m_cdr.isNull()));
652 CH_assert(!(m_ito.isNull()));
653 CH_assert(!(m_rte.isNull()));
654 CH_assert(!(m_sigmaSolver.isNull()));
655 CH_assert(!(m_fieldSolver.isNull()));
657 m_ito->initialData();
658 m_cdr->initialData();
659 m_rte->initialData();
660 this->initialSigma();
663 m_ito->organizeParticlesByCell(ItoSolver::WhichContainer::Bulk);
664 m_ito->makeSuperparticles(ItoSolver::WhichContainer::Bulk, m_particlesPerCell);
665 m_ito->organizeParticlesByPatch(ItoSolver::WhichContainer::Bulk);
668 m_fieldSolver->setPermittivities();
669 this->computeSpaceChargeDensity();
670 this->solvePoisson();
673 this->computeDriftVelocities();
674 this->computeDiffusionCoefficients();
677 template <
typename I,
typename C,
typename R,
typename F>
681 CH_TIME(
"ItoKMCStepper::initialSigma");
682 if (m_verbosity > 5) {
683 pout() << m_name +
"::initialSigma" << endl;
686 const RealVect probLo = m_amr->getProbLo();
690 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
691 const DisjointBoxLayout& dbl = m_amr->getGrids(m_sigmaSolver->getRealm())[lvl];
692 const DataIterator& dit = dbl.dataIterator();
693 const EBISLayout& ebisl = m_amr->getEBISLayout(m_sigmaSolver->getRealm(), m_sigmaSolver->getPhase())[lvl];
694 const Real dx = m_amr->getDx()[lvl];
696 const int nbox = dit.
size();
698 #pragma omp parallel for schedule(runtime)
699 for (
int mybox = 0; mybox < nbox; mybox++) {
700 const DataIndex& din = dit[mybox];
702 BaseIVFAB<Real>& phi = (*sigma[lvl])[din];
703 const EBISBox& ebisbox = ebisl[din];
705 CH_assert(phi.nComp() == 1);
707 auto kernel = [&](
const VolIndex& vof) ->
void {
708 const RealVect pos = probLo +
Location::position(Location::Cell::Boundary, vof, ebisbox, dx);
710 phi(vof, 0) = m_physics->initialSigma(m_time, pos);
713 VoFIterator& vofit = (*m_amr->getVofIterator(m_sigmaSolver->getRealm(), m_sigmaSolver->getPhase())[lvl])[din];
720 m_amr->conservativeAverage(sigma, m_fluidRealm, m_sigmaSolver->getPhase());
723 m_sigmaSolver->resetElectrodes(sigma, 0.0);
726 template <
typename I,
typename C,
typename R,
typename F>
730 CH_TIME(
"ItoKMCStepper::postCheckpointSetup");
731 if (m_verbosity > 5) {
732 pout() << m_name +
"::postCheckpointSetup" << endl;
738 this->postCheckpointPoisson();
741 this->computeDriftVelocities();
742 this->computeDiffusionCoefficients();
745 template <
typename I,
typename C,
typename R,
typename F>
749 CH_TIME(
"ItoKMCStepper::postCheckpointPoisson");
750 if (m_verbosity > 5) {
751 pout() << m_name +
"::postCheckpointPoisson" << endl;
755 m_fieldSolver->postCheckpoint();
760 m_amr->conservativeAverage(potential, m_fluidRealm);
761 m_amr->interpGhostMG(potential, m_fluidRealm);
763 m_fieldSolver->computeElectricField();
766 const EBAMRCellData E = m_amr->alias(m_plasmaPhase, m_fieldSolver->getElectricField());
769 m_amr->copyData(m_electricFieldFluid, E);
770 m_amr->conservativeAverage(m_electricFieldFluid, m_fluidRealm, m_plasmaPhase);
771 m_amr->interpGhostPwl(m_electricFieldFluid, m_fluidRealm, m_plasmaPhase);
772 m_amr->interpToCentroids(m_electricFieldFluid, m_fluidRealm, m_plasmaPhase);
775 m_amr->copyData(m_electricFieldParticle, E);
776 m_amr->conservativeAverage(m_electricFieldParticle, m_particleRealm, m_plasmaPhase);
777 m_amr->interpGhostPwl(m_electricFieldParticle, m_particleRealm, m_plasmaPhase);
778 m_amr->interpToCentroids(m_electricFieldParticle, m_particleRealm, m_plasmaPhase);
781 m_fieldSolver->setupSolver();
785 template <
typename I,
typename C,
typename R,
typename F>
789 CH_TIME(
"ItoKMCStepper::writeCheckpointHeader");
790 if (m_verbosity > 5) {
791 pout() << m_name +
"::writeCheckpointHeader" << endl;
797 template <
typename I,
typename C,
typename R,
typename F>
801 CH_TIME(
"ItoKMCStepper::readCheckpointHeader");
802 if (m_verbosity > 5) {
803 pout() << m_name +
"::readCheckpointHeader" << endl;
809 template <
typename I,
typename C,
typename R,
typename F>
813 CH_TIME(
"ItoKMCStepper::writeCheckpointData");
814 if (m_verbosity > 5) {
815 pout() << m_name +
"::writeCheckpointData" << endl;
819 solverIt()->writeCheckpointLevel(a_handle, a_lvl);
823 solverIt()->writeCheckpointLevel(a_handle, a_lvl);
827 solverIt()->writeCheckpointLevel(a_handle, a_lvl);
830 m_fieldSolver->writeCheckpointLevel(a_handle, a_lvl);
831 m_sigmaSolver->writeCheckpointLevel(a_handle, a_lvl);
836 template <
typename I,
typename C,
typename R,
typename F>
840 CH_TIME(
"ItoKMCStepper::readCheckpointData");
841 if (m_verbosity > 5) {
842 pout() << m_name +
"::readCheckpointData" << endl;
846 solverIt()->readCheckpointLevel(a_handle, a_lvl);
850 solverIt()->readCheckpointLevel(a_handle, a_lvl);
854 solverIt()->readCheckpointLevel(a_handle, a_lvl);
857 m_fieldSolver->readCheckpointLevel(a_handle, a_lvl);
858 m_sigmaSolver->readCheckpointLevel(a_handle, a_lvl);
862 template <
typename I,
typename C,
typename R,
typename F>
866 CH_TIME(
"ItoKMCStepper::getNumberOfPlotVariables");
867 if (m_verbosity > 5) {
868 pout() << m_name +
"::getNumberOfPlotVariables" << endl;
875 numComp += solverIt()->getNumberOfPlotVariables();
879 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
880 numComp += solverIt()->getNumberOfPlotVariables();
885 numComp += solverIt()->getNumberOfPlotVariables();
889 numComp += m_fieldSolver->getNumberOfPlotVariables();
892 numComp += m_sigmaSolver->getNumberOfPlotVariables();
895 if (m_plotConductivity) {
900 if (m_plotCurrentDensity) {
905 if (m_plotParticlesPerPatch) {
910 numComp += m_physics->getNumberOfPlotVariables();
915 template <
typename I,
typename C,
typename R,
typename F>
919 CH_TIME(
"ItoKMCStepper::getPlotVariableNames");
920 if (m_verbosity > 5) {
921 pout() << m_name +
"::getPlotVariableNames" << endl;
924 Vector<std::string> plotVarNames;
926 plotVarNames.append(m_fieldSolver->getPlotVariableNames());
927 plotVarNames.append(m_sigmaSolver->getPlotVariableNames());
930 plotVarNames.append(solverIt()->getPlotVariableNames());
933 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
934 plotVarNames.append(solverIt()->getPlotVariableNames());
938 plotVarNames.append(solverIt()->getPlotVariableNames());
942 if (m_plotConductivity) {
943 plotVarNames.push_back(
"Conductivity");
947 if (m_plotCurrentDensity) {
948 plotVarNames.push_back(
"x-J");
949 plotVarNames.push_back(
"y-J");
951 plotVarNames.push_back(
"z-J");
956 if (m_plotParticlesPerPatch) {
957 plotVarNames.push_back(
"Particles per patch");
961 plotVarNames.append(m_physics->getPlotVariableNames());
966 template <
typename I,
typename C,
typename R,
typename F>
970 const std::string a_outputRealm,
971 const int a_level)
const noexcept
973 CH_TIME(
"ItoKMCStepper::writePlotData");
974 if (m_verbosity > 5) {
975 pout() << m_name +
"::writePlotData" << endl;
979 m_fieldSolver->writePlotData(a_output, a_icomp, a_outputRealm, a_level);
982 m_sigmaSolver->writePlotData(a_output, a_icomp, a_outputRealm, a_level);
986 solverIt()->writePlotData(a_output, a_icomp, a_outputRealm, a_level);
990 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
991 solverIt()->writePlotData(a_output, a_icomp, a_outputRealm, a_level);
996 solverIt()->writePlotData(a_output, a_icomp, a_outputRealm, a_level);
1000 if (m_plotConductivity) {
1001 this->writeData(a_output, a_icomp, m_conductivityCell, a_outputRealm, a_level,
false,
true);
1005 if (m_plotCurrentDensity) {
1006 this->writeData(a_output, a_icomp, m_currentDensity, a_outputRealm, a_level,
false,
true);
1010 if (m_plotParticlesPerPatch) {
1011 this->writeNumberOfParticlesPerPatch(a_output, a_icomp, a_outputRealm, a_level);
1015 if (m_physics->getNumberOfPlotVariables() > 0) {
1016 this->writeData(a_output, a_icomp, m_physicsPlotVariables, a_outputRealm, a_level,
false,
true);
1020 template <
typename I,
typename C,
typename R,
typename F>
1025 const std::string a_outputRealm,
1027 const bool a_interpToCentroids,
1028 const bool a_interpGhost)
const noexcept
1031 CH_TIMERS(
"ItoKMCStepper::writeData");
1032 CH_TIMER(
"ItoKMCStepper::writeData::allocate", t1);
1033 CH_TIMER(
"ItoKMCStepper::writeData::local_copy", t2);
1034 CH_TIMER(
"ItoKMCStepper::writeData::interp_ghost", t3);
1035 CH_TIMER(
"ItoKMCStepper::writeData::interp_centroid", t4);
1036 CH_TIMER(
"ItoKMCStepper::writeData::final_copy", t5);
1037 if (m_verbosity > 5) {
1038 pout() << m_name +
"::writeData" << endl;
1042 const int numComp = a_data[a_level]->nComp();
1045 const Interval srcInterv(0, numComp - 1);
1046 const Interval dstInterv(a_comp, a_comp + numComp - 1);
1049 LevelData<EBCellFAB> scratch;
1050 m_amr->allocate(scratch, a_data.getRealm(), m_plasmaPhase, a_level, numComp);
1054 m_amr->copyData(scratch, *a_data[a_level], a_level, a_data.getRealm(), a_data.getRealm());
1059 if (a_level > 0 && a_interpGhost) {
1060 m_amr->interpGhost(scratch, *a_data[a_level - 1], a_level, a_data.getRealm(), m_plasmaPhase);
1065 if (a_interpToCentroids) {
1066 m_amr->interpToCentroids(scratch, a_data.getRealm(), m_plasmaPhase, a_level);
1073 m_amr->copyData(a_output,
1080 CopyStrategy::ValidGhost,
1081 CopyStrategy::ValidGhost);
1087 template <
typename I,
typename C,
typename R,
typename F>
1091 const std::string a_outputRealm,
1092 const int a_level)
const noexcept
1094 CH_TIME(
"ItoKMCStepper::writeNumberOfParticlesPerPatch");
1095 if (m_verbosity > 5) {
1096 pout() << m_name +
"::writeNumberOfParticlesPerPatch" << endl;
1099 CH_assert(a_level >= 0);
1100 CH_assert(a_level <= m_amr->getFinestLevel());
1104 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
1107 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
1108 const DisjointBoxLayout& dbl = m_amr->getGrids(m_particleRealm)[lvl];
1109 const DataIterator& dit = dbl.dataIterator();
1111 const int nbox = dit.size();
1113 #pragma omp parallel for schedule(runtime)
1114 for (
int mybox = 0; mybox < nbox; mybox++) {
1115 const DataIndex& din = dit[mybox];
1117 (*m_particleScratch1[lvl])[din] += particles[lvl][din].numItems();
1122 m_amr->copyData(a_output,
1123 *m_particleScratch1[a_level],
1127 Interval(a_icomp, a_icomp),
1133 template <
typename I,
typename C,
typename R,
typename F>
1137 CH_TIME(
"ItoKMCStepper::synchronizeSolverTimes");
1138 if (m_verbosity > 5) {
1139 pout() << m_name +
"::synchronizeSolverTimes" << endl;
1142 m_timeStep = a_step;
1146 m_ito->setTime(a_step, a_time, a_dt);
1147 m_fieldSolver->setTime(a_step, a_time, a_dt);
1148 m_rte->setTime(a_step, a_time, a_dt);
1149 m_sigmaSolver->setTime(a_step, a_time, a_dt);
1152 template <
typename I,
typename C,
typename R,
typename F>
1156 CH_TIME(
"ItoKMCStepper::printStepReport");
1157 if (m_verbosity > 5) {
1158 pout() << m_name +
"::printStepReport" << endl;
1161 const Real Emax = this->computeMaxElectricField(m_plasmaPhase);
1163 const unsigned long long localParticlesBulk = m_ito->getNumParticles(ItoSolver::WhichContainer::Bulk,
true);
1164 const unsigned long long globalParticlesBulk = m_ito->getNumParticles(ItoSolver::WhichContainer::Bulk,
false);
1165 const unsigned long long localParticlesEB = m_ito->getNumParticles(ItoSolver::WhichContainer::EB,
true);
1166 const unsigned long long globalParticlesEB = m_ito->getNumParticles(ItoSolver::WhichContainer::EB,
false);
1167 const unsigned long long localParticlesDomain = m_ito->getNumParticles(ItoSolver::WhichContainer::Domain,
true);
1168 const unsigned long long globalParticlesDomain = m_ito->getNumParticles(ItoSolver::WhichContainer::Domain,
false);
1169 const unsigned long long localParticlesSource = m_ito->getNumParticles(ItoSolver::WhichContainer::Source,
true);
1170 const unsigned long long globalParticlesSource = m_ito->getNumParticles(ItoSolver::WhichContainer::Source,
false);
1172 Real avgParticles = 0.0;
1175 Real minParticles = 0.0;
1176 Real maxParticles = 0.0;
1181 this->getParticleStatistics(avgParticles, stdDev, minParticles, maxParticles,
minRank,
maxRank);
1186 std::string maxSolver =
"invalid solver";
1187 std::string minSolver =
"invalid solver";
1189 this->getMaxMinItoDensity(maxDensity, minDensity, maxSolver, minSolver);
1190 this->getMaxMinCDRDensity(maxDensity, minDensity, maxSolver, minSolver);
1193 switch (m_timeCode) {
1194 case TimeCode::Physics: {
1195 str =
"dt restricted by 'Physics'";
1199 case TimeCode::AdvectionIto: {
1200 str =
"dt restricted by 'Advection (Ito)'";
1204 case TimeCode::DiffusionIto: {
1205 str =
"dt restricted by 'Diffusion (Ito)'";
1209 case TimeCode::AdvectionDiffusionIto: {
1210 str =
"dt restricted by 'AdvectionDiffusion (Ito)'";
1214 case TimeCode::AdvectionDiffusionCDR: {
1215 str =
"dt restricted by 'AdvectionDiffusion (CDR)'";
1219 case TimeCode::RelaxationTime: {
1220 str =
"dt restricted by 'Relaxation time'";
1224 case TimeCode::Hardcap: {
1225 str =
"dt restricted by 'Hardcap'";
1230 str =
"dt restricted by 'Unspecified'";
1237 const Real Qplus = this->computeQplus();
1238 const Real Qminu = this->computeQminu();
1239 const Real Qsurf = this->computeQsurf();
1240 const Real Qtot = Qplus + Qminu + Qsurf;
1245 const std::string whitespace =
" ";
1246 pout() <<
" " + str << endl;
1247 pout() << whitespace +
"Emax = " << Emax << endl
1248 << whitespace +
"Max density = " << maxDensity <<
" (" << maxSolver <<
")" << endl
1249 << whitespace +
"Qplus = " << Qplus << endl
1250 << whitespace +
"Qminu = " << Qminu << endl
1251 << whitespace +
"Qsurf = " << Qsurf << endl
1252 << whitespace +
"Qtot = " << Qtot << endl
1253 << whitespace +
"CFL (Ito) = " << m_dt / m_particleAdvectionDiffusionDt << endl
1254 << whitespace +
"CFL (CDR) = " << m_dt / m_fluidAdvectionDiffusionDt << endl
1255 << whitespace +
"dt/dt_relax = " << m_dt / m_relaxationTime << endl
1264 << whitespace +
"#Min part. = " << minParticles <<
" (on rank = " <<
minRank <<
")" << endl
1265 << whitespace +
"#Max part. = " << maxParticles <<
" (on rank = " <<
maxRank <<
")" << endl
1266 << whitespace +
"#Avg. part. = " << avgParticles << endl
1267 << whitespace +
"#Dev. part. = " << stdDev <<
" (" << 100. * stdDev / avgParticles <<
"%)" << endl;
1271 template <
typename I,
typename C,
typename R,
typename F>
1275 std::string& a_maxSolver,
1276 std::string& a_minSolver)
const noexcept
1278 CH_TIME(
"ItoKMCStepper::getMaxMinDensity(Realx2, std::string2x)");
1279 if (m_verbosity > 5) {
1280 pout() << m_name +
"::getMaxMinDensity(Realx2, std::string2x)" << endl;
1284 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
1285 const RefCountedPtr<ItoSolver>& solver = solverIt();
1292 if (curMax > a_maxDensity) {
1293 a_maxDensity = curMax;
1294 a_maxSolver = solver->getName();
1297 if (curMin < a_minDensity) {
1298 a_minDensity = curMin;
1299 a_minSolver = solver->getName();
1304 template <
typename I,
typename C,
typename R,
typename F>
1308 std::string& a_maxSolver,
1309 std::string& a_minSolver)
const noexcept
1311 CH_TIME(
"ItoKMCStepper::getMaxMinCDRDensity(Realx2, std::string2x)");
1312 if (m_verbosity > 5) {
1313 pout() << m_name +
"::getMaxMinCDRDensity(Realx2, std::string2x)" << endl;
1317 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
1318 const RefCountedPtr<CdrSolver>& solver = solverIt();
1325 if (curMax > a_maxDensity) {
1326 a_maxDensity = curMax;
1327 a_maxSolver = solver->getName();
1330 if (curMin < a_minDensity) {
1331 a_minDensity = curMin;
1332 a_minSolver = solver->getName();
1337 template <
typename I,
typename C,
typename R,
typename F>
1341 Real& a_minParticles,
1342 Real& a_maxParticles,
1346 CH_TIME(
"ItoKMCStepper::getParticleStatistics");
1347 if (m_verbosity > 5) {
1348 pout() << m_name +
"::getParticleStatistics" << endl;
1354 const Real numParticles = 1.0 * m_ito->getNumParticles(ItoSolver::WhichContainer::Bulk,
true);
1362 a_minParticles = minParticles.first;
1363 a_maxParticles = maxParticles.first;
1365 a_minRank = minParticles.second;
1366 a_maxRank = maxParticles.second;
1369 template <
typename I,
typename C,
typename R,
typename F>
1373 CH_TIME(
"ItoKMCStepper::computeDt");
1374 if (m_verbosity > 5) {
1375 pout() << m_name +
"::computeDt" << endl;
1378 Timer timer(m_name +
"::computeDt");
1382 const Real maxGrowthDt = m_prevDt > 0.0 ? m_prevDt * m_maxGrowthDt : dt;
1383 const Real minShrinkDt = m_prevDt > 0.0 ? m_prevDt / m_maxShrinkDt : 0.0;
1387 m_particleAdvectionDt = m_ito->computeAdvectiveDt();
1391 m_particleDiffusionDt = m_ito->computeDiffusiveDt();
1394 timer.
startEvent(
"AdvectionDiffusion (Ito)");
1395 m_particleAdvectionDiffusionDt = m_ito->computeDt();
1396 timer.
stopEvent(
"AdvectionDiffusion (Ito)");
1398 timer.
startEvent(
"AdvectionDiffusion (CDR)");
1399 m_fluidAdvectionDiffusionDt = m_cdr->computeAdvectionDiffusionDt();
1400 timer.
stopEvent(
"AdvectionDiffusion (CDR)");
1403 m_physicsDt = this->computePhysicsDt();
1407 m_relaxationTime = this->computeRelaxationTime();
1410 if (m_maxParticleAdvectionCFL * m_particleAdvectionDt < dt) {
1411 dt = m_maxParticleAdvectionCFL * m_particleAdvectionDt;
1412 m_timeCode = TimeCode::AdvectionIto;
1415 if (m_maxParticleDiffusionCFL * m_particleDiffusionDt < dt) {
1416 dt = m_maxParticleDiffusionCFL * m_particleDiffusionDt;
1417 m_timeCode = TimeCode::DiffusionIto;
1420 if (m_maxParticleAdvectionDiffusionCFL * m_particleAdvectionDiffusionDt < dt) {
1421 dt = m_maxParticleAdvectionDiffusionCFL * m_particleAdvectionDiffusionDt;
1422 m_timeCode = TimeCode::AdvectionDiffusionIto;
1425 if (
std::min(m_fluidAdvectionDiffusionCFL, 0.9) * m_fluidAdvectionDiffusionDt < dt) {
1426 dt =
std::min(m_fluidAdvectionDiffusionCFL, 0.9) * m_fluidAdvectionDiffusionDt;
1427 m_timeCode = TimeCode::AdvectionDiffusionCDR;
1430 if (m_relaxTimeFactor * m_relaxationTime < dt) {
1431 dt = m_relaxTimeFactor * m_relaxationTime;
1432 m_timeCode = TimeCode::RelaxationTime;
1435 if (m_physicsDt < dt) {
1437 m_timeCode = TimeCode::Physics;
1440 if (dt < m_minParticleAdvectionCFL * m_particleAdvectionDt) {
1441 dt = m_minParticleAdvectionCFL * m_particleAdvectionDt;
1443 m_timeCode = TimeCode::AdvectionIto;
1446 if (dt < m_minParticleDiffusionCFL * m_particleDiffusionDt) {
1447 dt = m_minParticleDiffusionCFL * m_particleDiffusionDt;
1449 m_timeCode = TimeCode::DiffusionIto;
1452 if (dt < m_minParticleAdvectionDiffusionCFL * m_particleAdvectionDiffusionDt) {
1453 dt = m_minParticleAdvectionDiffusionCFL * m_particleAdvectionDiffusionDt;
1455 m_timeCode = TimeCode::AdvectionDiffusionIto;
1458 if (dt > maxGrowthDt) {
1462 if (dt < minShrinkDt) {
1468 m_timeCode = TimeCode::Hardcap;
1473 m_timeCode = TimeCode::Hardcap;
1483 template <
typename I,
typename C,
typename R,
typename F>
1487 CH_TIME(
"ItoKMCStepper::registerRealms");
1488 if (m_verbosity > 5) {
1489 pout() << m_name +
"::registerRealms" << endl;
1493 m_amr->registerRealm(m_fluidRealm);
1494 m_amr->registerRealm(m_particleRealm);
1497 template <
typename I,
typename C,
typename R,
typename F>
1501 CH_TIME(
"ItoKMCStepper::registerOperators");
1502 if (m_verbosity > 5) {
1503 pout() << m_name +
"::registerOperators" << endl;
1506 m_ito->registerOperators();
1507 m_cdr->registerOperators();
1508 m_fieldSolver->registerOperators();
1509 m_rte->registerOperators();
1510 m_sigmaSolver->registerOperators();
1513 template <
typename I,
typename C,
typename R,
typename F>
1517 CH_TIME(
"ItoKMCStepper::prePlot");
1518 if (m_verbosity > 5) {
1519 pout() << m_name +
"::prePlot" << endl;
1522 const int numPhysicsPlotVars = m_physics->getNumberOfPlotVariables();
1524 if (numPhysicsPlotVars > 0) {
1525 m_amr->allocate(m_physicsPlotVariables, m_fluidRealm, m_plasmaPhase, numPhysicsPlotVars);
1528 this->computePhysicsPlotVariables(m_physicsPlotVariables);
1529 this->computeCurrentDensity(this->m_currentDensity);
1530 m_ito->depositParticles();
1533 template <
typename I,
typename C,
typename R,
typename F>
1537 CH_TIME(
"ItoKMCStepper::postPlot");
1538 if (m_verbosity > 5) {
1539 pout() << m_name +
"::postPlot" << endl;
1542 m_physicsPlotVariables.clear();
1545 template <
typename I,
typename C,
typename R,
typename F>
1549 CH_TIME(
"ItoKMCStepper::preRegrid");
1550 if (m_verbosity > 5) {
1551 pout() << m_name +
"::preRegrid" << endl;
1554 const int numItoSpecies = m_physics->getNumItoSpecies();
1555 const int numCdrSpecies = m_physics->getNumCdrSpecies();
1556 const int numPlasmaSpecies = m_physics->getNumPlasmaSpecies();
1557 const int numPhotonSpecies = m_physics->getNumPhotonSpecies();
1561 if (m_loadBalanceParticles) {
1562 Vector<RefCountedPtr<ItoSolver>> lbSolvers = this->getLoadBalanceSolvers();
1564 m_loadBalancePPC.resize(lbSolvers.size());
1567 for (
int i = 0; i < lbSolvers.size(); i++) {
1568 m_amr->allocate(m_loadBalancePPC[i], m_particleRealm, m_plasmaPhase, 1);
1578 m_fluidScratch1.clear();
1579 m_fluidScratchD.clear();
1580 m_fluidScratchEB.clear();
1582 m_particleScratch1.clear();
1583 m_particleScratchD.clear();
1584 m_particleScratchEB.clear();
1586 m_conductivityCell.clear();
1587 m_conductivityFace.clear();
1588 m_conductivityEB.clear();
1590 m_electricFieldParticle.clear();
1591 m_electricFieldFluid.clear();
1593 m_electricFieldParticle.clear();
1594 m_electricFieldFluid.clear();
1596 for (
int i = 0; i < numCdrSpecies; i++) {
1597 m_cdrMobilities[i].clear();
1598 m_cdrPhotoiProducts[i].clearParticles();
1601 for (
int i = 0; i < numItoSpecies; i++) {
1602 m_fluidGradPhiIto[i].clear();
1603 m_fluidPhiIto[i].clear();
1605 for (
int i = 0; i < numCdrSpecies; i++) {
1606 m_fluidGradPhiCDR[i].clear();
1609 for (
int i = 0; i < numItoSpecies; i++) {
1610 m_secondaryParticles[i].clearParticles();
1612 for (
int i = 0; i < numPhotonSpecies; i++) {
1613 m_secondaryPhotons[i].clearParticles();
1616 for (
int i = 0; i < numCdrSpecies; i++) {
1617 m_cdrFluxes[i].clear();
1618 m_cdrFluxesExtrap[i].clear();
1621 m_currentDensity.clear();
1624 m_particleItoPPC.clear();
1625 m_particleOldItoPPC.clear();
1627 if (numCdrSpecies > 0) {
1628 m_fluidCdrPPC.clear();
1629 m_fluidOldCdrPPC.clear();
1632 m_particleYPC.clear();
1636 m_ito->preRegrid(a_lmin, a_oldFinestLevel);
1637 m_cdr->preRegrid(a_lmin, a_oldFinestLevel);
1638 m_fieldSolver->preRegrid(a_lmin, a_oldFinestLevel);
1639 m_rte->preRegrid(a_lmin, a_oldFinestLevel);
1640 m_sigmaSolver->preRegrid(a_lmin, a_oldFinestLevel);
1643 template <
typename I,
typename C,
typename R,
typename F>
1647 CH_TIME(
"ItoKMCStepper::regrid");
1648 if (m_verbosity > 5) {
1649 pout() << m_name +
"::regrid" << endl;
1652 this->allocateInternals();
1654 m_ito->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
1655 m_cdr->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
1656 m_fieldSolver->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
1657 m_rte->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
1658 m_sigmaSolver->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
1660 if (m_regridSuperparticles) {
1661 m_ito->organizeParticlesByCell(ItoSolver::WhichContainer::Bulk);
1662 m_ito->makeSuperparticles(ItoSolver::WhichContainer::Bulk, m_particlesPerCell);
1663 m_ito->organizeParticlesByPatch(ItoSolver::WhichContainer::Bulk);
1667 m_ito->depositParticles();
1669 const bool converged = this->solvePoisson();
1671 const std::string err =
"ItoKMCStepper::regrid - Poisson solve did not converge after regrid!!!";
1673 if (m_abortOnFailure) {
1674 MayDay::Error(err.c_str());
1677 MayDay::Warning(err.c_str());
1681 this->computeDriftVelocities();
1682 this->computeDiffusionCoefficients();
1685 template <
typename I,
typename C,
typename R,
typename F>
1689 CH_TIME(
"ItoKMCStepper::postRegrid");
1691 if (m_loadBalanceParticles) {
1692 for (
int i = 0; i < m_loadBalancePPC.size(); i++) {
1693 m_amr->deallocate(m_loadBalancePPC[i]);
1698 template <
typename I,
typename C,
typename R,
typename F>
1702 CH_TIME(
"ItoKMCStepper::setVoltage");
1703 if (m_verbosity > 5) {
1704 pout() << m_name +
"::setVoltage" << endl;
1707 m_voltage = a_voltage;
1710 template <
typename I,
typename C,
typename R,
typename F>
1714 CH_TIME(
"ItoKMCStepper::computeMaxElectricField");
1715 if (m_verbosity > 5) {
1716 pout() << m_name +
"::computeMaxElectricField" << endl;
1720 const EBAMRCellData cellCenteredE = m_amr->alias(a_phase, m_fieldSolver->getElectricField());
1724 m_amr->allocate(centroidCenteredE, m_fluidRealm, a_phase, SpaceDim);
1728 m_amr->interpToCentroids(centroidCenteredE, m_fluidRealm, m_plasmaPhase);
1738 template <
typename I,
typename C,
typename R,
typename F>
1741 const phase::which_phase a_phase)
const noexcept
1743 CH_TIME(
"ItoKMCStepper::computeElectricField(EBAMRCellData, phase)");
1744 if (m_verbosity > 5) {
1745 pout() << m_name +
"::computeElectricField(EBAMRCellData, phase)" << endl;
1748 CH_assert(a_electricField.getRealm() == m_fluidRealm);
1750 m_fieldSolver->computeElectricField(a_electricField, a_phase, m_fieldSolver->getPotential());
1753 template <
typename I,
typename C,
typename R,
typename F>
1757 CH_TIME(
"ItoKMCStepper::getTime");
1758 if (m_verbosity > 5) {
1759 pout() << m_name +
"::getTime" << endl;
1765 template <
typename I,
typename C,
typename R,
typename F>
1769 CH_TIME(
"ItoKMCStepper::computeSpaceChargeDensity()");
1770 if (m_verbosity > 5) {
1771 pout() << m_name +
"::computeSpaceChargeDensity()" << endl;
1774 this->computeSpaceChargeDensity(m_fieldSolver->getRho(), m_ito->getDensities(), m_cdr->getPhis());
1777 template <
typename I,
typename C,
typename R,
typename F>
1780 const Vector<EBAMRCellData*>& a_itoDensities,
1781 const Vector<EBAMRCellData*>& a_cdrDensities) noexcept
1783 CH_TIME(
"ItoKMCStepper::computeSpaceChargeDensity(rho, densities)");
1784 if (m_verbosity > 5) {
1785 pout() << m_name +
"::computeSpaceChargeDensity(rho, densities)" << endl;
1788 CH_assert(a_rho.getRealm() == m_fluidRealm);
1789 CH_assert(a_itoDensities[0]->getRealm() == m_particleRealm);
1790 CH_assert(a_cdrDensities[0]->getRealm() == m_fluidRealm);
1797 EBAMRCellData rhoPhase = m_amr->alias(m_plasmaPhase, a_rho);
1799 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
1800 const RefCountedPtr<ItoSolver>& solver = solverIt();
1801 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
1802 const int idx = solverIt.index();
1803 const int Z = species->getChargeNumber();
1806 m_amr->copyData(m_fluidScratch1, *a_itoDensities[idx]);
1812 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
1813 const RefCountedPtr<CdrSolver>& solver = solverIt();
1814 const RefCountedPtr<CdrSpecies>& species = solver->getSpecies();
1815 const int idx = solverIt.index();
1816 const int Z = species->getChargeNumber();
1825 m_amr->arithmeticAverage(a_rho, m_fluidRealm);
1826 m_amr->interpGhostPwl(a_rho, m_fluidRealm);
1829 m_amr->interpToCentroids(rhoPhase, m_fluidRealm, m_plasmaPhase);
1832 template <
typename I,
typename C,
typename R,
typename F>
1836 CH_TIME(
"ItoKMCStepper::computeConductivityCell(EBAMRCellData)");
1837 if (m_verbosity > 5) {
1838 pout() << m_name +
"::computeConductivityCell(EBAMRCellData)" << endl;
1841 this->computeConductivityCell(a_conductivity, m_ito->getParticles(ItoSolver::WhichContainer::Bulk));
1844 template <
typename I,
typename C,
typename R,
typename F>
1849 CH_TIME(
"ItoKMCStepper::computeConductivityCell(EBAMRCellData, Particles)");
1850 if (m_verbosity > 5) {
1851 pout() << m_name +
"::computeConductivityCell(EBAMRCellData, Particles)" << endl;
1857 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
1858 RefCountedPtr<ItoSolver>& solver = solverIt();
1859 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
1861 const int idx = solverIt.index();
1862 const int Z = species->getChargeNumber();
1864 if (Z != 0 && solver->isMobile()) {
1865 solver->depositConductivity(m_particleScratch1, *a_particles[idx]);
1868 m_amr->copyData(m_fluidScratch1, m_particleScratch1);
1869 DataOps::incr(a_conductivity, m_fluidScratch1, 1.0 * std::abs(Z));
1874 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
1875 const RefCountedPtr<CdrSolver>& solver = solverIt();
1876 const RefCountedPtr<CdrSpecies>& species = solver->getSpecies();
1878 const int idx = solverIt.index();
1879 const int Z = species->getChargeNumber();
1881 if (Z != 0 && solver->isMobile()) {
1887 DataOps::incr(a_conductivity, m_fluidScratch1, 1.0 * std::abs(Z));
1893 m_amr->arithmeticAverage(a_conductivity, m_fluidRealm, m_plasmaPhase);
1894 m_amr->interpGhostPwl(a_conductivity, m_fluidRealm, m_plasmaPhase);
1897 m_amr->interpToCentroids(a_conductivity, m_fluidRealm, m_plasmaPhase);
1900 template <
typename I,
typename C,
typename R,
typename F>
1904 CH_TIME(
"ItoKMCStepper::computeDensityGradients()");
1905 if (m_verbosity > 5) {
1906 pout() << m_name +
"::computeDensityGradients()" << endl;
1910 for (
auto it = m_ito->iterator(); it.ok(); ++it) {
1911 const RefCountedPtr<ItoSolver>& solver = it();
1913 const int idx = it.index();
1916 m_amr->copyData(m_fluidPhiIto[idx], solver->getPhi());
1918 m_amr->arithmeticAverage(m_fluidPhiIto[idx], m_fluidRealm, m_plasmaPhase);
1919 m_amr->interpGhostPwl(m_fluidPhiIto[idx], m_fluidRealm, m_plasmaPhase);
1921 m_amr->computeGradient(m_fluidGradPhiIto[idx], m_fluidPhiIto[idx], m_fluidRealm, m_plasmaPhase);
1925 for (
auto it = m_cdr->iterator(); it.ok(); ++it) {
1926 const RefCountedPtr<CdrSolver>& solver = it();
1928 const int idx = it.index();
1931 m_amr->copyData(m_fluidScratch1, solver->getPhi());
1933 m_amr->arithmeticAverage(m_fluidScratch1, m_fluidRealm, m_plasmaPhase);
1934 m_amr->interpGhostPwl(m_fluidScratch1, m_fluidRealm, m_plasmaPhase);
1936 m_amr->computeGradient(m_fluidGradPhiCDR[idx], m_fluidScratch1, m_fluidRealm, m_plasmaPhase);
1940 template <
typename I,
typename C,
typename R,
typename F>
1944 CH_TIME(
"ItoKMCStepper::computeCurrentDensity(EBAMRCellData)");
1945 if (m_verbosity > 5) {
1946 pout() << m_name +
"::computeCurrentDensity(EBAMRCellData)" << endl;
1949 CH_assert(a_J[0]->nComp() == SpaceDim);
1954 this->computeConductivityCell(m_fluidScratch1);
1960 template <
typename I,
typename C,
typename R,
typename F>
1964 CH_TIME(
"ItoKMCStepper::computeRelaxationTime()");
1965 if (m_verbosity > 5) {
1966 pout() << m_name +
"::computeRelaxationTime()" << endl;
1974 m_amr->allocate(conductivity, m_fluidRealm, m_plasmaPhase, 1);
1975 m_amr->allocate(relaxTime, m_fluidRealm, m_plasmaPhase, 1);
1977 this->computeConductivityCell(conductivity);
1982 m_amr->conservativeAverage(relaxTime, m_fluidRealm, m_plasmaPhase);
1992 template <
typename I,
typename C,
typename R,
typename F>
1996 CH_TIME(
"ItoKMCStepper::solvePoisson()");
1997 if (m_verbosity > 5) {
1998 pout() << m_name +
"::solvePoisson()" << endl;
2006 const bool converged = m_fieldSolver->solve(phi, rho, sigma,
false);
2008 m_fieldSolver->computeElectricField();
2013 m_amr->allocatePointer(E, m_fluidRealm);
2014 m_amr->alias(E, m_plasmaPhase, m_fieldSolver->getElectricField());
2017 m_amr->copyData(m_electricFieldFluid, E);
2018 m_amr->conservativeAverage(m_electricFieldFluid, m_fluidRealm, m_plasmaPhase);
2019 m_amr->interpGhostPwl(m_electricFieldFluid, m_fluidRealm, m_plasmaPhase);
2020 m_amr->interpToCentroids(m_electricFieldFluid, m_fluidRealm, m_plasmaPhase);
2023 m_amr->copyData(m_electricFieldParticle, E);
2024 m_amr->conservativeAverage(m_electricFieldParticle, m_particleRealm, m_plasmaPhase);
2025 m_amr->interpGhostPwl(m_electricFieldParticle, m_particleRealm, m_plasmaPhase);
2026 m_amr->interpToCentroids(m_electricFieldParticle, m_particleRealm, m_plasmaPhase);
2031 template <
typename I,
typename C,
typename R,
typename F>
2034 const bool a_delete,
2035 const std::function<
void(
ItoParticle&)> a_nonDeletionModifier) noexcept
2037 CH_TIME(
"ItoKMCStepper::intersectParticles(SpeciesSubset, bool, std::function)");
2038 if (m_verbosity > 5) {
2039 pout() << m_name +
"::intersectParticles(SpeciesSubset, bool, std::function)" << endl;
2042 this->intersectParticles(a_speciesSubset,
2043 ItoSolver::WhichContainer::Bulk,
2044 ItoSolver::WhichContainer::EB,
2045 ItoSolver::WhichContainer::Domain,
2047 a_nonDeletionModifier);
2050 template <
typename I,
typename C,
typename R,
typename F>
2056 const bool a_delete,
2057 const std::function<
void(
ItoParticle&)> a_nonDeletionModifier) noexcept
2059 CH_TIME(
"ItoKMCStepper::intersectParticles(SpeciesSubset, Containerx3, bool, std::function)");
2060 if (m_verbosity > 5) {
2061 pout() << m_name +
"::intersectParticles(SpeciesSubset, Containerx3, bool, std::function)" << endl;
2064 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
2065 RefCountedPtr<ItoSolver>& solver = solverIt();
2066 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
2068 const bool mobile = solver->isMobile();
2069 const bool diffusive = solver->isDiffusive();
2070 const bool charged = (species->getChargeNumber() != 0);
2072 const EBIntersection intersectionAlgorithm = solver->getIntersectionAlgorithm();
2074 switch (a_speciesSubset) {
2075 case SpeciesSubset::All: {
2076 solver->intersectParticles(a_containerBulk,
2079 intersectionAlgorithm,
2081 a_nonDeletionModifier);
2085 case SpeciesSubset::AllMobile: {
2087 solver->intersectParticles(a_containerBulk,
2090 intersectionAlgorithm,
2092 a_nonDeletionModifier);
2097 case SpeciesSubset::AllDiffusive: {
2099 solver->intersectParticles(a_containerBulk,
2102 intersectionAlgorithm,
2104 a_nonDeletionModifier);
2109 case SpeciesSubset::AllMobileOrDiffusive: {
2110 if (mobile || diffusive) {
2111 solver->intersectParticles(a_containerBulk,
2114 intersectionAlgorithm,
2116 a_nonDeletionModifier);
2121 case SpeciesSubset::AllMobileAndDiffusive: {
2122 if (mobile && diffusive) {
2123 solver->intersectParticles(a_containerBulk,
2126 intersectionAlgorithm,
2128 a_nonDeletionModifier);
2133 case SpeciesSubset::Charged: {
2135 solver->intersectParticles(a_containerBulk,
2138 intersectionAlgorithm,
2140 a_nonDeletionModifier);
2145 case SpeciesSubset::ChargedMobile: {
2146 if (charged && mobile) {
2147 solver->intersectParticles(a_containerBulk,
2150 intersectionAlgorithm,
2152 a_nonDeletionModifier);
2157 case SpeciesSubset::ChargedDiffusive: {
2158 if (charged && diffusive) {
2159 solver->intersectParticles(a_containerBulk,
2162 intersectionAlgorithm,
2164 a_nonDeletionModifier);
2169 case SpeciesSubset::ChargedMobileOrDiffusive: {
2170 if (charged && (mobile || diffusive)) {
2171 solver->intersectParticles(a_containerBulk,
2174 intersectionAlgorithm,
2176 a_nonDeletionModifier);
2181 case SpeciesSubset::ChargedMobileAndDiffusive: {
2182 if (charged && (mobile && diffusive)) {
2183 solver->intersectParticles(a_containerBulk,
2186 intersectionAlgorithm,
2188 a_nonDeletionModifier);
2193 case SpeciesSubset::Stationary: {
2194 if (!mobile && !diffusive) {
2195 solver->intersectParticles(a_containerBulk,
2198 intersectionAlgorithm,
2200 a_nonDeletionModifier);
2206 MayDay::Abort(
"ItoKMCStepper::intersectParticles - logic bust");
2214 template <
typename I,
typename C,
typename R,
typename F>
2218 const Real a_tolerance) noexcept
2220 CH_TIME(
"ItoKMCStepper::removeCoveredParticles(SpeciesSubset, EBRepresentation, Real)");
2221 if (m_verbosity > 5) {
2222 pout() << m_name +
"::removeCoveredParticles(SpeciesSubset, EBRepresentation, Real)" << endl;
2225 this->removeCoveredParticles(a_speciesSubset, ItoSolver::WhichContainer::Bulk, a_representation, a_tolerance);
2228 template <
typename I,
typename C,
typename R,
typename F>
2233 const Real a_tolerance) noexcept
2235 CH_TIME(
"ItoKMCStepper::removeCoveredParticles(SpeciesSubset, container, EBRepresentation, tolerance)");
2236 if (m_verbosity > 5) {
2237 pout() << m_name +
"::removeCoveredParticles(SpeciesSubset, container, EBRepresentation, tolerance)" << endl;
2240 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
2241 RefCountedPtr<ItoSolver>& solver = solverIt();
2242 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
2244 const bool mobile = solver->isMobile();
2245 const bool diffusive = solver->isDiffusive();
2246 const bool charged = (species->getChargeNumber() != 0);
2249 case SpeciesSubset::All: {
2250 solver->removeCoveredParticles(a_container, a_representation, a_tolerance);
2254 case SpeciesSubset::AllMobile: {
2256 solver->removeCoveredParticles(a_container, a_representation, a_tolerance);
2261 case SpeciesSubset::AllDiffusive: {
2263 solver->removeCoveredParticles(a_container, a_representation, a_tolerance);
2268 case SpeciesSubset::AllMobileOrDiffusive: {
2269 if (mobile || diffusive) {
2270 solver->removeCoveredParticles(a_container, a_representation, a_tolerance);
2275 case SpeciesSubset::AllMobileAndDiffusive: {
2276 if (mobile && diffusive) {
2277 solver->removeCoveredParticles(a_container, a_representation, a_tolerance);
2282 case SpeciesSubset::Charged: {
2284 solver->removeCoveredParticles(a_container, a_representation, a_tolerance);
2289 case SpeciesSubset::ChargedMobile: {
2290 if (charged && mobile) {
2291 solver->removeCoveredParticles(a_container, a_representation, a_tolerance);
2296 case SpeciesSubset::ChargedDiffusive: {
2297 if (charged && diffusive) {
2298 solver->removeCoveredParticles(a_container, a_representation, a_tolerance);
2303 case SpeciesSubset::ChargedMobileOrDiffusive: {
2304 if (charged && (mobile || diffusive)) {
2305 solver->removeCoveredParticles(a_container, a_representation, a_tolerance);
2310 case SpeciesSubset::ChargedMobileAndDiffusive: {
2311 if (charged && (mobile && diffusive)) {
2312 solver->removeCoveredParticles(a_container, a_representation, a_tolerance);
2317 case SpeciesSubset::Stationary: {
2318 if (!mobile && !diffusive) {
2319 solver->removeCoveredParticles(a_container, a_representation, a_tolerance);
2325 MayDay::Abort(
"ItoKMCStepper::removeCoveredParticles - logic bust");
2333 template <
typename I,
typename C,
typename R,
typename F>
2337 const Real a_tolerance) noexcept
2339 CH_TIME(
"ItoKMCStepper::transferCoveredParticles(SpeciesSubset, EBRepresentation, Real)");
2340 if (m_verbosity > 5) {
2341 pout() << m_name +
"::transferCoveredParticles(SpeciesSubset, EBRepresentation, Real)" << endl;
2344 this->transferCoveredParticles(a_speciesSubset,
2345 ItoSolver::WhichContainer::Bulk,
2346 ItoSolver::WhichContainer::Covered,
2351 template <
typename I,
typename C,
typename R,
typename F>
2357 const Real a_tolerance) noexcept
2359 CH_TIME(
"ItoKMCStepper::transferCoveredParticles(SpeciesSubset, Containerx2, EBRepresentation, Real)");
2360 if (m_verbosity > 5) {
2361 pout() << m_name +
"::transferCoveredParticles(SpeciesSubset, Containerx2, EBRepresentation, Real)" << endl;
2364 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
2365 RefCountedPtr<ItoSolver>& solver = solverIt();
2366 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
2368 const bool mobile = solver->isMobile();
2369 const bool diffusive = solver->isDiffusive();
2370 const bool charged = (species->getChargeNumber() != 0);
2372 switch (a_speciesSubset) {
2373 case SpeciesSubset::All: {
2374 solver->transferCoveredParticles(a_containerFrom, a_containerTo, a_representation, a_tolerance);
2378 case SpeciesSubset::AllMobile: {
2380 solver->transferCoveredParticles(a_containerFrom, a_containerTo, a_representation, a_tolerance);
2385 case SpeciesSubset::AllDiffusive: {
2387 solver->transferCoveredParticles(a_containerFrom, a_containerTo, a_representation, a_tolerance);
2392 case SpeciesSubset::AllMobileOrDiffusive: {
2393 if (mobile || diffusive) {
2394 solver->transferCoveredParticles(a_containerFrom, a_containerTo, a_representation, a_tolerance);
2399 case SpeciesSubset::AllMobileAndDiffusive: {
2400 if (mobile && diffusive) {
2401 solver->transferCoveredParticles(a_containerFrom, a_containerTo, a_representation, a_tolerance);
2406 case SpeciesSubset::Charged: {
2408 solver->transferCoveredParticles(a_containerFrom, a_containerTo, a_representation, a_tolerance);
2413 case SpeciesSubset::ChargedMobile: {
2414 if (charged && mobile) {
2415 solver->transferCoveredParticles(a_containerFrom, a_containerTo, a_representation, a_tolerance);
2420 case SpeciesSubset::ChargedDiffusive: {
2421 if (charged && diffusive) {
2422 solver->transferCoveredParticles(a_containerFrom, a_containerTo, a_representation, a_tolerance);
2427 case SpeciesSubset::ChargedMobileOrDiffusive: {
2428 if (charged && (mobile || diffusive)) {
2429 solver->transferCoveredParticles(a_containerFrom, a_containerTo, a_representation, a_tolerance);
2434 case SpeciesSubset::ChargedMobileAndDiffusive: {
2435 if (charged && (mobile && diffusive)) {
2436 solver->transferCoveredParticles(a_containerFrom, a_containerTo, a_representation, a_tolerance);
2441 case SpeciesSubset::Stationary: {
2442 if (!mobile && !diffusive) {
2443 solver->transferCoveredParticles(a_containerFrom, a_containerTo, a_representation, a_tolerance);
2449 MayDay::Abort(
"ItoKMCStepper::transferCoveredParticles - logic bust");
2457 template <
typename I,
typename C,
typename R,
typename F>
2461 CH_TIME(
"ItoKMCStepper::remapParticles(SpeciesSubset)");
2462 if (m_verbosity > 5) {
2463 pout() << m_name +
"::remapParticles(SpeciesSubset)" << endl;
2466 this->remapParticles(a_speciesSubset, ItoSolver::WhichContainer::Bulk);
2469 template <
typename I,
typename C,
typename R,
typename F>
2474 CH_TIME(
"ItoKMCStepper::remapParticles(SpeciesSubset, WhichContainer)");
2475 if (m_verbosity > 5) {
2476 pout() << m_name +
"::remapParticles(SpeciesSubset, WhichContainer)" << endl;
2479 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
2480 RefCountedPtr<ItoSolver>& solver = solverIt();
2481 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
2483 const bool mobile = solver->isMobile();
2484 const bool diffusive = solver->isDiffusive();
2485 const bool charged = (species->getChargeNumber() != 0);
2487 switch (a_speciesSubset) {
2488 case SpeciesSubset::All: {
2489 solver->remap(a_container);
2493 case SpeciesSubset::AllMobile: {
2495 solver->remap(a_container);
2500 case SpeciesSubset::AllDiffusive: {
2502 solver->remap(a_container);
2507 case SpeciesSubset::AllMobileOrDiffusive: {
2508 if (mobile || diffusive) {
2509 solver->remap(a_container);
2514 case SpeciesSubset::AllMobileAndDiffusive: {
2515 if (mobile && diffusive) {
2516 solver->remap(a_container);
2521 case SpeciesSubset::Charged: {
2523 solver->remap(a_container);
2528 case SpeciesSubset::ChargedMobile: {
2529 if (charged && mobile) {
2530 solver->remap(a_container);
2535 case SpeciesSubset::ChargedDiffusive: {
2536 if (charged && diffusive) {
2537 solver->remap(a_container);
2542 case SpeciesSubset::ChargedMobileOrDiffusive: {
2543 if (charged && (mobile || diffusive)) {
2544 solver->remap(a_container);
2549 case SpeciesSubset::ChargedMobileAndDiffusive: {
2550 if (charged && (mobile && diffusive)) {
2551 solver->remap(a_container);
2556 case SpeciesSubset::Stationary: {
2557 if (!mobile && !diffusive) {
2558 solver->remap(a_container);
2564 MayDay::Abort(
"ItoKMCStepper::remapParticles - logic bust");
2572 template <
typename I,
typename C,
typename R,
typename F>
2576 CH_TIME(
"ItoKMCStepper::depositParticles(SpeciesSubset)");
2577 if (m_verbosity > 5) {
2578 pout() << m_name +
"::depositParticles(SpeciesSubset)" << endl;
2581 this->depositParticles(a_speciesSubset, ItoSolver::WhichContainer::Bulk);
2584 template <
typename I,
typename C,
typename R,
typename F>
2589 CH_TIME(
"ItoKMCStepper::depositParticles(SpeciesSubset)");
2590 if (m_verbosity > 5) {
2591 pout() << m_name +
"::depositParticles(SpeciesSubset)" << endl;
2594 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
2595 RefCountedPtr<ItoSolver>& solver = solverIt();
2596 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
2598 const bool mobile = solver->isMobile();
2599 const bool diffusive = solver->isDiffusive();
2600 const bool charged = (species->getChargeNumber() != 0);
2602 switch (a_speciesSubset) {
2603 case SpeciesSubset::All: {
2604 solver->depositParticles(a_container);
2608 case SpeciesSubset::AllMobile: {
2610 solver->depositParticles(a_container);
2615 case SpeciesSubset::AllDiffusive: {
2617 solver->depositParticles(a_container);
2622 case SpeciesSubset::AllMobileOrDiffusive: {
2623 if (mobile || diffusive) {
2624 solver->depositParticles(a_container);
2629 case SpeciesSubset::AllMobileAndDiffusive: {
2630 if (mobile && diffusive) {
2631 solver->depositParticles(a_container);
2636 case SpeciesSubset::Charged: {
2638 solver->depositParticles(a_container);
2643 case SpeciesSubset::ChargedMobile: {
2644 if (charged && mobile) {
2645 solver->depositParticles(a_container);
2650 case SpeciesSubset::ChargedDiffusive: {
2651 if (charged && diffusive) {
2652 solver->depositParticles(a_container);
2657 case SpeciesSubset::ChargedMobileOrDiffusive: {
2658 if (charged && (mobile || diffusive)) {
2659 solver->depositParticles(a_container);
2664 case SpeciesSubset::ChargedMobileAndDiffusive: {
2665 if (charged && (mobile && diffusive)) {
2666 solver->depositParticles(a_container);
2671 case SpeciesSubset::Stationary: {
2672 if (!mobile && !diffusive) {
2673 solver->depositParticles(a_container);
2679 MayDay::Abort(
"ItoKMCStepper::depositParticles - logic bust");
2687 template <
typename I,
typename C,
typename R,
typename F>
2691 CH_TIME(
"ItoKMCStepper::setItoVelocityFunctions");
2692 if (m_verbosity > 5) {
2693 pout() << m_name +
"::setItoVelocityFunctions" << endl;
2696 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
2697 RefCountedPtr<ItoSolver>& solver = solverIt();
2698 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
2699 const int Z = species->getChargeNumber();
2701 if (solver->isMobile() && Z != 0) {
2702 EBAMRCellData& velocityFunction = solver->getVelocityFunction();
2703 m_amr->copyData(velocityFunction, m_electricFieldParticle);
2705 const int Z = species->getChargeNumber();
2712 m_amr->conservativeAverage(velocityFunction, m_particleRealm, m_plasmaPhase);
2713 m_amr->interpGhostPwl(velocityFunction, m_particleRealm, m_plasmaPhase);
2718 template <
typename I,
typename C,
typename R,
typename F>
2722 CH_TIME(
"ItoKMCStepper::setCdrVelocityFunctions");
2723 if (m_verbosity > 5) {
2724 pout() << m_name +
"::setCdrVelocityFunctions" << endl;
2727 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
2728 RefCountedPtr<CdrSolver>& solver = solverIt();
2729 const RefCountedPtr<CdrSpecies>& species = solver->getSpecies();
2730 const int Z = species->getChargeNumber();
2732 if (solver->isMobile() && Z != 0) {
2733 EBAMRCellData& velocity = solver->getCellCenteredVelocity();
2734 m_amr->copyData(velocity, m_electricFieldFluid);
2736 const int Z = species->getChargeNumber();
2743 m_amr->conservativeAverage(velocity, m_fluidRealm, m_plasmaPhase);
2744 m_amr->interpGhostPwl(velocity, m_fluidRealm, m_plasmaPhase);
2746 else if (solver->isMobile() && Z == 0) {
2747 MayDay::Warning(
"ItoKMCStepper::setCdrVelocityFunctions -- how to handle mobile neutral species?");
2752 template <
typename I,
typename C,
typename R,
typename F>
2756 CH_TIME(
"ItoKMCStepper::multiplyCdrVelocitiesByMobilities()");
2757 if (m_verbosity > 5) {
2758 pout() << m_name +
"::multiplyCdrVelocitiesByMobilities()" << endl;
2761 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
2762 RefCountedPtr<CdrSolver>& solver = solverIt();
2763 const int idx = solverIt.index();
2765 if (solver->isMobile()) {
2766 EBAMRCellData& velocity = solver->getCellCenteredVelocity();
2772 m_amr->conservativeAverage(velocity, m_fluidRealm, m_plasmaPhase);
2773 m_amr->interpGhostPwl(velocity, m_fluidRealm, m_plasmaPhase);
2778 template <
typename I,
typename C,
typename R,
typename F>
2782 CH_TIME(
"ItoKMCStepper::computeDriftVelocities()");
2783 if (m_verbosity > 5) {
2784 pout() << m_name +
"::computeDriftVelocities()" << endl;
2788 this->setItoVelocityFunctions();
2789 this->setCdrVelocityFunctions();
2792 this->computeMobilities();
2796 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
2797 solverIt()->interpolateVelocities();
2800 this->multiplyCdrVelocitiesByMobilities();
2803 template <
typename I,
typename C,
typename R,
typename F>
2807 CH_TIME(
"ItoKMCStepper::computeMobilities()");
2808 if (m_verbosity > 5) {
2809 pout() << m_name +
"::computeMobilities()" << endl;
2812 Vector<EBAMRCellData*> itoMobilities = m_ito->getMobilityFunctions();
2814 this->computeMobilities(itoMobilities, m_cdrMobilities, m_electricFieldFluid, m_time);
2817 template <
typename I,
typename C,
typename R,
typename F>
2820 Vector<EBAMRCellData>& a_cdrMobilities,
2822 const Real a_time) noexcept
2824 CH_TIME(
"ItoKMCStepper::computeMobilities(mobilities, E, time)");
2825 if (m_verbosity > 5) {
2826 pout() << m_name +
"::computeMobilities(mobilities, E, time)" << endl;
2829 const int numItoSpecies = m_physics->getNumItoSpecies();
2830 const int numCdrSpecies = m_physics->getNumCdrSpecies();
2832 CH_assert(a_electricField.getRealm() == m_fluidRealm);
2833 CH_assert(a_itoMobilities.size() == numItoSpecies);
2834 CH_assert(a_cdrMobilities.size() == numCdrSpecies);
2838 Vector<EBAMRCellData> fluidScratchMobilities(numItoSpecies);
2839 for (
int i = 0; i < numItoSpecies; i++) {
2840 m_amr->allocate(fluidScratchMobilities[i], m_fluidRealm, m_plasmaPhase, 1);
2845 CH_assert(a_itoMobilities[i]->getRealm() == m_particleRealm);
2849 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
2850 Vector<LevelData<EBCellFAB>*> itoMobilities(numItoSpecies);
2851 Vector<LevelData<EBCellFAB>*> cdrMobilities(numCdrSpecies);
2853 for (
int i = 0; i < numItoSpecies; i++) {
2854 itoMobilities[i] = &(*(fluidScratchMobilities[i])[lvl]);
2857 for (
int i = 0; i < numCdrSpecies; i++) {
2858 cdrMobilities[i] = &(*(a_cdrMobilities[i])[lvl]);
2862 this->computeMobilities(itoMobilities, cdrMobilities, *a_electricField[lvl], lvl, a_time);
2866 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
2867 RefCountedPtr<ItoSolver>& solver = solverIt();
2869 if (solver->isMobile()) {
2870 const int idx = solverIt.index();
2872 m_amr->copyData(*a_itoMobilities[idx], fluidScratchMobilities[idx]);
2873 m_amr->conservativeAverage(*a_itoMobilities[idx], m_particleRealm, m_plasmaPhase);
2874 m_amr->interpGhostPwl(*a_itoMobilities[idx], m_particleRealm, m_plasmaPhase);
2876 solver->interpolateMobilities();
2881 template <
typename I,
typename C,
typename R,
typename F>
2884 Vector<LevelData<EBCellFAB>*>& a_cdrMobilities,
2885 const LevelData<EBCellFAB>& a_electricField,
2887 const Real a_time) noexcept
2889 CH_TIME(
"ItoKMCStepper::computeMobilities(mobilities, E, level, time)");
2890 if (m_verbosity > 5) {
2891 pout() << m_name +
"::computeMobilities(mobilities, E, level, time)" << endl;
2894 const DisjointBoxLayout& dbl = m_amr->getGrids(m_fluidRealm)[a_level];
2895 const DataIterator& dit = dbl.dataIterator();
2897 const int nbox = dit.size();
2899 #pragma omp parallel for schedule(runtime)
2900 for (
int mybox = 0; mybox < nbox; mybox++) {
2901 const DataIndex& din = dit[mybox];
2903 const EBCellFAB& E = a_electricField[din];
2904 const Box cellBox = dbl[din];
2906 Vector<EBCellFAB*> itoMobilities;
2907 Vector<EBCellFAB*> cdrMobilities;
2909 for (
int i = 0; i < a_itoMobilities.size(); i++) {
2910 itoMobilities.
push_back(&((*a_itoMobilities[i])[din]));
2913 for (
int i = 0; i < a_cdrMobilities.size(); i++) {
2914 cdrMobilities.push_back(&((*a_cdrMobilities[i])[din]));
2917 this->computeMobilities(itoMobilities, cdrMobilities, E, a_level, din, cellBox, a_time);
2921 template <
typename I,
typename C,
typename R,
typename F>
2924 Vector<EBCellFAB*>& a_cdrMobilities,
2925 const EBCellFAB& a_electricField,
2927 const DataIndex a_dit,
2929 const Real a_time) noexcept
2931 CH_TIME(
"ItoKMCStepper::computeMobilities(meshMobilities, E, level, dit, box, time)");
2932 if (m_verbosity > 5) {
2933 pout() << m_name +
"::computeMobilities(meshMobilities, E, level, dit, box, time)" << endl;
2938 const int numItoSpecies = m_physics->getNumItoSpecies();
2939 const int numCdrSpecies = m_physics->getNumCdrSpecies();
2940 const int numPlasmaSpecies = m_physics->getNumPlasmaSpecies();
2942 const Real dx = m_amr->getDx()[a_level];
2943 const RealVect probLo = m_amr->getProbLo();
2944 const EBISBox& ebisbox = m_amr->getEBISLayout(m_fluidRealm, m_plasmaPhase)[a_level][a_dit];
2947 const FArrayBox& electricFieldReg = a_electricField.getFArrayBox();
2948 Vector<FArrayBox*> itoMobilitiesReg(numItoSpecies);
2949 Vector<FArrayBox*> cdrMobilitiesReg(numCdrSpecies);
2951 for (
int i = 0; i < a_itoMobilities.size(); i++) {
2952 itoMobilitiesReg[i] = (&(a_itoMobilities[i]->getFArrayBox()));
2955 for (
int i = 0; i < a_cdrMobilities.size(); i++) {
2956 cdrMobilitiesReg[i] = (&(a_cdrMobilities[i]->getFArrayBox()));
2960 const std::map<int, std::pair<SpeciesType, int>>& speciesMap = m_physics->getSpeciesMap();
2963 auto regularKernel = [&](
const IntVect& iv) ->
void {
2964 const RealVect pos = m_amr->getProbLo() + dx * (RealVect(iv) + 0.5 * RealVect::Unit);
2965 const RealVect E = RealVect(D_DECL(electricFieldReg(iv, 0), electricFieldReg(iv, 1), electricFieldReg(iv, 2)));
2968 const Vector<Real> mobilities = m_physics->computeMobilities(a_time, pos, E);
2970 CH_assert(mobilities.size() == numPlasmaSpecies);
2973 for (
const auto& s : speciesMap) {
2974 const int& globalIndex = s.first;
2976 const int& localIndex = s.second.second;
2978 if (type == SpeciesType::Ito) {
2979 (*itoMobilitiesReg[localIndex])(iv, 0) = mobilities[globalIndex];
2981 else if (type == SpeciesType::CDR) {
2982 (*cdrMobilitiesReg[localIndex])(iv, 0) = mobilities[globalIndex];
2988 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
2989 const RealVect e = RealVect(D_DECL(a_electricField(vof, 0), a_electricField(vof, 1), a_electricField(vof, 2)));
2990 const RealVect pos = probLo +
Location::position(Location::Cell::Centroid, vof, ebisbox, dx);
2993 const Vector<Real> mobilities = m_physics->computeMobilities(a_time, pos, e);
2995 CH_assert(mobilities.size() == numPlasmaSpecies);
2998 for (
const auto& s : speciesMap) {
2999 const int& globalIndex = s.first;
3001 const int& localIndex = s.second.second;
3003 if (type == SpeciesType::Ito) {
3004 (*a_itoMobilities[localIndex])(vof, 0) = mobilities[globalIndex];
3006 else if (type == SpeciesType::CDR) {
3007 (*a_cdrMobilities[localIndex])(vof, 0) = mobilities[globalIndex];
3012 VoFIterator& vofit = (*m_amr->getVofIterator(m_fluidRealm, m_plasmaPhase)[a_level])[a_dit];
3019 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
3020 a_itoMobilities[solverIt.index()]->setCoveredCellVal(0.0, 0);
3023 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
3024 a_cdrMobilities[solverIt.index()]->setCoveredCellVal(0.0, 0);
3028 template <
typename I,
typename C,
typename R,
typename F>
3032 CH_TIME(
"ItoKMCStepper::computeDiffusionCoefficients()");
3033 if (m_verbosity > 5) {
3034 pout() << m_name +
"::computeDiffusionCoefficients()" << endl;
3037 Vector<EBAMRCellData*> itoDiffusionCoefficients = m_ito->getDiffusionFunctions();
3038 Vector<EBAMRCellData*> cdrDiffusionCoefficients = m_cdr->getCellCenteredDiffusionCoefficients();
3040 this->computeDiffusionCoefficients(itoDiffusionCoefficients, cdrDiffusionCoefficients, m_electricFieldFluid, m_time);
3041 this->averageDiffusionCoefficientsCellToFace();
3044 template <
typename I,
typename C,
typename R,
typename F>
3047 Vector<EBAMRCellData*>& a_cdrDiffusionCoefficients,
3049 const Real a_time) noexcept
3051 CH_TIME(
"ItoKMCStepper::computeDiffusionCoefficients(Vector<EBAMRCellData*>, EBAMRCellData, Real)");
3052 if (m_verbosity > 5) {
3053 pout() << m_name +
"::computeDiffusionCoefficients(Vector<EBAMRCellData*>, EBAMRCellData, Real)" << endl;
3056 const int numItoSpecies = m_physics->getNumItoSpecies();
3057 const int numCdrSpecies = m_physics->getNumCdrSpecies();
3059 CH_assert(a_electricField.getRealm() == m_fluidRealm);
3060 CH_assert(a_itoDiffusionCoefficients.size() == numItoSpecies);
3061 CH_assert(a_cdrDiffusionCoefficients.size() == numCdrSpecies);
3064 for (
int i = 0; i < numItoSpecies; i++) {
3065 CH_assert(a_itoDiffusionCoefficients[i]->getRealm() == m_particleRealm);
3067 for (
int i = 0; i < numCdrSpecies; i++) {
3068 CH_assert(a_cdrDiffusionCoefficients[i]->getRealm() == m_fluidRealm);
3073 Vector<EBAMRCellData> fluidScratchDiffusion(numItoSpecies);
3074 for (
int i = 0; i < numItoSpecies; i++) {
3075 m_amr->allocate(fluidScratchDiffusion[i], m_fluidRealm, m_plasmaPhase, 1);
3077 CH_assert(a_itoDiffusionCoefficients[i]->getRealm() == m_particleRealm);
3081 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3082 Vector<LevelData<EBCellFAB>*> itoDiffusionCoefficients(numItoSpecies);
3083 Vector<LevelData<EBCellFAB>*> cdrDiffusionCoefficients(numCdrSpecies);
3085 for (
int i = 0; i < numItoSpecies; i++) {
3086 itoDiffusionCoefficients[i] = &(*(fluidScratchDiffusion[i])[lvl]);
3088 for (
int i = 0; i < numCdrSpecies; i++) {
3089 cdrDiffusionCoefficients[i] = &(*(*a_cdrDiffusionCoefficients[i])[lvl]);
3092 this->computeDiffusionCoefficients(itoDiffusionCoefficients,
3093 cdrDiffusionCoefficients,
3094 *a_electricField[lvl],
3101 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
3102 RefCountedPtr<ItoSolver>& solver = solverIt();
3104 if (solver->isDiffusive()) {
3105 const int idx = solverIt.index();
3107 m_amr->copyData(*a_itoDiffusionCoefficients[idx], fluidScratchDiffusion[idx]);
3108 m_amr->conservativeAverage(*a_itoDiffusionCoefficients[idx], m_particleRealm, m_plasmaPhase);
3109 m_amr->interpGhostPwl(*a_itoDiffusionCoefficients[idx], m_particleRealm, m_plasmaPhase);
3111 solver->interpolateDiffusion();
3116 template <
typename I,
typename C,
typename R,
typename F>
3119 Vector<LevelData<EBCellFAB>*>& a_cdrDiffusionCoefficients,
3120 const LevelData<EBCellFAB>& a_electricField,
3122 const Real a_time) noexcept
3124 CH_TIME(
"ItoKMCStepper::computeDiffusionCoefficients(Vector<LD<EBCellFAB>*>, LD<EBCellFAB>, int, Real)");
3125 if (m_verbosity > 5) {
3126 pout() << m_name +
"::computeDiffusionCoefficients(Vector<LD<EBCellFAB>*>, LD<EBCellFAB>, int, Real)" << endl;
3129 const int numItoSpecies = m_physics->getNumItoSpecies();
3130 const int numCdrSpecies = m_physics->getNumCdrSpecies();
3132 CH_assert(a_itoDiffusionCoefficients.size() == numItoSpecies);
3133 CH_assert(a_cdrDiffusionCoefficients.size() == numCdrSpecies);
3135 const DisjointBoxLayout& dbl = m_amr->getGrids(m_fluidRealm)[a_level];
3136 const DataIterator& dit = dbl.dataIterator();
3138 const int nbox = dit.size();
3140 #pragma omp parallel for schedule(runtime)
3141 for (
int mybox = 0; mybox < nbox; mybox++) {
3142 const DataIndex& din = dit[mybox];
3144 Vector<EBCellFAB*> itoDiffusionCoefficients(numItoSpecies);
3145 Vector<EBCellFAB*> cdrDiffusionCoefficients(numCdrSpecies);
3147 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
3148 const int idx = solverIt.index();
3150 if (solverIt()->isDiffusive()) {
3151 itoDiffusionCoefficients[idx] = &(*a_itoDiffusionCoefficients[idx])[din];
3154 itoDiffusionCoefficients[idx] =
nullptr;
3158 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
3159 const int idx = solverIt.index();
3161 if (solverIt()->isDiffusive()) {
3162 cdrDiffusionCoefficients[idx] = &(*a_cdrDiffusionCoefficients[idx])[din];
3165 cdrDiffusionCoefficients[idx] =
nullptr;
3169 this->computeDiffusionCoefficients(itoDiffusionCoefficients,
3170 cdrDiffusionCoefficients,
3171 a_electricField[din],
3179 template <
typename I,
typename C,
typename R,
typename F>
3182 Vector<EBCellFAB*>& a_cdrDiffusionCoefficients,
3183 const EBCellFAB& a_electricField,
3185 const DataIndex a_dit,
3187 const Real a_time) noexcept
3189 CH_TIME(
"ItoKMCStepper::computeDiffusionCoefficients(Patch)");
3190 if (m_verbosity > 5) {
3191 pout() << m_name +
"::computeDiffusionCoefficients(Patch)" << endl;
3194 const int numItoSpecies = m_physics->getNumItoSpecies();
3195 const int numCdrSpecies = m_physics->getNumCdrSpecies();
3196 const int numPlasmaSpecies = m_physics->getNumPlasmaSpecies();
3198 CH_assert(a_electricField.nComp() == SpaceDim);
3199 CH_assert(a_itoDiffusionCoefficients.size() == numItoSpecies);
3200 CH_assert(a_cdrDiffusionCoefficients.size() == numCdrSpecies);
3203 const Real dx = m_amr->getDx()[a_level];
3204 const RealVect probLo = m_amr->getProbLo();
3205 const EBISBox& ebisbox = m_amr->getEBISLayout(m_fluidRealm, m_plasmaPhase)[a_level][a_dit];
3208 const FArrayBox& electricFieldReg = a_electricField.getFArrayBox();
3210 Vector<FArrayBox*> itoDiffCoReg(numItoSpecies,
nullptr);
3211 Vector<FArrayBox*> cdrDiffCoReg(numCdrSpecies,
nullptr);
3213 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
3214 RefCountedPtr<ItoSolver>& solver = solverIt();
3216 if (solver->isDiffusive()) {
3217 const int i = solverIt.index();
3218 itoDiffCoReg[i] = &(a_itoDiffusionCoefficients[i]->getFArrayBox());
3222 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
3223 RefCountedPtr<CdrSolver>& solver = solverIt();
3225 if (solver->isDiffusive()) {
3226 const int i = solverIt.index();
3227 cdrDiffCoReg[i] = &(a_cdrDiffusionCoefficients[i]->getFArrayBox());
3232 const std::map<int, std::pair<SpeciesType, int>>& speciesMap = m_physics->getSpeciesMap();
3235 auto regularKernel = [&](
const IntVect& iv) ->
void {
3236 const RealVect pos = probLo + dx * (RealVect(iv) + 0.5 * RealVect::Unit);
3237 const RealVect E = RealVect(D_DECL(electricFieldReg(iv, 0), electricFieldReg(iv, 1), electricFieldReg(iv, 2)));
3240 const Vector<Real> diffusionCoefficients = m_physics->computeDiffusionCoefficients(a_time, pos, E);
3242 CH_assert(diffusionCoefficients.size() == numPlasmaSpecies);
3245 for (
const auto& s : speciesMap) {
3246 const int& globalIndex = s.first;
3248 const int& localIndex = s.second.second;
3251 if (type == SpeciesType::Ito) {
3252 if (m_ito->getSolvers()[localIndex]->isDiffusive()) {
3253 (*itoDiffCoReg[localIndex])(iv, 0) = diffusionCoefficients[globalIndex];
3256 else if (type == SpeciesType::CDR) {
3257 if (m_cdr->getSolvers()[localIndex]->isDiffusive()) {
3258 (*cdrDiffCoReg[localIndex])(iv, 0) = diffusionCoefficients[globalIndex];
3265 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
3266 const RealVect E = RealVect(D_DECL(a_electricField(vof, 0), a_electricField(vof, 1), a_electricField(vof, 2)));
3267 const RealVect pos = probLo +
Location::position(Location::Cell::Centroid, vof, ebisbox, dx);
3270 const Vector<Real> diffusionCoefficients = m_physics->computeDiffusionCoefficients(a_time, pos, E);
3273 for (
const auto& s : speciesMap) {
3274 const int& globalIndex = s.first;
3276 const int& localIndex = s.second.second;
3279 if (type == SpeciesType::Ito) {
3280 if (m_ito->getSolvers()[localIndex]->isDiffusive()) {
3281 (*a_itoDiffusionCoefficients[localIndex])(vof, 0) = diffusionCoefficients[globalIndex];
3284 else if (type == SpeciesType::CDR) {
3285 if (m_cdr->getSolvers()[localIndex]->isDiffusive()) {
3286 (*a_cdrDiffusionCoefficients[localIndex])(vof, 0) = diffusionCoefficients[globalIndex];
3293 VoFIterator& vofit = (*m_amr->getVofIterator(m_fluidRealm, m_plasmaPhase)[a_level])[a_dit];
3299 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
3300 if (solverIt()->isDiffusive()) {
3301 a_itoDiffusionCoefficients[solverIt.index()]->setCoveredCellVal(0.0, 0);
3305 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
3306 if (solverIt()->isDiffusive()) {
3307 a_cdrDiffusionCoefficients[solverIt.index()]->setCoveredCellVal(0.0, 0);
3312 template <
typename I,
typename C,
typename R,
typename F>
3316 CH_TIME(
"ItoKMCStepper::averageDiffusionCoefficientsCellToFace");
3317 if (m_verbosity > 5) {
3318 pout() << m_name +
"::averageDiffusionCoefficientsCellToFace" << endl;
3321 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
3322 RefCountedPtr<CdrSolver>& solver = solverIt();
3324 if (solver->isDiffusive()) {
3326 EBAMRCellData& cellCenteredDiffusionCoefficient = solver->getCellCenteredDiffusionCoefficient();
3327 EBAMRFluxData& faceCenteredDiffusionCoefficient = solver->getFaceCenteredDiffusionCoefficient();
3329 CH_assert(cellCenteredDiffusionCoefficient.
getRealm() == m_fluidRealm);
3330 CH_assert(faceCenteredDiffusionCoefficient.
getRealm() == m_fluidRealm);
3335 m_amr->arithmeticAverage(cellCenteredDiffusionCoefficient, m_fluidRealm, m_cdr->getPhase());
3336 m_amr->interpGhostPwl(cellCenteredDiffusionCoefficient, m_fluidRealm, m_cdr->getPhase());
3339 const int tanGhost = 1;
3340 const Interval interv = Interval(0, 0);
3344 cellCenteredDiffusionCoefficient,
3345 m_amr->getDomains(),
3354 template <
typename I,
typename C,
typename R,
typename F>
3358 CH_TIME(
"ItoKMCStepper::getPhysicalParticlesPerCell(EBAMRCellData)");
3359 if (m_verbosity > 5) {
3360 pout() << m_name +
"::getPhysicaParticlesPerCell(EBAMRCellData)" << endl;
3363 CH_assert(a_ppc.getRealm() == m_particleRealm);
3365 for (
auto it = m_ito->iterator(); it.ok(); ++it) {
3366 const int idx = it.index();
3368 EBAMRCellData ppc = m_amr->slice(a_ppc, Interval(idx, idx));
3372 ParticleOps::getPhysicalParticlesPerCell<ItoParticle, &ItoParticle::weight>(ppc, particles);
3376 template <
typename I,
typename C,
typename R,
typename F>
3380 CH_TIME(
"ItoKMCStepper::computeReactiveItoParticlesPerCell(EBAMRCellData)");
3381 if (m_verbosity > 5) {
3382 pout() << m_name +
"::computeReactiveItoParticlesPerCell(EBAMRCellData)" << endl;
3385 CH_assert(a_ppc.getRealm() == m_particleRealm);
3389 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3390 this->computeReactiveItoParticlesPerCell(*a_ppc[lvl], lvl);
3394 template <
typename I,
typename C,
typename R,
typename F>
3398 CH_TIME(
"ItoKMCStepper::computeReactiveItoParticlesPerCell(LD<EBCellFAB>, int)");
3399 if (m_verbosity > 5) {
3400 pout() << m_name +
"::computeReactiveItoParticlesPerCell(LD<EBCellFAB>, int)" << endl;
3403 const int numItoSpecies = m_physics->getNumItoSpecies();
3405 CH_assert(a_ppc.nComp() == numItoSpecies);
3407 const DisjointBoxLayout& dbl = m_amr->getGrids(m_particleRealm)[a_level];
3408 const EBISLayout& ebisl = m_amr->getEBISLayout(m_particleRealm, m_plasmaPhase)[a_level];
3409 const DataIterator& dit = dbl.dataIterator();
3411 const int nbox = dit.size();
3413 #pragma omp parallel for schedule(runtime)
3414 for (
int mybox = 0; mybox < nbox; mybox++) {
3415 const DataIndex& din = dit[mybox];
3417 const Box box = dbl[din];
3418 const EBISBox& ebisbox = ebisl[din];
3420 this->computeReactiveItoParticlesPerCell(a_ppc[din], a_level, din, box, ebisbox);
3424 template <
typename I,
typename C,
typename R,
typename F>
3428 const DataIndex a_dit,
3430 const EBISBox& a_ebisbox) noexcept
3432 CH_TIME(
"ItoKMCStepper::computeReactiveItoParticlesPerCell(EBCellFAB, int, DataIndex, Box, EBISBox)");
3433 if (m_verbosity > 5) {
3434 pout() << m_name +
"::computeReactiveItoParticlesPerCell(EBCellFAB, int, DataIndex, Box, EBISBox)" << endl;
3437 const int numItoSpecies = m_physics->getNumItoSpecies();
3439 CH_assert(a_ppc.nComp() == numItoSpecies);
3441 const Real dx = m_amr->getDx()[a_level];
3442 const RealVect probLo = m_amr->getProbLo();
3446 FArrayBox& ppcRegular = a_ppc.getFArrayBox();
3448 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
3449 RefCountedPtr<ItoSolver>& solver = solverIt();
3450 const int idx = solverIt.index();
3455 const BinFab<ItoParticle>& cellParticles = particles.
getCellParticles(a_level, a_dit);
3458 auto regularKernel = [&](
const IntVect& iv) ->
void {
3461 if (a_ebisbox.isRegular(iv)) {
3462 for (ListIterator<ItoParticle> lit(cellParticles(iv, 0)); lit.ok(); ++lit) {
3463 num += lit().weight();
3467 ppcRegular(iv, idx) = num;
3471 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
3472 const IntVect iv = vof.gridIndex();
3473 const RealVect normal = a_ebisbox.normal(vof);
3474 const RealVect physCentroid = probLo +
Location::position(Location::Cell::Boundary, vof, a_ebisbox, dx);
3478 for (ListIterator<ItoParticle> lit(cellParticles(iv, 0)); lit.ok(); ++lit) {
3479 const RealVect& pos = lit().position();
3480 if ((pos - physCentroid).dotProduct(normal) >= 0.0) {
3481 num += lit().weight();
3485 ppcRegular(iv, idx) = num;
3489 VoFIterator& vofit = (*m_amr->getVofIterator(m_particleRealm, m_plasmaPhase)[a_level])[a_dit];
3496 template <
typename I,
typename C,
typename R,
typename F>
3500 CH_TIME(
"ItoKMCStepper::computeReactiveCdrParticlesPerCell(EBAMRCellData)");
3501 if (m_verbosity > 5) {
3502 pout() << m_name +
"::computeReactiveCdrParticlesPerCell(EBAMRCellData)" << endl;
3505 CH_assert(a_ppc.getRealm() == m_fluidRealm);
3509 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3510 this->computeReactiveCdrParticlesPerCell(*a_ppc[lvl], lvl);
3514 template <
typename I,
typename C,
typename R,
typename F>
3518 CH_TIME(
"ItoKMCStepper::computeReactiveCdrParticlesPerCell(LD<EBCellFAB>, int)");
3519 if (m_verbosity > 5) {
3520 pout() << m_name +
"::computeReactiveCdrParticlesPerCell(LD<EBCellFAB>, int)" << endl;
3523 const int numCdrSpecies = m_physics->getNumCdrSpecies();
3525 CH_assert(a_ppc.nComp() == numCdrSpecies);
3527 if (numCdrSpecies > 0) {
3528 const DisjointBoxLayout& dbl = m_amr->getGrids(m_fluidRealm)[a_level];
3529 const EBISLayout& ebisl = m_amr->getEBISLayout(m_fluidRealm, m_plasmaPhase)[a_level];
3530 const DataIterator& dit = dbl.dataIterator();
3532 const int nbox = dit.size();
3534 #pragma omp parallel for schedule(runtime)
3535 for (
int mybox = 0; mybox < nbox; mybox++) {
3536 const DataIndex& din = dit[mybox];
3538 const Box box = dbl[din];
3539 const EBISBox& ebisbox = ebisl[din];
3541 this->computeReactiveCdrParticlesPerCell(a_ppc[din], a_level, din, box, ebisbox);
3546 template <
typename I,
typename C,
typename R,
typename F>
3550 const DataIndex a_dit,
3552 const EBISBox& a_ebisbox) noexcept
3554 CH_TIME(
"ItoKMCStepper::computeReactiveCdrParticlesPerCell(EBCellFAB, int, DataIndex, Box, EBISBox)");
3555 if (m_verbosity > 5) {
3556 pout() << m_name +
"::computeReactiveCdrParticlesPerCell(EBCellFAB, int, DataIndex, Box, EBISBox)" << endl;
3559 constexpr Real zero = 0.0;
3561 const int numCdrSpecies = m_physics->getNumCdrSpecies();
3563 CH_assert(a_ppc.nComp() == numCdrSpecies);
3565 const Real dx = m_amr->getDx()[a_level];
3566 const Real vol = std::pow(dx, SpaceDim);
3567 const RealVect probLo = m_amr->getProbLo();
3570 FArrayBox& ppcRegular = a_ppc.getFArrayBox();
3572 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
3573 RefCountedPtr<CdrSolver>& solver = solverIt();
3574 const int idx = solverIt.index();
3576 const EBCellFAB& phi = (*(solver->getPhi())[a_level])[a_dit];
3577 const FArrayBox& phiReg = phi.getFArrayBox();
3580 auto regularKernel = [&](
const IntVect& iv) ->
void {
3581 if (a_ebisbox.isRegular(iv)) {
3582 ppcRegular(iv, idx) =
std::max(zero, std::floor(phiReg(iv, 0) * vol));
3587 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
3588 const Real kappa = a_ebisbox.volFrac(vof);
3590 a_ppc(vof, idx) =
std::max(zero, std::floor(kappa * phi(vof, 0) * vol));
3594 VoFIterator& vofit = (*m_amr->getVofIterator(m_fluidRealm, m_plasmaPhase)[a_level])[a_dit];
3601 template <
typename I,
typename C,
typename R,
typename F>
3605 CH_TIME(
"ItoKMCStepper::computeReactiveMaeanEnergiesPerCell(EBAMRCellData)");
3606 if (m_verbosity > 5) {
3607 pout() << m_name +
"::computeReactiveMaeanEnergiesPerCell(EBAMRCellData)" << endl;
3610 CH_assert(a_meanEnergies.getRealm() == m_particleRealm);
3614 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3615 this->computeReactiveMeanEnergiesPerCell(*a_meanEnergies[lvl], lvl);
3619 template <
typename I,
typename C,
typename R,
typename F>
3622 const int a_level) noexcept
3624 CH_TIME(
"ItoKMCStepper::computeReactiveMeanEnergiesPerCell(LD<EBCellFAB>, int)");
3625 if (m_verbosity > 5) {
3626 pout() << m_name +
"::computeReactiveMeanEnergiesPerCell(LD<EBCellFAB>, int)" << endl;
3629 const int numPlasmaSpecies = m_physics->getNumItoSpecies();
3631 CH_assert(a_meanEnergies.nComp() == numPlasmaSpecies);
3633 const DisjointBoxLayout& dbl = m_amr->getGrids(m_particleRealm)[a_level];
3634 const EBISLayout& ebisl = m_amr->getEBISLayout(m_particleRealm, m_plasmaPhase)[a_level];
3635 const DataIterator& dit = dbl.dataIterator();
3637 const int nbox = dit.size();
3639 #pragma omp parallel for schedule(runtime)
3640 for (
int mybox = 0; mybox < nbox; mybox++) {
3641 const DataIndex& din = dit[mybox];
3643 const Box box = dbl[din];
3644 const EBISBox& ebisbox = ebisl[din];
3646 this->computeReactiveMeanEnergiesPerCell(a_meanEnergies[din], a_level, din, box, ebisbox);
3650 template <
typename I,
typename C,
typename R,
typename F>
3654 const DataIndex a_dit,
3656 const EBISBox& a_ebisbox) noexcept
3658 CH_TIME(
"ItoKMCStepper::computeReactiveMeanEnergiesPerCell(EBCellFABint, DataIndex, Box, EBISBox)");
3659 if (m_verbosity > 5) {
3660 pout() << m_name +
"::computeReactiveMeanEnergiesPerCell(EBCellFABint, DataIndex, Box, EBISBox))" << endl;
3663 const int numPlasmaSpecies = m_physics->getNumItoSpecies();
3665 CH_assert(a_meanEnergies.nComp() == numPlasmaSpecies);
3667 const Real dx = m_amr->getDx()[a_level];
3668 const RealVect probLo = m_amr->getProbLo();
3671 FArrayBox& meanEnergiesReg = a_meanEnergies.getFArrayBox();
3673 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
3674 RefCountedPtr<ItoSolver>& solver = solverIt();
3675 const int idx = solverIt.index();
3680 const BinFab<ItoParticle>& cellParticles = particles.
getCellParticles(a_level, a_dit);
3683 auto regularKernel = [&](
const IntVect& iv) ->
void {
3684 if (a_ebisbox.isRegular(iv)) {
3685 Real totalWeight = 0.0;
3686 Real totalEnergy = 0.0;
3688 for (ListIterator<ItoParticle> lit(cellParticles(iv, 0)); lit.ok(); ++lit) {
3689 totalWeight += lit().weight();
3690 totalEnergy += lit().weight() * lit().energy();
3693 if (totalWeight > 0.0) {
3694 meanEnergiesReg(iv, idx) = totalEnergy / totalWeight;
3697 meanEnergiesReg(iv, idx) = 0.0;
3703 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
3704 const IntVect iv = vof.gridIndex();
3705 const RealVect normal = a_ebisbox.normal(vof);
3706 const RealVect ebCentroid = probLo +
Location::position(Location::Cell::Boundary, vof, a_ebisbox, dx);
3708 Real totalWeight = 0.0;
3709 Real totalEnergy = 0.0;
3711 for (ListIterator<ItoParticle> lit(cellParticles(iv, 0)); lit.ok(); ++lit) {
3712 const RealVect& pos = lit().position();
3714 if ((pos - ebCentroid).dotProduct(normal) >= 0.0) {
3715 totalWeight += lit().weight();
3716 totalEnergy += lit().weight() * lit().energy();
3720 if (totalWeight > 0.0) {
3721 meanEnergiesReg(iv, idx) = totalEnergy / totalWeight;
3724 meanEnergiesReg(iv, idx) = 0.0;
3729 VoFIterator& vofit = (*m_amr->getVofIterator(m_particleRealm, m_plasmaPhase)[a_level])[a_dit];
3736 template <
typename I,
typename C,
typename R,
typename F>
3740 CH_TIME(
"ItoKMCStepper::advanceReactionNetwork(dt)");
3741 if (m_verbosity > 5) {
3742 pout() << m_name +
"::advanceReactionNetwork(dt)" << endl;
3745 CH_assert(a_dt > 0.0);
3747 this->advanceReactionNetwork(m_electricFieldFluid, a_dt);
3750 template <
typename I,
typename C,
typename R,
typename F>
3754 CH_TIMERS(
"ItoKMCStepper::advanceReactionNetwork");
3755 CH_TIMER(
"ItoKMCStepper::advanceReactionNetwork::compute_ppc", t1);
3756 CH_TIMER(
"ItoKMCStepper::advanceReactionNetwork::integrate_network", t2);
3757 CH_TIMER(
"ItoKMCStepper::advanceReactionNetwork::copies", t3);
3758 CH_TIMER(
"ItoKMCStepper::advanceReactionNetwork::reconcile_particles", t4);
3759 CH_TIMER(
"ItoKMCStepper::advanceReactionNetwork::reconcile_cdr", t5);
3760 if (m_verbosity > 5) {
3761 pout() << m_name +
"::advanceReactionNetwork" << endl;
3764 const int numItoSpecies = m_physics->getNumItoSpecies();
3765 const int numCdrSpecies = m_physics->getNumCdrSpecies();
3766 const int numPhotonSpecies = m_physics->getNumPhotonSpecies();
3768 CH_assert(a_electricField.getRealm() == m_fluidRealm);
3769 CH_assert(a_dt > 0.0);
3774 if (numItoSpecies > 0) {
3775 this->computeReactiveItoParticlesPerCell(m_particleItoPPC);
3777 const Interval srcInterv(0, numItoSpecies - 1);
3778 const Interval dstInterv(0, numItoSpecies - 1);
3780 m_amr->copyData(m_fluidPPC, m_particleItoPPC, dstInterv, srcInterv);
3784 if (numCdrSpecies > 0) {
3785 this->computeReactiveCdrParticlesPerCell(m_fluidCdrPPC);
3787 const Interval srcInterv(0, numCdrSpecies - 1);
3788 const Interval dstInterv(numItoSpecies, numItoSpecies + numCdrSpecies - 1);
3790 m_amr->copyData(m_fluidPPC, m_fluidCdrPPC, dstInterv, srcInterv);
3802 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3803 this->advanceReactionNetwork(*m_fluidPPC[lvl], *m_fluidYPC[lvl], *a_electricField[lvl], lvl, a_dt);
3809 if (numItoSpecies > 0) {
3810 const Interval srcInterv(0, numItoSpecies - 1);
3811 const Interval dstInterv(0, numItoSpecies - 1);
3813 m_amr->copyData(m_particleItoPPC, m_fluidPPC, dstInterv, srcInterv);
3815 if (numCdrSpecies > 0) {
3816 const Interval srcInterv(numItoSpecies, numItoSpecies + numCdrSpecies - 1);
3817 const Interval dstInterv(0, numCdrSpecies - 1);
3819 m_amr->copyData(m_fluidCdrPPC, m_fluidPPC, dstInterv, srcInterv);
3821 if (numPhotonSpecies > 0) {
3822 m_amr->copyData(m_particleYPC, m_fluidYPC);
3829 for (
int i = 0; i < m_cdrPhotoiProducts.size(); i++) {
3830 m_cdrPhotoiProducts[i].clearParticles();
3831 m_cdrPhotoiProducts[i].organizeParticlesByCell();
3836 this->reconcileParticles(m_particleItoPPC, m_particleOldItoPPC, m_particleYPC);
3843 for (
int i = 0; i < m_cdrPhotoiProducts.size(); i++) {
3844 m_cdrPhotoiProducts[i].organizeParticlesByPatch();
3849 m_cdrPhotoiProducts[i],
3850 DepositionType::NGP,
3851 CoarseFineDeposition::Halo);
3853 m_amr->copyData(m_fluidScratch1, m_particleScratch1);
3856 EBAMRCellData fluidCdrPPC = m_amr->slice(m_fluidCdrPPC, Interval(i, i));
3860 m_cdrPhotoiProducts[i].clearParticles();
3863 this->reconcileCdrDensities(m_fluidCdrPPC, m_fluidOldCdrPPC, a_dt);
3867 template <
typename I,
typename C,
typename R,
typename F>
3870 LevelData<EBCellFAB>& a_newPhotonsPerCell,
3871 const LevelData<EBCellFAB>& a_electricField,
3873 const Real a_dt)
const noexcept
3875 CH_TIME(
"ItoKMCStepper::advanceReactionNetwork(LD<EBCellFAB>x3, int, Real)");
3876 if (m_verbosity > 5) {
3877 pout() << m_name +
"::advanceReactionNetwork(LD<EBCellFAB>x3, int, Real)" << endl;
3880 const int numPlasmaSpecies = m_physics->getNumPlasmaSpecies();
3881 const int numPhotonSpecies = m_physics->getNumPhotonSpecies();
3883 CH_assert(a_particlesPerCell.nComp() == numPlasmaSpecies);
3884 CH_assert(a_newPhotonsPerCell.nComp() == numPhotonSpecies);
3885 CH_assert(a_electricField.nComp() == SpaceDim);
3887 const DisjointBoxLayout& dbl = m_amr->getGrids(m_fluidRealm)[a_level];
3888 const DataIterator& dit = dbl.dataIterator();
3890 const int nbox = dit.size();
3892 #pragma omp parallel
3894 m_physics->defineKMC();
3896 #pragma omp for schedule(runtime)
3897 for (
int mybox = 0; mybox < nbox; mybox++) {
3898 const DataIndex& din = dit[mybox];
3900 this->advanceReactionNetwork(a_particlesPerCell[din],
3901 a_newPhotonsPerCell[din],
3902 a_electricField[din],
3906 m_amr->getDx()[a_level],
3910 m_physics->killKMC();
3914 template <
typename I,
typename C,
typename R,
typename F>
3917 EBCellFAB& a_newPhotonsPerCell,
3918 const EBCellFAB& a_electricField,
3920 const DataIndex a_dit,
3923 const Real a_dt)
const noexcept
3925 CH_TIME(
"ItoKMCStepper::advanceReactionNetwork(EBCellFABx3, int, DataIndex, Box, Realx2)");
3926 if (m_verbosity > 5) {
3927 pout() << m_name +
"::advanceReactionNetwork(EBCellFABx3, int, DataIndex, Box, Realx2)" << endl;
3930 const int numCdrSpecies = m_physics->getNumCdrSpecies();
3931 const int numItoSpecies = m_physics->getNumItoSpecies();
3932 const int numPlasmaSpecies = m_physics->getNumPlasmaSpecies();
3933 const int numPhotonSpecies = m_physics->getNumPhotonSpecies();
3935 CH_assert(a_particlesPerCell.nComp() == numPlasmaSpecies);
3936 CH_assert(a_newPhotonsPerCell.nComp() == numPhotonSpecies);
3937 CH_assert(a_electricField.nComp() == SpaceDim);
3940 const RealVect probLo = m_amr->getProbLo();
3941 const EBISBox& ebisbox = m_amr->getEBISLayout(m_fluidRealm, m_plasmaPhase)[a_level][a_dit];
3943 const FArrayBox& electricFieldReg = a_electricField.getFArrayBox();
3946 Vector<Physics::ItoKMC::FPR> particles(numPlasmaSpecies);
3947 Vector<Physics::ItoKMC::FPR> newPhotons(numPhotonSpecies);
3948 Vector<Real> meanEnergies(numPlasmaSpecies);
3949 Vector<Real> energySources(numPlasmaSpecies);
3950 Vector<Real> densities(numPlasmaSpecies, 0.0);
3951 Vector<RealVect> densityGradients(numPlasmaSpecies, RealVect::Zero);
3954 FArrayBox& particlesPerCellReg = a_particlesPerCell.getFArrayBox();
3955 FArrayBox& newPhotonsReg = a_newPhotonsPerCell.getFArrayBox();
3958 Vector<const EBCellFAB*> densitiesIto(numItoSpecies);
3959 Vector<const EBCellFAB*> densityGradientsIto(numItoSpecies);
3960 Vector<const FArrayBox*> densitiesItoReg(numItoSpecies);
3961 Vector<const FArrayBox*> densityGradientsItoReg(numItoSpecies);
3963 Vector<const EBCellFAB*> densitiesCDR(numCdrSpecies);
3964 Vector<const EBCellFAB*> densityGradientsCDR(numCdrSpecies);
3965 Vector<const FArrayBox*> densitiesCDRReg(numCdrSpecies);
3966 Vector<const FArrayBox*> densityGradientsCDRReg(numCdrSpecies);
3968 for (
auto it = m_ito->iterator(); it.ok(); ++it) {
3969 const RefCountedPtr<ItoSolver>& solver = it();
3971 const int i = it.index();
3973 densitiesIto[i] = &(*(m_fluidPhiIto[i])[a_level])[a_dit];
3974 densitiesItoReg[i] = &(densitiesIto[i]->getFArrayBox());
3975 densityGradientsIto[i] = &(*m_fluidGradPhiIto[i][a_level])[a_dit];
3976 densityGradientsItoReg[i] = &(densityGradientsIto[i]->getFArrayBox());
3979 for (
auto it = m_cdr->iterator(); it.ok(); ++it) {
3980 const RefCountedPtr<CdrSolver>& solver = it();
3983 const int i = it.index();
3985 densitiesCDR[i] = &(*phi[a_level])[a_dit];
3986 densitiesCDRReg[i] = &(densitiesCDR[i]->getFArrayBox());
3987 densityGradientsCDR[i] = &(*m_fluidGradPhiCDR[i][a_level])[a_dit];
3988 densityGradientsCDRReg[i] = &(densityGradientsCDR[i]->getFArrayBox());
3992 const BaseFab<bool>& validCells = (*m_amr->getValidCells(m_fluidRealm)[a_level])[a_dit];
3995 auto regularKernel = [&](
const IntVect& iv) ->
void {
3996 if (ebisbox.isRegular(iv) && validCells(iv, 0)) {
3997 const RealVect pos = probLo + a_dx * (RealVect(iv) + 0.5 * RealVect::Unit);
3998 const RealVect E = RealVect(D_DECL(electricFieldReg(iv, 0), electricFieldReg(iv, 1), electricFieldReg(iv, 2)));
4001 for (
int i = 0; i < numPlasmaSpecies; i++) {
4002 particles[i] = (
long long)particlesPerCellReg(iv, i);
4005 for (
int i = 0; i < numPhotonSpecies; i++) {
4006 newPhotons[i] = 0LL;
4010 for (
int i = 0; i < numItoSpecies; i++) {
4011 densities[i] = (*densitiesItoReg[i])(iv, 0);
4012 densityGradients[i] = RealVect(D_DECL((*densityGradientsItoReg[i])(iv, 0),
4013 (*densityGradientsItoReg[i])(iv, 1),
4014 (*densityGradientsItoReg[i])(iv, 2)));
4017 for (
int i = 0; i < numCdrSpecies; i++) {
4018 densities[numItoSpecies + i] = (*densitiesCDRReg[i])(iv, 0);
4019 densityGradients[numItoSpecies + i] = RealVect(D_DECL((*densityGradientsCDRReg[i])(iv, 0),
4020 (*densityGradientsCDRReg[i])(iv, 1),
4021 (*densityGradientsCDRReg[i])(iv, 2)));
4025 m_physics->advanceKMC(particles, newPhotons, densities, densityGradients, a_dt, E, pos, a_dx, 1.0);
4028 for (
int i = 0; i < numPlasmaSpecies; i++) {
4029 particlesPerCellReg(iv, i) = 1.0 * particles[i];
4032 for (
int i = 0; i < numPhotonSpecies; i++) {
4033 newPhotonsReg(iv, i) = 1.0 * newPhotons[i];
4039 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
4040 const IntVect iv = vof.gridIndex();
4042 if (validCells(iv, 0)) {
4043 const Real kappa = ebisbox.volFrac(vof);
4044 const RealVect pos = probLo +
Location::position(Location::Cell::Centroid, vof, ebisbox, a_dx);
4045 const RealVect E = RealVect(D_DECL(a_electricField(vof, 0), a_electricField(vof, 1), a_electricField(vof, 2)));
4048 for (
int i = 0; i < numPlasmaSpecies; i++) {
4049 particles[i] = (
long long)a_particlesPerCell(vof, i);
4052 for (
int i = 0; i < numPhotonSpecies; i++) {
4053 newPhotons[i] = 0LL;
4057 for (
int i = 0; i < numItoSpecies; i++) {
4058 densities[i] = (*densitiesIto[i])(vof, 0);
4059 densityGradients[i] = RealVect(D_DECL((*densityGradientsIto[i])(vof, 0),
4060 (*densityGradientsIto[i])(vof, 1),
4061 (*densityGradientsIto[i])(vof, 2)));
4064 for (
int i = 0; i < numCdrSpecies; i++) {
4065 densities[numItoSpecies + i] = (*densitiesCDR[i])(vof, 0);
4066 densityGradients[numItoSpecies + i] = RealVect(D_DECL((*densityGradientsCDR[i])(vof, 0),
4067 (*densityGradientsCDR[i])(vof, 1),
4068 (*densityGradientsCDR[i])(vof, 2)));
4072 m_physics->advanceKMC(particles, newPhotons, densities, densityGradients, a_dt, E, pos, a_dx, kappa);
4075 for (
int i = 0; i < numPlasmaSpecies; i++) {
4076 a_particlesPerCell(vof, i) = 1.0 * particles[i];
4079 for (
int i = 0; i < numPhotonSpecies; i++) {
4080 a_newPhotonsPerCell(vof, i) = 1.0 * newPhotons[i];
4086 VoFIterator& vofit = (*m_amr->getVofIterator(m_fluidRealm, m_plasmaPhase)[a_level])[a_dit];
4092 template <
typename I,
typename C,
typename R,
typename F>
4098 CH_TIME(
"ItoKMCStepper::reconcileParticles(EBAMRCellDatax3)");
4099 if (m_verbosity > 5) {
4100 pout() << m_name +
"::reconcileParticles(EBAMRCellDatax3)";
4103 CH_assert(a_newParticlesPerCell.getRealm() == m_particleRealm);
4104 CH_assert(a_oldParticlesPerCell.getRealm() == m_particleRealm);
4105 CH_assert(a_newPhotonsPerCell.getRealm() == m_particleRealm);
4107 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
4108 this->reconcileParticles(*a_newParticlesPerCell[lvl], *a_oldParticlesPerCell[lvl], *a_newPhotonsPerCell[lvl], lvl);
4112 template <
typename I,
typename C,
typename R,
typename F>
4115 const LevelData<EBCellFAB>& a_oldParticlesPerCell,
4116 const LevelData<EBCellFAB>& a_newPhotonsPerCell,
4117 const int a_level)
const noexcept
4119 CH_TIME(
"ItoKMCStepper::reconcileParticles(LevelData<EBCellFAB>x3, int)");
4120 if (m_verbosity > 5) {
4121 pout() << m_name +
"::reconcileParticles(LevelData<EBCellFAB>x3, int)" << endl;
4124 const int numItoSpecies = m_physics->getNumItoSpecies();
4125 const int numPhotonSpecies = m_physics->getNumPhotonSpecies();
4127 CH_assert(a_newParticlesPerCell.nComp() == numItoSpecies);
4128 CH_assert(a_oldParticlesPerCell.nComp() == numItoSpecies);
4129 CH_assert(a_newPhotonsPerCell.nComp() == numPhotonSpecies);
4131 const DisjointBoxLayout& dbl = m_amr->getGrids(m_particleRealm)[a_level];
4132 const DataIterator& dit = dbl.dataIterator();
4134 const int nbox = dit.size();
4136 #pragma omp parallel for schedule(runtime)
4137 for (
int mybox = 0; mybox < nbox; mybox++) {
4138 const DataIndex& din = dit[mybox];
4140 this->reconcileParticles(a_newParticlesPerCell[din],
4141 a_oldParticlesPerCell[din],
4142 a_newPhotonsPerCell[din],
4146 m_amr->getDx()[a_level]);
4150 template <
typename I,
typename C,
typename R,
typename F>
4153 const EBCellFAB& a_oldParticlesPerCell,
4154 const EBCellFAB& a_newPhotonsPerCell,
4156 const DataIndex a_dit,
4158 const Real a_dx)
const noexcept
4160 CH_TIMERS(
"ItoKMCStepper::reconcileParticles(patch)");
4161 CH_TIMER(
"ItoKMCStepper::reconcileParticles(patch)::collect_ptr", t1);
4162 CH_TIMER(
"ItoKMCStepper::reconcileParticles(patch)::regular_cells", t2);
4163 CH_TIMER(
"ItoKMCStepper::reconcileParticles(patch)::irregular_cells", t3);
4164 if (m_verbosity > 5) {
4165 pout() << m_name +
"::reconcileParticles(patch)" << endl;
4173 const int numItoSpecies = m_physics->getNumItoSpecies();
4174 const int numCdrSpecies = m_physics->getNumCdrSpecies();
4175 const int numPhotonSpecies = m_physics->getNumPhotonSpecies();
4177 CH_assert(a_newParticlesPerCell.nComp() == numItoSpecies);
4178 CH_assert(a_oldParticlesPerCell.nComp() == numItoSpecies);
4179 CH_assert(a_newPhotonsPerCell.nComp() == numPhotonSpecies);
4182 const RealVect probLo = m_amr->getProbLo();
4183 const EBISBox& ebisbox = m_amr->getEBISLayout(m_particleRealm, m_plasmaPhase)[a_level][a_dit];
4186 const int ppc = (a_level < m_particlesPerCell.size()) ? m_particlesPerCell[a_level] : m_particlesPerCell.back();
4190 const BaseFab<bool>& validCells = (*m_amr->getValidCells(m_particleRealm)[a_level])[a_dit];
4195 Vector<BinFab<ItoParticle>*> itoParticlesFAB(numItoSpecies);
4196 Vector<BinFab<PointParticle>*> cdrParticlesFAB(numCdrSpecies);
4197 Vector<BinFab<Photon>*> sourcePhotonsFAB(numPhotonSpecies);
4198 Vector<BinFab<Photon>*> bulkPhotonsFAB(numPhotonSpecies);
4201 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
4202 RefCountedPtr<ItoSolver>& solver = solverIt();
4204 const int idx = solverIt.index();
4208 itoParticlesFAB[idx] = &(solverParticles.
getCellParticles(a_level, a_dit));
4212 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
4213 const int idx = solverIt.index();
4221 for (
auto solverIt = m_rte->iterator(); solverIt.ok(); ++solverIt) {
4222 RefCountedPtr<McPhoto>& solver = solverIt();
4224 const int idx = solverIt.index();
4229 bulkPhotonsFAB[idx] = &(solverBulkPhotons.
getCellParticles(a_level, a_dit));
4230 sourcePhotonsFAB[idx] = &(solverSourcePhotons.
getCellParticles(a_level, a_dit));
4236 Vector<Physics::ItoKMC::FPR> numNewParticles(numItoSpecies);
4237 Vector<Physics::ItoKMC::FPR> numOldParticles(numItoSpecies);
4238 Vector<Physics::ItoKMC::FPR> numNewPhotons(numPhotonSpecies);
4242 Vector<List<ItoParticle>*> itoParticles(numItoSpecies);
4243 Vector<List<PointParticle>*> cdrParticles(numCdrSpecies);
4244 Vector<List<Photon>*> bulkPhotons(numPhotonSpecies);
4245 Vector<List<Photon>*> sourcePhotons(numPhotonSpecies);
4249 auto regularKernel = [&](
const IntVect& iv) ->
void {
4250 if (ebisbox.isRegular(iv) && validCells(iv)) {
4251 const RealVect cellPos = probLo + a_dx * (RealVect(iv) + 0.5 * RealVect::Unit);
4252 const RealVect centroidPos = RealVect::Zero;
4253 const RealVect lo = -0.5 * RealVect::Unit;
4254 const RealVect hi = 0.5 * RealVect::Unit;
4255 const RealVect bndryCentroid = RealVect::Zero;
4256 const RealVect bndryNormal = RealVect::Zero;
4257 const Real kappa = 1.0;
4260 for (
int i = 0; i < numItoSpecies; i++) {
4261 itoParticles[i] = &((*itoParticlesFAB[i])(iv, 0));
4262 numNewParticles[i] = (
long long)(a_newParticlesPerCell.getSingleValuedFAB()(iv, i));
4263 numOldParticles[i] = (
long long)(a_oldParticlesPerCell.getSingleValuedFAB()(iv, i));
4267 for (
int i = 0; i < numCdrSpecies; i++) {
4268 cdrParticles[i] = &((*cdrParticlesFAB[i])(iv, 0));
4272 for (
int i = 0; i < numPhotonSpecies; i++) {
4273 bulkPhotons[i] = &((*bulkPhotonsFAB[i])(iv, 0));
4274 sourcePhotons[i] = &((*sourcePhotonsFAB[i])(iv, 0));
4276 numNewPhotons[i] = (
long long)(a_newPhotonsPerCell.getSingleValuedFAB()(iv, i));
4280 sourcePhotons[i]->clear();
4285 m_physics->reconcileParticles(itoParticles,
4299 m_physics->reconcilePhotons(sourcePhotons,
4311 m_physics->reconcilePhotoionization(itoParticles, cdrParticles, bulkPhotons);
4314 if (this->m_mergeInterval > 0) {
4315 if ((this->m_timeStep + 1) % this->m_mergeInterval == 0) {
4316 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
4317 const int idx = solverIt.index();
4319 solverIt()->mergeParticles(*itoParticles[idx],
CellInfo(iv, a_dx), ppc);
4327 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
4328 const IntVect iv = vof.gridIndex();
4329 if (ebisbox.isIrregular(iv) && validCells(iv, 0)) {
4330 const Real kappa = ebisbox.volFrac(vof);
4331 const RealVect cellPos = probLo +
Location::position(Location::Cell::Center, vof, ebisbox, a_dx);
4332 const RealVect centroidPos = ebisbox.centroid(vof);
4333 const RealVect bndryCentroid = ebisbox.bndryCentroid(vof);
4334 const RealVect bndryNormal = ebisbox.normal(vof);
4337 RealVect lo = -0.5 * RealVect::Unit;
4338 RealVect hi = 0.5 * RealVect::Unit;
4344 for (
int i = 0; i < numItoSpecies; i++) {
4345 itoParticles[i] = &((*itoParticlesFAB[i])(iv, 0));
4346 numNewParticles[i] = (
long long)(a_newParticlesPerCell(vof, i));
4347 numOldParticles[i] = (
long long)(a_oldParticlesPerCell(vof, i));
4351 for (
int i = 0; i < numCdrSpecies; i++) {
4352 cdrParticles[i] = &((*cdrParticlesFAB[i])(iv, 0));
4356 for (
int i = 0; i < numPhotonSpecies; i++) {
4357 bulkPhotons[i] = &((*bulkPhotonsFAB[i])(iv, 0));
4358 sourcePhotons[i] = &((*sourcePhotonsFAB[i])(iv, 0));
4360 numNewPhotons[i] = (
long long)(a_newPhotonsPerCell(vof, i));
4364 sourcePhotons[i]->clear();
4369 m_physics->reconcileParticles(itoParticles,
4383 m_physics->reconcilePhotons(sourcePhotons,
4395 m_physics->reconcilePhotoionization(itoParticles, cdrParticles, bulkPhotons);
4398 if (this->m_mergeInterval > 0) {
4399 if ((this->m_timeStep + 1) % this->m_mergeInterval == 0) {
4400 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
4401 const int idx = solverIt.index();
4403 const CellInfo cellInfo(iv, a_dx, kappa, bndryCentroid, bndryNormal);
4405 solverIt()->mergeParticles(*itoParticles[idx], cellInfo, ppc);
4413 VoFIterator& vofit = (*m_amr->getVofIterator(m_particleRealm, m_plasmaPhase)[a_level])[a_dit];
4424 template <
typename I,
typename C,
typename R,
typename F>
4428 CH_TIME(
"ItoKMCStepper::reconcilePhotoionization()");
4429 if (m_verbosity > 5) {
4430 pout() << m_name +
"::reconcilePhotoionization()" << endl;
4433 const int numItoSpecies = m_physics->getNumItoSpecies();
4434 const int numCdrSpecies = m_physics->getNumCdrSpecies();
4435 const int numPhotonSpecies = m_physics->getNumPhotonSpecies();
4437 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
4438 const DisjointBoxLayout& dbl = m_amr->getGrids(m_particleRealm)[lvl];
4439 const DataIterator& dit = dbl.dataIterator();
4441 const int nbox = dit.size();
4443 #pragma omp parallel for schedule(runtime)
4444 for (
int mybox = 0; mybox < nbox; mybox++) {
4445 const DataIndex& din = dit[mybox];
4447 Vector<List<ItoParticle>*> itoParticles(numItoSpecies);
4448 Vector<List<PointParticle>*> cdrParticles(numCdrSpecies);
4449 Vector<List<Photon>*> photonParticles(numPhotonSpecies);
4451 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
4454 itoParticles[solverIt.index()] = &(particles[lvl][din].listItems());
4457 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
4460 cdrParticles[solverIt.index()] = &(particles[lvl][din].listItems());
4463 for (
auto solverIt = m_rte->iterator(); solverIt.ok(); ++solverIt) {
4466 photonParticles[solverIt.index()] = &(particles[lvl][din].listItems());
4469 m_physics->reconcilePhotoionization(itoParticles, cdrParticles, photonParticles);
4474 template <
typename I,
typename C,
typename R,
typename F>
4478 const Real a_dt) noexcept
4480 CH_TIME(
"ItoKMCStepper::reconcileCdrDensities(EBAMRCellDatax2, Real)");
4481 if (m_verbosity > 5) {
4482 pout() << m_name +
"::reconcileCdrDensities(EBAMRCellDatax2, Real)" << endl;
4485 const int numCdrSpecies = m_physics->getNumCdrSpecies();
4487 CH_assert(a_newParticlesPerCell.getRealm() == m_fluidRealm);
4488 CH_assert(a_oldParticlesPerCell.getRealm() == m_fluidRealm);
4489 CH_assert(a_dt > 0.0);
4491 if (numCdrSpecies > 0) {
4494 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
4495 this->reconcileCdrDensities(*a_newParticlesPerCell[lvl], *a_oldParticlesPerCell[lvl], lvl, a_dt);
4499 if (m_redistributeCDR) {
4500 for (
auto it = m_cdr->iterator(); it.ok(); ++it) {
4501 const int idx = it.index();
4503 const EBAMRCellData newPPC = m_amr->slice(a_newParticlesPerCell, Interval(idx, idx));
4504 const EBAMRCellData oldPPC = m_amr->slice(a_oldParticlesPerCell, Interval(idx, idx));
4506 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
4507 const DisjointBoxLayout& dbl = m_amr->getGrids(m_fluidRealm)[lvl];
4508 const DataIterator& dit = dbl.dataIterator();
4509 const EBISLayout& ebisl = m_amr->getEBISLayout(m_fluidRealm, m_plasmaPhase)[lvl];
4510 const Real dx = m_amr->getDx()[lvl];
4512 const int nbox = dit.
size();
4514 #pragma omp parallel for schedule(runtime)
4515 for (
int mybox = 0; mybox < nbox; mybox++) {
4516 const DataIndex& din = dit[mybox];
4517 const EBISBox& ebisbox = ebisl[din];
4519 BaseIVFAB<Real>& deltaMass = (*m_fluidScratchEB[lvl])[din];
4521 deltaMass.setVal(0.0);
4523 const EBCellFAB& newPPC = (*a_newParticlesPerCell[lvl])[din];
4524 const EBCellFAB& oldPPC = (*a_oldParticlesPerCell[lvl])[din];
4526 auto kernel = [&](
const VolIndex& vof) ->
void {
4527 const Real kappa = ebisbox.volFrac(vof);
4529 deltaMass(vof, 0) = (newPPC(vof, idx) - oldPPC(vof, idx)) * (1.0 - kappa) / std::pow(dx, SpaceDim);
4532 VoFIterator& vofit = (*m_amr->getVofIterator(m_fluidRealm, m_plasmaPhase)[lvl])[din];
4538 const RefCountedPtr<CdrSolver>& solver = it();
4540 solver->redistribute(solver->getPhi(), m_fluidScratchEB);
4544 this->coarsenCDRSolvers();
4548 template <
typename I,
typename C,
typename R,
typename F>
4551 const LevelData<EBCellFAB>& a_oldParticlesPerCell,
4553 const Real a_dt) noexcept
4555 CH_TIME(
"ItoKMCStepper::reconcileCdrDensities(LD<EBCellFAB>x2, int, Real)");
4556 if (m_verbosity > 5) {
4557 pout() << m_name +
"::reconcileCdrDensities(LD<EBCellFAB>x2, int, Real)" << endl;
4560 const int numCdrSpecies = m_physics->getNumCdrSpecies();
4562 CH_assert(a_newParticlesPerCell.nComp() == numCdrSpecies);
4563 CH_assert(a_oldParticlesPerCell.nComp() == numCdrSpecies);
4565 const DisjointBoxLayout& dbl = m_amr->getGrids(m_fluidRealm)[a_level];
4566 const DataIterator& dit = dbl.dataIterator();
4567 const Real dx = m_amr->getDx()[a_level];
4569 const int nbox = dit.size();
4571 #pragma omp parallel for schedule(runtime)
4572 for (
int mybox = 0; mybox < nbox; mybox++) {
4573 const DataIndex& din = dit[mybox];
4576 ->reconcileCdrDensities(a_newParticlesPerCell[din], a_oldParticlesPerCell[din], a_level, din, dbl[din], dx, a_dt);
4580 template <
typename I,
typename C,
typename R,
typename F>
4583 const EBCellFAB& a_oldParticlesPerCell,
4585 const DataIndex a_dit,
4588 const Real a_dt) noexcept
4590 CH_TIME(
"ItoKMCStepper::reconcileCdrDensities(EBCellFABx2, int, DataIndex, Box, Realx2)");
4591 if (m_verbosity > 5) {
4592 pout() << m_name +
"::reconcileCdrDensities(EBCellFABx2, int, DataIndex, Box, Realx2)" << endl;
4595 const int numCdrSpecies = m_physics->getNumCdrSpecies();
4597 CH_assert(a_newParticlesPerCell.nComp() == numCdrSpecies);
4598 CH_assert(a_oldParticlesPerCell.nComp() == numCdrSpecies);
4600 const Real volume = std::pow(a_dx, SpaceDim);
4602 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
4603 RefCountedPtr<CdrSolver>& solver = solverIt();
4604 const int index = solverIt.index();
4606 EBCellFAB& phi = (*(solver->getPhi()[a_level]))[a_dit];
4607 EBCellFAB& src = (*(solver->getSource()[a_level]))[a_dit];
4611 src.plus(a_newParticlesPerCell, index, 0, 1);
4612 src.minus(a_oldParticlesPerCell, index, 0, 1);
4623 template <
typename I,
typename C,
typename R,
typename F>
4627 CH_TIME(
"ItoKMCStepper::coarsenCDRSolvers");
4628 if (m_verbosity > 5) {
4629 pout() << m_name +
"::coarsenCDRSolvers" << endl;
4632 for (
auto solverIt = this->m_cdr->iterator(); solverIt.ok(); ++solverIt) {
4633 auto& solver = solverIt();
4638 this->m_amr->conservativeAverage(phi, phi.
getRealm(), this->m_plasmaPhase);
4639 this->m_amr->conservativeAverage(src, src.
getRealm(), this->m_plasmaPhase);
4641 this->m_amr->interpGhostPwl(phi, phi.
getRealm(), this->m_plasmaPhase);
4642 this->m_amr->interpGhostPwl(src, src.
getRealm(), this->m_plasmaPhase);
4649 template <
typename I,
typename C,
typename R,
typename F>
4653 CH_TIME(
"ItoKMCStepper::fillSecondaryEmissionEB(Real)");
4654 if (m_verbosity > 5) {
4655 pout() << m_name +
"::fillSecondaryEmissionEB(Real)" << endl;
4659 Vector<ParticleContainer<ItoParticle>*> primaryParticles;
4660 for (
auto it = m_ito->iterator(); it.ok(); ++it) {
4663 primaryParticles.push_back(&intersectedParticles);
4668 m_amr->allocate(tmp, m_fluidRealm, m_plasmaPhase, 1);
4670 for (
auto solverIt = m_cdr->iterator(); solverIt.ok(); ++solverIt) {
4671 const int idx = solverIt.index();
4672 const RefCountedPtr<CdrSolver>& solver = solverIt();
4676 if (solver->isMobile()) {
4677 solver->extrapolateAdvectiveFluxToEB(tmp);
4679 m_amr->copyData(extrapFlux, tmp);
4687 Vector<ParticleContainer<Photon>*> primaryPhotons;
4688 for (
auto it = m_rte->iterator(); it.ok(); ++it) {
4691 primaryPhotons.push_back(&intersectedPhotons);
4695 this->fillSecondaryEmissionEB(m_secondaryParticles,
4701 m_electricFieldParticle,
4705 template <
typename I,
typename C,
typename R,
typename F>
4708 Vector<EBAMRIVData>& a_cdrFluxes,
4711 Vector<EBAMRIVData>& a_cdrFluxesExtrap,
4714 const Real a_dt) noexcept
4716 CH_TIME(
"ItoKMCStepper::fillSecondaryEmissionEB(full)");
4717 if (m_verbosity > 5) {
4718 pout() << m_name +
"::fillSecondaryEmissionEB(full)" << endl;
4721 const int numItoSpecies = m_physics->getNumItoSpecies();
4722 const int numCdrSpecies = m_physics->getNumCdrSpecies();
4723 const int numPhotonSpecies = m_physics->getNumPhotonSpecies();
4725 CH_assert(a_secondaryParticles.size() == numItoSpecies);
4726 CH_assert(a_cdrFluxes.size() == numCdrSpecies);
4727 CH_assert(a_secondaryPhotons.size() == numPhotonSpecies);
4728 CH_assert(a_primaryParticles.size() == numItoSpecies);
4729 CH_assert(a_cdrFluxesExtrap.size() == numCdrSpecies);
4730 CH_assert(a_primaryPhotons.size() == numPhotonSpecies);
4731 CH_assert(a_electricField.getRealm() == m_particleRealm);
4732 CH_assert(a_dt >= 0.0);
4735 for (
int i = 0; i < numItoSpecies; i++) {
4736 CH_assert(a_secondaryParticles[i].getRealm() == m_particleRealm);
4737 CH_assert(a_primaryParticles[i]->getRealm() == m_particleRealm);
4739 a_secondaryParticles[i].clearParticles();
4740 a_secondaryParticles[i].organizeParticlesByCell();
4742 a_primaryParticles[i]->organizeParticlesByCell();
4745 for (
int i = 0; i < numCdrSpecies; i++) {
4746 CH_assert(a_cdrFluxes[i].getRealm() == m_particleRealm);
4747 CH_assert(a_cdrFluxesExtrap[i].getRealm() == m_particleRealm);
4753 for (
int i = 0; i < numPhotonSpecies; i++) {
4754 CH_assert(a_secondaryPhotons[i].getRealm() == m_particleRealm);
4755 CH_assert(a_primaryPhotons[i]->getRealm() == m_particleRealm);
4757 a_secondaryPhotons[i].clearParticles();
4759 a_secondaryPhotons[i].organizeParticlesByCell();
4760 a_primaryPhotons[i]->organizeParticlesByCell();
4763 const RealVect probLo = m_amr->getProbLo();
4765 const Vector<Electrode>& electrodes = m_computationalGeometry->getElectrodes();
4766 const Vector<Dielectric>& dielectrics = m_computationalGeometry->getDielectrics();
4768 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
4769 const DisjointBoxLayout& dbl = m_amr->getGrids(m_particleRealm)[lvl];
4770 const DataIterator& dit = dbl.dataIterator();
4771 const EBISLayout& ebisl = m_amr->getEBISLayout(m_particleRealm, m_plasmaPhase)[lvl];
4772 const Real dx = m_amr->getDx()[lvl];
4774 const int nbox = dit.size();
4776 #pragma omp parallel for schedule(runtime)
4777 for (
int mybox = 0; mybox < nbox; mybox++) {
4778 const DataIndex& din = dit[mybox];
4780 const EBISBox& ebisbox = ebisl[din];
4781 const EBCellFAB& electricField = (*a_electricField[lvl])[din];
4782 const BaseFab<bool>& validCells = (*m_amr->getValidCells(m_particleRealm)[lvl])[din];
4784 bool isDielectric =
false;
4786 Vector<BinFab<ItoParticle>*> secondaryParticlesFAB;
4787 Vector<BinFab<ItoParticle>*> primaryParticlesFAB;
4789 Vector<BinFab<Photon>*> secondaryPhotonsFAB;
4790 Vector<BinFab<Photon>*> primaryPhotonsFAB;
4792 Vector<BaseIVFAB<Real>*> cdrFluxesFAB;
4793 Vector<BaseIVFAB<Real>*> cdrFluxesExtrapFAB;
4795 for (
auto it = m_ito->iterator(); it.ok(); ++it) {
4796 secondaryParticlesFAB.push_back(&(a_secondaryParticles[it.index()].getCellParticles(lvl)[din]));
4797 primaryParticlesFAB.push_back(&(a_primaryParticles[it.index()]->getCellParticles(lvl)[din]));
4800 for (
auto it = m_cdr->iterator(); it.ok(); ++it) {
4801 cdrFluxesFAB.push_back(&((*(a_cdrFluxes[it.index()])[lvl])[din]));
4802 cdrFluxesExtrapFAB.push_back(&((*(a_cdrFluxesExtrap[it.index()])[lvl])[din]));
4805 for (
auto it = m_rte->iterator(); it.ok(); ++it) {
4806 secondaryPhotonsFAB.push_back(&(a_secondaryPhotons[it.index()].getCellParticles(lvl)[din]));
4807 primaryPhotonsFAB.push_back(&(a_primaryPhotons[it.index()]->getCellParticles(lvl)[din]));
4811 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
4812 const IntVect iv = vof.gridIndex();
4814 if (validCells(iv)) {
4815 const RealVect E = RealVect(D_DECL(electricField(vof, 0), electricField(vof, 1), electricField(vof, 2)));
4816 const RealVect bndryNormal = ebisbox.normal(vof);
4817 const RealVect bndryCentroid = ebisbox.bndryCentroid(vof);
4818 const RealVect cellCentroid = ebisbox.centroid(vof);
4819 const RealVect cellCenter = probLo +
Location::position(Location::Cell::Center, vof, ebisbox, dx);
4820 const RealVect physPos = cellCenter + bndryCentroid * dx;
4821 const Real bndryArea = ebisbox.bndryArea(vof);
4823 Vector<List<ItoParticle>> secondaryParticles(numItoSpecies);
4824 Vector<List<ItoParticle>> primaryParticles(numItoSpecies);
4826 Vector<Real> cdrFluxes(numCdrSpecies, 0.0);
4827 Vector<Real> cdrFluxesExtrap(numCdrSpecies, 0.0);
4829 Vector<List<Photon>> secondaryPhotons(numPhotonSpecies);
4830 Vector<List<Photon>> primaryPhotons(numPhotonSpecies);
4832 for (
int i = 0; i < numItoSpecies; i++) {
4833 secondaryParticles[i] = (*secondaryParticlesFAB[i])(iv, 0);
4834 primaryParticles[i] = (*primaryParticlesFAB[i])(iv, 0);
4838 for (
int i = 0; i < numCdrSpecies; i++) {
4840 cdrFluxesExtrap[i] = (*cdrFluxesExtrapFAB[i])(vof, 0);
4843 for (
int i = 0; i < numPhotonSpecies; i++) {
4844 secondaryPhotons[i] = (*secondaryPhotonsFAB[i])(iv, 0);
4845 primaryPhotons[i] = (*primaryPhotonsFAB[i])(iv, 0);
4852 for (
int i = 0; i < electrodes.size(); i++) {
4853 const Real curDist = electrodes[i].getImplicitFunction()->value(physPos);
4855 if (std::abs(curDist) < std::abs(minDist)) {
4861 for (
int i = 0; i < dielectrics.size(); i++) {
4862 const Real curDist = dielectrics[i].getImplicitFunction()->value(physPos);
4864 if (std::abs(curDist) < std::abs(minDist)) {
4867 isDielectric =
true;
4872 m_physics->secondaryEmissionEB(secondaryParticles,
4890 for (
int i = 0; i < numItoSpecies; i++) {
4891 (*secondaryParticlesFAB[i])(iv, 0) = secondaryParticles[i];
4894 for (
int i = 0; i < numCdrSpecies; i++) {
4895 (*cdrFluxesFAB[i])(vof, 0) = cdrFluxes[i];
4898 for (
int i = 0; i < numPhotonSpecies; i++) {
4899 (*secondaryPhotonsFAB[i])(iv, 0) = secondaryPhotons[i];
4905 VoFIterator& vofit = (*m_amr->getVofIterator(m_particleRealm, m_plasmaPhase)[lvl])[din];
4911 for (
int i = 0; i < numItoSpecies; i++) {
4912 a_secondaryParticles[i].organizeParticlesByPatch();
4913 a_primaryParticles[i]->organizeParticlesByPatch();
4916 for (
int i = 0; i < numPhotonSpecies; i++) {
4917 a_secondaryPhotons[i].organizeParticlesByPatch();
4918 a_primaryPhotons[i]->organizeParticlesByPatch();
4922 template <
typename I,
typename C,
typename R,
typename F>
4926 CH_TIME(
"ItoKMCStepper::resolveSecondaryEmissionEB(short)");
4927 if (m_verbosity > 5) {
4928 pout() << m_name +
"::resolveSecondaryEmissionEB(short)" << endl;
4931 Vector<ParticleContainer<ItoParticle>*> secondaryParticles;
4932 Vector<ParticleContainer<ItoParticle>*> primaryParticles;
4934 for (
auto it = m_ito->iterator(); it.ok(); ++it) {
4935 const int idx = it.index();
4937 primaryParticles.push_back(&(it()->getParticles(ItoSolver::WhichContainer::EB)));
4938 secondaryParticles.push_back(&(m_secondaryParticles[idx]));
4942 Vector<EBAMRIVData*> cdrFluxes;
4943 for (
auto it = m_cdr->iterator(); it.ok(); ++it) {
4944 const RefCountedPtr<CdrSolver>& solver = it();
4945 const int idx = it.index();
4949 m_amr->copyData(ebFlux, m_cdrFluxes[idx]);
4951 m_amr->arithmeticAverage(ebFlux, m_fluidRealm, m_plasmaPhase);
4957 EBAMRIVData& surfaceChargeDensity = m_sigmaSolver->getPhi();
4959 this->resolveSecondaryEmissionEB(secondaryParticles, primaryParticles, cdrFluxes, surfaceChargeDensity, a_dt);
4961 m_sigmaSolver->resetElectrodes(0.0);
4962 m_amr->arithmeticAverage(surfaceChargeDensity, m_fluidRealm, m_plasmaPhase);
4965 template <
typename I,
typename C,
typename R,
typename F>
4969 Vector<EBAMRIVData*>& a_cdrFluxes,
4971 const Real a_dt) noexcept
4973 CH_TIME(
"ItoKMCStepper::resolveSecondaryEmissionEB(full)");
4974 if (m_verbosity > 5) {
4975 pout() << m_name +
"::resolveSecondaryEmissionEB(full)" << endl;
4978 const int numItoSpecies = m_physics->getNumItoSpecies();
4979 const int numCdrSpecies = m_physics->getNumCdrSpecies();
4981 CH_assert(a_secondaryParticles.size() == numItoSpecies);
4982 CH_assert(a_primaryParticles.size() == numItoSpecies);
4983 CH_assert(a_cdrFluxes.size() == numCdrSpecies);
4984 CH_assert(a_surfaceChargeDensity.getRealm() == m_fluidRealm);
4986 for (
int i = 0; i < numItoSpecies; i++) {
4987 CH_assert(a_secondaryParticles[i]->getRealm() == m_particleRealm);
4988 CH_assert(a_primaryParticles[i]->getRealm() == m_particleRealm);
4991 for (
int i = 0; i < numCdrSpecies; i++) {
4992 CH_assert(a_secondaryParticles[i]->getRealm() == m_particleRealm);
4993 CH_assert(a_primaryParticles[i]->getRealm() == m_particleRealm);
4997 for (
auto it = m_ito->iterator(); it.ok(); ++it) {
4998 const RefCountedPtr<ItoSolver>& solver = it();
4999 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
5001 const int idx = it.index();
5002 const int Z = species->getChargeNumber();
5010 *a_primaryParticles[idx]);
5012 m_amr->copyData(m_fluidScratchEB, m_particleScratchEB);
5019 *a_secondaryParticles[idx]);
5021 m_amr->copyData(m_fluidScratchEB, m_particleScratchEB);
5029 a_primaryParticles[idx]->clearParticles();
5031 if (a_secondaryParticles[idx]->getNumberOfValidParticlesGlobal() > 0) {
5032 MayDay::Abort(
"logic bust");
5037 for (
auto it = m_cdr->iterator(); it.ok(); ++it) {
5038 const RefCountedPtr<CdrSolver>& solver = it();
5039 const RefCountedPtr<CdrSpecies>& species = solver->getSpecies();
5041 const int idx = it.index();
5042 const int Z = species->getChargeNumber();
5052 m_amr->allocate(divG, m_fluidRealm, m_plasmaPhase, 1);
5053 m_amr->allocate(G, m_fluidRealm, m_plasmaPhase, 1);
5057 solver->computeDivG(divG, G, *a_cdrFluxes[idx],
false);
5062 m_amr->conservativeAverage(phi, m_fluidRealm, m_plasmaPhase);
5063 m_amr->interpGhostPwl(phi, m_fluidRealm, m_plasmaPhase);
5070 m_amr->conservativeAverage(a_surfaceChargeDensity, m_fluidRealm, m_plasmaPhase);
5073 template <
typename I,
typename C,
typename R,
typename F>
5077 CH_TIME(
"ItoKMCStepper::computePhysicsDt()");
5078 if (m_verbosity > 5) {
5079 pout() << m_name +
"::computePhysicsDt()" << endl;
5082 const Real dt = this->computePhysicsDt(m_electricFieldFluid);
5087 template <
typename I,
typename C,
typename R,
typename F>
5091 CH_TIME(
"ItoKMCStepper::computePhysicsDt(EBAMRCellFAB, Vector<EBAMRCellFAB*>)");
5092 if (m_verbosity > 5) {
5093 pout() << m_name +
"::computePhysicsDt(EBAMRCellFAB, Vector<EBAMRCellFAB*>)" << endl;
5096 CH_assert(a_electricField.getRealm() == m_fluidRealm);
5098 const int numItoSpecies = m_physics->getNumItoSpecies();
5099 const int numCdrSpecies = m_physics->getNumCdrSpecies();
5104 m_ito->organizeParticlesByCell(ItoSolver::WhichContainer::Bulk);
5107 if (numItoSpecies > 0) {
5108 this->computeReactiveItoParticlesPerCell(m_particleItoPPC);
5110 const Interval srcInterv(0, numItoSpecies - 1);
5111 const Interval dstInterv(0, numItoSpecies - 1);
5113 m_amr->copyData(m_fluidPPC, m_particleItoPPC, dstInterv, srcInterv);
5115 if (numCdrSpecies > 0) {
5116 this->computeReactiveCdrParticlesPerCell(m_fluidCdrPPC);
5118 const Interval srcInterv(0, numCdrSpecies - 1);
5119 const Interval dstInterv(numItoSpecies, numItoSpecies + numCdrSpecies - 1);
5121 m_amr->copyData(m_fluidPPC, m_fluidCdrPPC, dstInterv, srcInterv);
5124 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
5125 const Real levelDt = this->computePhysicsDt(*a_electricField[lvl], *m_fluidPPC[lvl], lvl);
5131 m_ito->organizeParticlesByPatch(ItoSolver::WhichContainer::Bulk);
5136 template <
typename I,
typename C,
typename R,
typename F>
5139 const LevelData<EBCellFAB>& a_particlesPerCell,
5140 const int a_level) noexcept
5142 CH_TIME(
"ItoKMCStepper::computePhysicsDt(LD<EBCellFAB>, LD<EBCellFAB>, int)");
5143 if (m_verbosity > 5) {
5144 pout() << m_name +
"::computePhysicsDt(LD<EBCellFAB>, LD<EBCellFAB>, int)" << endl;
5147 const int numPlasmaSpecies = m_physics->getNumPlasmaSpecies();
5149 CH_assert(a_particlesPerCell.nComp() == numPlasmaSpecies);
5150 CH_assert(a_electricField.nComp() == SpaceDim);
5154 const DisjointBoxLayout& dbl = m_amr->getGrids(m_fluidRealm)[a_level];
5155 const DataIterator& dit = dbl.dataIterator();
5157 const int nbox = dit.size();
5159 #pragma omp parallel for schedule(runtime) reduction(min : minDt)
5160 for (
int mybox = 0; mybox < nbox; mybox++) {
5161 const DataIndex& din = dit[mybox];
5163 const Real patchDt = this->computePhysicsDt(a_electricField[din], a_particlesPerCell[din], a_level, din, dbl[din]);
5171 template <
typename I,
typename C,
typename R,
typename F>
5174 const EBCellFAB& a_particlesPerCell,
5176 const DataIndex a_dit,
5177 const Box a_box) noexcept
5179 CH_TIME(
"ItoKMCStepper::computePhysicsDt(EBCellFAB, EBCellFAB, int, DataIndex, Box)");
5180 if (m_verbosity > 5) {
5181 pout() << m_name +
"::computePhysicsDt(EBCellFAB, EBCellFAB, int, DataIndex, Box)" << endl;
5186 const int numPlasmaSpecies = m_physics->getNumPlasmaSpecies();
5188 CH_assert(a_electricField.nComp() == SpaceDim);
5189 CH_assert(a_particlesPerCell.nComp() == numPlasmaSpecies);
5192 const Real dx = m_amr->getDx()[a_level];
5193 const RealVect probLo = m_amr->getProbLo();
5194 const EBISBox& ebisbox = m_amr->getEBISLayout(m_fluidRealm, m_plasmaPhase)[a_level][a_dit];
5197 const BaseFab<bool>& validCells = (*m_amr->getValidCells(m_fluidRealm)[a_level])[a_dit];
5200 const FArrayBox& electricFieldReg = a_electricField.getFArrayBox();
5201 const FArrayBox& particlesPerCellReg = a_particlesPerCell.getFArrayBox();
5205 Vector<Physics::ItoKMC::FPR> ppc(numPlasmaSpecies);
5208 auto regularKernel = [&](
const IntVect& iv) ->
void {
5210 if (ebisbox.isRegular(iv) && validCells(iv, 0)) {
5211 const RealVect E = RealVect(D_DECL(electricFieldReg(iv, 0), electricFieldReg(iv, 1), electricFieldReg(iv, 2)));
5212 const RealVect pos = m_amr->getProbLo() + dx * (RealVect(iv) + 0.5 * RealVect::Unit);
5214 for (
int i = 0; i < numPlasmaSpecies; i++) {
5215 ppc[i] = particlesPerCellReg(iv, i);
5218 const Real cellDt = m_physics->computeDt(E, pos, ppc);
5225 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
5226 const IntVect& iv = vof.gridIndex();
5229 if (ebisbox.isIrregular(iv) && validCells(iv, 0)) {
5230 const RealVect E = RealVect(D_DECL(a_electricField(vof, 0), a_electricField(vof, 1), a_electricField(vof, 2)));
5231 const RealVect pos = probLo +
Location::position(Location::Cell::Centroid, vof, ebisbox, dx);
5233 for (
int i = 0; i < numPlasmaSpecies; i++) {
5234 ppc[i] = a_particlesPerCell(vof, i);
5237 const Real cellDt = m_physics->computeDt(E, pos, ppc);
5244 VoFIterator& vofit = (*m_amr->getVofIterator(m_fluidRealm, m_plasmaPhase)[a_level])[a_dit];
5252 template <
typename I,
typename C,
typename R,
typename F>
5256 CH_TIME(
"ItoKMCStepper::computeTotalCharge()");
5257 if (m_verbosity > 5) {
5258 pout() << m_name +
"::computeTotalCharge()" << endl;
5261 const bool kappaScale =
true;
5263 Real totalCharge = 0.0;
5265 totalCharge += this->computeQplus();
5266 totalCharge += this->computeQminu();
5267 totalCharge += this->computeQsurf();
5272 template <
typename I,
typename C,
typename R,
typename F>
5276 CH_TIME(
"ItoKMCStepper::computeQplus()");
5277 if (m_verbosity > 5) {
5278 pout() << m_name +
"::computeQplus()" << endl;
5281 const bool kappaScale =
true;
5283 Real totalCharge = 0.0;
5286 for (
auto it = m_ito->iterator(); it.ok(); ++it) {
5287 const RefCountedPtr<ItoSolver>& solver = it();
5288 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
5290 const int Z = species->getChargeNumber();
5295 totalCharge += Z * ParticleOps::sum<ItoParticle, &ItoParticle::weight>(particles);
5300 for (
auto it = m_cdr->iterator(); it.ok(); ++it) {
5301 const RefCountedPtr<CdrSolver>& solver = it();
5302 const RefCountedPtr<CdrSpecies>& species = solver->getSpecies();
5304 const int Z = species->getChargeNumber();
5309 totalCharge += Z * solver->computeMass(phi, kappaScale);
5316 template <
typename I,
typename C,
typename R,
typename F>
5320 CH_TIME(
"ItoKMCStepper::computeQminu()");
5321 if (m_verbosity > 5) {
5322 pout() << m_name +
"::computeQminu()" << endl;
5325 const bool kappaScale =
true;
5327 Real totalCharge = 0.0;
5330 for (
auto it = m_ito->iterator(); it.ok(); ++it) {
5331 const RefCountedPtr<ItoSolver>& solver = it();
5332 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
5334 const int Z = species->getChargeNumber();
5339 totalCharge += Z * ParticleOps::sum<ItoParticle, &ItoParticle::weight>(particles);
5344 for (
auto it = m_cdr->iterator(); it.ok(); ++it) {
5345 const RefCountedPtr<CdrSolver>& solver = it();
5346 const RefCountedPtr<CdrSpecies>& species = solver->getSpecies();
5348 const int Z = species->getChargeNumber();
5353 totalCharge += Z * solver->computeMass(phi, kappaScale);
5360 template <
typename I,
typename C,
typename R,
typename F>
5364 CH_TIME(
"ItoKMCStepper::computeQsurf()");
5365 if (m_verbosity > 5) {
5366 pout() << m_name +
"::computeQsurf()" << endl;
5369 return m_sigmaSolver->computeMass();
5372 template <
typename I,
typename C,
typename R,
typename F>
5376 CH_TIME(
"ItoKMCStepper::advancePhotons(Real)");
5377 if (m_verbosity > 5) {
5378 pout() << m_name +
"::advancePhotons(Real)" << endl;
5386 for (
auto solverIt = m_rte->iterator(); solverIt.ok(); ++solverIt) {
5387 RefCountedPtr<McPhoto>& solver = solverIt();
5398 solver->
clear(bulkPhotons);
5399 solver->clear(ebPhotons);
5400 solver->clear(domainPhotons);
5402 if (solver->isInstantaneous()) {
5403 solver->clear(photons);
5407 solver->clear(sourcePhotons);
5410 solver->advancePhotonsInstantaneous(bulkPhotons, ebPhotons, domainPhotons, photons);
5415 solver->clear(sourcePhotons);
5418 solver->advancePhotonsTransient(bulkPhotons, ebPhotons, domainPhotons, photons, a_dt);
5423 template <
typename I,
typename C,
typename R,
typename F>
5427 CH_TIME(
"ItoKMCStepper::sortPhotonsByCell(McPhoto::WhichContainer)");
5428 if (m_verbosity > 5) {
5429 pout() << m_name +
"::sortPhotonsByCell(McPhoto::WhichContainer)" << endl;
5432 for (
auto solverIt = m_rte->iterator(); solverIt.ok(); ++solverIt) {
5433 solverIt()->sortPhotonsByCell(a_which);
5437 template <
typename I,
typename C,
typename R,
typename F>
5441 CH_TIME(
"ItoKMCStepper::sortPhotonsByPatch(McPhoto::WhichContainer)");
5442 if (m_verbosity > 5) {
5443 pout() << m_name +
"::sortPhotonsByPatch(McPhoto::WhichContainer)" << endl;
5446 for (
auto solverIt = m_rte->iterator(); solverIt.ok(); ++solverIt) {
5447 solverIt()->sortPhotonsByPatch(a_which);
5451 template <
typename I,
typename C,
typename R,
typename F>
5452 Vector<RefCountedPtr<ItoSolver>>
5455 CH_TIME(
"ItoKMCStepper::getLoadBalanceSolvers()");
5456 if (m_verbosity > 5) {
5457 pout() << m_name +
"::getLoadBalanceSolvers()" << endl;
5460 Vector<RefCountedPtr<ItoSolver>> lbSolvers;
5463 bool loadBalanceAll =
false;
5464 for (
int i = 0; i < m_loadBalanceIndices.size(); i++) {
5465 if (m_loadBalanceIndices[i] < 0) {
5466 loadBalanceAll =
true;
5470 if (loadBalanceAll) {
5471 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
5472 lbSolvers.push_back(solverIt());
5476 for (
int i = 0; i < m_loadBalanceIndices.size(); i++) {
5477 RefCountedPtr<ItoSolver>& solver = m_ito->getSolvers()[i];
5479 lbSolvers.push_back(solver);
5486 template <
typename I,
typename C,
typename R,
typename F>
5490 CH_TIME(
"TimeStepper::loadBalanceThisRealm");
5491 if (m_verbosity > 5) {
5492 pout() <<
"TimeStepper::loadBalanceThisRealm" << endl;
5497 if (a_realm == m_particleRealm && m_loadBalanceParticles) {
5500 else if (a_realm == m_fluidRealm && m_loadBalanceFluid) {
5507 template <
typename I,
typename C,
typename R,
typename F>
5510 Vector<Vector<Box>>& a_boxes,
5511 const std::string a_realm,
5512 const Vector<DisjointBoxLayout>& a_grids,
5514 const int a_finestLevel)
5516 CH_TIME(
"ItoKMCStepper::loadBalanceBoxes");
5517 if (m_verbosity > 5) {
5518 pout() << m_name +
"::loadBalanceBoxes" << endl;
5521 if (m_loadBalanceParticles && a_realm == m_particleRealm) {
5522 this->loadBalanceParticleRealm(a_procs, a_boxes, a_realm, a_grids, a_lmin, a_finestLevel);
5524 else if (m_loadBalanceFluid && a_realm == m_fluidRealm) {
5525 this->loadBalanceFluidRealm(a_procs, a_boxes, a_realm, a_grids, a_lmin, a_finestLevel);
5529 template <
typename I,
typename C,
typename R,
typename F>
5532 Vector<Vector<Box>>& a_boxes,
5533 const std::string a_realm,
5534 const Vector<DisjointBoxLayout>& a_grids,
5536 const int a_finestLevel) noexcept
5538 CH_TIME(
"ItoKMCStepper::loadBalanceParticleRealm(...)");
5539 if (m_verbosity > 5) {
5540 pout() << m_name +
"::loadBalanceParticleRealm(...)" << endl;
5559 if (!m_loadBalanceParticles) {
5560 MayDay::Error(
"ItoKMCStepper::loadBalanceParticleRealm -- logic bust, should not have been called!");
5564 Vector<RefCountedPtr<ItoSolver>> lbSolvers = this->getLoadBalanceSolvers();
5567 a_procs.resize(1 + a_finestLevel);
5568 a_boxes.resize(1 + a_finestLevel);
5570 for (
int lvl = a_lmin; lvl <= a_finestLevel; lvl++) {
5571 a_procs[lvl] = a_grids[lvl].procIDs();
5572 a_boxes[lvl] = a_grids[lvl].boxArray();
5580 m_amr->allocate(totalPPC, m_particleRealm, m_plasmaPhase, 1);
5581 m_amr->allocate(speciesPPC, m_particleRealm, m_plasmaPhase, 1);
5588 Vector<RefCountedPtr<EBCoarseToFineInterp>> interpOp(1 + a_finestLevel);
5589 for (
int lvl = 1; lvl <= a_finestLevel; lvl++) {
5590 const EBLevelGrid& eblgFine = *m_amr->getEBLevelGrid(m_particleRealm, m_plasmaPhase)[lvl];
5591 const EBLevelGrid& eblgCoFi = *m_amr->getEBLevelGridCoFi(m_particleRealm, m_plasmaPhase)[lvl - 1];
5592 const EBLevelGrid& eblgCoar = *m_amr->getEBLevelGrid(m_particleRealm, m_plasmaPhase)[lvl - 1];
5593 const int refRat = m_amr->getRefinementRatios()[lvl - 1];
5595 interpOp[lvl] = RefCountedPtr<EBCoarseToFineInterp>(
new EBCoarseToFineInterp(eblgFine, eblgCoFi, eblgCoar, refRat));
5600 for (
int i = 0; i < lbSolvers.size(); i++) {
5602 const int oldFinestLevel = oldData.
size() - 1;
5605 for (
int lvl = 0; lvl <=
std::max(0, a_lmin - 1); lvl++) {
5606 oldData[lvl]->copyTo(*speciesPPC[lvl]);
5610 for (
int lvl =
std::max(1, a_lmin); lvl <= a_finestLevel; lvl++) {
5611 RefCountedPtr<EBCoarseToFineInterp>& interpolator = interpOp[lvl];
5613 interpolator->interpolate(*speciesPPC[lvl],
5614 *speciesPPC[lvl - 1],
5616 EBCoarseToFineInterp::Type::ConservativePWC);
5620 if (lvl <=
std::min(oldFinestLevel, a_finestLevel)) {
5621 oldData[lvl]->copyTo(*speciesPPC[lvl]);
5631 Vector<Vector<long int>> loads(1 + a_finestLevel, 0L);
5632 for (
int lvl = 0; lvl <= a_finestLevel; lvl++) {
5633 const DisjointBoxLayout& dbl = a_grids[lvl];
5634 const DataIterator& dit = dbl.dataIterator();
5636 Vector<long int>& levelLoads = loads[lvl];
5638 levelLoads.resize(dbl.size());
5640 const int nbox = dit.size();
5642 #pragma omp parallel for schedule(runtime)
5643 for (
int mybox = 0; mybox < nbox; mybox++) {
5644 const DataIndex& din = dit[mybox];
5646 const Box cellBox = dbl[din];
5647 const EBCellFAB& PPC = (*totalPPC[lvl])[din];
5648 const EBISBox& ebisbox = PPC.getEBISBox();
5649 const BaseFab<bool>& validCells = (*m_amr->getValidCells(m_particleRealm)[lvl])[din];
5650 const FArrayBox& regPPC = PPC.getFArrayBox();
5652 auto regularKernel = [&](
const IntVect& iv) ->
void {
5653 if (validCells(iv, 0) && ebisbox.isRegular(iv)) {
5654 levelLoads[din.intCode()] += (
long int)regPPC(iv, 0);
5664 for (LayoutIterator lit = dbl.layoutIterator(); lit.ok(); ++lit) {
5665 const Box cellBox = dbl[lit()];
5667 levelLoads[lit().intCode()] += (
long int)m_loadPerCell * cellBox.numPts();
5677 for (
int lvl = 0; lvl <= a_finestLevel; lvl++) {
5682 template <
typename I,
typename C,
typename R,
typename F>
5685 Vector<Vector<Box>>& a_boxes,
5686 const std::string a_realm,
5687 const Vector<DisjointBoxLayout>& a_grids,
5689 const int a_finestLevel) noexcept
5691 CH_TIME(
"ItoKMCStepper::loadBalanceFluidRealm(...)");
5692 if (m_verbosity > 5) {
5693 pout() << m_name +
"::loadBalanceFluidRealm(...)" << endl;
5696 CH_assert(m_loadBalanceFluid);
5697 CH_assert(a_realm == m_fluidRealm);
5703 a_procs.resize(1 + a_finestLevel);
5704 a_boxes.resize(1 + a_finestLevel);
5708 m_amr->regridOperators(m_fluidRealm, a_lmin);
5711 m_fieldSolver->allocate();
5712 m_fieldSolver->setupSolver();
5719 for (
int lvl = 0; lvl <= a_finestLevel; lvl++) {
5720 Vector<long long> boxLoads = m_fieldSolver->computeLoads(a_grids[lvl], lvl);
5723 a_boxes[lvl] = a_grids[lvl].boxArray();
5730 template <
typename I,
typename C,
typename R,
typename F>
5734 CH_TIME(
"ItoKMCStepper::getCheckpointLoads(...)");
5735 if (m_verbosity > 5) {
5736 pout() << m_name +
"::getCheckpointLoads(...)" << endl;
5739 const DisjointBoxLayout& dbl = m_amr->getGrids(a_realm)[a_level];
5740 const int nbox = dbl.size();
5742 Vector<long int> loads(nbox, 0L);
5744 if (m_loadBalanceParticles && a_realm == m_particleRealm) {
5749 Vector<RefCountedPtr<ItoSolver>> loadBalanceProxySolvers = this->getLoadBalanceSolvers();
5751 for (
int isolver = 0; isolver < loadBalanceProxySolvers.size(); isolver++) {
5755 Vector<long int> solverLoads(nbox, 0L);
5756 loadBalanceProxySolvers[isolver]->computeLoads(solverLoads, dbl, a_level);
5759 for (
int ibox = 0; ibox < nbox; ibox++) {
5760 loads[ibox] += solverLoads[ibox];
5766 for (LayoutIterator lit = dbl.layoutIterator(); lit.ok(); ++lit) {
5767 const Box box = dbl[lit()];
5769 loads[lit().intCode()] += lround(m_loadPerCell * box.numPts());
5779 template <
typename I,
typename C,
typename R,
typename F>
5783 CH_TIME(
"ItoKMCStepper::computeEdotJSource(a_dt)");
5784 if (m_verbosity > 5) {
5785 pout() << m_name +
"::computeEdotJSource(a_dt)" << endl;
5788 CH_assert(a_dt > 0.0);
5792 CH_assert(m_EdotJ.getRealm() == m_fluidRealm);
5813 m_amr->allocate(computationParticles, m_particleRealm);
5817 const EBAMRCellData potentialPhase = m_amr->alias(m_plasmaPhase, m_fieldSolver->getPotential());
5818 m_amr->copyData(m_particleScratch1, potentialPhase);
5820 m_amr->conservativeAverage(m_particleScratch1, m_particleRealm, m_plasmaPhase);
5821 m_amr->interpGhost(m_particleScratch1, m_particleRealm, m_plasmaPhase);
5823 for (
auto solverIt = m_ito->iterator(); solverIt.ok(); ++solverIt) {
5824 RefCountedPtr<ItoSolver>& solver = solverIt();
5825 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
5827 const int idx = solverIt.index();
5828 const int Z = species->getChargeNumber();
5829 const bool mobile = solver->isMobile();
5830 const bool diffusive = solver->isDiffusive();
5832 if (Z != 0 && (mobile || diffusive)) {
5837 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
5838 const DisjointBoxLayout& dbl = m_amr->getGrids(m_particleRealm)[lvl];
5839 const DataIterator& dit = dbl.dataIterator();
5841 const int nbox = dit.size();
5843 #pragma omp parallel for schedule(runtime)
5844 for (
int mybox = 0; mybox < nbox; mybox++) {
5845 const DataIndex& din = dit[mybox];
5847 List<CompParticle>& patchCompParticles = computationParticles[lvl][din].listItems();
5848 const List<ItoParticle>& patchItoParticles = particles[lvl][din].listItems();
5850 for (ListIterator<ItoParticle> lit(patchItoParticles); lit.ok(); ++lit) {
5857 p.position() = itoParticle.
position();
5858 p.template real<0>() = itoParticle.
weight();
5859 p.template real<1>() = 0.0;
5860 p.template real<2>() = 0.0;
5863 patchCompParticles.add(p);
5869 m_amr->interpolateParticles<CompParticle, &CompParticle::template real<1>>(computationParticles,
5873 solver->getDeposition(),
5877 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
5878 const DisjointBoxLayout& dbl = m_amr->getGrids(m_particleRealm)[lvl];
5879 const DataIterator& dit = dbl.dataIterator();
5881 const int nbox = dit.size();
5883 #pragma omp parallel for schedule(runtime)
5884 for (
int mybox = 0; mybox < nbox; mybox++) {
5885 const DataIndex& din = dit[mybox];
5887 List<CompParticle>& particles = computationParticles[lvl][din].listItems();
5889 for (ListIterator<CompParticle> lit(particles); lit.ok(); ++lit) {
5892 const RealVect tmp = lit().position();
5895 lit().position() = lit().template vect<0>();
5896 lit().template vect<0>() = tmp;
5901 computationParticles.remap();
5904 m_amr->interpolateParticles<CompParticle, &CompParticle::template real<2>>(computationParticles,
5908 solver->getDeposition());
5911 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
5912 const DisjointBoxLayout& dbl = m_amr->getGrids(m_particleRealm)[lvl];
5913 const DataIterator& dit = dbl.dataIterator();
5915 const int nbox = dit.size();
5917 #pragma omp parallel for schedule(runtime)
5918 for (
int mybox = 0; mybox < nbox; mybox++) {
5919 const DataIndex& din = dit[mybox];
5921 List<CompParticle>& particles = computationParticles[lvl][din].listItems();
5923 for (ListIterator<CompParticle> lit(particles); lit.ok(); ++lit) {
5924 lit().position() = lit().template vect<0>();
5927 lit().template real<0>() *= (lit().template real<1>() - lit().template real<2>());
5932 computationParticles.remap();
5935 m_amr->depositParticles<CompParticle, &CompParticle::template real<0>>(m_particleScratch1,
5938 computationParticles,
5939 solver->getDeposition(),
5940 solver->getCoarseFineDeposition());
5943 m_amr->copyData(m_fluidScratch1, m_particleScratch1);
5952 template <
typename I,
typename C,
typename R,
typename F>
5956 CH_TIME(
"ItoKMCStepper::computePhysicsPlotVariables");
5957 if (m_verbosity > 5) {
5958 pout() << m_name +
"::computePhysicsPlotVariables" << endl;
5962 const int numVars = m_physics->getNumberOfPlotVariables();
5963 const int numItoSpecies = m_physics->getNumItoSpecies();
5964 const int numCdrSpecies = m_physics->getNumCdrSpecies();
5965 const int numPlasmaSpecies = m_physics->getNumPlasmaSpecies();
5966 const int numPhotonSpecies = m_physics->getNumPhotonSpecies();
5968 CH_assert(!(a_physicsPlotVars[0].isNull()));
5969 CH_assert(a_physicsPlotVars[0]->nComp() == numVars);
5970 CH_assert(a_physicsPlotVars.getRealm() == m_fluidRealm);
5973 this->computeDensityGradients();
5975 const RealVect probLo = m_amr->getProbLo();
5977 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
5978 const DisjointBoxLayout& dbl = m_amr->getGrids(m_fluidRealm)[lvl];
5979 const DataIterator& dit = dbl.dataIterator();
5980 const EBISLayout& ebisl = m_amr->getEBISLayout(m_fluidRealm, m_plasmaPhase)[lvl];
5981 const Real dx = m_amr->getDx()[lvl];
5983 const int nbox = dit.size();
5985 #pragma omp parallel for schedule(runtime)
5986 for (
int mybox = 0; mybox < nbox; mybox++) {
5987 const DataIndex& din = dit[mybox];
5989 const Box& cellBox = dbl[din];
5990 const EBISBox& ebisBox = ebisl[din];
5993 const EBCellFAB& electricField = (*m_electricFieldFluid[lvl])[din];
5994 const FArrayBox& electricFieldReg = electricField.getFArrayBox();
5997 Vector<const EBCellFAB*> densitiesIto(numItoSpecies);
5998 Vector<const EBCellFAB*> densityGradientsIto(numItoSpecies);
5999 Vector<const FArrayBox*> densitiesItoReg(numItoSpecies);
6000 Vector<const FArrayBox*> densityGradientsItoReg(numItoSpecies);
6002 Vector<const EBCellFAB*> densitiesCDR(numCdrSpecies);
6003 Vector<const EBCellFAB*> densityGradientsCDR(numCdrSpecies);
6004 Vector<const FArrayBox*> densitiesCDRReg(numCdrSpecies);
6005 Vector<const FArrayBox*> densityGradientsCDRReg(numCdrSpecies);
6007 for (
auto it = m_ito->iterator(); it.ok(); ++it) {
6008 const RefCountedPtr<ItoSolver>& solver = it();
6010 const int i = it.index();
6012 densitiesIto[i] = &(*(m_fluidPhiIto[i])[lvl])[din];
6013 densitiesItoReg[i] = &(densitiesIto[i]->getFArrayBox());
6014 densityGradientsIto[i] = &(*m_fluidGradPhiIto[i][lvl])[din];
6015 densityGradientsItoReg[i] = &(densityGradientsIto[i]->getFArrayBox());
6018 for (
auto it = m_cdr->iterator(); it.ok(); ++it) {
6019 const RefCountedPtr<CdrSolver>& solver = it();
6022 const int i = it.index();
6024 densitiesCDR[i] = &(*phi[lvl])[din];
6025 densitiesCDRReg[i] = &(densitiesCDR[i]->getFArrayBox());
6026 densityGradientsCDR[i] = &(*m_fluidGradPhiCDR[i][lvl])[din];
6027 densityGradientsCDRReg[i] = &(densityGradientsCDR[i]->getFArrayBox());
6031 const BaseFab<bool>& validCells = (*m_amr->getValidCells(m_fluidRealm)[lvl])[din];
6034 EBCellFAB& physicsPlotVars = (*a_physicsPlotVars[lvl])[din];
6035 FArrayBox& physicsPlotVarsReg = physicsPlotVars.getFArrayBox();
6038 Vector<Real> densities(numPlasmaSpecies);
6039 Vector<RealVect> densityGradients(numPlasmaSpecies);
6042 auto regularKernel = [&](
const IntVect& iv) ->
void {
6043 if (ebisBox.isRegular(iv) && validCells(iv, 0)) {
6044 const RealVect pos = probLo + dx * (RealVect(iv) + 0.5 * RealVect::Unit);
6045 const RealVect E = RealVect(
6046 D_DECL(electricFieldReg(iv, 0), electricFieldReg(iv, 1), electricFieldReg(iv, 2)));
6049 for (
int i = 0; i < numItoSpecies; i++) {
6050 densities[i] = (*densitiesItoReg[i])(iv, 0);
6051 densityGradients[i] = RealVect(D_DECL((*densityGradientsItoReg[i])(iv, 0),
6052 (*densityGradientsItoReg[i])(iv, 1),
6053 (*densityGradientsItoReg[i])(iv, 2)));
6056 for (
int i = 0; i < numCdrSpecies; i++) {
6057 densities[numItoSpecies + i] = (*densitiesCDRReg[i])(iv, 0);
6058 densityGradients[numItoSpecies + i] = RealVect(D_DECL((*densityGradientsCDRReg[i])(iv, 0),
6059 (*densityGradientsCDRReg[i])(iv, 1),
6060 (*densityGradientsCDRReg[i])(iv, 2)));
6064 const Vector<Real> plotVars = m_physics->getPlotVariables(E, pos, densities, densityGradients, dx, 1.0);
6066 CH_assert(plotVars.size() == numVars);
6068 for (
int i = 0; i < numVars; i++) {
6069 physicsPlotVarsReg(iv, i) = plotVars[i];
6075 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
6076 if (validCells(vof.gridIndex(), 0)) {
6077 const RealVect pos = probLo + dx * (RealVect(vof.gridIndex()) + 0.5 * RealVect::Unit);
6078 const RealVect E = RealVect(D_DECL(electricField(vof, 0), electricField(vof, 1), electricField(vof, 2)));
6081 for (
int i = 0; i < numItoSpecies; i++) {
6082 densities[i] = (*densitiesIto[i])(vof, 0);
6083 densityGradients[i] = RealVect(D_DECL((*densityGradientsIto[i])(vof, 0),
6084 (*densityGradientsIto[i])(vof, 1),
6085 (*densityGradientsIto[i])(vof, 2)));
6088 for (
int i = 0; i < numCdrSpecies; i++) {
6089 densities[numItoSpecies + i] = (*densitiesCDR[i])(vof, 0);
6090 densityGradients[numItoSpecies + i] = RealVect(D_DECL((*densityGradientsCDR[i])(vof, 0),
6091 (*densityGradientsCDR[i])(vof, 1),
6092 (*densityGradientsCDR[i])(vof, 2)));
6096 const Vector<Real> plotVars = m_physics->getPlotVariables(E, pos, densities, densityGradients, dx, 1.0);
6098 CH_assert(plotVars.size() == numVars);
6100 for (
int i = 0; i < numVars; i++) {
6101 physicsPlotVars(vof, i) = plotVars[i];
6107 VoFIterator& vofit = (*m_amr->getVofIterator(m_fluidRealm, m_plasmaPhase)[lvl])[din];
6114 m_amr->average(a_physicsPlotVars, m_fluidRealm, m_plasmaPhase, Average::Arithmetic, Interval(0, numVars - 1));
6115 m_amr->interpGhost(a_physicsPlotVars, m_fluidRealm, m_plasmaPhase);
6118 #include <CD_NamespaceFooter.H>
Average
Various averaging methods.
Definition: CD_Average.H:24
Agglomeration of useful data operations.
Declaration of an aggregated class for regrid operations.
EBIntersection
Enum for putting some logic into how we think about intersection between particles and EBs.
Definition: CD_EBIntersection.H:21
EBRepresentation
Enum for putting some logic into how we think about EBs. This is just a simply supporting class for v...
Definition: CD_EBRepresentation.H:22
SpeciesType
Map to species type.
Definition: CD_ItoKMCPhysics.H:66
Declaration of an abstract class for integrating the Ito-KMC-Poisson equations.
SpeciesSubset
Enum for differentiating between types of particles.
Definition: CD_ItoKMCStepper.H:40
Declaration of cell positions.
Agglomeration of basic MPI reductions.
Declaration of a static class containing some common useful particle routines that would otherwise be...
Implementation of CD_Timer.H.
Declaration of various useful units.
Factory class for CdrLayout. T is (usually) CdrSolver and S is the implementation class (e....
Definition: CD_CdrLayout.H:302
RefCountedPtr< CdrLayout< T > > newLayout(const Vector< RefCountedPtr< CdrSpecies >> &a_species) const
Factory method, create a new CdrLayout.
Definition: CD_CdrLayoutImplem.H:546
Iterator class for CdrLayout. This allows iteration through solvers (or subsets of solvers).
Definition: CD_CdrIterator.H:27
virtual bool ok() const
Ok or not.
Definition: CD_CdrIteratorImplem.H:76
Class for the cell-information that is often queried when merging particles inside a cell.
Definition: CD_CellInfo.H:25
static void scale(MFAMRCellData &a_lhs, const Real &a_scale) noexcept
Scale data by factor.
Definition: CD_DataOps.cpp:2384
static void divideFallback(EBAMRCellData &a_numerator, const EBAMRCellData &a_denominator, const Real a_fallback)
Divide data. If the denominator is zero, set the value to a fallback option.
Definition: CD_DataOps.cpp:1303
static void volumeScale(EBAMRCellData &a_data, const Vector< Real > &a_dx)
Scale data by dx^SpaceDim.
Definition: CD_DataOps.cpp:2132
static void getMaxMinNorm(Real &a_max, Real &a_min, EBAMRCellData &data)
Get maximum and minimum value of normed data.
Definition: CD_DataOps.cpp:1783
static void floor(EBAMRCellData &a_lhs, const Real a_value)
Floor values in data holder. This sets all values below a_value to a_value.
Definition: CD_DataOps.cpp:1380
static void setValue(LevelData< MFInterfaceFAB< T >> &a_lhs, const T &a_value)
Set value in an MFInterfaceFAB data holder.
Definition: CD_DataOpsImplem.H:23
static void computeMinValidBox(RealVect &a_lo, RealVect &a_hi, const RealVect a_normal, const RealVect a_centroid)
Compute the tightest possible valid box around a cut-cell volume.
Definition: CD_DataOps.cpp:3567
static void getMaxMin(Real &max, Real &min, EBAMRCellData &a_data, const int a_comp)
Get maximum and minimum value of specified component.
Definition: CD_DataOps.cpp:1637
static void incr(MFAMRCellData &a_lhs, const MFAMRCellData &a_rhs, const Real a_scale) noexcept
Function which increments data in the form a_lhs = a_lhs + a_rhs*a_scale for all components.
Definition: CD_DataOps.cpp:787
static void setCoveredValue(EBAMRCellData &a_lhs, const int a_comp, const Real a_value)
Set value in covered cells. Does specified component.
Definition: CD_DataOps.cpp:2538
static void plus(EBAMRCellData &a_lhs, const EBAMRCellData &a_rhs, const int a_srcComp, const int a_dstComp, const int a_numComp)
General addition operator for adding together data. The user can choose which components to add.
Definition: CD_DataOps.cpp:852
static void averageCellToFace(EBAMRFluxData &a_faceData, const EBAMRCellData &a_cellData, const Vector< ProblemDomain > &a_domains)
Average all components of the cell-centered data to faces.
Definition: CD_DataOps.cpp:153
static void copy(MFAMRCellData &a_dst, const MFAMRCellData &a_src)
Copy data from one data holder to another.
Definition: CD_DataOps.cpp:1118
static void multiplyScalar(EBAMRCellData &a_lhs, const EBAMRCellData &a_rhs)
Multiply data holder by another data holder.
Definition: CD_DataOps.cpp:2239
void push_back(RefCountedPtr< LevelData< T >> &a_levelData) noexcept
Push a LevelData<T> object to the back of the data vector.
Definition: CD_EBAMRDataImplem.H:128
int size() const noexcept
Get size of m_data.
Definition: CD_EBAMRDataImplem.H:66
const std::string getRealm() const noexcept
Returns the string identifier for whatever realm this data is supposed to be allocated over.
Definition: CD_EBAMRDataImplem.H:135
Class for interpolating data to fine grids. Can use constant interpolation or include limiters.
Definition: CD_EBCoarseToFineInterp.H:32
A generic particle class, holding the position and a specified number of real and vector values.
Definition: CD_GenericParticle.H:33
RealVect & position()
Get the particle position.
Definition: CD_GenericParticleImplem.H:47
Factory class for making ItoLayout.
Definition: CD_ItoLayout.H:368
RefCountedPtr< ItoLayout< T > > newLayout(const Vector< RefCountedPtr< ItoSpecies >> &a_species) const
Factory method which creates a new layout from a set of species. This can do automated casting betwee...
Definition: CD_ItoLayoutImplem.H:417
"Iterator" class for going through solvers in an ItoLayout.
Definition: CD_ItoIterator.H:24
virtual bool ok()
Ok or not.
Definition: CD_ItoIteratorImplem.H:71
A particle class for use with ItoSolvers, i.e. drifting Brownian walkers.
Definition: CD_ItoParticle.H:40
RealVect & oldPosition()
Get the old particle position.
Definition: CD_ItoParticleImplem.H:119
Real & weight()
Get particle weight.
Definition: CD_ItoParticleImplem.H:71
WhichContainer
Enum class for distinguishing various types of particle containers.
Definition: CD_ItoSolver.H:49
static void makeBalance(Vector< int > &a_ranks, const Vector< T > &a_loads, const Vector< Box > &a_boxes)
Load balancing, assigning ranks to boxes.
Definition: CD_LoadBalancingImplem.H:31
static void sort(Vector< Vector< Box >> &a_boxes, Vector< Vector< T >> &a_loads, const BoxSorting a_whichSorting)
Sorts boxes and loads over a hierarchy according to some sorting criterion.
Definition: CD_LoadBalancingImplem.H:221
Class for holding computational loads.
Definition: CD_Loads.H:30
virtual void resetLoads() noexcept
Reset loads. Sets all loads to 0.
Definition: CD_Loads.cpp:54
WhichContainer
Enum class for identifying various containers. Only used for interface reasons.
Definition: CD_McPhoto.H:45
Templated class for holding particles on an AMR hierarchy with particle remapping.
Definition: CD_ParticleContainer.H:50
AMRCellParticles< P > & getCellParticles()
Get all cell particles.
Definition: CD_ParticleContainerImplem.H:358
void addParticles(const List< P > &a_particles)
Add particles to container.
Definition: CD_ParticleContainerImplem.H:551
void clear(AMRParticles< P > &a_particles) const
Clear particles on input data holder.
Definition: CD_ParticleContainerImplem.H:1712
void clearParticles()
Clear all particles.
Definition: CD_ParticleContainerImplem.H:1670
AMRParticles< P > & getParticles()
Get all particles on all levels.
Definition: CD_ParticleContainerImplem.H:270
void transferParticles(ParticleContainer< P > &a_otherContainer)
Move particles into this container.
Definition: CD_ParticleContainerImplem.H:914
static void getComputationalParticlesPerCell(EBAMRCellData &a_ppc, const ParticleContainer< P > &a_src) noexcept
Get the number of computational particles per cell.
Definition: CD_ParticleOpsImplem.H:83
Base time stepper class that advances the Ito-KMC-Poisson system of equations. If you want a differen...
Definition: CD_ItoKMCStepper.H:60
virtual void loadBalanceBoxes(Vector< Vector< int >> &a_procs, Vector< Vector< Box >> &a_boxes, const std::string a_realm, const Vector< DisjointBoxLayout > &a_grids, const int a_lmin, const int a_finestLevel) override
Load balance grid boxes for a specified realm.
Definition: CD_ItoKMCStepperImplem.H:5509
virtual void transferCoveredParticles(const SpeciesSubset a_speciesSubset, const EBRepresentation a_representation, const Real a_tolerance) noexcept
Transfer covered particles (i.e., particles inside the EB) from the ItoSolver bulk container to EB co...
Definition: CD_ItoKMCStepperImplem.H:2335
virtual void setupCdr() noexcept
Set up the CDR solvers.
Definition: CD_ItoKMCStepperImplem.H:433
virtual void getParticleStatistics(Real &a_avgParticles, Real &a_sigma, Real &a_minParticles, Real &a_maxParticles, int &a_minRank, int &a_maxRank)
Compute some particle statistics.
Definition: CD_ItoKMCStepperImplem.H:1339
virtual void computePhysicsPlotVariables(EBAMRCellData &a_physicsPlotVars) noexcept
Compute physics plot variables.
Definition: CD_ItoKMCStepperImplem.H:5954
virtual void computeReactiveMeanEnergiesPerCell(EBAMRCellData &a_meanEnergies) noexcept
Compute the mean particle energy in all grid cells.
Definition: CD_ItoKMCStepperImplem.H:3603
virtual void parseRuntimeOptions() noexcept override
Parse runtime configurable options.
Definition: CD_ItoKMCStepperImplem.H:106
virtual void computeElectricField(EBAMRCellData &a_electricField, const phase::which_phase a_phase) const noexcept
Recompute the electric field onto the specified data holder.
Definition: CD_ItoKMCStepperImplem.H:1740
virtual void removeCoveredParticles(const SpeciesSubset a_which, const EBRepresentation a_representation, const Real a_tolerance) noexcept
Remove covered particles (i.e., particles inside the EB)
Definition: CD_ItoKMCStepperImplem.H:2216
virtual void setupRadiativeTransfer() noexcept
Set up the radiative transfer solver.
Definition: CD_ItoKMCStepperImplem.H:452
virtual void registerRealms() noexcept override
Register realms used for the simulation.
Definition: CD_ItoKMCStepperImplem.H:1485
virtual Vector< RefCountedPtr< ItoSolver > > getLoadBalanceSolvers() const noexcept
Get the solvers used for load balancing.
Definition: CD_ItoKMCStepperImplem.H:5453
virtual void computeSpaceChargeDensity() noexcept
Compute the space charge. Calls the other version.
Definition: CD_ItoKMCStepperImplem.H:1767
virtual void setVoltage(const std::function< Real(const Real a_time)> &a_voltage) noexcept
Set voltage used for the simulation.
Definition: CD_ItoKMCStepperImplem.H:1700
virtual void advanceReactionNetwork(const Real a_dt) noexcept
Chemistry advance over time a_dt.
Definition: CD_ItoKMCStepperImplem.H:3738
virtual Real getTime() const noexcept
Get current simulation time.
Definition: CD_ItoKMCStepperImplem.H:1755
virtual int getNumberOfPlotVariables() const noexcept override
Get number of plot variables for the output file.
Definition: CD_ItoKMCStepperImplem.H:864
virtual void remapParticles(const SpeciesSubset a_speciesSubset) noexcept
Remap a subset of ItoSolver particles.
Definition: CD_ItoKMCStepperImplem.H:2459
virtual void parseVerbosity() noexcept
Parse chattiness.
Definition: CD_ItoKMCStepperImplem.H:133
virtual void computeReactiveCdrParticlesPerCell(EBAMRCellData &a_ppc) noexcept
Compute the number of reactive particles per cell for the CDR solvers.
Definition: CD_ItoKMCStepperImplem.H:3498
virtual void registerOperators() noexcept override
Register operators used for the simulation.
Definition: CD_ItoKMCStepperImplem.H:1499
virtual void averageDiffusionCoefficientsCellToFace() noexcept
Average cell-centered diffusion coefficient to faces.
Definition: CD_ItoKMCStepperImplem.H:3314
virtual void parsePlotVariables() noexcept
Parse plot variables.
Definition: CD_ItoKMCStepperImplem.H:176
virtual void parseSuperParticles() noexcept
Parse the desired number of particles per cell.
Definition: CD_ItoKMCStepperImplem.H:212
virtual void writeData(LevelData< EBCellFAB > &a_output, int &a_comp, const EBAMRCellData &a_data, const std::string a_outputRealm, const int a_level, const bool a_interpToCentroids, const bool a_interpGhost) const noexcept
Write data to output. Convenience function.
Definition: CD_ItoKMCStepperImplem.H:1022
virtual void computeDensityGradients() noexcept
Compute grad(phi) and phi for both CDR and Ito species and put the result on the fluid realm.
Definition: CD_ItoKMCStepperImplem.H:1902
virtual void computeEdotJSource(const Real a_dt) noexcept
Compute the energy source term for the various plasma species.
Definition: CD_ItoKMCStepperImplem.H:5781
virtual bool solvePoisson() noexcept
Solve the electrostatic problem.
Definition: CD_ItoKMCStepperImplem.H:1994
virtual Real computeQminu() const noexcept
Compute negative charge.
Definition: CD_ItoKMCStepperImplem.H:5318
virtual void multiplyCdrVelocitiesByMobilities() noexcept
Multiply CDR solver velocities by mobilities.
Definition: CD_ItoKMCStepperImplem.H:2754
virtual void parseRedistributeCDR() noexcept
Parse CDR mass redistribution when assigning reactive products.
Definition: CD_ItoKMCStepperImplem.H:162
virtual void computeCurrentDensity(EBAMRCellData &a_J) noexcept
Compute the current density.
Definition: CD_ItoKMCStepperImplem.H:1942
virtual void writeNumberOfParticlesPerPatch(LevelData< EBCellFAB > &a_output, int &a_icomp, const std::string a_outputRealm, const int a_level) const noexcept
Write number of particles per patch to output holder.
Definition: CD_ItoKMCStepperImplem.H:1089
virtual void parseTimeStepRestrictions() noexcept
Parse time step restrictions.
Definition: CD_ItoKMCStepperImplem.H:309
virtual void fillSecondaryEmissionEB(const Real a_dt) noexcept
Resolve particle injection at EBs.
Definition: CD_ItoKMCStepperImplem.H:4651
virtual void initialSigma() noexcept
Fill surface charge solver with initial data taken from the physics interface.
Definition: CD_ItoKMCStepperImplem.H:679
ItoKMCStepper() noexcept
Default constructor. Sets default options.
Definition: CD_ItoKMCStepperImplem.H:35
virtual void printStepReport() noexcept override
Print a step report. Used by Driver for user monitoring of simulation.
Definition: CD_ItoKMCStepperImplem.H:1154
virtual void depositParticles(const SpeciesSubset a_speciesSubset) noexcept
Deposit a subset of the ItoSolver particles on the mesh.
Definition: CD_ItoKMCStepperImplem.H:2574
virtual Real computePhysicsDt() noexcept
Compute a maximum time step from the physics interface.
Definition: CD_ItoKMCStepperImplem.H:5075
virtual void getMaxMinItoDensity(Real &a_maxDensity, Real &a_minDensity, std::string &a_maxSolver, std::string &a_minSolver) const noexcept
Get maximum density of the Ito species.
Definition: CD_ItoKMCStepperImplem.H:1273
virtual void setupSigma() noexcept
Set up the surface charge solver.
Definition: CD_ItoKMCStepperImplem.H:489
virtual void loadBalanceFluidRealm(Vector< Vector< int >> &a_procs, Vector< Vector< Box >> &a_boxes, const std::string a_realm, const Vector< DisjointBoxLayout > &a_grids, const int a_lmin, const int a_finestLevel) noexcept
Routine called by loadBalanceBoxes and used for particle-based load balancing.
Definition: CD_ItoKMCStepperImplem.H:5684
virtual void setupSolvers() noexcept override
Set up solvers.
Definition: CD_ItoKMCStepperImplem.H:398
virtual void parseOptions() noexcept
Parse options.
Definition: CD_ItoKMCStepperImplem.H:86
virtual void advancePhotons(const Real a_dt) noexcept
Photon advancement routine.
Definition: CD_ItoKMCStepperImplem.H:5374
virtual void preRegrid(const int a_lmin, const int a_oldFinestLevel) noexcept override
Perform pre-regrid operations - storing relevant data from the old grids.
Definition: CD_ItoKMCStepperImplem.H:1547
virtual void loadBalanceParticleRealm(Vector< Vector< int >> &a_procs, Vector< Vector< Box >> &a_boxes, const std::string a_realm, const Vector< DisjointBoxLayout > &a_grids, const int a_lmin, const int a_finestLevel) noexcept
Routine called by loadBalanceBoxes and used for particle-based load balancing.
Definition: CD_ItoKMCStepperImplem.H:5531
virtual void parseDualGrid() noexcept
Parse dual or single realm calculations.
Definition: CD_ItoKMCStepperImplem.H:236
virtual void reconcilePhotoionization() noexcept
Reconcile the results from photoionization reactions.
Definition: CD_ItoKMCStepperImplem.H:4426
virtual Vector< std::string > getPlotVariableNames() const noexcept override
Get plot variable names.
Definition: CD_ItoKMCStepperImplem.H:917
virtual void sortPhotonsByCell(const McPhoto::WhichContainer a_which) noexcept
Sort photons by cells.
Definition: CD_ItoKMCStepperImplem.H:5425
virtual Real computeQplus() const noexcept
Compute positive charge.
Definition: CD_ItoKMCStepperImplem.H:5274
virtual void parseLoadBalance() noexcept
Parse load balancing.
Definition: CD_ItoKMCStepperImplem.H:259
virtual void computeDriftVelocities() noexcept
Compute ItoSolver velocities.
Definition: CD_ItoKMCStepperImplem.H:2780
virtual void getMaxMinCDRDensity(Real &a_maxDensity, Real &a_minDensity, std::string &a_maxSolver, std::string &a_minSolver) const noexcept
Get maximum density of the CDr species.
Definition: CD_ItoKMCStepperImplem.H:1306
virtual void setupPoisson() noexcept
Set up the electrostatic field solver.
Definition: CD_ItoKMCStepperImplem.H:472
virtual void setupIto() noexcept
Set up the Ito particle solvers.
Definition: CD_ItoKMCStepperImplem.H:414
virtual Real computeQsurf() const noexcept
Compute surface charge.
Definition: CD_ItoKMCStepperImplem.H:5362
virtual Real computeDt() override
Compute a time step used for the advance method.
Definition: CD_ItoKMCStepperImplem.H:1371
virtual void synchronizeSolverTimes(const int a_step, const Real a_time, const Real a_dt) noexcept override
Synchronize solver times for all the solvers.
Definition: CD_ItoKMCStepperImplem.H:1135
virtual Real computeTotalCharge() const noexcept
Compute total charge.
Definition: CD_ItoKMCStepperImplem.H:5254
virtual void resolveSecondaryEmissionEB(const Real a_dt) noexcept
Resolve secondary emission at the EB.
Definition: CD_ItoKMCStepperImplem.H:4924
void reconcileParticles(const EBAMRCellData &a_newParticlesPerCell, const EBAMRCellData &a_oldParticlesPerCell, const EBAMRCellData &a_newPhotonsPerCell) const noexcept
Reconcile particles. At the bottom, this will call the physics interface for particle reconciliation.
Definition: CD_ItoKMCStepperImplem.H:4094
virtual void regrid(const int a_lmin, const int a_oldFinestLevel, const int a_newFinestLevel) noexcept override
Regrid methods – puts all data on the new mesh.
Definition: CD_ItoKMCStepperImplem.H:1645
virtual Vector< long int > getCheckpointLoads(const std::string a_realm, const int a_level) const override
Get computational loads to be checkpointed.
Definition: CD_ItoKMCStepperImplem.H:5732
virtual void computeDiffusionCoefficients() noexcept
Compute mesh-based diffusion coefficients for LFA coupling.
Definition: CD_ItoKMCStepperImplem.H:3030
virtual void allocateInternals() noexcept
Allocate "internal" storage.
Definition: CD_ItoKMCStepperImplem.H:524
virtual Real computeMaxElectricField(const phase::which_phase a_phase) const noexcept
Compute the maximum electric field (norm)
Definition: CD_ItoKMCStepperImplem.H:1712
virtual void setCdrVelocityFunctions() noexcept
Set the Cdr velocities to be sgn(charge) * E.
Definition: CD_ItoKMCStepperImplem.H:2720
virtual void postRegrid() noexcept override
Perform post-regrid operations.
Definition: CD_ItoKMCStepperImplem.H:1687
virtual Real computeRelaxationTime() noexcept
Compute the dielectric relaxation time.
Definition: CD_ItoKMCStepperImplem.H:1962
virtual void parseParametersEB() noexcept
Parse parameters related to how we treat particle-EB interaction.
Definition: CD_ItoKMCStepperImplem.H:382
virtual void initialData() noexcept override
Fill solvers with initial data.
Definition: CD_ItoKMCStepperImplem.H:644
virtual void postPlot() noexcept override
Perform post-plot operations.
Definition: CD_ItoKMCStepperImplem.H:1535
virtual ~ItoKMCStepper() noexcept
Destructor.
Definition: CD_ItoKMCStepperImplem.H:79
virtual void computeReactiveItoParticlesPerCell(EBAMRCellData &a_ppc) noexcept
Compute the number of reactive particles per cell.
Definition: CD_ItoKMCStepperImplem.H:3378
virtual void writePlotData(LevelData< EBCellFAB > &a_output, int &a_icomp, const std::string a_outputRealm, const int a_level) const noexcept override
Write plot data to output holder.
Definition: CD_ItoKMCStepperImplem.H:968
virtual void allocate() noexcept override
Allocate storage for solvers.
Definition: CD_ItoKMCStepperImplem.H:506
virtual void parseExitOnFailure() noexcept
Parse exit on failure.
Definition: CD_ItoKMCStepperImplem.H:148
virtual void reconcileCdrDensities(const EBAMRCellData &a_newParticlesPerCell, const EBAMRCellData &a_oldParticlesPerCell, const Real a_dt) noexcept
Reconcile the CDR densities after the reaction network.
Definition: CD_ItoKMCStepperImplem.H:4476
virtual void computeConductivityCell(EBAMRCellData &a_conductivity) noexcept
Compute the cell-centered conductiivty.
Definition: CD_ItoKMCStepperImplem.H:1834
virtual void postCheckpointPoisson() noexcept
Do some post-checkpoint operations for the electrostatic part.
Definition: CD_ItoKMCStepperImplem.H:747
virtual bool loadBalanceThisRealm(const std::string a_realm) const override
Load balancing query for a specified realm. If this returns true for a_realm, load balancing routines...
Definition: CD_ItoKMCStepperImplem.H:5488
virtual void prePlot() noexcept override
Perform pre-plot operations.
Definition: CD_ItoKMCStepperImplem.H:1515
virtual void postInitialize() noexcept override
Post-initialization operations. Default does nothing.
Definition: CD_ItoKMCStepperImplem.H:634
virtual void coarsenCDRSolvers() noexcept
Coarsen data for CDR solvers.
Definition: CD_ItoKMCStepperImplem.H:4625
virtual void postCheckpointSetup() noexcept override
Perform post-checkpoint operations.
Definition: CD_ItoKMCStepperImplem.H:728
virtual void intersectParticles(const SpeciesSubset a_speciesSubset, const bool a_delete, const std::function< void(ItoParticle &)> a_nonDeletionModifier=[](ItoParticle &) -> void { return;}) noexcept
Intersect a subset of the particles with the domain and embedded boundary.
Definition: CD_ItoKMCStepperImplem.H:2033
virtual void computeMobilities() noexcept
Compute mesh-based mobilities for LFA coupling.
Definition: CD_ItoKMCStepperImplem.H:2805
virtual void setItoVelocityFunctions() noexcept
Set the Ito velocity functions. This is sgn(charge) * E.
Definition: CD_ItoKMCStepperImplem.H:2689
virtual void sortPhotonsByPatch(const McPhoto::WhichContainer a_which) noexcept
Sort photons by patch.
Definition: CD_ItoKMCStepperImplem.H:5439
virtual void getPhysicalParticlesPerCell(EBAMRCellData &a_ppc) const noexcept
Get the physical number of particles per cell.
Definition: CD_ItoKMCStepperImplem.H:3356
A particle class that only has a position and a weight.
Definition: CD_PointParticle.H:29
Real & weight()
Get weight.
Definition: CD_PointParticleImplem.H:38
static const std::string Primal
Identifier for perimal realm.
Definition: CD_Realm.H:47
Factory class for RtLayout.
Definition: CD_RtLayout.H:270
RefCountedPtr< RtLayout< T > > newLayout(const Vector< RefCountedPtr< RtSpecies >> &a_species) const
Get a new Layout. This will cast S to a specific class (T)
Definition: CD_RtLayoutImplem.H:457
Iterator class for RtLayout.
Definition: CD_RtIterator.H:24
virtual bool ok()
Check if we can cycle further through the solvers.
Definition: CD_RtIteratorImplem.H:63
Surface ODE solver.
Definition: CD_SurfaceODESolver.H:28
virtual Vector< long int > getCheckpointLoads(const std::string a_realm, const int a_level) const
Get computational loads to be checkpointed.
Definition: CD_TimeStepper.cpp:70
Class which is used for run-time monitoring of events.
Definition: CD_Timer.H:31
void stopEvent(const std::string a_event) noexcept
Stop an event.
Definition: CD_TimerImplem.H:88
void startEvent(const std::string a_event) noexcept
Start an event.
Definition: CD_TimerImplem.H:59
void eventReport(std::ostream &a_outputStream, const bool a_localReportOnly=false) const noexcept
Print all timed events to cout.
Definition: CD_TimerImplem.H:173
ALWAYS_INLINE void loop(const Box &a_computeBox, Functor &&kernel, const IntVect &a_stride=IntVect::Unit)
Launch a C++ kernel over a regular grid.
Definition: CD_BoxLoopsImplem.H:20
std::string numberFmt(const long long a_number, char a_sep=',') noexcept
Number formatting method – writes big numbers using an input separator. E.g. the number 123456 is wri...
Definition: CD_DischargeIO.cpp:25
RealVect position(const Location::Cell a_location, const VolIndex &a_vof, const EBISBox &a_ebisbox, const Real &a_dx)
Compute the position (ignoring the "origin) of a Vof.
Definition: CD_LocationImplem.H:20
Real max(const Real &a_input) noexcept
Get the maximum of the input, reduced over MPI ranks (in the Chombo communicator)
Definition: CD_ParallelOpsImplem.H:176
std::pair< Real, int > maxRank(const Real &a_val) noexcept
Get the maximum value and the rank having the maximum value.
Definition: CD_ParallelOpsImplem.H:293
Real average(const Real &a_val) noexcept
Compute the average (across MPI ranks) of the input value.
Definition: CD_ParallelOpsImplem.H:500
Real standardDeviation(const Real &a_value) noexcept
Compute the standard deviation of the input value.
Definition: CD_ParallelOpsImplem.H:512
std::pair< Real, int > minRank(const Real &a_val) noexcept
Get the minimum value and the rank having the minimum value.
Definition: CD_ParallelOpsImplem.H:323
void vectorSum(Vector< Real > &a_data) noexcept
Perform a summation of all the MPI ranks's input data.
Definition: CD_ParallelOpsImplem.H:448
Real min(const Real &a_input) noexcept
Get the minimum of the input, reduced over MPI ranks (in the Chombo communicator)
Definition: CD_ParallelOpsImplem.H:58
constexpr Real eps0
Permittivity of free space.
Definition: CD_Units.H:29
constexpr Real Qe
Elementary charge.
Definition: CD_Units.H:34