13#ifndef CD_ITOKMCGODUNOVSTEPPERIMPLEM_H
14#define CD_ITOKMCGODUNOVSTEPPERIMPLEM_H
29#include <CD_NamespaceHeader.H>
31using namespace Physics::ItoKMC;
43depositPointParticlesLikeSolver(
const RefCountedPtr<ItoSolver>& a_solver,
47 a_solver->depositWeight(a_phi, a_particles, a_solver->getDeposition(), a_solver->getCoarseFineDeposition());
52template <
typename I,
typename C,
typename R,
typename F>
56 CH_TIME(
"ItoKMCGodunovStepper::ItoKMCGodunovStepper");
58 this->
m_name =
"ItoKMCGodunovStepper";
74template <
typename I,
typename C,
typename R,
typename F>
77 CH_TIME(
"ItoKMCGodunovStepper::~ItoKMCGodunovStepper");
78 if (this->m_verbosity > 5) {
79 pout() <<
"ItoKMCGodunovStepper::~ItoKMCGodunovStepper" << endl;
83template <
typename I,
typename C,
typename R,
typename F>
87 CH_TIME(
"ItoKMCGodunovStepper::registerOperators");
88 if (this->m_verbosity > 5) {
89 pout() <<
"ItoKMCGodunovStepper::registerOperators" << endl;
96 (this->m_amr)->registerOperator(s_particle_mesh, this->m_particleRealm,
phase::solid);
99template <
typename I,
typename C,
typename R,
typename F>
103 CH_TIME(
"ItoKMCGodunovStepper::allocate");
104 if (this->m_verbosity > 5) {
105 pout() <<
"ItoKMCGodunovStepper::allocate" << endl;
113 const int numItoSpecies = this->m_physics->getNumItoSpecies();
115 m_conductivityParticles.resize(numItoSpecies);
116 m_irregularParticles.resize(numItoSpecies);
117 m_rhoDaggerParticles.resize(numItoSpecies);
119 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
120 const int idx = solverIt.index();
126 (this->m_amr)->allocate(*m_conductivityParticles[idx], this->m_particleRealm);
127 (this->m_amr)->allocate(*m_irregularParticles[idx], this->m_particleRealm);
128 (this->m_amr)->allocate(*m_rhoDaggerParticles[idx], this->m_particleRealm);
132template <
typename I,
typename C,
typename R,
typename F>
136 CH_TIME(
"ItoKMCGodunovStepper::allocateInternals");
137 if (this->m_verbosity > 5) {
138 pout() << this->m_name +
"::allocateInternals" << endl;
143 const int numCdrSpecies = this->m_physics->getNumCdrSpecies();
145 m_cdrDivD.resize(numCdrSpecies);
146 for (
int i = 0; i < numCdrSpecies; i++) {
147 this->m_amr->allocate(m_cdrDivD[i], this->m_fluidRealm, this->m_plasmaPhase, 1);
150 this->m_amr->allocate(m_semiImplicitRhoCDR, this->m_fluidRealm, this->m_plasmaPhase, 1);
151 this->m_amr->allocate(m_semiImplicitConductivityCDR, this->m_fluidRealm, this->m_plasmaPhase, 1);
161 this->m_amr->allocate(m_reactiveElectricField, this->m_fluidRealm, this->m_plasmaPhase, SpaceDim);
165 this->m_amr->allocate(m_particleScratchSum, this->m_particleRealm, this->m_plasmaPhase, 1);
170 const RefCountedPtr<MultiFluidIndexSpace>& mfis = (this->m_computationalGeometry)->getMfIndexSpace();
171 const Vector<Dielectric>& dielectrics = (this->m_computationalGeometry)->getDielectrics();
173 if ((mfis->numPhases() > 1) && (dielectrics.size() > 0)) {
174 this->m_amr->allocate(m_particleScratchSolid, this->m_particleRealm,
phase::solid, 1);
175 this->m_amr->allocate(m_particleScratchSumSolid, this->m_particleRealm,
phase::solid, 1);
176 this->m_amr->allocate(m_fluidScratchSolid, this->m_fluidRealm,
phase::solid, 1);
180template <
typename I,
typename C,
typename R,
typename F>
184 CH_TIME(
"ItoKMCGodunovStepper::barrier");
185 if (this->m_verbosity > 5) {
186 pout() << this->m_name +
"::barrier" << endl;
189 if ((this->m_profile)) {
194template <
typename I,
typename C,
typename R,
typename F>
198 CH_TIME(
"ItoKMCGodunovStepper::parseOptions");
199 if (this->m_verbosity > 5) {
200 pout() << this->m_name +
"::parseOptions" << endl;
205 this->parseAlgorithm();
206 this->parseFiltering();
207 this->parseCheckpointParticles();
208 this->parseSecondaryEmissionSpecification();
209 this->parseDiffusiveDeposit();
210 this->parseRhoDaggerHop();
211 this->parseReactiveFieldCentering();
214template <
typename I,
typename C,
typename R,
typename F>
218 CH_TIME(
"ItoKMCGodunovStepper::parseRuntimeOptions");
219 if (this->m_verbosity > 5) {
220 pout() << this->m_name +
"::parseRuntimeOptions" << endl;
225 this->parseAlgorithm();
226 this->parseFiltering();
227 this->parseCheckpointParticles();
228 this->parseSecondaryEmissionSpecification();
229 this->parseDiffusiveDeposit();
230 this->parseRhoDaggerHop();
231 this->parseReactiveFieldCentering();
234template <
typename I,
typename C,
typename R,
typename F>
238 CH_TIME(
"ItoKMCGodunovStepper::parseAlgorithm");
239 if (this->m_verbosity > 5) {
240 pout() << this->m_name +
"::parseAlgorithm" << endl;
243 ParmParse pp(this->m_name.c_str());
246 pp.get(
"extend_conductivity", m_extendConductivityEB);
247 pp.get(
"algorithm", str);
248 pp.get(
"abort_max_field", m_maxFieldAbort);
251 if (str ==
"euler_maruyama") {
252 m_algorithm = WhichAlgorithm::EulerMaruyama;
255 MayDay::Abort(
"ItoKMCGodunovStepper::parseAlgorithm - unknown algorithm requested");
259template <
typename I,
typename C,
typename R,
typename F>
263 CH_TIME(
"ItoKMCGodunovStepper::parseFiltering");
264 if (this->m_verbosity > 5) {
265 pout() << this->m_name +
"::parseFiltering" << endl;
268 ParmParse pp(this->m_name.c_str());
272 m_rhoFilterMaxStride = 1;
273 m_rhoFilterAlpha = 0.5;
275 m_condFilterNum = -1;
276 m_condFilterMaxStride = 1;
277 m_condFilterAlpha = 0.5;
279 pp.get(
"rho_filter_num", m_rhoFilterNum);
280 pp.get(
"rho_filter_max_stride", m_rhoFilterMaxStride);
281 pp.get(
"rho_filter_alpha", m_rhoFilterAlpha);
283 pp.get(
"cond_filter_num", m_condFilterNum);
284 pp.get(
"cond_filter_max_stride", m_condFilterMaxStride);
285 pp.get(
"cond_filter_alpha", m_condFilterAlpha);
287 if (m_rhoFilterAlpha <= 0.0 || m_rhoFilterAlpha >= 1.0) {
288 MayDay::Abort(
"ItoKMCGodunovStepper::parseFiltering -- cannot have alpha <= 0 or alpha >= 1 for rho_filter");
290 if (m_condFilterAlpha <= 0.0 || m_condFilterAlpha >= 1.0) {
291 MayDay::Abort(
"ItoKMCGodunovStepper::parseFiltering -- cannot have alpha <= 0 or alpha >= 1 for cond_filter");
295template <
typename I,
typename C,
typename R,
typename F>
299 CH_TIME(
"ItoKMCGodunovStepper::parseCheckpointParticles");
300 if (this->m_verbosity > 5) {
301 pout() << this->m_name +
"::parseCheckpointParticles" << endl;
304 ParmParse pp(this->m_name.c_str());
306 pp.query(
"checkpoint_particles", m_writeCheckpointParticles);
309template <
typename I,
typename C,
typename R,
typename F>
313 CH_TIME(
"ItoKMCGodunovStepper::parseSecondaryEmissionSpecifiation");
314 if (this->m_verbosity > 5) {
315 pout() << this->m_name +
"::parseSecondaryEmissionSpecification" << endl;
318 ParmParse pp(this->m_name.c_str());
322 pp.query(
"secondary_emission", str);
324 if (str ==
"before_reactions") {
325 m_emitSecondaryParticlesBeforeReactions =
true;
327 else if (str ==
"after_reactions") {
328 m_emitSecondaryParticlesBeforeReactions =
false;
333 err =
"ItoKMCGodunovStepper::parseSecondaryEmissionSpecification - expected 'before_reactions' or 'after_reactions'";
334 err +=
"but got" + str;
336 MayDay::Abort(err.c_str());
340template <
typename I,
typename C,
typename R,
typename F>
343 const RealVect& a_disp,
347 const Real a_bisectStep)
const noexcept
351 constexpr int numAttempts = 2;
354 constexpr Real raycastTolerance = 1.E-3;
356 const RefCountedPtr<BaseIF>& baseif = (this->m_amr)->getBaseImplicitFunction(this->m_plasmaPhase);
360 const Real fluidSign = (a_fOld > 0.0) ? 1.0 : -1.0;
361 const Real h = 1.E-2 * a_dx;
363 const auto inFluid = [&](
const RealVect& a_x) ->
bool {
364 return fluidSign * baseif->value(a_x) > 0.0;
369 const auto findCrossing = [&](
const RealVect& a_end, Real& a_s) ->
bool {
370 switch (a_intersectionAlg) {
371 case EBIntersection::Bisection: {
374 case EBIntersection::Raycast: {
378 MayDay::Abort(
"ItoKMCGodunovStepper::reflectDiffusionHop - unsupported EB intersection requested");
385 RealVect end = a_pos + a_disp;
387 for (
int attempt = 0; attempt < numAttempts; attempt++) {
388 Real s = std::numeric_limits<Real>::max();
393 if (!findCrossing(end, s)) {
397 return inFluid(end) ? (end - a_pos) : RealVect::Zero;
400 const RealVect cross = a_pos + s * (end - a_pos);
403 RealVect grad = RealVect::Zero;
405 for (
int dir = 0; dir < SpaceDim; dir++) {
412 grad[dir] = (baseif->value(hi) - baseif->value(lo)) / (2.0 * h);
415 const Real gradLen = grad.vectorLength();
417 if (gradLen <= 0.0) {
418 return RealVect::Zero;
421 const RealVect n = grad / gradLen;
425 const RealVect overshoot = end - cross;
427 end = cross + overshoot - 2.0 * overshoot.dotProduct(n) * n;
434 return RealVect::Zero;
437template <
typename I,
typename C,
typename R,
typename F>
441 CH_TIME(
"ItoKMCGodunovStepper::parseDiffusiveDeposit");
442 if (this->m_verbosity > 5) {
443 pout() << this->m_name +
"::parseDiffusiveDeposit" << endl;
446 ParmParse pp(this->m_name.c_str());
450 pp.get(
"diffusive_deposit", str);
452 if (str ==
"inside") {
453 m_diffusiveDeposit = DiffusiveDeposit::Inside;
455 else if (str ==
"cancel") {
456 m_diffusiveDeposit = DiffusiveDeposit::Cancel;
458 else if (str ==
"reflect_rho") {
459 m_diffusiveDeposit = DiffusiveDeposit::ReflectRho;
461 else if (str ==
"reflect_ito") {
462 m_diffusiveDeposit = DiffusiveDeposit::ReflectIto;
465 const std::string err =
"ItoKMCGodunovStepper::parseDiffusiveDeposit - expected 'inside', 'cancel', "
466 "'reflect_rho' or 'reflect_ito' but got '" +
469 MayDay::Abort(err.c_str());
473template <
typename I,
typename C,
typename R,
typename F>
477 CH_TIME(
"ItoKMCGodunovStepper::parseRhoDaggerHop");
478 if (this->m_verbosity > 5) {
479 pout() << this->m_name +
"::parseRhoDaggerHop" << endl;
482 ParmParse pp(this->m_name.c_str());
484 pp.get(
"rho_dagger_hop", m_rhoDaggerHop);
487template <
typename I,
typename C,
typename R,
typename F>
491 CH_TIME(
"ItoKMCGodunovStepper::parseReactiveFieldCentering");
492 if (this->m_verbosity > 5) {
493 pout() << this->m_name +
"::parseReactiveFieldCentering" << endl;
496 ParmParse pp(this->m_name.c_str());
498 pp.get(
"reactive_E_centering", m_reactiveFieldCentering);
502 if (m_reactiveFieldCentering < 0.0 || m_reactiveFieldCentering > 1.0) {
503 MayDay::Abort(
"ItoKMCGodunovStepper::parseReactiveFieldCentering -- 'reactive_E_centering' must lie in [0,1]");
507template <
typename I,
typename C,
typename R,
typename F>
511 CH_TIME(
"ItoKMCGodunovStepper::computeDt");
512 if (this->m_verbosity > 5) {
513 pout() << this->m_name +
"::computeDt" << endl;
518 if ((this->m_maxReducedField > m_maxFieldAbort) && (m_maxFieldAbort > 0.0)) {
519 pout() << this->m_name +
" stopping because maximum field is too high (" << this->m_maxReducedField <<
")" << endl;
521 this->m_keepGoing =
false;
527template <
typename I,
typename C,
typename R,
typename F>
531 CH_TIME(
"ItoKMCGodunovStepper::advance");
532 if (this->m_verbosity > 5) {
533 pout() << this->m_name +
"::advance" << endl;
540 m_canRegridOnRestart =
true;
542 m_timer =
Timer(
"ItoKMCGodunovStepper::advance");
545 this->m_prevDt = a_dt;
551 m_timer.startEvent(
"Store E^k");
552 if (m_reactiveFieldCentering < 1.0) {
553 DataOps::copy(m_reactiveElectricField, this->m_electricFieldFluid);
555 m_timer.stopEvent(
"Store E^k");
559 switch (m_algorithm) {
560 case WhichAlgorithm::EulerMaruyama: {
561 this->advanceEulerMaruyama(a_dt);
566 MayDay::Abort(
"ItoKMCGodunovStepper::advance - logic bust");
575 m_timer.startEvent(
"EB/Particle intersection");
576 if (m_extendConductivityEB) {
585 const std::size_t i) ->
void {
586 leaf.template get<&ItoParticle::scratch>(i) = 1.0;
590 leaf.template get<&ItoParticle::scratch>(i) = -1.0;
596 for (
auto it = this->m_ito->iterator(); it.ok(); ++it) {
597 const RefCountedPtr<ItoSolver>& solver = it();
599 if (solver->isMobile() || solver->isDiffusive()) {
605 const bool deleteParticles =
false;
606 this->intersectParticles(SpeciesSubset::AllMobileOrDiffusive, deleteParticles, nonDeletionModifier);
609 for (
auto it = this->m_ito->iterator(); it.ok(); ++it) {
610 const RefCountedPtr<ItoSolver>& solver = it();
611 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
613 const int idx = it.index();
614 const int Z = species->getChargeNumber();
622 if (Z != 0 && solver->isMobile()) {
623 for (
int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
624 const DisjointBoxLayout& dbl = (this->m_amr)->getGrids((this->m_particleRealm))[lvl];
625 const DataIterator& dit = dbl.dataIterator();
627 const int nbox = dit.size();
629#pragma omp parallel for schedule(runtime)
630 for (
int mybox = 0; mybox < nbox; mybox++) {
631 const DataIndex& din = dit[mybox];
636 for (std::size_t i = 0; i < leaf.
size(); i++) {
637 if (leaf.template get<&ItoParticle::scratch>(i) < 0.0) {
638 const RealVect pos = leaf.
position(i);
640 const Real mobility = leaf.template get<&ItoParticle::mobility>(i);
642 pointParticles.
append(pos, weight * mobility);
651 for (
auto it = this->m_ito->iterator(); it.ok(); ++it) {
652 const RefCountedPtr<ItoSolver>& solver = it();
654 if (!(solver->isMobile() || solver->isDiffusive())) {
660 for (
int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
661 const DisjointBoxLayout& dbl = (this->m_amr)->getGrids((this->m_particleRealm))[lvl];
662 const DataIterator& dit = dbl.dataIterator();
664 const int nbox = dit.size();
666#pragma omp parallel for schedule(runtime)
667 for (
int mybox = 0; mybox < nbox; mybox++) {
668 const DataIndex& din = dit[mybox];
673 while (i < leaf.
size()) {
674 if (leaf.template get<&ItoParticle::scratch>(i) < 0.0) {
688 this->intersectParticles(SpeciesSubset::AllMobileOrDiffusive, deleteParticles);
698 for (
auto it = this->m_ito->iterator(); it.ok(); ++it) {
699 const RefCountedPtr<ItoSolver>& solver = it();
704 this->m_amr->transferIrregularParticles(ebParticles, bulkParticles, this->m_plasmaPhase);
706 m_timer.stopEvent(
"EB/Particle intersection");
711 m_timer.startEvent(
"Photon transport");
712 this->advancePhotons(a_dt);
713 m_timer.stopEvent(
"Photon transport");
716 if ((this->m_physics)->needGradients()) {
717 m_timer.startEvent(
"Gradient calculation");
724 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
725 if ((this->m_physics)->needGradient(solverIt.index())) {
726 solverIt()->depositParticles();
730 this->computeDensityGradients();
731 m_timer.stopEvent(
"Gradient calculation");
736 if (m_emitSecondaryParticlesBeforeReactions) {
738 m_timer.startEvent(
"EB particle injection");
739 if (this->needSecondaryEmissionEB()) {
740 this->fillSecondaryEmissionEB(a_dt);
741 this->resolveSecondaryEmissionEB(a_dt);
743 m_timer.stopEvent(
"EB particle injection");
748 m_timer.startEvent(
"Sort by cell");
749 (this->m_ito)->organizeParticlesByCell(ItoSolver::WhichContainer::Bulk);
750 this->sortPhotonsByCell(McPhoto::WhichContainer::Bulk);
751 this->sortPhotonsByCell(McPhoto::WhichContainer::Source);
752 m_timer.stopEvent(
"Sort by cell");
762 m_timer.startEvent(
"Reaction network");
763 if (m_reactiveFieldCentering >= 1.0) {
765 this->advanceReactionNetwork(this->m_electricFieldFluid, a_dt);
769 if (m_reactiveFieldCentering > 0.0) {
770 DataOps::scale(m_reactiveElectricField, 1.0 - m_reactiveFieldCentering);
771 DataOps::incr(m_reactiveElectricField, this->m_electricFieldFluid, m_reactiveFieldCentering);
774 this->advanceReactionNetwork(m_reactiveElectricField, a_dt);
776 m_timer.stopEvent(
"Reaction network");
783 m_timer.startEvent(
"Make superparticles");
784 if (this->m_mergeInterval > 0 && (this->m_timeStep + 1) % this->m_mergeInterval == 0) {
785 (this->m_ito)->makeSuperparticles(ItoSolver::WhichContainer::Bulk);
787 m_timer.stopEvent(
"Make superparticles");
791 m_timer.startEvent(
"Sort by patch");
792 (this->m_ito)->organizeParticlesByPatch(ItoSolver::WhichContainer::Bulk);
793 this->sortPhotonsByPatch(McPhoto::WhichContainer::Bulk);
794 this->sortPhotonsByPatch(McPhoto::WhichContainer::Source);
795 m_timer.stopEvent(
"Sort by patch");
799 if (!m_emitSecondaryParticlesBeforeReactions) {
801 m_timer.startEvent(
"EB particle injection");
802 if (this->needSecondaryEmissionEB()) {
803 this->fillSecondaryEmissionEB(a_dt);
804 this->resolveSecondaryEmissionEB(a_dt);
806 m_timer.stopEvent(
"EB particle injection");
812 m_timer.startEvent(
"Remove covered");
813 this->removeCoveredParticles(SpeciesSubset::AllMobileOrDiffusive, EBRepresentation::Discrete, this->m_toleranceEB);
814 m_timer.stopEvent(
"Remove covered");
817 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
818 solverIt()->clear(ItoSolver::WhichContainer::EB);
819 solverIt()->clear(ItoSolver::WhichContainer::Domain);
831 m_timer.startEvent(
"Post-compute v");
832 this->setCdrVelocityFunctions();
833 this->computeMobilities();
834 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
835 solverIt()->interpolateVelocities();
837 this->multiplyCdrVelocitiesByMobilities();
838 m_timer.stopEvent(
"Post-compute v");
841 m_timer.startEvent(
"Post-compute D");
842 this->computeDiffusionCoefficients();
843 m_timer.stopEvent(
"Post-compute D");
845 this->computePhysicsDt();
847 if ((this->m_profile)) {
848 m_timer.eventReport(pout(),
false);
854 this->m_maxReducedField = this->computeMaxReducedElectricField(this->m_plasmaPhase);
859template <
typename I,
typename C,
typename R,
typename F>
863 CH_TIME(
"ItoKMCGodunovStepper::preRegrid");
864 if (this->m_verbosity > 5) {
865 pout() <<
"ItoKMCGodunovStepper::preRegrid" << endl;
868 const int numItoSpecies = (this->m_physics)->getNumItoSpecies();
869 const int numCdrSpecies = (this->m_physics)->getNumCdrSpecies();
870 const int numPlasmaSpecies = (this->m_physics)->getNumPlasmaSpecies();
871 const int numPhotonSpecies = (this->m_physics)->getNumPhotonSpecies();
875 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
876 const int idx = solverIt.index();
878 m_conductivityParticles[idx]->preRegrid();
879 m_irregularParticles[idx]->preRegrid();
880 m_rhoDaggerParticles[idx]->preRegrid();
883 this->m_amr->allocate(m_scratchSemiImplicitRhoCDR, this->m_fluidRealm, this->m_plasmaPhase, 1);
884 this->m_amr->allocate(m_scratchSemiImplicitConductivityCDR, this->m_fluidRealm, this->m_plasmaPhase, 1);
886 DataOps::copy(m_scratchSemiImplicitRhoCDR, m_semiImplicitRhoCDR);
887 DataOps::copy(m_scratchSemiImplicitConductivityCDR, m_semiImplicitConductivityCDR);
890 for (
int i = 0; i < numCdrSpecies; i++) {
891 m_cdrDivD[i].clear();
894 m_semiImplicitRhoCDR.clear();
895 m_semiImplicitConductivityCDR.clear();
898template <
typename I,
typename C,
typename R,
typename F>
901 const int a_oldFinestLevel,
902 const int a_newFinestLevel)
noexcept
904 CH_TIME(
"ItoKMCGodunovStepper::regrid");
905 if (this->m_verbosity > 5) {
906 pout() <<
"ItoKMCGodunovStepper::regrid" << endl;
909 m_timer =
Timer(
"ItoKMCGodunovStepper::regrid");
913 if (!m_canRegridOnRestart) {
914 const std::string baseErr =
"ItoKMCGodunovStepper::regrid -- can't regrid because";
915 const std::string err1 =
"checkpoint file does not contain particles. Set Driver.initial_regrids=0";
917 pout() << baseErr + err1 << endl;
919 MayDay::Error((baseErr + err1).c_str());
923 m_timer.startEvent(
"Regrid ItoSolver");
924 (this->m_ito)->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
925 if (this->m_timeStep == 0) {
929 (this->m_ito)->depositParticles();
931 m_timer.stopEvent(
"Regrid ItoSolver");
933 m_timer.startEvent(
"Regrid CdrSolver");
934 (this->m_cdr)->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
935 m_timer.stopEvent(
"Regrid CdrSolver");
937 m_timer.startEvent(
"Regrid FieldSolver");
938 (this->m_fieldSolver)->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
939 m_timer.stopEvent(
"Regrid FieldSolver");
941 m_timer.startEvent(
"Regrid RTE");
942 (this->m_rte)->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
943 m_timer.stopEvent(
"Regrid RTE");
945 m_timer.startEvent(
"Regrid SurfaceODESolver");
946 this->m_sigmaSolver->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
947 m_timer.stopEvent(
"Regrid SurfaceODESolver");
950 m_timer.startEvent(
"Allocate internals");
951 this->allocateInternals();
952 m_timer.stopEvent(
"Allocate internals");
955 m_timer.startEvent(
"Remap algorithm-particles");
956 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
957 const int idx = solverIt.index();
958 (this->m_amr)->remapToNewGrids(*m_rhoDaggerParticles[idx], a_lmin, a_newFinestLevel);
959 (this->m_amr)->remapToNewGrids(*m_conductivityParticles[idx], a_lmin, a_newFinestLevel);
960 (this->m_amr)->remapToNewGrids(*m_irregularParticles[idx], a_lmin, a_newFinestLevel);
962 m_timer.stopEvent(
"Remap algorithm-particles");
965 this->m_amr->interpToNewGrids(m_semiImplicitRhoCDR,
966 m_scratchSemiImplicitRhoCDR,
971 EBCoarseToFineInterp::Type::ConservativeMinMod);
973 this->m_amr->interpToNewGrids(m_semiImplicitConductivityCDR,
974 m_scratchSemiImplicitConductivityCDR,
979 EBCoarseToFineInterp::Type::ConservativeMinMod);
983 m_timer.startEvent(
"Setup field solver");
984 (this->m_fieldSolver)->setupSolver();
985 this->computeConductivities(m_conductivityParticles,
true);
986 this->setupSemiImplicitPoisson(this->m_prevDt);
987 m_timer.stopEvent(
"Setup field solver");
990 m_timer.startEvent(
"Solve Poisson");
991 if (this->m_timeStep == 0) {
992 this->computeSpaceChargeDensity();
995 this->depositPointParticles(m_rhoDaggerParticles, SpeciesSubset::All);
996 this->computeSemiImplicitRho();
999 const bool converged = this->solvePoisson();
1002 const std::string errMsg =
"ItoKMCGodunovStepper::regrid - Poisson solve did not converge after regrid";
1004 pout() << errMsg << endl;
1006 if (this->m_abortOnFailure) {
1007 MayDay::Error(errMsg.c_str());
1010 m_timer.stopEvent(
"Solve Poisson");
1026 m_timer.startEvent(
"Deposit particles");
1027 (this->m_ito)->depositParticles();
1028 m_timer.stopEvent(
"Deposit particles");
1031 m_timer.startEvent(
"Prepare next step");
1032 this->computeDiffusionCoefficients();
1033 this->computeDriftVelocities();
1034 m_timer.stopEvent(
"Prepare next step");
1036 m_timer.eventReport(pout(),
false);
1039 m_scratchSemiImplicitRhoCDR.clear();
1040 m_scratchSemiImplicitConductivityCDR.clear();
1043 this->fillNeutralDensity();
1046template <
typename I,
typename C,
typename R,
typename F>
1050 CH_TIME(
"ItoKMCGodunovStepper::setOldPositions");
1051 if (this->m_verbosity > 5) {
1052 pout() << this->m_name +
"::setOldPositions" << endl;
1055 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
1056 RefCountedPtr<ItoSolver>& solver = solverIt();
1058 for (
int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
1059 const DisjointBoxLayout& dbl = (this->m_amr)->getGrids((this->m_particleRealm))[lvl];
1060 const DataIterator& dit = dbl.dataIterator();
1062 auto& particles = solver->getParticles(ItoSolver::WhichContainer::Bulk)[lvl];
1064 const int nbox = dit.size();
1066#pragma omp parallel for schedule(runtime)
1067 for (
int mybox = 0; mybox < nbox; mybox++) {
1068 const DataIndex& din = dit[mybox];
1073 double*
const oldPos[SpaceDim] = {D_DECL(leaf.template column<&ItoParticle::old_x>(),
1074 leaf.template column<&ItoParticle::old_y>(),
1075 leaf.template column<&ItoParticle::old_z>())};
1078 D_DECL(oldPos[0][i] = pos[0][i], oldPos[1][i] = pos[1][i], oldPos[2][i] = pos[2][i]);
1085template <
typename I,
typename C,
typename R,
typename F>
1090 CH_TIME(
"ItoKMCGodunovStepper::remapPointParticles");
1091 if (this->m_verbosity > 5) {
1092 pout() << this->m_name +
"::remapPointParticles" << endl;
1095 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
1096 RefCountedPtr<ItoSolver>& solver = solverIt();
1097 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
1099 const int idx = solverIt.index();
1101 const bool mobile = solver->isMobile();
1102 const bool diffusive = solver->isDiffusive();
1103 const bool charged = species->getChargeNumber() != 0;
1106 case SpeciesSubset::All: {
1107 a_particles[idx]->remap();
1111 case SpeciesSubset::AllMobile: {
1113 a_particles[idx]->remap();
1118 case SpeciesSubset::AllDiffusive: {
1120 a_particles[idx]->remap();
1125 case SpeciesSubset::AllMobileOrDiffusive: {
1126 if (mobile || diffusive) {
1127 a_particles[idx]->remap();
1132 case SpeciesSubset::AllMobileAndDiffusive: {
1133 if (mobile && diffusive) {
1134 a_particles[idx]->remap();
1139 case SpeciesSubset::Charged: {
1141 a_particles[idx]->remap();
1146 case SpeciesSubset::ChargedMobile: {
1147 if (charged && mobile) {
1148 a_particles[idx]->remap();
1153 case SpeciesSubset::ChargedDiffusive: {
1154 if (charged && diffusive) {
1155 a_particles[idx]->remap();
1160 case SpeciesSubset::ChargedMobileOrDiffusive: {
1161 if (charged && (mobile || diffusive)) {
1162 a_particles[idx]->remap();
1167 case SpeciesSubset::ChargedMobileAndDiffusive: {
1168 if (charged && (mobile && diffusive)) {
1169 a_particles[idx]->remap();
1174 case SpeciesSubset::Stationary: {
1175 if (!mobile && !diffusive) {
1176 a_particles[idx]->remap();
1182 MayDay::Abort(
"ItoKMCGodunovStepper::remapPointParticles - logic bust");
1190template <
typename I,
typename C,
typename R,
typename F>
1196 CH_TIME(
"ItoKMCGodunovStepper::depositPointParticles");
1197 if (this->m_verbosity > 5) {
1198 pout() << this->m_name +
"::depositPointParticles" << endl;
1201 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
1202 RefCountedPtr<ItoSolver>& solver = solverIt();
1203 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
1205 const int idx = solverIt.index();
1207 const bool mobile = solver->isMobile();
1208 const bool diffusive = solver->isDiffusive();
1209 const bool charged = species->getChargeNumber() != 0;
1212 case SpeciesSubset::All: {
1213 depositPointParticlesLikeSolver(solver, solver->getPhi(), *a_particles[idx]);
1217 case SpeciesSubset::AllMobile: {
1219 depositPointParticlesLikeSolver(solver, solver->getPhi(), *a_particles[idx]);
1224 case SpeciesSubset::AllDiffusive: {
1226 depositPointParticlesLikeSolver(solver, solver->getPhi(), *a_particles[idx]);
1231 case SpeciesSubset::AllMobileOrDiffusive: {
1232 if (mobile || diffusive) {
1233 depositPointParticlesLikeSolver(solver, solver->getPhi(), *a_particles[idx]);
1237 case SpeciesSubset::AllMobileAndDiffusive: {
1238 if (mobile && diffusive) {
1239 depositPointParticlesLikeSolver(solver, solver->getPhi(), *a_particles[idx]);
1243 case SpeciesSubset::Charged: {
1245 depositPointParticlesLikeSolver(solver, solver->getPhi(), *a_particles[idx]);
1249 case SpeciesSubset::ChargedMobile: {
1250 if (charged && mobile) {
1251 depositPointParticlesLikeSolver(solver, solver->getPhi(), *a_particles[idx]);
1255 case SpeciesSubset::ChargedDiffusive: {
1256 if (charged && diffusive) {
1257 depositPointParticlesLikeSolver(solver, solver->getPhi(), *a_particles[idx]);
1262 case SpeciesSubset::ChargedMobileOrDiffusive: {
1263 if (charged && (mobile || diffusive)) {
1264 depositPointParticlesLikeSolver(solver, solver->getPhi(), *a_particles[idx]);
1269 case SpeciesSubset::ChargedMobileAndDiffusive: {
1270 if (charged && (mobile && diffusive)) {
1271 depositPointParticlesLikeSolver(solver, solver->getPhi(), *a_particles[idx]);
1276 case SpeciesSubset::Stationary: {
1277 if (!mobile && !diffusive) {
1278 depositPointParticlesLikeSolver(solver, solver->getPhi(), *a_particles[idx]);
1284 MayDay::Abort(
"ItoKMCGodunovStepper::depositPointParticles - logic bust");
1292template <
typename I,
typename C,
typename R,
typename F>
1298 CH_TIME(
"ItoKMCGodunovStepper::clearPointParticles");
1299 if (this->m_verbosity > 5) {
1300 pout() << this->m_name +
"::clearPointParticles" << endl;
1303 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
1304 RefCountedPtr<ItoSolver>& solver = solverIt();
1305 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
1307 const int idx = solverIt.index();
1309 const bool mobile = solver->isMobile();
1310 const bool diffusive = solver->isDiffusive();
1311 const bool charged = species->getChargeNumber() != 0;
1314 case SpeciesSubset::All: {
1315 a_particles[idx]->clearParticles();
1319 case SpeciesSubset::AllMobile: {
1321 a_particles[idx]->clearParticles();
1326 case SpeciesSubset::AllDiffusive: {
1328 a_particles[idx]->clearParticles();
1333 case SpeciesSubset::AllMobileOrDiffusive: {
1334 if (mobile || diffusive) {
1335 a_particles[idx]->clearParticles();
1340 case SpeciesSubset::AllMobileAndDiffusive: {
1341 if (mobile && diffusive) {
1342 a_particles[idx]->clearParticles();
1347 case SpeciesSubset::Charged: {
1349 a_particles[idx]->clearParticles();
1354 case SpeciesSubset::ChargedMobile: {
1355 if (charged && mobile) {
1356 a_particles[idx]->clearParticles();
1361 case SpeciesSubset::ChargedDiffusive: {
1362 if (charged && diffusive) {
1363 a_particles[idx]->clearParticles();
1368 case SpeciesSubset::ChargedMobileOrDiffusive: {
1369 if (charged && (mobile || diffusive)) {
1370 a_particles[idx]->clearParticles();
1375 case SpeciesSubset::ChargedMobileAndDiffusive: {
1376 if (charged && (mobile && diffusive)) {
1377 a_particles[idx]->clearParticles();
1382 case SpeciesSubset::Stationary: {
1383 if (!mobile && !diffusive) {
1384 a_particles[idx]->clearParticles();
1390 MayDay::Abort(
"ItoKMCGodunovStepper::clearPointParticles - logic bust");
1398template <
typename I,
typename C,
typename R,
typename F>
1402 CH_TIME(
"ItoKMCGodunovStepper::computeCdrConductivity");
1403 if (this->m_verbosity > 5) {
1404 pout() << this->m_name +
"::computeCdrConductivity" << endl;
1409 for (
auto solverIt = (this->m_cdr)->iterator(); solverIt.ok(); ++solverIt) {
1410 const RefCountedPtr<CdrSolver>& solver = solverIt();
1411 const RefCountedPtr<CdrSpecies>& species = solver->getSpecies();
1413 const int index = solverIt.index();
1414 const int Z = species->getChargeNumber();
1416 if (Z != 0 && solver->isMobile()) {
1417 const EBAMRCellData& phi = solver->getPhi();
1418 const EBAMRCellData& mu = this->m_cdrMobilities[index];
1423 DataOps::incr(m_semiImplicitConductivityCDR, this->m_fluidScratch1, 1.0 * std::abs(Z));
1428template <
typename I,
typename C,
typename R,
typename F>
1432 const bool a_useStoredCdrConductivity)
noexcept
1434 CH_TIME(
"ItoKMCGodunovStepper::computeConductivities");
1435 if (this->m_verbosity > 5) {
1436 pout() << this->m_name +
"::computeConductivities" << endl;
1439 this->computeCellConductivity((this->m_conductivityCell), a_particles, a_useStoredCdrConductivity);
1440 this->computeFaceConductivity();
1443template <
typename I,
typename C,
typename R,
typename F>
1446 EBAMRCellData& a_conductivityCell,
1448 const bool a_useStoredCdrConductivity)
noexcept
1450 CH_TIME(
"ItoKMCGodunovStepper::computeCellConductivity(EBAMRCellData, ParticleContainer)");
1451 if (this->m_verbosity > 5) {
1452 pout() << this->m_name +
"::computeCellConductivity(EBAMRCellData, ParticleContainer)" << endl;
1463 bool anyItoConductivity =
false;
1465 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
1466 RefCountedPtr<ItoSolver>& solver = solverIt();
1467 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
1469 const int idx = solverIt.index();
1470 const int Z = species->getChargeNumber();
1472 if (Z != 0 && solver->isMobile()) {
1474 depositPointParticlesLikeSolver(solver, this->m_particleScratch1, *a_particles[idx]);
1476 DataOps::incr(m_particleScratchSum, this->m_particleScratch1, 1.0 * std::abs(Z));
1478 anyItoConductivity =
true;
1482 if (anyItoConductivity) {
1488 (this->m_amr)->copyData(this->m_fluidScratch1, m_particleScratchSum);
1489 DataOps::incr(a_conductivityCell, this->m_fluidScratch1, 1.0);
1495 if (!a_useStoredCdrConductivity) {
1496 this->computeCdrConductivity();
1499 DataOps::incr(a_conductivityCell, m_semiImplicitConductivityCDR, 1.0);
1505 (this->m_amr)->arithmeticAverage(a_conductivityCell, this->m_fluidRealm, (this->m_plasmaPhase));
1506 (this->m_amr)->interpGhostPwl(a_conductivityCell, this->m_fluidRealm, (this->m_plasmaPhase));
1509 if (m_condFilterNum > 0 && m_condFilterMaxStride > 0) {
1510 for (
int i = 0; i < m_condFilterNum; i++) {
1511 for (
int curStride = 1; curStride <= m_condFilterMaxStride; curStride++) {
1514 (this->m_amr)->arithmeticAverage(a_conductivityCell, this->m_fluidRealm, (this->m_plasmaPhase));
1515 (this->m_amr)->interpGhostPwl(a_conductivityCell, this->m_fluidRealm, (this->m_plasmaPhase));
1520 (this->m_amr)->interpToCentroids(a_conductivityCell, this->m_fluidRealm, (this->m_plasmaPhase));
1526 DataOps::floor(a_conductivityCell, 0.0, (this->m_amr)->getVofIterator(this->m_fluidRealm, this->m_plasmaPhase));
1529template <
typename I,
typename C,
typename R,
typename F>
1533 CH_TIME(
"ItoKMCGodunovStepper::computeFaceConductivity");
1534 if (this->m_verbosity > 5) {
1535 pout() << this->m_name +
"::computeFaceConductivity" << endl;
1543 const Average average = Average::Arithmetic;
1544 const int tanGhost = 1;
1545 const Interval interv(0, 0);
1548 (this->m_conductivityFace),
1549 (this->m_conductivityCell),
1550 (this->m_amr)->getDomains(),
1555 (this->m_amr)->getFaceIteratorWithTangentialGhosts(this->m_fluidRealm, this->m_plasmaPhase));
1559 (this->m_conductivityCell),
1561 (this->m_amr)->getVofIterator(this->m_fluidRealm, this->m_plasmaPhase));
1564template <
typename I,
typename C,
typename R,
typename F>
1568 CH_TIMERS(
"ItoKMCGodunovStepper::computeSemiImplicitRho");
1569 CH_TIMER(
"ItoKMCGodunovStepper::computeSemiImplicitRho::plasma_phase", t1);
1570 CH_TIMER(
"ItoKMCGodunovStepper::computeSemiImplicitRho::solid_phase", t2);
1571 CH_TIMER(
"ItoKMCGodunovStepper::computeSemiImplicitRho::filter", t3);
1572 if (this->m_verbosity > 5) {
1573 pout() << this->m_name +
"::computeSemiImplicitRho" << endl;
1577 CH_assert(this->m_plasmaPhase ==
phase::gas);
1579 const RefCountedPtr<MultiFluidIndexSpace>& mfis = (this->m_computationalGeometry)->getMfIndexSpace();
1580 const Vector<Dielectric>& dielectrics = (this->m_computationalGeometry)->getDielectrics();
1582 const bool hasDielectrics = (mfis->numPhases() > 1) && (dielectrics.size() > 0);
1584 MFAMRCellData& rho = this->m_fieldSolver->getRho();
1585 EBAMRCellData rhoGas = (this->m_amr)->alias(
phase::gas, rho);
1586 EBAMRCellData rhoSolid;
1588 if (hasDielectrics) {
1600 bool anyItoCharge =
false;
1602 for (
auto solverIt = this->m_ito->iterator(); solverIt.ok(); ++solverIt) {
1603 const RefCountedPtr<ItoSolver>& solver = solverIt();
1604 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
1605 const int Z = species->getChargeNumber();
1613 anyItoCharge =
true;
1621 (this->m_amr)->copyData(this->m_fluidScratch1, m_particleScratchSum);
1632 if (hasDielectrics) {
1639 bool anySolidCharge =
false;
1641 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
1642 const RefCountedPtr<ItoSolver>& solver = solverIt();
1643 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
1644 const int Z = species->getChargeNumber();
1654 ->depositWeight(m_particleScratchSolid,
1655 this->m_particleRealm,
1657 *m_rhoDaggerParticles[solverIt.index()],
1658 DepositionType::CIC,
1659 CoarseFineDeposition::Halo,
1665 anySolidCharge =
true;
1669 if (anySolidCharge) {
1673 (this->m_amr)->copyData(m_fluidScratchSolid, m_particleScratchSumSolid);
1681 this->m_amr->arithmeticAverage(rho, this->m_fluidRealm);
1682 this->m_amr->interpGhostPwl(rho, this->m_fluidRealm);
1685 if (m_rhoFilterNum > 0 && m_rhoFilterMaxStride > 0) {
1687 for (
int i = 0; i < m_rhoFilterNum; i++) {
1688 for (
int curStride = 1; curStride <= m_rhoFilterMaxStride; curStride++) {
1692 this->m_amr->arithmeticAverage(rhoGas, this->m_fluidRealm, this->m_plasmaPhase);
1693 this->m_amr->interpGhost(rhoGas, this->m_fluidRealm, this->m_plasmaPhase);
1700 this->m_amr->interpToCentroids(rhoGas, this->m_fluidRealm,
phase::gas);
1701 if (hasDielectrics) {
1702 this->m_amr->interpToCentroids(rhoSolid, this->m_fluidRealm,
phase::solid);
1706template <
typename I,
typename C,
typename R,
typename F>
1710 CH_TIME(
"ItoKMCGodunovStepper::setupSemiImplicitPoisson");
1711 if (this->m_verbosity > 5) {
1712 pout() << this->m_name +
"::setupSemiImplicitPoisson" << endl;
1716 (this->m_fieldSolver)->setPermittivities();
1719 MFAMRCellData& permCell = (this->m_fieldSolver)->getPermittivityCell();
1720 MFAMRFluxData& permFace = (this->m_fieldSolver)->getPermittivityFace();
1721 MFAMRIVData& permEB = (this->m_fieldSolver)->getPermittivityEB();
1724 EBAMRFluxData permFaceGas = (this->m_amr)->alias((this->m_plasmaPhase), permFace);
1725 EBAMRIVData permEBGas = (this->m_amr)->alias((this->m_plasmaPhase), permEB);
1731 (this->m_conductivityEB),
1733 (this->m_amr)->getVofIterator(this->m_fluidRealm, this->m_plasmaPhase));
1736 (this->m_amr)->arithmeticAverage(permFaceGas, this->m_fluidRealm, (this->m_plasmaPhase));
1737 (this->m_amr)->arithmeticAverage(permEBGas, this->m_fluidRealm, (this->m_plasmaPhase));
1740 (this->m_fieldSolver)->setSolverPermittivities(permCell, permFace, permEB);
1743template <
typename I,
typename C,
typename R,
typename F>
1748 const Real a_tolerance)
const noexcept
1750 CH_TIME(
"ItoKMCGodunovStepper::removeCoveredPointParticles");
1751 if (this->m_verbosity > 5) {
1752 pout() << this->m_name +
"::removeCoveredPointParticles" << endl;
1755 for (
int i = 0; i < a_particles.size(); i++) {
1756 if (a_particles[i] !=
nullptr) {
1759 switch (a_representation) {
1760 case EBRepresentation::Discrete: {
1761 (this->m_amr)->removeCoveredParticlesDiscrete(particles, (this->m_plasmaPhase), a_tolerance);
1765 case EBRepresentation::ImplicitFunction: {
1766 (this->m_amr)->removeCoveredParticlesIF(particles, (this->m_plasmaPhase), a_tolerance);
1770 case EBRepresentation::Voxel: {
1771 (this->m_amr)->removeCoveredParticlesVoxels(particles, (this->m_plasmaPhase));
1776 MayDay::Error(
"ItoKMCGodunovStepper::removeCoveredParticles - logic bust");
1783template <
typename I,
typename C,
typename R,
typename F>
1788 CH_TIME(
"ItoKMCGodunovStepper::copyConductivityParticles");
1789 if (this->m_verbosity > 5) {
1790 pout() << this->m_name +
"::copyConductivityParticles" << endl;
1794 this->clearPointParticles(a_conductivityParticles, SpeciesSubset::All);
1796 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
1797 const RefCountedPtr<ItoSolver>& solver = solverIt();
1798 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
1800 const int idx = solverIt.index();
1801 const int Z = species->getChargeNumber();
1803 if (Z != 0 && solver->isMobile()) {
1806 for (
int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
1807 const DisjointBoxLayout& dbl = (this->m_amr)->getGrids((this->m_particleRealm))[lvl];
1808 const DataIterator& dit = dbl.dataIterator();
1810 const int nbox = dit.size();
1812#pragma omp parallel for schedule(runtime)
1813 for (
int mybox = 0; mybox < nbox; mybox++) {
1814 const DataIndex& din = dit[mybox];
1826 for (std::size_t i = 0; i < leaf.
size(); i++) {
1827 const RealVect pos = leaf.
position(i);
1828 const Real weight = leaf.
weight(i);
1829 const Real mobility = leaf.template get<&ItoParticle::mobility>(i);
1831 pointParticles.
append(pos, weight * mobility);
1834 pointParticles.
catenate(irregParticles);
1841template <
typename I,
typename C,
typename R,
typename F>
1845 CH_TIME(
"ItoKMCGodunovStepper::solvePoisson()");
1846 if (this->m_verbosity > 5) {
1847 pout() << this->m_name +
"::solvePoisson()" << endl;
1851 MFAMRCellData& phi = this->m_fieldSolver->getPotential();
1852 MFAMRCellData& rho = this->m_fieldSolver->getRho();
1853 EBAMRIVData& sigma = this->m_sigmaSolver->getPhi();
1855 const bool converged = (this->m_fieldSolver)->solve(phi, rho, sigma,
false);
1857 (this->m_fieldSolver)->computeElectricField();
1862 (this->m_amr)->allocatePointer(E, this->m_fluidRealm);
1863 (this->m_amr)->alias(E, this->m_plasmaPhase, (this->m_fieldSolver)->getElectricField());
1866 (this->m_amr)->copyData(this->m_electricFieldFluid, E);
1867 (this->m_amr)->conservativeAverage(this->m_electricFieldFluid, this->m_fluidRealm, this->m_plasmaPhase);
1868 (this->m_amr)->interpGhostPwl(this->m_electricFieldFluid, this->m_fluidRealm, this->m_plasmaPhase);
1869 (this->m_amr)->interpToCentroids(this->m_electricFieldFluid, this->m_fluidRealm, this->m_plasmaPhase);
1872 (this->m_amr)->copyData(this->m_electricFieldParticle, E);
1873 (this->m_amr)->conservativeAverage(this->m_electricFieldParticle, this->m_particleRealm, this->m_plasmaPhase);
1874 (this->m_amr)->interpGhostPwl(this->m_electricFieldParticle, this->m_particleRealm, this->m_plasmaPhase);
1875 (this->m_amr)->interpToCentroids(this->m_electricFieldParticle, this->m_particleRealm, this->m_plasmaPhase);
1880template <
typename I,
typename C,
typename R,
typename F>
1884 CH_TIME(
"ItoKMCGodunovStepper::advanceEulerMaruyama");
1885 if (this->m_verbosity > 5) {
1886 pout() << this->m_name +
"::advanceEulerMaruyama" << endl;
1890 this->setOldPositions();
1896 m_timer.startEvent(
"Diffuse particles");
1897 this->diffuseParticlesEulerMaruyama(m_rhoDaggerParticles, a_dt);
1898 this->remapPointParticles(m_rhoDaggerParticles, SpeciesSubset::ChargedDiffusive);
1899 m_timer.stopEvent(
"Diffuse particles");
1903 m_timer.startEvent(
"Diffuse CDR");
1904 this->computeDiffusionTermCDR(m_semiImplicitRhoCDR, a_dt);
1905 m_timer.stopEvent(
"Diffuse CDR");
1909 m_timer.startEvent(
"Compute conductivities");
1910 this->copyConductivityParticles(m_conductivityParticles);
1911 this->computeConductivities(m_conductivityParticles,
false);
1912 m_timer.stopEvent(
"Compute conductivities");
1916 m_timer.startEvent(
"Setup Poisson");
1917 this->setupSemiImplicitPoisson(a_dt);
1918 m_timer.stopEvent(
"Setup Poisson");
1923 m_timer.startEvent(
"Deposit point particles");
1924 this->depositPointParticles(m_rhoDaggerParticles, SpeciesSubset::Charged);
1925 this->computeSemiImplicitRho();
1926 m_timer.stopEvent(
"Deposit point particles");
1930 m_timer.startEvent(
"Solve Poisson");
1931 const bool converged = this->solvePoisson();
1933 const std::string errMsg =
"ItoKMCGodunovStepper::advanceEulerMaruyama - Poisson solve did not converge";
1935 pout() << errMsg << endl;
1937 if (this->m_abortOnFailure) {
1938 MayDay::Error(errMsg.c_str());
1941 m_timer.stopEvent(
"Solve Poisson");
1946 m_timer.startEvent(
"Step-compute v");
1948 this->setCdrVelocityFunctions();
1949 this->setItoVelocityFunctions();
1950 (this->m_ito)->interpolateVelocities();
1951 this->multiplyCdrVelocitiesByMobilities();
1953 this->computeDriftVelocities();
1955 m_timer.stopEvent(
"Step-compute v");
1959 m_timer.startEvent(
"Euler-Maruyama step");
1960 this->stepEulerMaruyamaParticles(a_dt);
1961 this->remapParticles(SpeciesSubset::AllMobileOrDiffusive);
1962 this->stepEulerMaruyamaCDR(a_dt);
1963 m_timer.stopEvent(
"Euler-Maruyama step");
1966template <
typename I,
typename C,
typename R,
typename F>
1970 const Real a_dt)
noexcept
1972 CH_TIME(
"ItoKMCGodunovStepper::diffuseParticlesEulerMaruyama");
1973 if (this->m_verbosity > 5) {
1974 pout() << this->m_name +
"::diffuseParticlesEulerMaruyama" << endl;
1977 this->clearPointParticles(a_rhoDaggerParticles, SpeciesSubset::All);
1980 long long numCrossings = 0;
1981 long long numTotalTested = 0;
1982 long long numReflectFailed = 0;
1984 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
1985 RefCountedPtr<ItoSolver>& solver = solverIt();
1986 const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
1988 const int idx = solverIt.index();
1990 const bool mobile = solver->isMobile();
1991 const bool diffusive = solver->isDiffusive();
1992 const int Z = species->getChargeNumber();
1994 const auto& diffusionFunction = (this->m_physics)->getItoDiffusionFunctions()[idx];
2005 const bool gradientDrift = diffusive && solver->isDiffusionGradientDrift();
2007 if (gradientDrift) {
2008 solver->computeDiffusionGradient();
2011 for (
int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
2012 const DisjointBoxLayout& dbl = (this->m_amr)->getGrids((this->m_particleRealm))[lvl];
2013 const DataIterator& dit = dbl.dataIterator();
2018 const RefCountedPtr<BaseIF>& baseif = (this->m_amr)->getBaseImplicitFunction(this->m_plasmaPhase);
2019 const Real dx = (this->m_amr)->getDx()[lvl];
2020 const EBIntersection intersectionAlg = solver->getIntersectionAlgorithm();
2021 const Real bisectStep = solver->getBisectionStep();
2023 const bool checkEB = (m_diffusiveDeposit != DiffusiveDeposit::Inside) && !baseif.isNull();
2026 const bool correctTrajectory = (m_diffusiveDeposit == DiffusiveDeposit::ReflectIto);
2028 auto& particles = solver->getParticles(ItoSolver::WhichContainer::Bulk)[lvl];
2030 const int nbox = dit.size();
2032#pragma omp parallel for schedule(runtime) reduction(+ : numCrossings, numTotalTested, numReflectFailed)
2033 for (
int mybox = 0; mybox < nbox; mybox++) {
2034 const DataIndex& din = dit[mybox];
2050 if (gradientDrift) {
2051 solver->interpolateDiffusionGradient(lvl, din);
2059 const bool depositFollowsHop = correctTrajectory && m_rhoDaggerHop;
2062 std::vector<std::size_t> hopCrossings;
2063 std::vector<Real> hopCrossingsFOld;
2067 std::vector<std::size_t> depositCrossings;
2068 std::vector<Real> depositCrossingsFOld;
2069 std::vector<RealVect> depositCrossingsDisp;
2072 for (std::size_t i = 0; i < leaf.
size(); i++) {
2073 const Real weight = leaf.
weight(i);
2074 const RealVect pos = leaf.
position(i);
2080 const RealVect hop = diffusive ? diffusionFunction(p, a_dt) : RealVect::Zero;
2088 const RealVect disp = hop + a_dt * gradD;
2090 D_DECL(leaf.template get<&ItoParticle::scratch_x>(i) =
static_cast<ParticleReal>(disp[0]),
2091 leaf.template get<&ItoParticle::scratch_y>(i) =
static_cast<ParticleReal>(disp[1]),
2092 leaf.template get<&ItoParticle::scratch_z>(i) =
static_cast<ParticleReal>(disp[2]));
2097 const RealVect depositDisp = m_rhoDaggerHop ? disp : a_dt * gradD;
2099 const bool deposits = (Z != 0);
2103 pointParticles.
append(pos + depositDisp, weight);
2111 const Real fOld = baseif->value(pos);
2113 const auto crosses = [&](
const RealVect& a_disp) ->
bool {
2114 return fOld * baseif->value(pos + a_disp) < 0.0;
2119 bool hopCrossed =
false;
2121 if (correctTrajectory) {
2124 hopCrossed = crosses(disp);
2127 hopCrossings.push_back(i);
2128 hopCrossingsFOld.push_back(fOld);
2138 if (depositFollowsHop) {
2140 pointParticles.
append(pos + depositDisp, weight);
2148 if (crosses(depositDisp)) {
2149 depositCrossings.push_back(i);
2150 depositCrossingsFOld.push_back(fOld);
2151 depositCrossingsDisp.push_back(depositDisp);
2154 pointParticles.
append(pos + depositDisp, weight);
2163 for (std::size_t k = 0; k < hopCrossings.size(); k++) {
2164 const std::size_t i = hopCrossings[k];
2165 const Real fOld = hopCrossingsFOld[k];
2167 const RealVect pos = leaf.
position(i);
2168 const RealVect disp = RealVect(D_DECL(leaf.template get<&ItoParticle::scratch_x>(i),
2169 leaf.template get<&ItoParticle::scratch_y>(i),
2170 leaf.template get<&ItoParticle::scratch_z>(i)));
2174 const RealVect correctedDisp = this->reflectDiffusionHop(pos, disp, fOld, dx, intersectionAlg, bisectStep);
2176 if (correctedDisp == RealVect::Zero) {
2180 D_DECL(leaf.template get<&ItoParticle::scratch_x>(i) =
static_cast<ParticleReal>(correctedDisp[0]),
2181 leaf.template get<&ItoParticle::scratch_y>(i) =
static_cast<ParticleReal>(correctedDisp[1]),
2182 leaf.template get<&ItoParticle::scratch_z>(i) =
static_cast<ParticleReal>(correctedDisp[2]));
2185 if (Z != 0 && depositFollowsHop) {
2186 pointParticles.
append(pos + correctedDisp, leaf.
weight(i));
2193 for (std::size_t k = 0; k < depositCrossings.size(); k++) {
2194 const std::size_t i = depositCrossings[k];
2195 const Real fOld = depositCrossingsFOld[k];
2196 const RealVect depositDisp = depositCrossingsDisp[k];
2198 const RealVect pos = leaf.
position(i);
2202 RealVect correctedDisp = RealVect::Zero;
2204 if (m_diffusiveDeposit != DiffusiveDeposit::Cancel) {
2205 correctedDisp = this->reflectDiffusionHop(pos, depositDisp, fOld, dx, intersectionAlg, bisectStep);
2207 if (correctedDisp == RealVect::Zero) {
2212 pointParticles.
append(pos + correctedDisp, leaf.
weight(i));
2223 if (this->m_verbosity > 5 && numTotalTested > 0) {
2224 const std::string what = (m_diffusiveDeposit == DiffusiveDeposit::ReflectIto) ?
"particle hops"
2225 :
"rho^dagger deposits";
2227 pout() << this->m_name +
"::diffuseParticlesEulerMaruyama - "
2228 << ((m_diffusiveDeposit == DiffusiveDeposit::Cancel) ?
"cancelled " :
"reflected ") << numCrossings <<
" of "
2229 << numTotalTested <<
" " << what <<
" (" << (100.0 * numCrossings) / numTotalTested
2230 <<
"%) that would have crossed the EB";
2232 if (m_diffusiveDeposit != DiffusiveDeposit::Cancel) {
2233 pout() <<
"; " << numReflectFailed <<
" could not be reflected into the fluid and were cancelled";
2240template <
typename I,
typename C,
typename R,
typename F>
2244 CH_TIME(
"ItoKMCGodunovStepper::diffuseCDREulerMaruyama");
2245 if (this->m_verbosity > 5) {
2246 pout() << this->m_name +
"::diffuseCDREulerMaruyama" << endl;
2251 for (
auto solverIt = this->m_cdr->iterator(); solverIt.ok(); ++solverIt) {
2252 const RefCountedPtr<CdrSolver>& solver = solverIt();
2253 const RefCountedPtr<CdrSpecies>& species = solver->getSpecies();
2255 const int index = solverIt.index();
2256 const int Z = species->getChargeNumber();
2258 const EBAMRCellData& phi = solver->getPhi();
2261 if (solver->isDiffusive()) {
2262 solver->computeDivD(m_cdrDivD[index], solver->getPhi(),
false,
false,
false);
2268 if (solver->isDiffusive()) {
2269 DataOps::incr(a_semiImplicitRhoCDR, m_cdrDivD[index], 1.0 * Z * a_dt);
2276 this->m_amr->arithmeticAverage(a_semiImplicitRhoCDR, this->m_fluidRealm, this->m_plasmaPhase);
2277 this->m_amr->interpGhostPwl(a_semiImplicitRhoCDR, this->m_fluidRealm, this->m_plasmaPhase);
2280template <
typename I,
typename C,
typename R,
typename F>
2284 CH_TIME(
"ItoKMCGodunovStepper::stepEulerMaruyamaParticles");
2285 if (this->m_verbosity > 5) {
2286 pout() << this->m_name +
"::stepEulerMaruyamaParticles" << endl;
2289 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
2290 RefCountedPtr<ItoSolver>& solver = solverIt();
2292 const bool mobile = solver->isMobile();
2293 const bool diffusive = solver->isDiffusive();
2295 const Real f = mobile ? a_dt : 0.0;
2296 const Real g = diffusive ? 1.0 : 0.0;
2298 if (mobile || diffusive) {
2299 for (
int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
2300 const DisjointBoxLayout& dbl = (this->m_amr)->getGrids((this->m_particleRealm))[lvl];
2301 const DataIterator& dit = dbl.dataIterator();
2303 auto& particles = solver->getParticles(ItoSolver::WhichContainer::Bulk)[lvl];
2305 const int nbox = dit.size();
2307#pragma omp parallel for schedule(runtime)
2308 for (
int mybox = 0; mybox < nbox; mybox++) {
2309 const DataIndex& din = dit[mybox];
2313 double*
const pos[SpaceDim] = {
2315 double*
const oldPos[SpaceDim] = {D_DECL(leaf.template column<&ItoParticle::old_x>(),
2316 leaf.template column<&ItoParticle::old_y>(),
2317 leaf.template column<&ItoParticle::old_z>())};
2318 ParticleReal*
const vel[SpaceDim] = {D_DECL(leaf.template column<&ItoParticle::vx>(),
2319 leaf.template column<&ItoParticle::vy>(),
2320 leaf.template column<&ItoParticle::vz>())};
2321 ParticleReal*
const disp[SpaceDim] = {D_DECL(leaf.template column<&ItoParticle::scratch_x>(),
2322 leaf.template column<&ItoParticle::scratch_y>(),
2323 leaf.template column<&ItoParticle::scratch_z>())};
2327 for (
int dir = 0; dir < SpaceDim; dir++) {
2328 pos[dir][i] = oldPos[dir][i] + f * vel[dir][i] + g * disp[dir][i];
2337template <
typename I,
typename C,
typename R,
typename F>
2341 CH_TIME(
"ItoKMCGodunovStepper::stepEulerMaruyamaCDR");
2342 if (this->m_verbosity > 5) {
2343 pout() << this->m_name +
"::stepEulerMaruyamaCDR" << endl;
2346 for (
auto solverIt = (this->m_cdr)->iterator(); solverIt.ok(); ++solverIt) {
2347 RefCountedPtr<CdrSolver>& solver = solverIt();
2349 const int index = solverIt.index();
2351 EBAMRCellData& phi = solver->getPhi();
2360 if (!solver->isDiffusive()) {
2361 this->m_amr->conservativeAverage(phi, this->m_fluidRealm, this->m_plasmaPhase);
2362 this->m_amr->interpGhostPwl(phi, this->m_fluidRealm, this->m_plasmaPhase);
2366 if (solver->isMobile()) {
2371 solver->computeDivF(this->m_fluidScratch1, phi, a_dt,
false,
true,
true);
2377 if (solver->isDiffusive()) {
2381 DataOps::floor(phi, 0.0, this->m_amr->getVofIterator(this->m_fluidRealm, this->m_plasmaPhase));
2384 this->coarsenCDRSolvers(
true);
2388template <
typename I,
typename C,
typename R,
typename F>
2392 CH_TIME(
"ItoKMCGodunovStepper::writeCheckpointHeader");
2393 if (this->m_verbosity > 5) {
2394 pout() << this->m_name +
"::writeCheckpointHeader" << endl;
2397 a_header.m_real[
"prev_dt"] = this->m_prevDt;
2398 a_header.m_real[
"physics_dt"] = this->m_physicsDt;
2399 a_header.m_int[
"checkpoint_particles"] = m_writeCheckpointParticles ? 1 : 0;
2404template <
typename I,
typename C,
typename R,
typename F>
2408 CH_TIME(
"ItoKMCGodunovStepper::readCheckpointHeader");
2409 if (this->m_verbosity > 5) {
2410 pout() << this->m_name +
"::readCheckpointHeader" << endl;
2413 this->m_prevDt = a_header.m_real[
"prev_dt"];
2414 this->m_physicsDt = a_header.m_real[
"physics_dt"];
2416 m_readCheckpointParticles = (a_header.m_int[
"checkpoint_particles"] != 0) ?
true : false;
2417 m_canRegridOnRestart = m_readCheckpointParticles;
2422template <
typename I,
typename C,
typename R,
typename F>
2426 CH_TIME(
"ItoKMCGodunovStepper::writeCheckpointData");
2427 if (this->m_verbosity > 5) {
2428 pout() << this->m_name +
"::writeCheckpointData" << endl;
2434 if (m_writeCheckpointParticles) {
2435 for (
int i = 0; i < (this->m_physics)->getNumItoSpecies(); i++) {
2436 const std::string identifierSigma =
"ItoKMCGodunovStepper::conductivityParticles_" + std::to_string(i);
2437 const std::string identifierRho =
"ItoKMCGodunovStepper::spaceChargeParticles_" + std::to_string(i);
2442 DischargeIO::writeCheckParticlesToHDF(a_handle, conductivityParticles[a_lvl], identifierSigma);
2443 DischargeIO::writeCheckParticlesToHDF(a_handle, rhoDaggerParticles[a_lvl], identifierRho);
2448 if (this->m_physics->getNumCdrSpecies() > 0) {
2449 write(a_handle, *m_semiImplicitRhoCDR[a_lvl],
"ItoKMCGodunovStepper::semiImplicitRhoCDR");
2450 write(a_handle, *m_semiImplicitConductivityCDR[a_lvl],
"ItoKMCGodunovStepper::semiImplicitConductivityCDR");
2456template <
typename I,
typename C,
typename R,
typename F>
2460 CH_TIME(
"ItoKMCGodunovStepper::readCheckpointData");
2461 if (this->m_verbosity > 5) {
2462 pout() << this->m_name +
"::readCheckpointData" << endl;
2468 if (m_readCheckpointParticles) {
2469 for (
int i = 0; i < (this->m_physics)->getNumItoSpecies(); i++) {
2470 const std::string identifierSigma =
"ItoKMCGodunovStepper::conductivityParticles_" + std::to_string(i);
2471 const std::string identifierRho =
"ItoKMCGodunovStepper::spaceChargeParticles_" + std::to_string(i);
2476 DischargeIO::readCheckParticlesFromHDF(a_handle, conductivityParticles[a_lvl], identifierSigma);
2477 DischargeIO::readCheckParticlesFromHDF(a_handle, rhoDaggerParticles[a_lvl], identifierRho);
2482 if (this->m_physics->getNumCdrSpecies() > 0) {
2483 const Interval interv(0, 0);
2485 read<EBCellFAB>(a_handle,
2486 *m_semiImplicitRhoCDR[a_lvl],
2487 "ItoKMCGodunovStepper::semiImplicitRhoCDR",
2488 this->m_amr->getGrids(this->m_fluidRealm)[a_lvl],
2492 read<EBCellFAB>(a_handle,
2493 *m_semiImplicitConductivityCDR[a_lvl],
2494 "ItoKMCGodunovStepper::semiImplicitConductivityCDR",
2495 this->m_amr->getGrids(this->m_fluidRealm)[a_lvl],
2502template <
typename I,
typename C,
typename R,
typename F>
2506 CH_TIME(
"ItoKMCGodunovStepper::prePlot");
2507 if (this->m_verbosity > 5) {
2508 pout() <<
"ItoKMCGodunovStepper::prePlot" << endl;
2520 for (
auto solverIt = (this->m_rte)->iterator(); solverIt.ok(); ++solverIt) {
2521 RefCountedPtr<McPhoto> solver = solverIt();
2523 EBAMRCellData& phi = solver->getPhi();
2526 solver->depositPhotons(phi, photons, DepositionType::NGP);
2530template <
typename I,
typename C,
typename R,
typename F>
2534 CH_TIME(
"ItoKMCGodunovStepper::postPlot");
2535 if (this->m_verbosity > 5) {
2536 pout() << this->m_name +
"::postPlot" << endl;
2539 this->m_physicsPlotVariables.clear();
2541 this->plotParticles();
2544template <
typename I,
typename C,
typename R,
typename F>
2548 CH_TIME(
"ItoKMCGodunovStepper::plotParticles");
2549 if (this->m_verbosity > 2) {
2550 pout() << this->m_name +
"::plotParticles" << endl;
2553 bool plotParticles =
false;
2555 ParmParse pp(this->m_name.c_str());
2557 pp.query(
"plot_particles", plotParticles);
2559 if (plotParticles) {
2561 for (
auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
2562 const RefCountedPtr<ItoSolver>& solver = solverIt();
2568 std::string cmd =
"mkdir -p 'particles/" + solver->getName() +
"'";
2570 if (procID() == 0) {
2571 success = system(cmd.c_str());
2575 MayDay::Error(
"ItoKMCGodunovStepper::plotParticles - could not create 'particles' directory");
2579 const std::string prefix =
"./particles/" + solver->getName() +
"/" + solver->getName();
2580 char fileChar[1000];
2581 sprintf(fileChar,
"%s.step%07d.%dd.h5part", prefix.c_str(), this->m_timeStep, SpaceDim);
2590#include <CD_NamespaceFooter.H>
Average
Various averaging methods.
Definition CD_Average.H:25
Agglomeration of useful data operations.
Silly, but useful functions that override standard Chombo HDF5 IO.
EBIntersection
Enum for putting some logic into how we think about intersection between particles and EBs.
Definition CD_EBIntersection.H:22
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:23
@ NGP
Put the particle's entire cloud in its own cell when that cell is a cut cell.
Declaration of a class which uses a semi-implicit Godunov method for Ito plasma equations.
SpeciesSubset
Enum for selecting a subset of plasma species by mobility/diffusion/charge properties.
Definition CD_ItoKMCStepper.H:43
Agglomeration of basic MPI reductions.
Declaration of a namespace for SIMD-decorated loops over SoA particles.
Declaration of a static class containing some common useful particle routines that would otherwise be...
CD_PARTICLE_REAL ParticleReal
Floating-point type a user may use for payload columns.
Definition CD_ParticleSoA.H:156
SoA payload for Monte Carlo radiative-transfer photons.
Implementation of CD_Timer.H.
Declaration of various useful units.
static void scale(MFAMRCellData &a_lhs, const Real &a_scale) noexcept
Scale data by factor.
Definition CD_DataOps.cpp:2564
static void floor(EBAMRCellData &a_lhs, const Real a_value, const Vector< RefCountedPtr< LayoutData< VoFIterator > > > &a_vofIter)
Floor values in data holder. This sets all values below a_value to a_value.
Definition CD_DataOps.cpp:1526
static void filterSmooth(EBAMRCellData &a_data, const Real a_alpha, const int a_stride, const bool a_zeroEB) noexcept
Apply a convolved filter phi = alpha * phi_i + 0.5*(1-alpha) * [phi_(i+s) + phi_(i-s)] in each direct...
Definition CD_DataOps.cpp:680
static void multiply(EBAMRCellData &a_lhs, const EBAMRCellData &a_rhs)
Multiply data holder by another data holder.
Definition CD_DataOps.cpp:2307
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:881
static void setValue(LevelData< MFInterfaceFAB< T > > &a_lhs, const T &a_value)
Set value in an MFInterfaceFAB data holder.
Definition CD_DataOpsImplem.H:24
static void copy(MFAMRCellData &a_dst, const MFAMRCellData &a_src)
Copy data from one data holder to another.
Definition CD_DataOps.cpp:1262
static void averageCellToFace(EBAMRFluxData &a_faceData, const EBAMRCellData &a_cellData, const Vector< ProblemDomain > &a_domains, Vector< RefCountedPtr< LayoutData< std::array< FaceIterator, SpaceDim > > > > &a_faceIter)
Average all components of the cell-centered data to faces (arithmetic, no tangential ghost faces).
Definition CD_DataOps.cpp:149
AMR-hierarchy container of computational particles, stored per patch in Struct-of-Arrays form.
Definition CD_ParticleContainer.H:123
void clearParticles()
Drop all valid particles on every level (keeps each leaf's arena capacity).
Definition CD_ParticleContainer.H:442
RealVect getProbLo() const
Lower-left corner of the physical domain.
Definition CD_ParticleContainer.H:280
AMRParticlesSoA< P, Traits > & getParticles()
The valid particles on all levels.
Definition CD_ParticleContainer.H:317
static bool ebIntersectionRaycast(const RefCountedPtr< BaseIF > &a_impFunc, const RealVect &a_oldPos, const RealVect &a_newPos, const Real &a_tolerance, Real &a_s)
Compute the intersection point between a particle path and an implicit function using a ray-casting a...
Definition CD_ParticleOpsImplem.H:224
static bool ebIntersectionBisect(const RefCountedPtr< BaseIF > &a_impFunc, const RealVect &a_oldPos, const RealVect &a_newPos, const Real &a_bisectStep, Real &a_s)
Compute the intersection point between a particle path and an implicit function using a bisection alg...
Definition CD_ParticleOpsImplem.H:175
static void setData(ParticleContainer< P, Traits > &a_particles, const std::function< void(ParticleSoA< P, Traits > &, std::size_t)> &a_functor) noexcept
Set value function for SoA containers. Lets the user set particle parameters via a (leaf,...
Definition CD_ParticleOpsImplem.H:334
Arena-backed Struct-of-Arrays particle container for a single grid patch.
Definition CD_ParticleSoA.H:655
void append(const RealVect &a_position, const double a_weight)
Append one particle with a default-constructed payload.
Definition CD_ParticleSoA.H:962
RealVect position(const std::size_t a_index) const noexcept
Position of particle i as a RealVect (by value, assembled from the scalar columns).
Definition CD_ParticleSoA.H:1195
double & weight(const std::size_t a_index) noexcept
Weight of particle i.
Definition CD_ParticleSoA.H:1229
std::size_t size() const noexcept
Number of particles currently stored.
Definition CD_ParticleSoA.H:882
double * positionColumn(const int a_dir) noexcept
Raw position component column dir (double*, for SIMD kernels).
Definition CD_ParticleSoA.H:1144
P gather(const std::size_t a_index) const
Gather particle i's payload back into the AoS payload view.
Definition CD_ParticleSoA.H:1028
void catenate(ParticleSoA &a_other)
Move every particle of another container into this one, leaving a_other empty (catenate).
Definition CD_ParticleSoA.H:1009
void remove(const std::size_t a_index) noexcept
Remove particle i using swap-and-pop (O(1), does NOT preserve order).
Definition CD_ParticleSoA.H:1040
void reserve(const std::size_t a_capacity)
Ensure capacity for at least a_capacity particles (reallocates + moves on growth).
Definition CD_ParticleSoAImplem.H:88
Implementation of ItoKMCStepper that uses a semi-implicit split-step formalism for advancing the Ito-...
Definition CD_ItoKMCGodunovStepper.H:32
virtual void setupSemiImplicitPoisson(const Real a_dt) noexcept
Set up the semi-implicit Poisson solver.
Definition CD_ItoKMCGodunovStepperImplem.H:1708
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_ItoKMCGodunovStepperImplem.H:900
virtual void computeDiffusionTermCDR(EBAMRCellData &m_semiImplicitRhoCDR, const Real a_dt) noexcept
Compute the diffusion term for the CDR equations as well as the resulting CDR-contributions to the sp...
Definition CD_ItoKMCGodunovStepperImplem.H:2242
virtual void allocate() noexcept override
Allocate storage required for advancing the equations.
Definition CD_ItoKMCGodunovStepperImplem.H:101
bool m_readCheckpointParticles
If true, then the HDF5 checkpoint file contained particles that we can read.
Definition CD_ItoKMCGodunovStepper.H:222
@ Inside
Deposit from inside the solid, into a covered cell that contributes nothing to rho.
virtual Real advance(const Real a_dt) override
Advance the Ito-Poisson-KMC system over a_dt.
Definition CD_ItoKMCGodunovStepperImplem.H:529
virtual void allocateInternals() noexcept override
Allocate "internal" storage.
Definition CD_ItoKMCGodunovStepperImplem.H:134
Real m_maxFieldAbort
Limit for maximum field abort.
Definition CD_ItoKMCGodunovStepper.H:288
virtual void stepEulerMaruyamaCDR(const Real a_dt) noexcept
Step the CDR equations according to the regular Euler-Maruyama scheme.
Definition CD_ItoKMCGodunovStepperImplem.H:2339
DiffusiveDeposit m_diffusiveDeposit
What to do with a rho^dagger deposit that would land inside the embedded boundary....
Definition CD_ItoKMCGodunovStepper.H:243
virtual void computeConductivities(const Vector< RefCountedPtr< ParticleContainer< NoPayload > > > &a_particles, const bool a_useStoredCdrConductivity) noexcept
Compute all conductivities (cell, face, and EB) from the input point particles.
Definition CD_ItoKMCGodunovStepperImplem.H:1430
virtual void parseAlgorithm() noexcept
Parse advancement algorithm.
Definition CD_ItoKMCGodunovStepperImplem.H:236
virtual void clearPointParticles(const Vector< RefCountedPtr< ParticleContainer< NoPayload > > > &a_particles, const SpeciesSubset a_subset) noexcept
Clear the input particle data holders.
Definition CD_ItoKMCGodunovStepperImplem.H:1294
virtual void postPlot() noexcept override
Perform post-plot operations.
Definition CD_ItoKMCGodunovStepperImplem.H:2532
virtual Real computeDt() override
Compute a time step used for the advance method.
Definition CD_ItoKMCGodunovStepperImplem.H:509
virtual void diffuseParticlesEulerMaruyama(Vector< RefCountedPtr< ParticleContainer< NoPayload > > > &a_rhoDaggerParticles, const Real a_dt) noexcept
Perform the explicit half of the Ito advance in the Euler-Maruyama step.
Definition CD_ItoKMCGodunovStepperImplem.H:1968
virtual void parseSecondaryEmissionSpecification() noexcept
Parse when secondary particles are emitted.
Definition CD_ItoKMCGodunovStepperImplem.H:311
virtual void parseFiltering() noexcept
Parse filter settings.
Definition CD_ItoKMCGodunovStepperImplem.H:261
virtual void parseRuntimeOptions() noexcept override
Parse run-time options.
Definition CD_ItoKMCGodunovStepperImplem.H:216
virtual void depositPointParticles(const Vector< RefCountedPtr< ParticleContainer< NoPayload > > > &a_particles, const SpeciesSubset a_subset) noexcept
Deposit the input point particles on the mesh.
Definition CD_ItoKMCGodunovStepperImplem.H:1192
virtual bool solvePoisson() noexcept override
Solve the electrostatic problem.
Definition CD_ItoKMCGodunovStepperImplem.H:1843
bool m_canRegridOnRestart
If true, then the class supports regrid-on-restart.
Definition CD_ItoKMCGodunovStepper.H:228
virtual void computeFaceConductivity() noexcept
Compute the cell-centered conductivity.
Definition CD_ItoKMCGodunovStepperImplem.H:1531
virtual void computeCellConductivity(EBAMRCellData &a_conductivityCell, const Vector< RefCountedPtr< ParticleContainer< NoPayload > > > &a_particles, const bool a_useStoredCdrConductivity) noexcept
Compute the cell-centered conductivity.
Definition CD_ItoKMCGodunovStepperImplem.H:1445
virtual void removeCoveredPointParticles(Vector< RefCountedPtr< ParticleContainer< NoPayload > > > &a_particles, const EBRepresentation a_representation, const Real a_tolerance) const noexcept
Remove covered particles.
Definition CD_ItoKMCGodunovStepperImplem.H:1745
bool m_rhoDaggerHop
If true, the stochastic diffusion hop enters rho^dagger along with the rest of the explicit displacem...
Definition CD_ItoKMCGodunovStepper.H:217
virtual void remapPointParticles(Vector< RefCountedPtr< ParticleContainer< NoPayload > > > &a_particles, const SpeciesSubset a_subset) noexcept
Remap the input point particles.
Definition CD_ItoKMCGodunovStepperImplem.H:1087
virtual void prePlot() noexcept override
Perform pre-plot operations.
Definition CD_ItoKMCGodunovStepperImplem.H:2504
virtual ~ItoKMCGodunovStepper()
Destructor. Does nothing.
Definition CD_ItoKMCGodunovStepperImplem.H:75
bool m_extendConductivityEB
For achieving a slightly smoother gradient in the conductivity near the EB.
Definition CD_ItoKMCGodunovStepper.H:233
virtual void setOldPositions() noexcept
Set the starting positions for the ItoSolver particles.
Definition CD_ItoKMCGodunovStepperImplem.H:1048
virtual void parseDiffusiveDeposit() noexcept
Parse what happens to a diffusion hop that would cross the embedded boundary.
Definition CD_ItoKMCGodunovStepperImplem.H:439
bool m_writeCheckpointParticles
If true, then the particles are checkpointed so we can regrid on checkpoint-restart.
Definition CD_ItoKMCGodunovStepper.H:207
virtual void parseRhoDaggerHop() noexcept
Parse whether the stochastic diffusion hop enters rho^dagger.
Definition CD_ItoKMCGodunovStepperImplem.H:475
virtual void computeSemiImplicitRho() noexcept
Set up the space charge density for the regrid operation.
Definition CD_ItoKMCGodunovStepperImplem.H:1566
virtual void advanceEulerMaruyama(const Real a_dt) noexcept
Advance the particles using the Euler-Maruyama scheme.
Definition CD_ItoKMCGodunovStepperImplem.H:1882
virtual void preRegrid(const int a_lmin, const int a_oldFinestLevel) noexcept override
Perform pre-regrid operations.
Definition CD_ItoKMCGodunovStepperImplem.H:861
virtual void registerOperators() noexcept override
Register operators used for the simulation.
Definition CD_ItoKMCGodunovStepperImplem.H:85
virtual RealVect reflectDiffusionHop(const RealVect &a_pos, const RealVect &a_disp, const Real a_fOld, const Real a_dx, const EBIntersection a_intersectionAlg, const Real a_bisectStep) const noexcept
Reflect a rho^dagger deposit displacement that crosses the embedded boundary back into the fluid.
Definition CD_ItoKMCGodunovStepperImplem.H:342
virtual void plotParticles() const noexcept
Utility function for plotting the ItoSolver particles. These are written in a particles folder.
Definition CD_ItoKMCGodunovStepperImplem.H:2546
ItoKMCGodunovStepper()=delete
Disallowed default constructor. Use the full constructor.
virtual void parseReactiveFieldCentering() noexcept
Parse the time-centering of the electric field used for the reactive substep.
Definition CD_ItoKMCGodunovStepperImplem.H:489
virtual void parseCheckpointParticles() noexcept
Parse checkpoint-restart functionality.
Definition CD_ItoKMCGodunovStepperImplem.H:297
virtual void barrier() const noexcept
Set an MPI barrier if using debug mode.
Definition CD_ItoKMCGodunovStepperImplem.H:182
virtual void parseOptions() noexcept override
Parse options.
Definition CD_ItoKMCGodunovStepperImplem.H:196
virtual void computeCdrConductivity() noexcept
Compute the CDR contribution to the semi-implicit conductivity, i.e. sum(|Z| * phi * mu).
Definition CD_ItoKMCGodunovStepperImplem.H:1400
virtual void stepEulerMaruyamaParticles(const Real a_dt) noexcept
Step the particles according to the regular Euler-Maruyama scheme.
Definition CD_ItoKMCGodunovStepperImplem.H:2282
virtual void copyConductivityParticles(Vector< RefCountedPtr< ParticleContainer< NoPayload > > > &a_conductivityParticles) noexcept
Copy particles from the ItoSolver into PointParticles whose weight are ItoParticle::m_weight * ItoPar...
Definition CD_ItoKMCGodunovStepperImplem.H:1785
Abstract TimeStepper for the Ito-KMC-Poisson system of equations.
Definition CD_ItoKMCStepper.H:66
virtual void parseRuntimeOptions() noexcept override
Parse runtime configurable options.
Definition CD_ItoKMCStepperImplem.H:173
std::string m_name
Time stepper name.
Definition CD_ItoKMCStepper.H:402
virtual void registerOperators() noexcept override
Register operators used for the simulation.
Definition CD_ItoKMCStepperImplem.H:1648
virtual void parseOptions() noexcept
Parse options.
Definition CD_ItoKMCStepperImplem.H:152
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:1700
Real m_prevDt
Previous time step.
Definition CD_ItoKMCStepper.H:541
virtual Real computeDt() override
Compute a time step used for the advance method.
Definition CD_ItoKMCStepperImplem.H:1519
virtual void allocateInternals() noexcept
Allocate "internal" storage.
Definition CD_ItoKMCStepperImplem.H:621
virtual void allocate() noexcept override
Allocate storage for solvers.
Definition CD_ItoKMCStepperImplem.H:603
virtual void prePlot() noexcept override
Perform pre-plot operations.
Definition CD_ItoKMCStepperImplem.H:1667
Class which is used for run-time monitoring of events.
Definition CD_Timer.H:32
void writeH5Part(std::string a_filename, const ParticleContainer< P, Traits > &a_particles, RealVect a_shift, Real a_time) noexcept
Write an SoA particle container to an H5Part file (quick visualization).
Definition CD_DischargeIOImplem.H:201
Real sum(const Real &a_value) noexcept
Compute the sum across all MPI ranks.
Definition CD_ParallelOpsImplem.H:354
void barrier() noexcept
MPI barrier.
Definition CD_ParallelOpsImplem.H:26
ALWAYS_INLINE void loop(const ParticleSoA< P, Traits > &a_soa, Functor &&a_kernel)
Launch a kernel over every particle in a ParticleSoA, decorating the loop with CD_PRAGMA_SIMD.
Definition CD_ParticleLoops.H:87
void deleteParticles(ParticleSoA< P, Traits > &a_particles, const Real a_weightThresh) noexcept
Remove particles from an SoA container if their weight is below the threshold (swap-and-pop).
Definition CD_ParticleManagementImplem.H:788
constexpr Real eps0
Permittivity of free space.
Definition CD_Units.H:30
constexpr Real Qe
Elementary charge.
Definition CD_Units.H:35
@ solid
Solid (dielectric) phase.
Definition CD_MultiFluidIndexSpace.H:40
@ gas
Gas phase.
Definition CD_MultiFluidIndexSpace.H:39
SoA payload for ItoSolver particles, i.e. drifting Brownian walkers.
Definition CD_ItoParticle.H:31
ParticleReal scratch_x
Scratch vector storage, x-component.
Definition CD_ItoParticle.H:49
ParticleReal scratch_y
Scratch vector storage, y-component.
Definition CD_ItoParticle.H:50
ParticleReal scratch_z
Scratch vector storage, z-component.
Definition CD_ItoParticle.H:52