15 #ifndef CD_DischargeInceptionStepperImplem_H
16 #define CD_DischargeInceptionStepperImplem_H
30 #include <CD_NamespaceHeader.H>
32 using namespace Physics::DischargeInception;
34 template <
typename P,
typename F,
typename C>
37 CH_TIME(
"DischargeInceptionStepper::DischargeInceptionStepper");
38 if (m_verbosity > 5) {
39 pout() <<
"DischargeInceptionStepper::DischargeInceptionStepper" << endl;
46 m_mode = Mode::Stationary;
47 m_transportAlgorithm = TransportAlgorithm::ImExCTU;
48 m_timeStepRestriction = TimeStepRestriction::Unknown;
51 m_fullIntegration =
false;
52 m_evaluateTownsend =
false;
56 m_rho = [](
const RealVect x) -> Real {
60 m_sigma = [](
const RealVect x) -> Real {
64 m_alpha = [](
const Real E,
const RealVect x) -> Real {
68 m_eta = [](
const Real E,
const RealVect x) -> Real {
72 m_voltageCurve = [](
const Real a_time) -> Real {
76 m_backgroundRate = [](
const Real E,
const RealVect x) -> Real {
80 m_detachmentRate = [](
const Real E,
const RealVect x) -> Real {
84 m_fieldEmission = [](
const Real E,
const RealVect x) -> Real {
88 m_secondaryEmission = [](
const Real E,
const RealVect x) -> Real {
92 m_initialIonDensity = [](
const RealVect x) -> Real {
96 m_ionMobility = [](
const Real E) -> Real {
100 m_ionDiffusion = [](
const Real E) -> Real {
105 template <
typename P,
typename F,
typename C>
108 CH_TIME(
"DischargeInceptionStepper::~DischargeInceptionStepper");
109 if (m_verbosity > 5) {
110 pout() <<
"DischargeInceptionStepper::~DischargeInceptionStepper" << endl;
114 template <
typename P,
typename F,
typename C>
118 CH_TIME(
"DischargeInceptionStepper::setupSolvers");
119 if (m_verbosity > 5) {
120 pout() <<
"DischargeInceptionStepper::setupSolvers" << endl;
124 auto voltage = [](
const Real a_time) -> Real {
129 m_fieldSolver = RefCountedPtr<FieldSolver>(
new F());
130 m_fieldSolver->setVerbosity(m_verbosity);
131 m_fieldSolver->parseOptions();
132 m_fieldSolver->setAmr(m_amr);
133 m_fieldSolver->setComputationalGeometry(m_computationalGeometry);
134 m_fieldSolver->setVoltage(voltage);
135 m_fieldSolver->setRealm(m_realm);
136 m_fieldSolver->setTime(0, 0.0, 0.0);
140 m_tracerParticleSolver->parseOptions();
141 m_tracerParticleSolver->setAmr(m_amr);
142 m_tracerParticleSolver->setComputationalGeometry(m_computationalGeometry);
143 m_tracerParticleSolver->setRealm(m_realm);
144 m_tracerParticleSolver->setPhase(m_phase);
145 m_tracerParticleSolver->setTime(0, 0.0, 0.0);
146 m_tracerParticleSolver->setName(
"Tracer particle solver");
147 m_tracerParticleSolver->setVolumeScale(
true);
148 m_tracerParticleSolver->setDeposition(DepositionType::NGP);
151 m_ionSolver = RefCountedPtr<CdrSolver>(
new C());
153 m_ionSolver->parseOptions();
154 m_ionSolver->setPhase(m_phase);
155 m_ionSolver->setAmr(m_amr);
156 m_ionSolver->setComputationalGeometry(m_computationalGeometry);
157 m_ionSolver->setRealm(m_realm);
161 m_ionSolver->setSpecies(species);
164 template <
typename P,
typename F,
typename C>
168 CH_TIME(
"DischargeInceptionStepper::allocate");
169 if (m_verbosity > 5) {
170 pout() <<
"DischargeInceptionStepper::allocate" << endl;
173 m_fieldSolver->allocate();
174 m_tracerParticleSolver->allocate();
175 m_ionSolver->allocate();
178 m_amr->allocate(m_potential, m_realm, 1);
179 m_amr->allocate(m_potentialHomo, m_realm, 1);
180 m_amr->allocate(m_potentialInho, m_realm, 1);
182 m_amr->allocate(m_electricField, m_realm, SpaceDim);
183 m_amr->allocate(m_electricFieldHomo, m_realm, SpaceDim);
184 m_amr->allocate(m_electricFieldInho, m_realm, SpaceDim);
190 case Mode::Stationary: {
191 m_amr->allocate(m_inceptionIntegralPlus, m_realm, m_phase, m_voltageSweeps.size());
192 m_amr->allocate(m_inceptionIntegralMinu, m_realm, m_phase, m_voltageSweeps.size());
193 m_amr->allocate(m_inceptionVoltagePlus, m_realm, m_phase, 1);
194 m_amr->allocate(m_inceptionVoltageMinu, m_realm, m_phase, 1);
195 m_amr->allocate(m_streamerInceptionVoltagePlus, m_realm, m_phase, 1);
196 m_amr->allocate(m_streamerInceptionVoltageMinu, m_realm, m_phase, 1);
197 m_amr->allocate(m_townsendInceptionVoltagePlus, m_realm, m_phase, 1);
198 m_amr->allocate(m_townsendInceptionVoltageMinu, m_realm, m_phase, 1);
200 if (m_plotFieldEmission) {
201 m_amr->allocate(m_emissionRatesPlus, m_realm, m_phase, m_voltageSweeps.size());
202 m_amr->allocate(m_emissionRatesMinu, m_realm, m_phase, m_voltageSweeps.size());
208 if (m_plotBackgroundIonization) {
209 m_amr->allocate(m_backgroundIonization, m_realm, m_phase, m_voltageSweeps.size());
214 if (m_plotDetachment) {
215 m_amr->allocate(m_detachment, m_realm, m_phase, m_voltageSweeps.size());
220 m_amr->allocate(m_townsendCriterionPlus, m_realm, m_phase, m_voltageSweeps.size());
221 m_amr->allocate(m_townsendCriterionMinu, m_realm, m_phase, m_voltageSweeps.size());
233 case Mode::Transient: {
234 m_amr->allocate(m_inceptionIntegral, m_realm, m_phase, 1);
235 m_amr->allocate(m_townsendCriterion, m_realm, m_phase, 1);
236 m_amr->allocate(m_emissionRate, m_realm, m_phase, 1);
237 m_amr->allocate(m_backgroundIonization, m_realm, m_phase, 1);
238 m_amr->allocate(m_detachment, m_realm, m_phase, 1);
254 template <
typename P,
typename F,
typename C>
258 CH_TIME(
"DischargeInceptionStepper::initialData");
259 if (m_verbosity > 5) {
260 pout() <<
"DischargeInceptionStepper::initialData" << endl;
263 this->solvePoisson();
266 template <
typename P,
typename F,
typename C>
270 CH_TIME(
"DischargeInceptionStepper::solvePoisson");
271 if (m_verbosity > 5) {
272 pout() <<
"DischargeInceptionStepper::solvePoisson" << endl;
276 m_fieldSolver->setRho(m_rho);
277 m_fieldSolver->setSigma(m_sigma);
278 m_fieldSolver->setVoltage([](
const Real& a_time) {
283 DataOps::copy(m_fieldSolver->getPotential(), m_potentialInho);
284 const bool convergedInho = m_fieldSolver->solve(m_fieldSolver->getPotential(),
285 m_fieldSolver->getRho(),
286 m_fieldSolver->getSigma(),
289 if (!convergedInho) {
290 MayDay::Warning(
"DischargeInceptionStepper::solvePoisson -- could not solve the inhomogeneous Poisson equation. ");
293 DataOps::copy(m_potentialInho, m_fieldSolver->getPotential());
294 DataOps::copy(m_electricFieldInho, m_fieldSolver->getElectricField());
297 m_fieldSolver->setRho([](
const RealVect& a_pos) {
300 m_fieldSolver->setSigma([](
const RealVect& a_pos) {
303 m_fieldSolver->setVoltage([](
const Real& a_time) {
307 DataOps::copy(m_fieldSolver->getPotential(), m_potentialHomo);
308 const bool convergedHomo = m_fieldSolver->solve(m_fieldSolver->getPotential(),
309 m_fieldSolver->getRho(),
310 m_fieldSolver->getSigma(),
313 if (!convergedHomo) {
314 MayDay::Warning(
"DischargeInceptionStepper::solvePoisson -- could not solve the homogeneous Poisson equation. ");
317 DataOps::copy(m_potentialHomo, m_fieldSolver->getPotential());
318 DataOps::copy(m_electricFieldHomo, m_fieldSolver->getElectricField());
321 m_homogeneousFieldGas = m_amr->alias(phase::gas, m_electricFieldHomo);
327 const Real testVoltage = 1.0;
328 const Real errorThresh = 1.E-6;
336 auto voltage = [V = testVoltage](
const Real& a_time) {
342 m_fieldSolver->setRho(m_rho);
343 m_fieldSolver->setSigma(m_sigma);
344 m_fieldSolver->setVoltage(voltage);
345 m_fieldSolver->solve(m_fieldSolver->getPotential(), m_fieldSolver->getRho(), m_fieldSolver->getSigma(),
false);
348 DataOps::incr(m_potential, m_fieldSolver->getPotential(), -1.0);
350 EBAMRCellData phiGas = m_amr->alias(phase::gas, m_potential);
357 if (
std::max(std::abs(
max), std::abs(
min)) > errorThresh * testVoltage) {
358 MayDay::Error(
"DischargeInceptionStepper::solvePoisson - debug test failed. Check your BCs!");
363 template <
typename P,
typename F,
typename C>
367 CH_TIME(
"DischargeInceptionStepper::registerRealms");
368 if (m_verbosity > 5) {
369 pout() <<
"DischargeInceptionStepper::registerRealms" << endl;
372 m_amr->registerRealm(m_realm);
375 template <
typename P,
typename F,
typename C>
379 CH_TIME(
"DischargeInceptionStepper::registerOperators");
380 if (m_verbosity > 5) {
381 pout() <<
"DischargeInceptionStepper::registerOperators" << endl;
384 m_fieldSolver->registerOperators();
385 m_tracerParticleSolver->registerOperators();
386 m_ionSolver->registerOperators();
389 template <
typename P,
typename F,
typename C>
393 CH_TIME(
"DischargeInceptionStepper::parseOptions");
395 this->parseVerbosity();
397 this->parseVoltages();
399 this->parsePlotVariables();
400 this->parseInceptionAlgorithm();
401 this->parseTransportAlgorithm();
404 template <
typename P,
typename F,
typename C>
408 CH_TIME(
"DischargeInceptionStepper::parseRuntimeOptions");
409 if (m_verbosity > 5) {
410 pout() <<
"DischargeInceptionStepper::parseRuntimeOptions" << endl;
413 this->parseVerbosity();
414 this->parsePlotVariables();
415 this->parseInceptionAlgorithm();
416 this->parseTransportAlgorithm();
419 template <
typename P,
typename F,
typename C>
423 CH_TIME(
"DischargeInceptionStepper::parseVerbosity");
424 if (m_verbosity > 5) {
425 pout() <<
"DischargeInceptionStepper::parseVerbosity" << endl;
428 ParmParse pp(
"DischargeInceptionStepper");
429 pp.get(
"verbosity", m_verbosity);
430 pp.get(
"profile", m_profile);
431 pp.query(
"debug", m_debug);
434 template <
typename P,
typename F,
typename C>
438 CH_TIME(
"DischargeInceptionStepper::parseMode");
439 if (m_verbosity > 5) {
440 pout() <<
"DischargeInceptionStepper::parseMode" << endl;
443 ParmParse pp(
"DischargeInceptionStepper");
448 if (str ==
"stationary") {
449 m_mode = Mode::Stationary;
451 else if (str ==
"transient") {
452 m_mode = Mode::Transient;
455 MayDay::Error(
"Expected 'none', 'stationary', or 'transient' for 'DischargeInceptionStepper.mode'");
459 template <
typename P,
typename F,
typename C>
463 CH_TIME(
"DischargeInceptionStepper::parseVoltages");
464 if (m_verbosity > 5) {
465 pout() <<
"DischargeInceptionStepper::parseVoltages" << endl;
468 ParmParse pp(
"DischargeInceptionStepper");
472 Real voltageLo = 0.0;
473 Real voltageHi = 0.0;
475 int voltageSteps = 0;
477 pp.get(
"voltage_lo", voltageLo);
478 pp.get(
"voltage_hi", voltageHi);
479 pp.get(
"voltage_steps", voltageSteps);
480 pp.get(
"K_inception", m_inceptionK);
481 pp.get(
"eval_townsend", m_evaluateTownsend);
484 const Real deltaV = voltageHi - voltageLo;
486 const Real dV = deltaV / (1 + voltageSteps);
488 m_voltageSweeps.push_back(voltageLo);
490 for (
size_t i = 0; i < voltageSteps; i++) {
491 m_voltageSweeps.push_back(m_voltageSweeps[i] + dV);
494 m_voltageSweeps.push_back(voltageHi);
495 m_maxTPlus.resize(m_voltageSweeps.size(), 0.0);
496 m_maxTMinu.resize(m_voltageSweeps.size(), 0.0);
499 template <
typename P,
typename F,
typename C>
503 CH_TIME(
"DischargeInceptionStepper::parseOutput");
504 if (m_verbosity > 5) {
505 pout() <<
"DischargeInceptionStepper::parseOutput" << endl;
508 ParmParse pp(
"DischargeInceptionStepper");
510 pp.get(
"output_file", m_outputFile);
513 template <
typename P,
typename F,
typename C>
517 CH_TIME(
"DischargeInceptionStepper::parseInceptionAlgorithm");
518 if (m_verbosity > 5) {
519 pout() <<
"DischargeInceptionStepper::parseInceptionAlgorithm" << endl;
522 ParmParse pp(
"DischargeInceptionStepper");
527 pp.get(
"full_integration", m_fullIntegration);
528 pp.get(
"inception_alg", str, 0);
529 if (str ==
"euler") {
530 m_inceptionAlgorithm = IntegrationAlgorithm::Euler;
532 else if (str ==
"trapz") {
533 m_inceptionAlgorithm = IntegrationAlgorithm::Trapezoidal;
536 MayDay::Error(
"Expected 'euler' or 'trapz' for 'DischargeInceptionStepper.inception_alg'");
541 pp.get(
"inception_alg", str, 1);
542 pp.get(
"inception_alg", stepSize, 2);
544 m_stepSizeFactor = stepSize;
546 m_stepSizeMethod = StepSizeMethod::Fixed;
548 else if (str ==
"fixed") {
549 m_stepSizeFactor = stepSize;
551 m_stepSizeMethod = StepSizeMethod::Dx;
553 else if (str ==
"alpha") {
554 m_stepSizeFactor = stepSize;
556 m_stepSizeMethod = StepSizeMethod::Alpha;
559 MayDay::Error(
"Expected 'fixed', 'dx', or 'alpha' for 'DischargeInceptionStepper.inception_alg'");
563 template <
typename P,
typename F,
typename C>
567 CH_TIME(
"DischargeInceptionStepper::parseTransportAlgorithm");
568 if (m_verbosity > 5) {
569 pout() <<
"DischargeInceptionStepper::parseTransportAlgorithm" << endl;
572 ParmParse pp(
"DischargeInceptionStepper");
576 pp.get(
"transport_alg", str);
577 pp.get(
"ion_transport", m_ionTransport);
578 pp.get(
"cfl", m_cfl);
579 pp.get(
"first_dt", m_firstDt);
580 pp.get(
"min_dt", m_minDt);
581 pp.get(
"max_dt", m_maxDt);
582 pp.get(
"max_dt_growth", m_maxDtGrowth);
583 pp.get(
"voltage_eps", m_epsVoltage);
585 CH_assert(m_minDt >= 0.0);
586 CH_assert(m_maxDt >= 0.0);
587 CH_assert(m_firstDt > 0.0);
589 if (str ==
"euler") {
590 m_transportAlgorithm = TransportAlgorithm::Euler;
592 else if (str ==
"heun") {
593 m_transportAlgorithm = TransportAlgorithm::Heun;
595 else if (str ==
"imex") {
596 m_transportAlgorithm = TransportAlgorithm::ImExCTU;
599 MayDay::Error(
"Expected 'euler', 'heun', or 'imex' for 'DischargeInceptionStepper.transport_alg'");
603 template <
typename P,
typename F,
typename C>
607 CH_TIME(
"DischargeInceptionStepper::parsePlotVariables");
608 if (m_verbosity > 5) {
609 pout() <<
"DischargeInceptionStepper::parsePlotVariables" << endl;
613 m_plotPoisson =
false;
614 m_plotTracer =
false;
615 m_plotNegativeIons =
false;
616 m_plotInceptionIntegral =
false;
617 m_plotInceptionVoltage =
false;
618 m_plotBackgroundIonization =
false;
619 m_plotDetachment =
false;
620 m_plotFieldEmission =
false;
623 m_plotTownsend =
false;
625 ParmParse pp(
"DischargeInceptionStepper");
628 const int num = pp.countval(
"plt_vars");
630 Vector<std::string> plotVars(num);
631 pp.getarr(
"plt_vars", plotVars, 0, num);
633 for (
int i = 0; i < num; i++) {
634 if (plotVars[i] ==
"field") {
637 else if (plotVars[i] ==
"poisson") {
638 m_plotPoisson =
true;
640 else if (plotVars[i] ==
"tracer") {
643 else if (plotVars[i] ==
"ions") {
644 m_plotNegativeIons =
true;
646 else if (plotVars[i] ==
"K") {
647 m_plotInceptionIntegral =
true;
649 else if (plotVars[i] ==
"Uinc") {
650 m_plotInceptionVoltage =
true;
652 else if (plotVars[i] ==
"bg_rate") {
653 m_plotBackgroundIonization =
true;
655 else if (plotVars[i] ==
"detachment") {
656 m_plotDetachment =
true;
658 else if (plotVars[i] ==
"emission") {
659 m_plotFieldEmission =
true;
661 else if (plotVars[i] ==
"alpha") {
664 else if (plotVars[i] ==
"eta") {
667 else if (plotVars[i] ==
"T") {
668 m_plotTownsend =
true;
675 template <
typename P,
typename F,
typename C>
679 CH_TIME(
"DischargeInceptionStepper::writeCheckpointData");
680 if (m_verbosity > 5) {
681 pout() <<
"DischargeInceptionStepper::writeCheckpointData" << endl;
687 template <
typename P,
typename F,
typename C>
691 CH_TIME(
"DischargeInceptionStepper::readCheckpointData");
692 if (m_verbosity > 5) {
693 pout() <<
"DischargeInceptionStepper::readCheckpointData" << endl;
696 MayDay::Error(
"DischargeInceptionStepper::readCheckpointData -- restart not supported. Use Driver.restart=0");
700 template <
typename P,
typename F,
typename C>
704 CH_TIME(
"DischargeInceptionStepper::getNumberOfPlotVariables");
705 if (m_verbosity > 5) {
706 pout() <<
"DischargeInceptionStepper::getNumberOfPlotVariables" << endl;
712 ncomp += m_fieldSolver->getNumberOfPlotVariables();
715 ncomp += m_tracerParticleSolver->getNumberOfPlotVariables();
717 if (m_plotNegativeIons) {
718 ncomp += m_ionSolver->getNumberOfPlotVariables();
722 case Mode::Stationary: {
726 ncomp += 2 * m_voltageSweeps.size();
729 ncomp += 2 * m_voltageSweeps.size();
732 ncomp += 2 * SpaceDim * m_voltageSweeps.size();
739 if (m_plotInceptionIntegral) {
740 ncomp += 2 * m_voltageSweeps.size();
744 if (m_plotInceptionVoltage) {
749 if (m_plotBackgroundIonization) {
750 ncomp += m_voltageSweeps.size();
754 if (m_plotDetachment) {
755 ncomp += m_voltageSweeps.size();
759 if (m_plotFieldEmission) {
760 ncomp += 2 * m_voltageSweeps.size();
765 ncomp += m_voltageSweeps.size();
770 ncomp += m_voltageSweeps.size();
774 if (m_plotAlpha && m_plotEta) {
775 ncomp += m_voltageSweeps.size();
779 if (m_plotTownsend) {
780 ncomp += 2 * m_voltageSweeps.size();
785 case Mode::Transient: {
802 if (m_plotInceptionIntegral) {
805 if (m_plotTownsend) {
808 if (m_plotBackgroundIonization) {
811 if (m_plotDetachment) {
814 if (m_plotFieldEmission) {
823 if (m_plotAlpha && m_plotEta) {
837 template <
typename P,
typename F,
typename C>
841 CH_TIME(
"DischargeInceptionStepper::getPlotVariableNames");
842 if (m_verbosity > 5) {
843 pout() <<
"DischargeInceptionStepper::getPlotVariableNames" << endl;
846 Vector<std::string> plotVars;
849 Vector<std::string> poissonVars = m_fieldSolver->getPlotVariableNames();
850 for (
int i = 0; i < poissonVars.size(); i++) {
851 poissonVars[i] =
"Poisson/" + poissonVars[i];
853 plotVars.append(poissonVars);
857 Vector<std::string> tracerVars = m_tracerParticleSolver->getPlotVariableNames();
858 for (
int i = 0; i < tracerVars.size(); i++) {
859 tracerVars[i] =
"Tracer/" + tracerVars[i];
861 plotVars.append(tracerVars);
864 if (m_plotNegativeIons) {
865 Vector<std::string> cdrVars = m_ionSolver->getPlotVariableNames();
866 for (
int i = 0; i < cdrVars.size(); i++) {
867 cdrVars[i] =
"CDR/" + cdrVars[i];
869 plotVars.append(cdrVars);
873 case Mode::Stationary: {
874 plotVars.append(this->getStationaryPlotVariableNames());
878 case Mode::Transient: {
879 plotVars.append(this->getTransientPlotVariableNames());
884 MayDay::Error(
"DischargeInceptionStepper::getPlotVariableNames - logic bust");
893 template <
typename P,
typename F,
typename C>
897 CH_TIME(
"DischargeInceptionStepper::getStationaryPlotVariableNames");
898 if (m_verbosity > 5) {
899 pout() <<
"DischargeInceptionStepper::getStationaryPlotVariableNames" << endl;
902 Vector<std::string> plotVars;
904 const std::string prefix =
"DischargeInceptionStepper/";
908 for (
const Real& V : m_voltageSweeps) {
909 plotVars.push_back(prefix +
"Potential/+/ V = +" + std::to_string(V));
910 plotVars.push_back(prefix +
"Potential/-/ V = -" + std::to_string(V));
913 for (
const Real& V : m_voltageSweeps) {
914 plotVars.push_back(prefix +
"E/+/ V = +" + std::to_string(V));
915 plotVars.push_back(prefix +
"x-E/+/ V= +" + std::to_string(V));
916 plotVars.push_back(prefix +
"y-E/+/ V= +" + std::to_string(V));
918 plotVars.push_back(prefix +
"z-E/+/ V= +" + std::to_string(V));
921 plotVars.push_back(prefix +
"E/-/ V = -" + std::to_string(V));
922 plotVars.push_back(prefix +
"x-E/-/ V = -" + std::to_string(V));
923 plotVars.push_back(prefix +
"y-E/-/ V = -" + std::to_string(V));
925 plotVars.push_back(prefix +
"z-E/-/ V= -" + std::to_string(V));
930 plotVars.push_back(prefix +
"Space charge density");
931 plotVars.push_back(prefix +
"Surface charge density");
934 if (m_plotInceptionVoltage) {
935 plotVars.push_back(prefix +
"Minimum inception voltage +");
936 plotVars.push_back(prefix +
"Minimum inception voltage -");
937 plotVars.push_back(prefix +
"Streamer inception voltage +");
938 plotVars.push_back(prefix +
"Streamer inception voltage -");
939 plotVars.push_back(prefix +
"Townsend inception voltage +");
940 plotVars.push_back(prefix +
"Townsend inception voltage -");
943 if (m_plotInceptionIntegral) {
946 for (
const Real& V : m_voltageSweeps) {
947 varName = prefix +
"K-value/+/ V = +" + std::to_string(V);
948 plotVars.push_back(varName);
951 for (
const Real& V : m_voltageSweeps) {
952 varName = prefix +
"K-value/-/ V = -" + std::to_string(V);
953 plotVars.push_back(varName);
958 if (m_plotTownsend) {
959 for (
size_t i = 0; i < m_voltageSweeps.size(); i++) {
960 const std::string varName = prefix +
"T-value/+/ V = +" + std::to_string(m_voltageSweeps[i]);
962 plotVars.push_back(varName);
965 for (
size_t i = 0; i < m_voltageSweeps.size(); i++) {
966 const std::string varName = prefix +
"T-value/-/ V = -" + std::to_string(m_voltageSweeps[i]);
968 plotVars.push_back(varName);
973 if (m_plotBackgroundIonization) {
976 for (
const Real& V : m_voltageSweeps) {
977 varName = prefix +
"Background ionization rate/ V = " + std::to_string(V);
978 plotVars.push_back(varName);
983 if (m_plotDetachment) {
986 for (
const Real& V : m_voltageSweeps) {
987 varName = prefix +
"Detachment rate/ V = " + std::to_string(V);
988 plotVars.push_back(varName);
993 if (m_plotFieldEmission) {
996 for (
const Real& V : m_voltageSweeps) {
997 varName = prefix +
"Field emission rate/+/ V = +" + std::to_string(V);
998 plotVars.push_back(varName);
1001 for (
const Real& V : m_voltageSweeps) {
1002 varName = prefix +
"Field emission rate/-/ V = -" + std::to_string(V);
1003 plotVars.push_back(varName);
1009 for (
size_t i = 0; i < m_voltageSweeps.size(); i++) {
1011 const std::string varName = prefix +
"Alpha coefficient/ V = " + std::to_string(m_voltageSweeps[i]);
1013 plotVars.push_back(varName);
1019 for (
size_t i = 0; i < m_voltageSweeps.size(); i++) {
1020 const std::string varName = prefix +
"Eta coefficient/ V = " + std::to_string(m_voltageSweeps[i]);
1022 plotVars.push_back(varName);
1027 if (m_plotAlpha && m_plotEta) {
1028 for (
size_t i = 0; i < m_voltageSweeps.size(); i++) {
1029 const std::string varName = prefix +
"Alpha_eff/ V = " + std::to_string(m_voltageSweeps[i]);
1031 plotVars.push_back(varName);
1038 template <
typename P,
typename F,
typename C>
1042 CH_TIME(
"DischargeInceptionStepper::getTransientPlotVariableNames");
1043 if (m_verbosity > 5) {
1044 pout() <<
"DischargeInceptionStepper::getTransientPlotVariableNames" << endl;
1047 Vector<std::string> plotVars;
1051 plotVars.push_back(
"Electric potential");
1052 plotVars.push_back(
"E");
1053 plotVars.push_back(
"x-E");
1054 plotVars.push_back(
"y-E");
1055 if (SpaceDim == 3) {
1056 plotVars.push_back(
"z-E");
1060 plotVars.push_back(
"Space charge density");
1061 plotVars.push_back(
"Surface charge density");
1064 if (m_plotInceptionIntegral) {
1065 plotVars.push_back(
"Inception integral");
1068 if (m_plotTownsend) {
1069 plotVars.push_back(
"Townsend criterion");
1072 if (m_plotBackgroundIonization) {
1073 plotVars.push_back(
"Background rate");
1076 if (m_plotDetachment) {
1077 plotVars.push_back(
"Detachment rate");
1080 if (m_plotFieldEmission) {
1081 plotVars.push_back(
"Field emission");
1085 plotVars.push_back(
"Townsend alpha coefficient");
1089 plotVars.push_back(
"Townsend eta coefficient");
1092 if (m_plotAlpha && m_plotEta) {
1093 plotVars.push_back(
"Effective Townsend coefficient");
1096 for (
int i = 0; i < plotVars.size(); i++) {
1097 plotVars[i] =
"DischargeInceptionStepper/" + plotVars[i];
1103 template <
typename P,
typename F,
typename C>
1107 const std::string a_outputRealm,
1108 const int a_level)
const
1110 CH_TIME(
"DischargeInceptionStepper::writePlotData");
1111 if (m_verbosity > 5) {
1112 pout() <<
"DischargeInceptionStepper::writePlotData" << endl;
1115 if (m_plotPoisson) {
1116 m_fieldSolver->writePlotData(a_output, a_icomp, a_outputRealm, a_level);
1120 m_tracerParticleSolver->writePlotData(a_output, a_icomp, a_outputRealm, a_level);
1123 if (m_plotNegativeIons) {
1124 m_ionSolver->writePlotData(a_output, a_icomp, a_outputRealm, a_level);
1129 case Mode::Stationary: {
1130 this->writePlotDataStationary(a_output, a_icomp, a_outputRealm, a_level);
1134 case Mode::Transient:
1135 this->writePlotDataTransient(a_output, a_icomp, a_outputRealm, a_level);
1139 MayDay::Error(
"DischargeInceptionStepper::writePlotData - logic bust");
1146 template <
typename P,
typename F,
typename C>
1150 const std::string a_outputRealm,
1151 const int a_level)
const noexcept
1153 CH_TIME(
"DischargeInceptionStepper::writePlotDataStationary");
1154 if (m_verbosity > 5) {
1155 pout() <<
"DischargeInceptionStepper::writePlotDataStationary" << endl;
1158 const std::string prefix =
"DischargeInceptionStepper/";
1164 m_amr->allocate(scratch, m_realm, 1);
1165 m_amr->allocate(scratchSurf, m_realm, phase::gas, 1);
1167 for (
const auto& V : m_voltageSweeps) {
1173 m_fieldSolver->writeMultifluidData(a_output, a_icomp, m_potential, phase::gas, a_outputRealm, a_level,
true);
1179 m_fieldSolver->writeMultifluidData(a_output, a_icomp, m_potential, phase::gas, a_outputRealm, a_level,
true);
1182 for (
const auto& V : m_voltageSweeps) {
1185 DataOps::incr(m_electricField, m_electricFieldHomo, Real(V));
1189 m_fieldSolver->writeMultifluidData(a_output, a_icomp, scratch, phase::gas, a_outputRealm, a_level,
true);
1190 m_fieldSolver->writeMultifluidData(a_output, a_icomp, m_electricField, phase::gas, a_outputRealm, a_level,
true);
1194 DataOps::incr(m_electricField, m_electricFieldHomo, -Real(V));
1198 m_fieldSolver->writeMultifluidData(a_output, a_icomp, scratch, phase::gas, a_outputRealm, a_level,
true);
1199 m_fieldSolver->writeMultifluidData(a_output, a_icomp, m_electricField, phase::gas, a_outputRealm, a_level,
true);
1204 m_amr->arithmeticAverage(scratch, m_realm);
1205 m_amr->interpGhostPwl(scratch, m_realm);
1206 m_fieldSolver->writeMultifluidData(a_output, a_icomp, scratch, phase::gas, a_outputRealm, a_level,
true);
1209 m_fieldSolver->writeSurfaceData(a_output, a_icomp, *scratchSurf[a_level], a_outputRealm, a_level);
1212 if (m_plotInceptionVoltage) {
1213 this->writeData(a_output, a_icomp, m_inceptionVoltagePlus, a_outputRealm, a_level,
false,
true);
1214 this->writeData(a_output, a_icomp, m_inceptionVoltageMinu, a_outputRealm, a_level,
false,
true);
1215 this->writeData(a_output, a_icomp, m_streamerInceptionVoltagePlus, a_outputRealm, a_level,
false,
true);
1216 this->writeData(a_output, a_icomp, m_streamerInceptionVoltageMinu, a_outputRealm, a_level,
false,
true);
1217 this->writeData(a_output, a_icomp, m_townsendInceptionVoltagePlus, a_outputRealm, a_level,
false,
true);
1218 this->writeData(a_output, a_icomp, m_townsendInceptionVoltageMinu, a_outputRealm, a_level,
false,
true);
1221 if (m_plotInceptionIntegral) {
1222 this->writeData(a_output, a_icomp, m_inceptionIntegralPlus, a_outputRealm, a_level,
false,
true);
1223 this->writeData(a_output, a_icomp, m_inceptionIntegralMinu, a_outputRealm, a_level,
false,
true);
1226 if (m_plotTownsend) {
1227 this->writeData(a_output, a_icomp, m_townsendCriterionPlus, a_outputRealm, a_level,
false,
true);
1228 this->writeData(a_output, a_icomp, m_townsendCriterionMinu, a_outputRealm, a_level,
false,
true);
1231 if (m_plotBackgroundIonization) {
1232 this->writeData(a_output, a_icomp, m_backgroundIonization, a_outputRealm, a_level,
false,
true);
1235 if (m_plotDetachment) {
1236 this->writeData(a_output, a_icomp, m_detachment, a_outputRealm, a_level,
false,
true);
1239 if (m_plotFieldEmission) {
1240 this->writeData(a_output, a_icomp, m_emissionRatesPlus, a_outputRealm, a_level,
false,
true);
1241 this->writeData(a_output, a_icomp, m_emissionRatesMinu, a_outputRealm, a_level,
false,
true);
1245 LevelData<EBCellFAB> alpha;
1246 LevelData<EBCellFAB> alphaCoar;
1248 m_amr->allocate(alpha, m_realm, m_phase, a_level, 1);
1250 m_amr->allocate(alphaCoar, m_realm, m_phase, a_level - 1, 1);
1253 for (
size_t i = 0; i < m_voltageSweeps.size(); i++) {
1254 this->evaluateFunction(alpha, m_voltageSweeps[i], m_alpha, a_level);
1256 this->evaluateFunction(alphaCoar, m_voltageSweeps[i], m_alpha, a_level - 1);
1257 m_amr->interpGhost(alpha, alphaCoar, a_level, m_realm, m_phase);
1263 m_amr->copyData(a_output, alpha, a_level, a_outputRealm, m_realm, Interval(a_icomp, a_icomp), Interval(0, 0));
1270 LevelData<EBCellFAB> eta;
1271 LevelData<EBCellFAB> etaCoar;
1273 m_amr->allocate(eta, m_realm, m_phase, a_level, 1);
1275 m_amr->allocate(etaCoar, m_realm, m_phase, a_level - 1, 1);
1278 for (
size_t i = 0; i < m_voltageSweeps.size(); i++) {
1279 this->evaluateFunction(eta, m_voltageSweeps[i], m_eta, a_level);
1281 this->evaluateFunction(etaCoar, m_voltageSweeps[i], m_eta, a_level - 1);
1282 m_amr->interpGhost(eta, etaCoar, a_level, m_realm, m_phase);
1288 m_amr->copyData(a_output, eta, a_level, a_outputRealm, m_realm, Interval(a_icomp, a_icomp), Interval(0, 0));
1294 if (m_plotAlpha && m_plotEta) {
1295 LevelData<EBCellFAB> alphaEff;
1296 LevelData<EBCellFAB> alphaEffCoar;
1298 m_amr->allocate(alphaEff, m_realm, m_phase, a_level, 1);
1300 m_amr->allocate(alphaEffCoar, m_realm, m_phase, a_level - 1, 1);
1303 auto alphaFunc = [alpha = this->m_alpha, eta = this->m_eta](
const Real E,
const RealVect x) -> Real {
1304 return alpha(E, x) - eta(E, x);
1307 for (
size_t i = 0; i < m_voltageSweeps.size(); i++) {
1308 this->evaluateFunction(alphaEff, m_voltageSweeps[i], alphaFunc, a_level);
1310 this->evaluateFunction(alphaEffCoar, m_voltageSweeps[i], alphaFunc, a_level - 1);
1311 m_amr->interpGhost(alphaEff, alphaEffCoar, a_level, m_realm, m_phase);
1314 alphaEff.exchange();
1319 m_amr->copyData(a_output, alphaEff, a_level, a_outputRealm, m_realm, Interval(a_icomp, a_icomp), Interval(0, 0));
1326 template <
typename P,
typename F,
typename C>
1330 const std::string a_outputRealm,
1331 const int a_level)
const noexcept
1333 CH_TIME(
"DischargeInceptionStepper::writePlotDataTransient");
1334 if (m_verbosity > 5) {
1335 pout() <<
"DischargeInceptionStepper::writePlotDataTransient" << endl;
1338 CH_assert(a_level >= 0);
1339 CH_assert(a_level <= m_amr->getFinestLevel());
1348 m_amr->allocate(scratch, m_realm, 1);
1349 m_amr->allocate(scratchSurf, m_realm, phase::gas, 1);
1353 m_amr->arithmeticAverage(scratch, m_realm);
1354 m_amr->interpGhostPwl(scratch, m_realm);
1356 m_fieldSolver->writeMultifluidData(a_output, a_icomp, m_potential, phase::gas, a_outputRealm, a_level,
true);
1357 m_fieldSolver->writeMultifluidData(a_output, a_icomp, scratch, phase::gas, a_outputRealm, a_level,
true);
1358 m_fieldSolver->writeMultifluidData(a_output, a_icomp, m_electricField, phase::gas, a_outputRealm, a_level,
true);
1362 m_amr->arithmeticAverage(scratch, m_realm);
1363 m_amr->interpGhostPwl(scratch, m_realm);
1364 m_fieldSolver->writeMultifluidData(a_output, a_icomp, scratch, phase::gas, a_outputRealm, a_level,
true);
1367 m_fieldSolver->writeSurfaceData(a_output, a_icomp, *scratchSurf[a_level], a_outputRealm, a_level);
1370 if (m_plotInceptionIntegral) {
1371 this->writeData(a_output, a_icomp, m_inceptionIntegral, a_outputRealm, a_level,
false,
true);
1374 if (m_plotTownsend) {
1375 this->writeData(a_output, a_icomp, m_townsendCriterion, a_outputRealm, a_level,
false,
true);
1378 if (m_plotBackgroundIonization) {
1379 LevelData<EBCellFAB> bgIonization;
1380 m_amr->allocate(bgIonization, m_realm, m_phase, a_level, 1);
1382 this->evaluateFunction(bgIonization, m_voltageCurve(m_time), m_backgroundRate, a_level);
1387 ->copyData(a_output, bgIonization, a_level, a_outputRealm, m_realm, Interval(a_icomp, a_icomp), Interval(0, 0));
1392 if (m_plotDetachment) {
1393 LevelData<EBCellFAB> detachRate;
1394 LevelData<EBCellFAB> detachRateCoar;
1396 m_amr->allocate(detachRate, m_realm, m_phase, a_level, 1);
1398 m_amr->allocate(detachRateCoar, m_realm, m_phase, a_level - 1, 1);
1401 this->evaluateFunction(detachRate, m_voltageCurve(m_time), m_detachmentRate, a_level);
1403 this->evaluateFunction(detachRateCoar, m_voltageCurve(m_time), m_detachmentRate, a_level - 1);
1404 m_amr->interpGhost(detachRate, detachRateCoar, a_level, m_realm, m_phase);
1407 m_amr->copyData(a_output, detachRate, a_level, a_outputRealm, m_realm, Interval(a_icomp, a_icomp), Interval(0, 0));
1412 if (m_plotFieldEmission) {
1413 this->writeData(a_output, a_icomp, m_emissionRate, a_outputRealm, a_level,
false,
false);
1417 LevelData<EBCellFAB> alpha;
1418 LevelData<EBCellFAB> alphaCoar;
1420 m_amr->allocate(alpha, m_realm, m_phase, a_level, 1);
1422 m_amr->allocate(alphaCoar, m_realm, m_phase, a_level - 1, 1);
1425 this->evaluateFunction(alpha, m_voltageCurve(m_time), m_alpha, a_level);
1427 this->evaluateFunction(alphaCoar, m_voltageCurve(m_time), m_alpha, a_level - 1);
1428 m_amr->interpGhost(alpha, alphaCoar, a_level, m_realm, m_phase);
1436 m_amr->copyData(a_output, alpha, a_level, a_outputRealm, m_realm, Interval(a_icomp, a_icomp), Interval(0, 0));
1442 LevelData<EBCellFAB> eta;
1443 LevelData<EBCellFAB> etaCoar;
1445 m_amr->allocate(eta, m_realm, m_phase, a_level, 1);
1447 m_amr->allocate(etaCoar, m_realm, m_phase, a_level - 1, 1);
1450 this->evaluateFunction(eta, m_voltageCurve(m_time), m_eta, a_level);
1452 this->evaluateFunction(etaCoar, m_voltageCurve(m_time), m_eta, a_level - 1);
1453 m_amr->interpGhost(eta, etaCoar, a_level, m_realm, m_phase);
1461 m_amr->copyData(a_output, eta, a_level, a_outputRealm, m_realm, Interval(a_icomp, a_icomp), Interval(0, 0));
1466 if (m_plotAlpha && m_plotEta) {
1467 LevelData<EBCellFAB> alphaEff;
1468 LevelData<EBCellFAB> alphaEffCoar;
1470 m_amr->allocate(alphaEff, m_realm, m_phase, a_level, 1);
1472 m_amr->allocate(alphaEffCoar, m_realm, m_phase, a_level - 1, 1);
1475 auto alphaFunc = [alpha = this->m_alpha, eta = this->m_eta](
const Real E,
const RealVect x) -> Real {
1476 return alpha(E, x) - eta(E, x);
1479 this->evaluateFunction(alphaEff, m_voltageCurve(m_time), alphaFunc, a_level);
1481 this->evaluateFunction(alphaEffCoar, m_voltageCurve(m_time), alphaFunc, a_level - 1);
1482 m_amr->interpGhost(alphaEff, alphaEffCoar, a_level, m_realm, m_phase);
1485 alphaEff.exchange();
1490 m_amr->copyData(a_output, alphaEff, a_level, a_outputRealm, m_realm, Interval(a_icomp, a_icomp), Interval(0, 0));
1496 template <
typename P,
typename F,
typename C>
1500 CH_TIME(
"DischargeInceptionStepper::computeDt");
1501 if (m_verbosity > 5) {
1502 pout() <<
"DischargeInceptionStepper::computeDt" << endl;
1507 if (m_mode == Mode::Transient) {
1510 m_timeStepRestriction = TimeStepRestriction::Unknown;
1513 if (m_ionTransport) {
1514 Real ionDt = std::numeric_limits<Real>::infinity();
1515 switch (m_transportAlgorithm) {
1516 case TransportAlgorithm::Euler: {
1517 ionDt = m_cfl * m_ionSolver->computeAdvectionDiffusionDt();
1521 case TransportAlgorithm::Heun: {
1522 ionDt = m_cfl * m_ionSolver->computeAdvectionDiffusionDt();
1526 case TransportAlgorithm::ImExCTU: {
1527 ionDt = m_cfl * m_ionSolver->computeAdvectionDt();
1532 MayDay::Error(
"DischargeInceptionStepper::computDt -- logic bust");
1540 m_timeStepRestriction = TimeStepRestriction::CDR;
1546 if (m_timeStep == 0) {
1547 curveDt = m_firstDt;
1550 const Real preU = m_voltageCurve(m_time - m_dt);
1551 const Real curU = m_voltageCurve(m_time);
1552 const Real dVdt = std::abs(curU - preU) / dt;
1554 if (dVdt > std::numeric_limits<Real>::epsilon()) {
1555 curveDt = m_epsVoltage * std::abs(curU) / dVdt;
1559 curveDt =
std::min(m_dt * (1.0 + m_maxDtGrowth), curveDt);
1560 curveDt =
std::max(m_dt * (1.0 - m_maxDtGrowth), curveDt);
1565 m_timeStepRestriction = TimeStepRestriction::VoltageCurve;
1571 m_timeStepRestriction = TimeStepRestriction::MaxHardcap;
1576 m_timeStepRestriction = TimeStepRestriction::MinHardcap;
1583 template <
typename P,
typename F,
typename C>
1587 CH_TIME(
"DischargeInceptionStepper::advance");
1588 if (m_verbosity > 5) {
1589 pout() <<
"DischargeInceptionStepper::advance" << endl;
1592 if (m_mode == Mode::Transient) {
1593 Timer timer(
"DischargeInceptionStepper::advance");
1595 const Real curTime = m_time + a_dt;
1596 const Real curVoltage = m_voltageCurve(curTime);
1603 m_amr->arithmeticAverage(m_potential, m_realm);
1604 m_amr->interpGhostPwl(m_potential, m_realm);
1607 DataOps::incr(m_electricField, m_electricFieldHomo, curVoltage);
1610 m_amr->arithmeticAverage(m_electricField, m_realm);
1611 m_amr->interpGhostPwl(m_electricField, m_realm);
1615 if (m_ionTransport) {
1616 this->computeIonVelocity(curVoltage);
1617 this->computeIonDiffusion(curVoltage);
1618 this->advanceIons(a_dt);
1624 this->seedIonizationParticles(curVoltage);
1625 this->computeInceptionIntegralTransient(curVoltage);
1628 if (m_evaluateTownsend) {
1630 this->seedIonizationParticles(curVoltage);
1631 this->computeTownsendCriterionTransient(curVoltage);
1637 const Real Vcr = this->computeCriticalVolumeTransient();
1638 const Real Acr = this->computeCriticalAreaTransient();
1639 const Real Vion = this->computeIonizationVolumeTransient(curVoltage);
1640 const Real Rdot = this->computeRdot(curVoltage);
1643 m_criticalVolume.emplace_back(curTime, Vcr);
1644 m_criticalArea.emplace_back(curTime, Acr);
1645 m_ionizationVolumeTransient.emplace_back(curTime, Vion);
1646 m_Rdot.emplace_back(curTime, Rdot);
1649 if (m_Rdot.size() >= 2) {
1652 for (
size_t i = 0; i < m_Rdot.size() - 1; i++) {
1653 const Real dt = m_Rdot[i + 1].first - m_Rdot[i].first;
1655 p += 0.5 * dt * (m_Rdot[i + 1].second + m_Rdot[i].second);
1658 m_inceptionProbability.emplace_back(curTime, 1.0 - exp(-p));
1672 if (!m_fullIntegration) {
1673 maxK =
std::min(maxK, m_inceptionK);
1676 m_maxK.emplace_back(m_time + a_dt, maxK);
1677 m_maxT.emplace_back(m_time + a_dt, maxT);
1681 this->writeReportTransient();
1689 MayDay::Error(
"DischargeInceptionStepper::advance -- must have 'DischargeInceptionStepper.mode = transient'");
1695 template <
typename P,
typename F,
typename C>
1699 CH_TIME(
"DischargeInceptionStepper::advanceIons");
1700 if (m_verbosity > 5) {
1701 pout() <<
"DischargeInceptionStepper::advanceIons" << endl;
1710 m_ionSolver->extrapolateAdvectiveFluxToEB(ebFlux);
1713 switch (m_transportAlgorithm) {
1714 case TransportAlgorithm::Euler: {
1716 m_amr->allocate(divJ, m_realm, m_phase, 1.0);
1718 m_ionSolver->computeDivJ(divJ, phi, 0.0,
false,
true,
false);
1724 case TransportAlgorithm::Heun: {
1730 m_amr->allocate(yp, m_realm, m_phase, 1);
1731 m_amr->allocate(k1, m_realm, m_phase, 1);
1732 m_amr->allocate(k2, m_realm, m_phase, 1);
1735 m_ionSolver->computeDivJ(k1, phi, 0.0,
false,
true,
false);
1740 m_ionSolver->computeDivJ(k2, yp, 0.0,
false,
true,
false);
1746 case TransportAlgorithm::ImExCTU: {
1747 const bool addEbFlux =
true;
1748 const bool addDomainFlux =
true;
1754 m_amr->allocate(k1, m_realm, m_phase, 1);
1755 m_amr->allocate(k2, m_realm, m_phase, 1);
1757 m_ionSolver->computeDivF(k1, phi, a_dt,
false,
true,
true);
1766 m_ionSolver->advanceCrankNicholson(phi, k2, k1, a_dt);
1771 MayDay::Error(
"DischargeInceptionStepper::advanceIons -- logic bust");
1777 m_amr->average(phi, m_realm, m_phase, Average::Conservative);
1778 m_amr->interpGhost(phi, m_realm, m_phase);
1781 template <
typename P,
typename F,
typename C>
1785 CH_TIME(
"DischargeInceptionStepper::synchronizeSolverTimes");
1786 if (m_verbosity > 5) {
1787 pout() <<
"DischargeInceptionStepper::synchronizeSolverTimes" << endl;
1790 m_timeStep = a_step;
1794 m_fieldSolver->setTime(a_step, a_time, a_dt);
1795 m_tracerParticleSolver->setTime(a_step, a_time, a_dt);
1796 m_ionSolver->setTime(a_step, a_time, a_dt);
1799 template <
typename P,
typename F,
typename C>
1803 CH_TIME(
"DischargeInceptionStepper::printStepReport");
1805 if (m_verbosity > 5) {
1806 pout() <<
"DischargeInceptionStepper::printStepReport" << endl;
1810 std::string timeStepMessage;
1811 switch (m_timeStepRestriction) {
1812 case TimeStepRestriction::Unknown: {
1813 timeStepMessage =
"Unknown";
1817 case TimeStepRestriction::CDR: {
1818 timeStepMessage =
"CFL";
1822 case TimeStepRestriction::VoltageCurve: {
1823 timeStepMessage =
"Voltage curve";
1827 case TimeStepRestriction::MinHardcap: {
1828 timeStepMessage =
"Min hardcap";
1832 case TimeStepRestriction::MaxHardcap: {
1833 timeStepMessage =
"Max hardcap";
1838 MayDay::Warning(
"DischargeInceptionStepper::printStepReport - logic bust");
1845 pout() <<
" ** Voltage = " << m_voltageCurve(m_time) << endl;
1846 pout() <<
" ** Crit. volume = " << m_criticalVolume.back().second << endl;
1847 pout() <<
" ** Inception probability = " << m_inceptionProbability.back().second << endl;
1848 pout() <<
" ** Time step restriction = " <<
"'" << timeStepMessage <<
"'" << endl;
1852 template <
typename P,
typename F,
typename C>
1856 CH_TIME(
"DischargeInceptionStepper::preRegrid");
1857 if (m_verbosity > 5) {
1858 pout() <<
"DischargeInceptionStepper::preRegrid" << endl;
1861 m_fieldSolver->preRegrid(a_lmin, a_oldFinestLevel);
1862 m_tracerParticleSolver->preRegrid(a_lmin, a_oldFinestLevel);
1863 m_ionSolver->preRegrid(a_lmin, a_oldFinestLevel);
1865 m_amr->allocate(m_scratchHomo, m_realm, 1);
1866 m_amr->allocate(m_scratchInho, m_realm, 1);
1868 m_amr->copyData(m_scratchHomo, m_potentialHomo);
1869 m_amr->copyData(m_scratchInho, m_potentialInho);
1872 template <
typename P,
typename F,
typename C>
1876 CH_TIME(
"DischargeInceptionStepper::regrid");
1877 if (m_verbosity > 5) {
1878 pout() <<
"DischargeInceptionStepper::regrid" << endl;
1882 m_fieldSolver->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
1883 m_tracerParticleSolver->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
1884 m_ionSolver->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
1887 m_amr->reallocate(m_potential, a_lmin);
1888 m_amr->reallocate(m_potentialHomo, a_lmin);
1889 m_amr->reallocate(m_potentialInho, a_lmin);
1891 m_amr->reallocate(m_electricField, a_lmin);
1892 m_amr->reallocate(m_electricFieldHomo, a_lmin);
1893 m_amr->reallocate(m_electricFieldInho, a_lmin);
1897 m_amr->interpToNewGrids(m_potentialHomo, m_scratchHomo, a_lmin, a_oldFinestLevel, a_newFinestLevel, interpType);
1898 m_amr->interpToNewGrids(m_potentialInho, m_scratchInho, a_lmin, a_oldFinestLevel, a_newFinestLevel, interpType);
1901 case Mode::Stationary: {
1902 m_amr->reallocate(m_inceptionIntegralPlus, m_phase, a_lmin);
1903 m_amr->reallocate(m_inceptionIntegralMinu, m_phase, a_lmin);
1904 m_amr->reallocate(m_inceptionVoltagePlus, m_phase, a_lmin);
1905 m_amr->reallocate(m_inceptionVoltageMinu, m_phase, a_lmin);
1906 m_amr->reallocate(m_streamerInceptionVoltagePlus, m_phase, a_lmin);
1907 m_amr->reallocate(m_streamerInceptionVoltageMinu, m_phase, a_lmin);
1908 m_amr->reallocate(m_townsendInceptionVoltagePlus, m_phase, a_lmin);
1909 m_amr->reallocate(m_townsendInceptionVoltageMinu, m_phase, a_lmin);
1911 if (m_plotBackgroundIonization) {
1912 m_amr->reallocate(m_backgroundIonization, m_phase, a_lmin);
1915 if (m_plotDetachment) {
1916 m_amr->reallocate(m_detachment, m_phase, a_lmin);
1919 if (m_plotFieldEmission) {
1920 m_amr->reallocate(m_emissionRatesPlus, m_phase, a_lmin);
1921 m_amr->reallocate(m_emissionRatesMinu, m_phase, a_lmin);
1924 m_amr->reallocate(m_townsendCriterionPlus, m_phase, a_lmin);
1925 m_amr->reallocate(m_townsendCriterionMinu, m_phase, a_lmin);
1929 case Mode::Transient: {
1931 m_amr->reallocate(m_inceptionIntegral, m_phase, a_lmin);
1932 m_amr->reallocate(m_townsendCriterion, m_phase, a_lmin);
1933 m_amr->reallocate(m_emissionRate, m_phase, a_lmin);
1934 m_amr->reallocate(m_backgroundIonization, m_phase, a_lmin);
1944 this->solvePoisson();
1947 this->computeIonVelocity(m_voltageCurve(m_time));
1948 this->computeIonDiffusion(m_voltageCurve(m_time));
1951 template <
typename P,
typename F,
typename C>
1955 CH_TIME(
"DischargeInceptionStepper::postRegrid");
1956 if (m_verbosity > 5) {
1957 pout() <<
"DischargeInceptionStepper::postRegrid" << endl;
1960 m_scratchHomo.clear();
1961 m_scratchInho.clear();
1964 template <
typename P,
typename F,
typename C>
1968 CH_TIME(
"DischargeInceptionStepper::setVoltageCurve");
1969 if (m_verbosity > 5) {
1970 pout() <<
"DischargeInceptionStepper::setVoltageCurve" << endl;
1973 m_voltageCurve = a_voltageCurve;
1976 template <
typename P,
typename F,
typename C>
1980 CH_TIME(
"DischargeInceptionStepper::setRho");
1981 if (m_verbosity > 5) {
1982 pout() <<
"DischargeInceptionStepper::setRho" << endl;
1988 template <
typename P,
typename F,
typename C>
1992 CH_TIME(
"DischargeInceptionStepper::setSigma");
1993 if (m_verbosity > 5) {
1994 pout() <<
"DischargeInceptionStepper::setSigma" << endl;
2000 template <
typename P,
typename F,
typename C>
2004 CH_TIME(
"DischargeInceptionStepper::setIonDensity");
2005 if (m_verbosity > 5) {
2006 pout() <<
"DischargeInceptionStepper::setIonDensity" << endl;
2009 m_initialIonDensity = a_density;
2012 template <
typename P,
typename F,
typename C>
2016 CH_TIME(
"DischargeInceptionStepper::setIonMobility");
2017 if (m_verbosity > 5) {
2018 pout() <<
"DischargeInceptionStepper::setIonMobility" << endl;
2021 m_ionMobility = a_mobility;
2024 template <
typename P,
typename F,
typename C>
2028 CH_TIME(
"DischargeInceptionStepper::setIonDiffusion");
2029 if (m_verbosity > 5) {
2030 pout() <<
"DischargeInceptionStepper::setIonDiffusion" << endl;
2033 m_ionDiffusion = a_diffCo;
2036 template <
typename P,
typename F,
typename C>
2039 const std::function<Real(
const Real& E,
const RealVect& x)>& a_alpha) noexcept
2041 CH_TIME(
"DischargeInceptionStepper::setAlpha");
2042 if (m_verbosity > 5) {
2043 pout() <<
"DischargeInceptionStepper::setAlpha" << endl;
2049 template <
typename P,
typename F,
typename C>
2053 CH_TIME(
"DischargeInceptionStepper::setEta");
2054 if (m_verbosity > 5) {
2055 pout() <<
"DischargeInceptionStepper::setEta" << endl;
2061 template <
typename P,
typename F,
typename C>
2062 const std::function<Real(
const Real& E,
const RealVect& x)>&
2068 template <
typename P,
typename F,
typename C>
2069 const std::function<Real(
const Real& E,
const RealVect& x)>&
2075 template <
typename P,
typename F,
typename C>
2078 const std::function<Real(
const Real& E,
const RealVect& x)>& a_backgroundRate) noexcept
2080 CH_TIME(
"DischargeInceptionStepper::setBackgroundRate");
2081 if (m_verbosity > 5) {
2082 pout() <<
"DischargeInceptionStepper::setBackgroundRate" << endl;
2085 m_backgroundRate = a_backgroundRate;
2088 template <
typename P,
typename F,
typename C>
2091 const std::function<Real(
const Real& E,
const RealVect& x)>& a_detachmentRate) noexcept
2093 CH_TIME(
"DischargeInceptionStepper::setDetachmentRate");
2094 if (m_verbosity > 5) {
2095 pout() <<
"DischargeInceptionStepper::setDetachmentRate" << endl;
2098 m_detachmentRate = a_detachmentRate;
2101 template <
typename P,
typename F,
typename C>
2104 const std::function<Real(
const Real& E,
const RealVect& x)>& a_currentDensity) noexcept
2106 CH_TIME(
"DischargeInceptionStepper::setFieldEmission");
2107 if (m_verbosity > 5) {
2108 pout() <<
"DischargeInceptionStepper::setFieldEmission" << endl;
2111 m_fieldEmission = a_currentDensity;
2114 template <
typename P,
typename F,
typename C>
2117 const std::function<Real(
const Real& E,
const RealVect& x)>& a_coefficient) noexcept
2119 CH_TIME(
"DischargeInceptionStepper::setSecondaryEmission");
2120 if (m_verbosity > 5) {
2121 pout() <<
"DischargeInceptionStepper::setSecondaryEmission" << endl;
2124 m_secondaryEmission = a_coefficient;
2127 template <
typename P,
typename F,
typename C>
2134 template <
typename P,
typename F,
typename C>
2138 CH_TIME(
"DischargeInceptionStepper::seedUniformParticles");
2139 if (m_verbosity > 5) {
2140 pout() <<
"DischargeInceptionStepper::seedUniformParticles" << endl;
2146 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
2147 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
2148 const DataIterator& dit = dbl.dataIterator();
2149 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
2151 const LevelData<BaseFab<bool>>& validCellsLD = *m_amr->getValidCells(m_realm)[lvl];
2153 const Real dx = m_amr->getDx()[lvl];
2155 ParticleData<P>& levelParticles = amrParticles[lvl];
2157 const int nbox = dit.size();
2159 #pragma omp parallel for schedule(runtime)
2160 for (
int mybox = 0; mybox < nbox; mybox++) {
2161 const DataIndex& din = dit[mybox];
2163 const EBISBox& ebisbox = ebisl[din];
2164 const BaseFab<bool>& validCells = validCellsLD[din];
2166 List<P>& particles = levelParticles[din].listItems();
2168 auto regularKernel = [&](
const IntVect& iv) ->
void {
2169 if (validCells(iv, 0) && ebisbox.isRegular(iv)) {
2171 p.position() = m_amr->
getProbLo() + (0.5 * RealVect::Unit + RealVect(iv)) * dx;
2177 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
2178 if (validCells(vof.gridIndex())) {
2180 p.position() = m_amr->getProbLo() +
Location::position(Location::Cell::Centroid, vof, ebisbox, dx);
2187 const Box cellBox = dbl[din];
2188 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
2193 for (ListIterator<P> lit(particles); lit.ok(); ++lit) {
2200 p.template vect<0>() = p.position();
2206 m_amr->removeCoveredParticlesIF(amrParticles, m_phase);
2208 amrParticles.
remap();
2211 template <
typename P,
typename F,
typename C>
2215 CH_TIME(
"DischargeInceptionStepper::seedIonizationParticles");
2216 if (m_verbosity > 5) {
2217 pout() <<
"DischargeInceptionStepper::seedIonizationParticles" << endl;
2225 m_amr->allocate(scratch, m_realm, m_phase, SpaceDim);
2226 this->superposition(scratch, a_voltage);
2228 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
2229 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
2230 const DataIterator& dit = dbl.dataIterator();
2231 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
2233 const LevelData<BaseFab<bool>>& validCellsLD = *m_amr->getValidCells(m_realm)[lvl];
2235 const Real dx = m_amr->getDx()[lvl];
2236 const RealVect probLo = m_amr->getProbLo();
2238 ParticleData<P>& levelParticles = amrParticles[lvl];
2240 const int nbox = dit.size();
2242 #pragma omp parallel for schedule(runtime)
2243 for (
int mybox = 0; mybox < nbox; mybox++) {
2244 const DataIndex& din = dit[mybox];
2246 const EBISBox& ebisbox = ebisl[din];
2247 const BaseFab<bool>& validCells = validCellsLD[din];
2249 List<P>& particles = levelParticles[din].listItems();
2251 const EBCellFAB& electricField = (*scratch[lvl])[din];
2252 const FArrayBox& electricFieldReg = electricField.getFArrayBox();
2254 if (!ebisbox.isAllCovered()) {
2256 auto regularKernel = [&](
const IntVect& iv) ->
void {
2257 if (validCells(iv, 0) && ebisbox.isRegular(iv)) {
2259 const RealVect x = probLo + dx * (0.5 * RealVect::Unit + RealVect(iv));
2260 const RealVect EE = RealVect(
2261 D_DECL(electricFieldReg(iv, 0), electricFieldReg(iv, 1), electricFieldReg(iv, 2)));
2263 const Real E = EE.vectorLength();
2264 const Real alpha = m_alpha(E, x);
2265 const Real eta = m_eta(E, x);
2277 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
2278 const IntVect iv = vof.gridIndex();
2280 if (validCells(iv, 0) && ebisbox.isIrregular(iv)) {
2282 const RealVect x = probLo +
Location::position(Location::Cell::Centroid, vof, ebisbox, dx);
2283 const RealVect EE = RealVect(D_DECL(electricField(vof, 0), electricField(vof, 1), electricField(vof, 2)));
2284 const Real E = EE.vectorLength();
2286 const Real alpha = m_alpha(E, x);
2287 const Real eta = m_eta(E, x);
2300 const Box cellBox = dbl[din];
2301 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
2307 for (ListIterator<P> lit(particles); lit.ok(); ++lit) {
2311 p.template vect<0>() = p.position();
2317 template <
typename P,
typename F,
typename C>
2321 CH_TIME(
"DischargeInceptionStepper::postInitialize");
2322 if (m_verbosity > 5) {
2323 pout() <<
"DischargeInceptionStepper::postInitialize" << endl;
2327 m_ionSolver->initialData();
2328 this->computeIonVelocity(m_voltageCurve(m_time));
2329 this->computeIonDiffusion(m_voltageCurve(m_time));
2332 case Mode::Stationary: {
2333 this->computeInceptionIntegralStationary();
2334 if (m_evaluateTownsend) {
2335 this->computeTownsendCriterionStationary();
2337 this->computeCriticalVolumeStationary();
2338 this->computeCriticalAreaStationary();
2339 this->computeIonizationVolumeStationary();
2340 this->computeInceptionVoltageVolume();
2343 if (m_plotBackgroundIonization) {
2344 this->computeBackgroundIonizationStationary();
2347 if (m_plotDetachment) {
2348 this->computeDetachmentStationary();
2351 if (m_plotFieldEmission) {
2352 this->computeFieldEmissionStationary();
2355 this->writeReportStationary();
2359 case Mode::Transient: {
2362 this->seedIonizationParticles(m_voltageCurve(m_time));
2363 this->computeInceptionIntegralTransient(m_voltageCurve(m_time));
2366 if (m_evaluateTownsend) {
2367 this->seedIonizationParticles(m_voltageCurve(m_time));
2368 this->computeTownsendCriterionTransient(m_voltageCurve(m_time));
2380 if (!m_fullIntegration) {
2381 maxK =
std::min(maxK, m_inceptionK);
2385 m_Rdot.emplace_back(m_time, this->computeRdot(m_voltageCurve(m_time)));
2386 m_criticalVolume.emplace_back(m_time, this->computeCriticalVolumeTransient());
2387 m_criticalArea.emplace_back(m_time, this->computeCriticalAreaTransient());
2388 m_ionizationVolumeTransient.emplace_back(m_time, this->computeIonizationVolumeTransient(m_voltageCurve(m_time)));
2389 m_inceptionProbability.emplace_back(m_time, 0.0);
2390 m_maxK.emplace_back(m_time, maxK);
2391 m_maxT.emplace_back(m_time, maxT);
2401 template <
typename P,
typename F,
typename C>
2405 CH_TIME(
"DischargeInceptionStepper::computeInceptionIntegralStationary");
2406 if (m_verbosity > 5) {
2407 pout() <<
"DischargeInceptionStepper::computeInceptionIntegralStationary" << endl;
2429 m_amr->allocate(Kplus, m_realm, m_phase, 1);
2430 m_amr->allocate(Kminu, m_realm, m_phase, 1);
2433 for (
int i = 0; i < m_voltageSweeps.size(); ++i) {
2440 std::vector<Real> polarities{1.0, -1.0};
2442 this->seedIonizationParticles(m_voltageSweeps[i]);
2444 for (
const auto& p : polarities) {
2446 this->resetTracerParticles();
2451 switch (m_inceptionAlgorithm) {
2452 case IntegrationAlgorithm::Euler: {
2453 this->inceptionIntegrateEuler(p * m_voltageSweeps[i]);
2457 case IntegrationAlgorithm::Trapezoidal: {
2458 this->inceptionIntegrateTrapezoidal(p * m_voltageSweeps[i]);
2463 MayDay::Error(
"DischargeInceptionStepper::computeInceptionIntegralStationary -- logic bust");
2471 m_tracerParticleSolver->deposit(Kplus);
2473 m_amr->conservativeAverage(Kplus, m_realm, m_phase);
2474 m_amr->interpGhost(Kplus, m_realm, m_phase);
2476 DataOps::copy(m_inceptionIntegralPlus, Kplus, Interval(i, i), Interval(0, 0));
2483 if (!m_fullIntegration) {
2484 maxK =
std::min(maxK, m_inceptionK);
2487 m_maxKPlus.push_back(maxK);
2490 m_tracerParticleSolver->deposit(Kminu);
2492 m_amr->conservativeAverage(Kminu, m_realm, m_phase);
2493 m_amr->interpGhost(Kminu, m_realm, m_phase);
2495 DataOps::copy(m_inceptionIntegralMinu, Kminu, Interval(i, i), Interval(0, 0));
2502 if (!m_fullIntegration) {
2503 maxK =
std::min(maxK, m_inceptionK);
2506 m_maxKMinu.push_back(maxK);
2512 template <
typename P,
typename F,
typename C>
2516 CH_TIME(
"DischargeInceptionStepper::computeInceptionIntegralTransient");
2517 if (m_verbosity > 5) {
2518 pout() <<
"DischargeInceptionStepper::computeInceptionIntegralTransient" << endl;
2522 switch (m_inceptionAlgorithm) {
2523 case IntegrationAlgorithm::Euler: {
2524 this->inceptionIntegrateEuler(a_voltage);
2528 case IntegrationAlgorithm::Trapezoidal: {
2529 this->inceptionIntegrateTrapezoidal(a_voltage);
2534 MayDay::Error(
"DischargeInceptionStepper::computeInceptionIntegralTransient - logic bust");
2541 m_tracerParticleSolver->deposit(m_inceptionIntegral);
2543 m_amr->conservativeAverage(m_inceptionIntegral, m_realm, m_phase);
2544 m_amr->interpGhost(m_inceptionIntegral, m_realm, m_phase);
2547 template <
typename P,
typename F,
typename C>
2551 CH_TIME(
"DischargeInceptionStepper::inceptionIntegrateEuler");
2552 if (m_verbosity > 5) {
2553 pout() <<
"DischargeInceptionStepper::inceptionIntegrateEuler" << endl;
2556 const RealVect probLo = m_amr->getProbLo();
2557 const RealVect probHi = m_amr->getProbHi();
2563 m_amr->allocate(amrProcessedParticles, m_realm);
2567 m_tracerParticleSolver->remap();
2569 size_t particlesBefore = 0;
2577 m_amr->allocate(scratch, m_realm, m_phase, SpaceDim);
2578 this->superposition(scratch, a_voltage);
2581 m_tracerParticleSolver->setVelocity(scratch);
2582 m_tracerParticleSolver->interpolateVelocities();
2587 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
2588 const Real dx = m_amr->getDx()[lvl];
2593 switch (m_stepSizeMethod) {
2594 case StepSizeMethod::Fixed: {
2595 spaceStep = m_stepSizeFactor;
2599 case StepSizeMethod::Dx: {
2600 spaceStep = m_stepSizeFactor * dx;
2604 case StepSizeMethod::Alpha: {
2605 spaceStep = m_stepSizeFactor * dx;
2606 alphaStep = m_stepSizeFactor;
2611 MayDay::Error(
"DischargeInceptionStepper::inceptionIntegrateEuler - logic bust");
2617 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
2618 const DataIterator& dit = dbl.dataIterator();
2620 const int nbox = dit.size();
2622 #pragma omp parallel for schedule(runtime)
2623 for (
int mybox = 0; mybox < nbox; mybox++) {
2624 const DataIndex& din = dit[mybox];
2626 List<P>& solverParticles = amrParticles[lvl][din].listItems();
2627 List<P>& processedParticles = amrProcessedParticles[lvl][din].listItems();
2629 for (ListIterator<P> lit(solverParticles); lit.ok();) {
2632 const RealVect x = p.position();
2633 const RealVect vel = p.velocity();
2634 const Real v = vel.vectorLength();
2636 const Real alpha = m_alpha(E, x);
2637 const Real eta = m_eta(E, x);
2638 const Real alphaEff = alpha - eta;
2640 const Real deltaX =
std::min(spaceStep, alphaStep / alphaEff);
2641 const Real dt = deltaX / v;
2642 const RealVect newPos = p.position() + dt * vel;
2643 const Real delta = (newPos - x).vectorLength();
2645 const bool outsideDomain = this->particleOutsideGrid(newPos, probLo, probHi);
2646 const bool insideEB = this->particleInsideEB(newPos);
2651 if (alphaEff < 0.0) {
2652 processedParticles.transfer(lit);
2654 else if (insideEB) {
2655 const RefCountedPtr<BaseIF>& impFunc = m_amr->getBaseImplicitFunction(m_phase);
2658 p.weight() = p.weight() + s * delta * alphaEff;
2661 processedParticles.transfer(lit);
2663 else if (outsideDomain) {
2665 p.weight() = p.weight() + s * delta * alphaEff;
2668 processedParticles.transfer(lit);
2672 p.position() = newPos;
2673 p.weight() = p.weight() + deltaX * alphaEff;
2680 if (!m_fullIntegration) {
2681 for (ListIterator<P> lit(solverParticles); lit.ok();) {
2684 if (p.weight() >= m_inceptionK) {
2685 processedParticles.transfer(lit);
2696 m_tracerParticleSolver->remap();
2697 m_tracerParticleSolver->interpolateVelocities();
2703 if (!m_fullIntegration) {
2704 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
2705 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
2706 const DataIterator& dit = dbl.dataIterator();
2708 const int nbox = dit.size();
2710 #pragma omp parallel for schedule(runtime)
2711 for (
int mybox = 0; mybox < nbox; mybox++) {
2712 const DataIndex& din = dit[mybox];
2714 List<P>& solverParticles = amrParticles[lvl][din].listItems();
2716 for (ListIterator<P> lit(solverParticles); lit.ok(); ++lit) {
2717 lit().weight() =
std::min(m_inceptionK, lit().weight());
2723 this->rewindTracerParticles();
2725 size_t particlesAfter = 0;
2731 if (particlesBefore != particlesAfter) {
2732 MayDay::Warning(
"DischargeInceptionStepper::inceptionIntegrateEuler - lost/gained particles!");
2736 template <
typename P,
typename F,
typename C>
2740 CH_TIME(
"DischargeInceptionStepper::inceptionIntegrateTrapezoidal");
2741 if (m_verbosity > 5) {
2742 pout() <<
"DischargeInceptionStepper::inceptionIntegrateTrapezoidal" << endl;
2757 const RealVect probLo = m_amr->getProbLo();
2758 const RealVect probHi = m_amr->getProbHi();
2764 m_amr->allocate(amrProcessedParticles, m_realm);
2768 m_tracerParticleSolver->remap();
2770 size_t particlesBefore = 0;
2778 m_amr->allocate(scratch, m_realm, m_phase, SpaceDim);
2779 this->superposition(scratch, a_voltage);
2782 m_tracerParticleSolver->setVelocity(scratch);
2783 m_tracerParticleSolver->interpolateVelocities();
2788 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
2789 const Real dx = m_amr->getDx()[lvl];
2794 switch (m_stepSizeMethod) {
2795 case StepSizeMethod::Fixed: {
2796 spaceStep = m_stepSizeFactor;
2800 case StepSizeMethod::Dx: {
2801 spaceStep = m_stepSizeFactor * dx;
2805 case StepSizeMethod::Alpha: {
2806 spaceStep = m_stepSizeFactor * dx;
2807 alphaStep = m_stepSizeFactor;
2812 MayDay::Error(
"DischargeInceptionStepper::inceptionIntegrateTrapezoidal - logic bust");
2818 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
2819 const DataIterator& dit = dbl.dataIterator();
2821 const int nbox = dit.size();
2823 #pragma omp parallel for schedule(runtime)
2824 for (
int mybox = 0; mybox < nbox; mybox++) {
2825 const DataIndex& din = dit[mybox];
2827 List<P>& solverParticles = amrParticles[lvl][din].listItems();
2828 List<P>& processedParticles = amrProcessedParticles[lvl][din].listItems();
2830 for (ListIterator<P> lit(solverParticles); lit.ok();) {
2833 const RealVect x = p.position();
2834 const RealVect vel = p.velocity();
2835 const Real v = vel.vectorLength();
2837 const Real alpha = m_alpha(E, x);
2838 const Real eta = m_eta(E, x);
2839 const Real alphaEff = alpha - eta;
2841 const Real deltaX =
std::min(spaceStep, alphaStep / alphaEff);
2842 const Real dt = deltaX / v;
2843 const RealVect newPos = p.position() + dt * vel;
2844 const Real delta = (newPos - x).vectorLength();
2846 const bool outsideDomain = this->particleOutsideGrid(newPos, probLo, probHi);
2847 const bool insideEB = this->particleInsideEB(newPos);
2852 if (alphaEff < 0.0) {
2853 processedParticles.transfer(lit);
2855 else if (insideEB) {
2856 const RefCountedPtr<BaseIF>& impFunc = m_amr->getBaseImplicitFunction(m_phase);
2859 p.weight() = p.weight() + s * delta * alphaEff;
2862 processedParticles.transfer(lit);
2864 else if (outsideDomain) {
2866 p.weight() = p.weight() + s * delta * alphaEff;
2869 processedParticles.transfer(lit);
2873 p.template real<0>() = alphaEff;
2874 p.template real<1>() = dt;
2875 p.template vect<1>() = vel;
2877 p.position() = newPos;
2886 m_tracerParticleSolver->remap();
2887 m_tracerParticleSolver->interpolateVelocities();
2890 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
2891 const Real dx = m_amr->getDx()[lvl];
2896 switch (m_stepSizeMethod) {
2897 case StepSizeMethod::Fixed: {
2898 spaceStep = m_stepSizeFactor;
2902 case StepSizeMethod::Dx: {
2903 spaceStep = m_stepSizeFactor * dx;
2907 case StepSizeMethod::Alpha: {
2908 spaceStep = m_stepSizeFactor * dx;
2909 alphaStep = m_stepSizeFactor;
2914 MayDay::Error(
"DischargeInceptionStepper::inceptionIntegrateTrapezoidal - logic bust");
2920 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
2921 const DataIterator& dit = dbl.dataIterator();
2923 const int nbox = dit.size();
2925 #pragma omp parallel for schedule(runtime)
2926 for (
int mybox = 0; mybox < nbox; mybox++) {
2927 const DataIndex& din = dit[mybox];
2929 List<P>& solverParticles = amrParticles[lvl][din].listItems();
2930 List<P>& processedParticles = amrProcessedParticles[lvl][din].listItems();
2932 for (ListIterator<P> lit(solverParticles); lit.ok();) {
2936 const Real dt = p.template real<1>();
2937 const RealVect vk = p.template vect<1>();
2938 const RealVect vk1 = p.velocity();
2939 const RealVect x = p.position();
2940 const Real E = vk1.vectorLength();
2944 const RealVect oldPos = p.position() - dt * vk;
2945 const RealVect newPos = oldPos + 0.5 * dt * (vk + vk1);
2948 const Real alphak = p.template real<0>();
2949 const Real alphak1 = m_alpha(E, x) - m_eta(E, x);
2950 const Real delta = (newPos - oldPos).vectorLength();
2954 const bool negativeAlpha = (alphak + alphak1) < 0.0;
2955 const bool outsideDomain = this->particleOutsideGrid(newPos, probLo, probHi);
2956 const bool insideEB = this->particleInsideEB(newPos);
2961 if (negativeAlpha) {
2962 processedParticles.transfer(lit);
2964 else if (insideEB) {
2965 const RefCountedPtr<BaseIF>& impFunc = m_amr->getBaseImplicitFunction(m_phase);
2968 p.weight() = p.weight() + s * delta * alphak;
2971 processedParticles.transfer(lit);
2973 else if (outsideDomain) {
2975 p.weight() = p.weight() + s * delta * alphak;
2978 processedParticles.transfer(lit);
2981 p.position() = newPos;
2982 p.weight() = p.weight() + 0.5 * delta * (alphak + alphak1);
2989 if (!m_fullIntegration) {
2990 for (ListIterator<P> lit(solverParticles); lit.ok();) {
2993 if (p.weight() >= m_inceptionK) {
2994 processedParticles.transfer(lit);
3005 m_tracerParticleSolver->remap();
3006 m_tracerParticleSolver->interpolateVelocities();
3013 if (!m_fullIntegration) {
3014 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3015 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
3016 const DataIterator& dit = dbl.dataIterator();
3018 const int nbox = dit.size();
3020 #pragma omp parallel for schedule(runtime)
3021 for (
int mybox = 0; mybox < nbox; mybox++) {
3022 const DataIndex& din = dit[mybox];
3024 List<P>& solverParticles = amrParticles[lvl][din].listItems();
3026 for (ListIterator<P> lit(solverParticles); lit.ok(); ++lit) {
3027 lit().weight() =
std::min(m_inceptionK, lit().weight());
3033 this->rewindTracerParticles();
3036 template <
typename P,
typename F,
typename C>
3040 CH_TIME(
"DischargeInceptionStepper::computeTownsendCriterionStationary");
3041 if (m_verbosity > 5) {
3042 pout() <<
"DischargeInceptionStepper::computeTownsendCriterionStationary" << endl;
3049 m_amr->allocate(gamma, m_realm, m_phase, 1);
3050 m_amr->allocate(expK, m_realm, m_phase, 1);
3053 for (
int i = 0; i < m_voltageSweeps.size(); ++i) {
3056 std::vector<Real> polarities{1.0, -1.0};
3058 this->seedIonizationParticles(m_voltageSweeps[i]);
3060 for (
const auto& p : polarities) {
3064 this->resetTracerParticles();
3066 switch (m_inceptionAlgorithm) {
3067 case IntegrationAlgorithm::Euler: {
3068 this->townsendTrackEuler(p * m_voltageSweeps[i]);
3072 case IntegrationAlgorithm::Trapezoidal: {
3073 this->townsendTrackTrapezoidal(p * m_voltageSweeps[i]);
3078 MayDay::Error(
"DischargeInceptionStepper::computeTownsendCriterionStationary -- logic bust");
3085 m_tracerParticleSolver->deposit(gamma);
3087 m_amr->conservativeAverage(gamma, m_realm, m_phase);
3088 m_amr->interpGhost(gamma, m_realm, m_phase);
3091 auto exponentiate = [](
const Real x) -> Real {
3092 return x > 0.0 ? exp(x) - 1 : 0.0;
3096 EBAMRCellData Kplus = m_amr->slice(m_inceptionIntegralPlus, Interval(i, i));
3102 if (!m_fullIntegration) {
3108 DataOps::copy(m_townsendCriterionPlus, gamma, Interval(i, i), Interval(0, 0));
3115 m_maxTPlus[i] = maxT;
3118 EBAMRCellData Kminu = m_amr->slice(m_inceptionIntegralMinu, Interval(i, i));
3124 if (!m_fullIntegration) {
3130 DataOps::copy(m_townsendCriterionMinu, gamma, Interval(i, i), Interval(0, 0));
3137 m_maxTMinu[i] = maxT;
3143 template <
typename P,
typename F,
typename C>
3147 CH_TIME(
"DischargeInceptionStepper::computeTownsendCriterionTransient");
3148 if (m_verbosity > 5) {
3149 pout() <<
"DischargeInceptionStepper::computeTownsendCriterionTransient" << endl;
3153 switch (m_inceptionAlgorithm) {
3154 case IntegrationAlgorithm::Euler: {
3155 this->townsendTrackEuler(a_voltage);
3159 case IntegrationAlgorithm::Trapezoidal: {
3160 this->townsendTrackTrapezoidal(a_voltage);
3165 MayDay::Error(
"DischargeInceptionStepper::computeTownsendCriterionTransient - logic bust");
3173 m_amr->allocate(gamma, m_realm, m_phase, 1);
3175 m_tracerParticleSolver->deposit(gamma);
3178 auto exponentiate = [](
const Real x) -> Real {
3179 return x > 0.0 ? exp(x) - 1 : 0.0;
3186 if (!m_fullIntegration) {
3192 m_amr->conservativeAverage(m_townsendCriterion, m_realm, m_phase);
3193 m_amr->interpGhost(m_townsendCriterion, m_realm, m_phase);
3196 template <
typename P,
typename F,
typename C>
3200 CH_TIME(
"DischargeInceptionStepper::townsendTrackEuler");
3201 if (m_verbosity > 5) {
3202 pout() <<
"DischargeInceptionStepper::townsendTrackEuler" << endl;
3205 const RealVect probLo = m_amr->getProbLo();
3206 const RealVect probHi = m_amr->getProbHi();
3212 m_amr->allocate(amrProcessedParticles, m_realm);
3216 m_tracerParticleSolver->remap();
3218 size_t particlesBefore = 0;
3226 m_amr->allocate(scratch, m_realm, m_phase, SpaceDim);
3227 this->superposition(scratch, a_voltage);
3229 m_tracerParticleSolver->setVelocity(scratch);
3230 m_tracerParticleSolver->interpolateVelocities();
3235 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3236 const Real dx = m_amr->getDx()[lvl];
3241 switch (m_stepSizeMethod) {
3242 case StepSizeMethod::Fixed: {
3243 spaceStep = m_stepSizeFactor;
3247 case StepSizeMethod::Dx: {
3248 spaceStep = m_stepSizeFactor * dx;
3252 case StepSizeMethod::Alpha: {
3253 spaceStep = m_stepSizeFactor * dx;
3258 MayDay::Error(
"DischargeInceptionStepper::townsendTrackEuler - logic bust");
3265 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
3266 const DataIterator& dit = dbl.dataIterator();
3268 const int nbox = dit.size();
3270 #pragma omp parallel for schedule(runtime)
3271 for (
int mybox = 0; mybox < nbox; mybox++) {
3272 const DataIndex& din = dit[mybox];
3274 List<P>& solverParticles = amrParticles[lvl][din].listItems();
3275 List<P>& processedParticles = amrProcessedParticles[lvl][din].listItems();
3277 for (ListIterator<P> lit(solverParticles); lit.ok();) {
3280 const RealVect x = p.position();
3281 const RealVect vel = p.velocity();
3282 const Real v = vel.vectorLength();
3284 const Real deltaX = spaceStep;
3285 const Real dt = deltaX / v;
3286 const RealVect newPos = p.position() + dt * vel;
3288 const bool outsideDomain = this->particleOutsideGrid(newPos, probLo, probHi);
3289 const bool insideEB = this->particleInsideEB(newPos);
3292 const Real alpha = m_alpha(E, x);
3293 const Real eta = m_eta(E, x);
3294 const Real alphaEff = alpha - eta;
3295 const bool negativeAlpha = alphaEff <= 0.0;
3300 p.weight() = m_secondaryEmission(E, x);
3302 processedParticles.transfer(lit);
3304 else if (outsideDomain || negativeAlpha) {
3305 processedParticles.transfer(lit);
3308 p.position() = newPos;
3317 m_tracerParticleSolver->remap();
3318 m_tracerParticleSolver->interpolateVelocities();
3323 this->rewindTracerParticles();
3325 size_t particlesAfter = 0;
3331 if (particlesBefore != particlesAfter) {
3332 MayDay::Warning(
"DischargeInceptionStepper::townsendTrackEuler - lost/gained particles!");
3336 template <
typename P,
typename F,
typename C>
3340 CH_TIME(
"DischargeInceptionStepper::townsendTrackTrapezoidal");
3341 if (m_verbosity > 5) {
3342 pout() <<
"DischargeInceptionStepper::townsendTrackTrapezoidal" << endl;
3351 const RealVect probLo = m_amr->getProbLo();
3352 const RealVect probHi = m_amr->getProbHi();
3358 m_amr->allocate(amrProcessedParticles, m_realm);
3362 m_tracerParticleSolver->remap();
3364 size_t particlesBefore = 0;
3372 m_amr->allocate(scratch, m_realm, m_phase, SpaceDim);
3373 this->superposition(scratch, a_voltage);
3375 m_tracerParticleSolver->setVelocity(scratch);
3376 m_tracerParticleSolver->interpolateVelocities();
3381 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3382 const Real dx = m_amr->getDx()[lvl];
3387 switch (m_stepSizeMethod) {
3388 case StepSizeMethod::Fixed: {
3389 spaceStep = m_stepSizeFactor;
3393 case StepSizeMethod::Dx: {
3394 spaceStep = m_stepSizeFactor * dx;
3398 case StepSizeMethod::Alpha: {
3399 spaceStep = m_stepSizeFactor * dx;
3404 MayDay::Error(
"DischargeInceptionStepper::townsendTrackTrapezoidal - logic bust");
3411 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
3412 const DataIterator& dit = dbl.dataIterator();
3414 const int nbox = dit.size();
3416 #pragma omp parallel for schedule(runtime)
3417 for (
int mybox = 0; mybox < nbox; mybox++) {
3418 const DataIndex& din = dit[mybox];
3420 List<P>& solverParticles = amrParticles[lvl][din].listItems();
3421 List<P>& processedParticles = amrProcessedParticles[lvl][din].listItems();
3423 for (ListIterator<P> lit(solverParticles); lit.ok();) {
3426 const RealVect x = p.position();
3427 const RealVect vel = p.velocity();
3428 const Real v = vel.vectorLength();
3430 const Real alpha = m_alpha(E, x);
3431 const Real eta = m_eta(E, x);
3432 const Real alphaEff = alpha - eta;
3435 const Real deltaX = spaceStep;
3436 const Real dt = deltaX / v;
3437 const RealVect newPos = p.position() + vel * dt;
3439 const bool outsideDomain = this->particleOutsideGrid(newPos, probLo, probHi);
3440 const bool insideEB = this->particleInsideEB(newPos);
3443 p.weight() = m_secondaryEmission(E, x);
3445 processedParticles.transfer(lit);
3447 else if (alphaEff < 0.0) {
3448 processedParticles.transfer(lit);
3450 else if (outsideDomain) {
3451 processedParticles.transfer(lit);
3455 p.template real<0>() = alphaEff;
3456 p.template real<1>() = dt;
3457 p.template vect<1>() = vel;
3459 p.position() = newPos;
3468 m_tracerParticleSolver->remap();
3469 m_tracerParticleSolver->interpolateVelocities();
3472 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3473 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
3474 const DataIterator& dit = dbl.dataIterator();
3476 const int nbox = dit.size();
3478 #pragma omp parallel for schedule(runtime)
3479 for (
int mybox = 0; mybox < nbox; mybox++) {
3480 const DataIndex& din = dit[mybox];
3482 List<P>& solverParticles = amrParticles[lvl][din].listItems();
3483 List<P>& processedParticles = amrProcessedParticles[lvl][din].listItems();
3485 for (ListIterator<P> lit(solverParticles); lit.ok();) {
3489 const Real dt = p.template real<1>();
3490 const RealVect vk = p.template vect<1>();
3491 const RealVect vk1 = p.velocity();
3492 const RealVect x = p.position();
3493 const Real E = vk1.vectorLength();
3497 const RealVect oldPos = p.position() - dt * vk;
3498 const RealVect newPos = p.position() + 0.5 * dt * (vk1 - vk);
3501 const Real alphak = p.template real<0>();
3502 const Real alphak1 = m_alpha(E, x) - m_eta(E, x);
3506 const bool negativeAlpha = (alphak + alphak1) < 0.0;
3507 const bool outsideDomain = this->particleOutsideGrid(newPos, probLo, probHi);
3508 const bool insideEB = this->particleInsideEB(newPos);
3514 p.weight() = m_secondaryEmission(E, oldPos);
3516 processedParticles.transfer(lit);
3518 else if (outsideDomain) {
3519 processedParticles.transfer(lit);
3522 p.position() = newPos;
3531 m_tracerParticleSolver->remap();
3532 m_tracerParticleSolver->interpolateVelocities();
3538 this->rewindTracerParticles();
3540 size_t particlesAfter = 0;
3546 if (particlesBefore != particlesAfter) {
3547 MayDay::Warning(
"DischargeInceptionStepper::townsendTrackTrapezoidal - lost/gained particles!");
3551 template <
typename P,
typename F,
typename C>
3555 CH_TIME(
"DischargeInceptionStepper::computeRdot");
3556 if (m_verbosity > 5) {
3557 pout() <<
"DischargeInceptionStepper::computeRdot" << endl;
3563 const RealVect probLo = m_amr->getProbLo();
3567 m_amr->allocate(scratch, m_realm, m_phase, SpaceDim);
3568 this->superposition(scratch, a_voltage);
3570 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3571 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
3572 const DataIterator& dit = dbl.dataIterator();
3573 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
3574 const Real dx = m_amr->getDx()[lvl];
3576 const Real vol = std::pow(dx, SpaceDim);
3577 const Real area = std::pow(dx, SpaceDim - 1);
3579 const int nbox = dit.size();
3581 #pragma omp parallel for schedule(runtime) reduction(+ : Rdot)
3582 for (
int mybox = 0; mybox < nbox; mybox++) {
3583 const DataIndex& din = dit[mybox];
3585 const EBISBox& ebisbox = ebisl[din];
3586 const BaseFab<bool>& validCells = (*m_amr->getValidCells(m_realm)[lvl])[din];
3588 const EBCellFAB& electricField = (*scratch[lvl])[din];
3589 const EBCellFAB& inceptionIntegral = (*m_inceptionIntegral[lvl])[din];
3590 const EBCellFAB& fieldEmission = (*m_emissionRate[lvl])[din];
3591 const EBCellFAB& ionDensity = (*m_ionSolver->getPhi()[lvl])[din];
3593 const FArrayBox& electricFieldReg = electricField.getFArrayBox();
3594 const FArrayBox& inceptionIntegralReg = inceptionIntegral.getFArrayBox();
3595 const FArrayBox& ionDensityReg = ionDensity.getFArrayBox();
3598 auto regularKernel = [&](
const IntVect& iv) ->
void {
3599 if (ebisbox.isRegular(iv) && validCells(iv, 0)) {
3600 if (inceptionIntegralReg(iv, 0) >= m_inceptionK) {
3601 const RealVect pos = probLo + (0.5 * RealVect::Unit + RealVect(iv)) * dx;
3602 const RealVect EE = RealVect(
3603 D_DECL(electricFieldReg(iv, 0), electricFieldReg(iv, 1), electricFieldReg(iv, 2)));
3604 const Real E = EE.vectorLength();
3606 const Real alpha = m_alpha(E, pos);
3607 const Real eta = m_eta(E, pos);
3608 const Real k = m_detachmentRate(E, pos);
3609 const Real dndt = m_backgroundRate(E, pos) + k * ionDensityReg(iv, 0);
3611 CH_assert(alpha >= eta);
3613 Rdot += dndt * (1.0 - eta / alpha) * vol;
3619 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
3620 const IntVect iv = vof.gridIndex();
3621 if (ebisbox.isIrregular(iv) && validCells(iv, 0)) {
3622 if (inceptionIntegral(vof, 0) >= m_inceptionK) {
3623 const RealVect pos = probLo +
Location::position(Location::Cell::Centroid, vof, ebisbox, dx);
3624 const RealVect EE = RealVect(D_DECL(electricField(vof, 0), electricField(vof, 1), electricField(vof, 2)));
3625 const Real E = EE.vectorLength();
3627 const Real kappa = ebisbox.volFrac(vof);
3628 const Real areaFrac = ebisbox.bndryArea(vof);
3629 const Real alpha = m_alpha(E, pos);
3630 const Real eta = m_eta(E, pos);
3631 const Real k = m_detachmentRate(E, pos);
3632 const Real j = m_fieldEmission(E, pos);
3633 const Real dndt = m_backgroundRate(E, pos) + k * ionDensity(vof, 0);
3635 Rdot += dndt * (1.0 - eta / alpha) * kappa * vol;
3636 Rdot += j /
Units::Qe * areaFrac * area;
3642 Box cellBox = dbl[din];
3643 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
3653 template <
typename P,
typename F,
typename C>
3657 CH_TIME(
"DischargeInceptionStepper::rewindTracerParticles");
3658 if (m_verbosity > 5) {
3659 pout() <<
"DischargeInceptionStepper::rewindTracerParticles" << endl;
3664 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3665 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
3666 const DataIterator& dit = dbl.dataIterator();
3668 const int nbox = dit.size();
3670 #pragma omp parallel for schedule(runtime)
3671 for (
int mybox = 0; mybox < nbox; mybox++) {
3672 const DataIndex& din = dit[mybox];
3674 for (ListIterator<P> lit(amrParticles[lvl][din].listItems()); lit.ok(); ++lit) {
3677 p.position() = p.template vect<0>();
3682 amrParticles.
remap();
3685 template <
typename P,
typename F,
typename C>
3689 CH_TIME(
"DischargeInceptionStepper::resetTracerParticles");
3690 if (m_verbosity > 5) {
3691 pout() <<
"DischargeInceptionStepper::resetTracerParticles" << endl;
3696 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3697 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
3698 const DataIterator& dit = dbl.dataIterator();
3700 const int nbox = dit.size();
3702 #pragma omp parallel for schedule(runtime)
3703 for (
int mybox = 0; mybox < nbox; mybox++) {
3704 const DataIndex& din = dit[mybox];
3706 for (ListIterator<P> lit(amrParticles[lvl][din].listItems()); lit.ok(); ++lit) {
3715 template <
typename P,
typename F,
typename C>
3719 CH_TIME(
"DischargeInceptionStepper::computeBackgroundIonizationStationary");
3720 if (m_verbosity > 5) {
3721 pout() <<
"DischargeInceptionStepper::computeBackgroundIonizationStationary" << endl;
3724 const RealVect probLo = m_amr->getProbLo();
3728 m_amr->allocate(scratch, m_realm, m_phase, SpaceDim);
3730 for (
int i = 0; i < m_voltageSweeps.size(); i++) {
3733 this->superposition(scratch, m_voltageSweeps[i]);
3735 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3736 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
3737 const DataIterator& dit = dbl.dataIterator();
3738 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
3739 const Real dx = m_amr->getDx()[lvl];
3741 const int nbox = dit.size();
3743 #pragma omp parallel for schedule(runtime)
3744 for (
int mybox = 0; mybox < nbox; mybox++) {
3745 const DataIndex& din = dit[mybox];
3747 const EBISBox& ebisbox = ebisl[din];
3749 EBCellFAB& bgIonization = (*m_backgroundIonization[lvl])[din];
3750 FArrayBox& bgIonizationReg = bgIonization.getFArrayBox();
3752 const EBCellFAB& electricField = (*scratch[lvl])[din];
3753 const FArrayBox& electricFieldReg = electricField.getFArrayBox();
3755 auto regularKernel = [&](
const IntVect& iv) ->
void {
3756 const RealVect pos = probLo + (0.5 * RealVect::Unit + RealVect(iv)) * dx;
3757 const RealVect EE = RealVect(
3758 D_DECL(electricFieldReg(iv, 0), electricFieldReg(iv, 1), electricFieldReg(iv, 2)));
3759 const Real E = EE.vectorLength();
3761 bgIonizationReg(iv, i) = m_backgroundRate(E, pos);
3764 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
3765 const RealVect pos = probLo +
Location::position(Location::Cell::Centroid, vof, ebisbox, dx);
3766 const RealVect EE = RealVect(D_DECL(electricField(vof, 0), electricField(vof, 1), electricField(vof, 2)));
3767 const Real E = EE.vectorLength();
3769 bgIonization(vof, i) = m_backgroundRate(E, pos);
3773 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
3782 template <
typename P,
typename F,
typename C>
3786 CH_TIME(
"DischargeInceptionStepper::computeDetachmentStationary");
3787 if (m_verbosity > 5) {
3788 pout() <<
"DischargeInceptionStepper::computeDetachmentStationary" << endl;
3791 const RealVect probLo = m_amr->getProbLo();
3795 m_amr->allocate(scratch, m_realm, m_phase, SpaceDim);
3797 for (
int i = 0; i < m_voltageSweeps.size(); i++) {
3800 this->superposition(scratch, m_voltageSweeps[i]);
3802 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3803 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
3804 const DataIterator& dit = dbl.dataIterator();
3805 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
3806 const Real dx = m_amr->getDx()[lvl];
3808 const int nbox = dit.size();
3810 #pragma omp parallel for schedule(runtime)
3811 for (
int mybox = 0; mybox < nbox; mybox++) {
3812 const DataIndex& din = dit[mybox];
3814 const EBISBox& ebisbox = ebisl[din];
3816 EBCellFAB& detachment = (*m_detachment[lvl])[din];
3817 FArrayBox& detachmentReg = detachment.getFArrayBox();
3819 const EBCellFAB& ionDensity = (*m_ionSolver->getPhi()[lvl])[din];
3820 const EBCellFAB& electricField = (*scratch[lvl])[din];
3822 const FArrayBox& ionDensityReg = ionDensity.getFArrayBox();
3823 const FArrayBox& electricFieldReg = electricField.getFArrayBox();
3825 auto regularKernel = [&](
const IntVect& iv) ->
void {
3826 const RealVect pos = probLo + (0.5 * RealVect::Unit + RealVect(iv)) * dx;
3827 const RealVect EE = RealVect(
3828 D_DECL(electricFieldReg(iv, 0), electricFieldReg(iv, 1), electricFieldReg(iv, 2)));
3829 const Real E = EE.vectorLength();
3830 const Real phi = ionDensityReg(iv, 0);
3832 detachmentReg(iv, i) = m_detachmentRate(E, pos) * phi;
3835 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
3836 const RealVect pos = probLo +
Location::position(Location::Cell::Centroid, vof, ebisbox, dx);
3837 const RealVect EE = RealVect(D_DECL(electricField(vof, 0), electricField(vof, 1), electricField(vof, 2)));
3838 const Real E = EE.vectorLength();
3839 const Real phi = ionDensity(vof, 0);
3841 detachment(vof, i) = m_detachmentRate(E, pos) * phi;
3845 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
3852 m_amr->conservativeAverage(m_detachment, m_realm, m_phase);
3856 template <
typename P,
typename F,
typename C>
3860 CH_TIME(
"DischargeInceptionStepper::computeFieldEmissionStationary");
3861 if (m_verbosity > 5) {
3862 pout() <<
"DischargeInceptionStepper::computeFieldEmissionStationary" << endl;
3865 const RealVect probLo = m_amr->getProbLo();
3871 m_amr->allocate(scratchPlus, m_realm, m_phase, SpaceDim);
3872 m_amr->allocate(scratchMinu, m_realm, m_phase, SpaceDim);
3874 for (
int i = 0; i < m_voltageSweeps.size(); i++) {
3877 this->superposition(scratchPlus, m_voltageSweeps[i]);
3878 this->superposition(scratchMinu, -m_voltageSweeps[i]);
3880 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3881 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
3882 const DataIterator& dit = dbl.dataIterator();
3883 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
3884 const Real& dx = m_amr->getDx()[lvl];
3886 const int nbox = dit.size();
3888 #pragma omp parallel for schedule(runtime)
3889 for (
int mybox = 0; mybox < nbox; mybox++) {
3890 const DataIndex& din = dit[mybox];
3892 const EBISBox& ebisbox = ebisl[din];
3896 EBCellFAB& emissionPlus = (*m_emissionRatesPlus[lvl])[din];
3897 EBCellFAB& emissionMinu = (*m_emissionRatesMinu[lvl])[din];
3899 emissionPlus.setVal(0.0);
3900 emissionMinu.setVal(0.0);
3902 const EBCellFAB& electricFieldPlus = (*scratchPlus[lvl])[din];
3903 const EBCellFAB& electricFieldMinu = (*scratchMinu[lvl])[din];
3905 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
3906 const RealVect pos = probLo +
Location::position(Location::Cell::Centroid, vof, ebisbox, dx);
3908 const RealVect Eplus = RealVect(
3909 D_DECL(electricFieldPlus(vof, 0), electricFieldPlus(vof, 1), electricFieldPlus(vof, 2)));
3910 const RealVect Eminu = RealVect(
3911 D_DECL(electricFieldMinu(vof, 0), electricFieldMinu(vof, 1), electricFieldMinu(vof, 2)));
3913 const Real normalEplus = Eplus.dotProduct(ebisbox.normal(vof));
3914 const Real normalEminu = Eminu.dotProduct(ebisbox.normal(vof));
3916 emissionPlus(vof, i) = 0.0;
3917 emissionMinu(vof, i) = 0.0;
3919 if (normalEplus < 0.0) {
3920 emissionPlus(vof, i) = m_fieldEmission(Eplus.vectorLength(), pos);
3922 if (normalEminu < 0.0) {
3923 emissionMinu(vof, i) = m_fieldEmission(Eminu.vectorLength(), pos);
3928 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
3935 template <
typename P,
typename F,
typename C>
3938 const Real& a_voltage)
const noexcept
3940 CH_TIME(
"DischargeInceptionStepper::computeFieldEmission");
3941 if (m_verbosity > 5) {
3942 pout() <<
"DischargeInceptionStepper::computeFieldEmission" << endl;
3945 CH_assert(a_emissionRate[0]->nComp() == 1);
3947 const RealVect probLo = m_amr->getProbLo();
3951 m_amr->allocate(scratch, m_realm, m_phase, SpaceDim);
3952 this->superposition(scratch, a_voltage);
3954 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
3955 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
3956 const DataIterator& dit = dbl.dataIterator();
3957 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
3958 const Real dx = m_amr->getDx()[lvl];
3960 const int nbox = dit.size();
3962 #pragma omp parallel for schedule(runtime)
3963 for (
int mybox = 0; mybox < nbox; mybox++) {
3964 const DataIndex& din = dit[mybox];
3966 const EBISBox& ebisbox = ebisl[din];
3970 EBCellFAB& emission = (*a_emissionRate[lvl])[din];
3972 emission.setVal(0.0);
3974 const EBCellFAB& electricField = (*scratch[lvl])[din];
3975 const FArrayBox& electricFieldReg = electricField.getFArrayBox();
3977 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
3978 const RealVect pos = probLo +
Location::position(Location::Cell::Centroid, vof, ebisbox, dx);
3979 const RealVect EE = RealVect(D_DECL(electricField(vof, 0), electricField(vof, 1), electricField(vof, 2)));
3980 const Real E = EE.vectorLength();
3982 if (EE.dotProduct(ebisbox.normal(vof)) > 0.0) {
3983 emission(vof, 0) = m_fieldEmission(E, pos);
3988 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
3994 template <
typename P,
typename F,
typename C>
3998 const Real& a_voltage,
3999 const std::function<Real(
const Real E,
const RealVect x)>& a_func)
const noexcept
4001 CH_TIME(
"DischargeInceptionStepper::evaluateFunction");
4002 if (m_verbosity > 5) {
4003 pout() <<
"DischargeInceptionStepper::evaluateFunction" << endl;
4006 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
4007 this->evaluateFunction(*a_data[lvl], a_voltage, a_func, lvl);
4011 template <
typename P,
typename F,
typename C>
4014 const Real& a_voltage,
4015 const std::function<Real(
const Real E,
const RealVect x)>& a_func,
4016 const int a_level)
const noexcept
4018 CH_TIME(
"DischargeInceptionStepper::evaluateFunction(level)");
4019 if (m_verbosity > 5) {
4020 pout() <<
"DischargeInceptionStepper::evaluateFunction(level)" << endl;
4023 CH_assert(a_level >= 0);
4024 CH_assert(a_level <= m_amr->getFinestLevel());
4028 m_amr->allocate(scratch, m_realm, m_phase, SpaceDim);
4029 this->superposition(scratch, a_voltage);
4031 const RealVect probLo = m_amr->getProbLo();
4033 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[a_level];
4034 const DataIterator& dit = dbl.dataIterator();
4035 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[a_level];
4036 const Real dx = m_amr->getDx()[a_level];
4038 const int nbox = dit.size();
4040 #pragma omp parallel for schedule(runtime)
4041 for (
int mybox = 0; mybox < nbox; mybox++) {
4042 const DataIndex& din = dit[mybox];
4044 const EBISBox& ebisbox = ebisl[din];
4048 EBCellFAB& data = a_data[din];
4049 FArrayBox& dataReg = data.getFArrayBox();
4053 const EBCellFAB& electricField = (*scratch[a_level])[din];
4054 const FArrayBox& electricFieldReg = electricField.getFArrayBox();
4056 auto regularKernel = [&](
const IntVect& iv) ->
void {
4057 const RealVect pos = probLo + (0.5 * RealVect::Unit + RealVect(iv)) * dx;
4058 const RealVect EE = RealVect(D_DECL(electricFieldReg(iv, 0), electricFieldReg(iv, 1), electricFieldReg(iv, 2)));
4059 const Real E = EE.vectorLength();
4061 dataReg(iv, 0) = a_func(E, pos);
4064 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
4065 const RealVect pos = probLo +
Location::position(Location::Cell::Centroid, vof, ebisbox, dx);
4066 const RealVect EE = RealVect(D_DECL(electricField(vof, 0), electricField(vof, 1), electricField(vof, 2)));
4067 const Real E = EE.vectorLength();
4069 data(vof, 0) = a_func(E, pos);
4073 Box cellBox = dbl[din];
4074 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[a_level])[din];
4081 template <
typename P,
typename F,
typename C>
4085 CH_TIME(
"DischargeInceptionStepper::computeInceptionVoltageVolume");
4086 if (m_verbosity > 5) {
4087 pout() <<
"DischargeInceptionStepper::computeInceptionVoltageVolume" << endl;
4093 CH_assert(m_mode == Mode::Stationary);
4095 if (m_voltageSweeps.size() < 2) {
4096 DataOps::setValue(m_inceptionVoltagePlus, std::numeric_limits<Real>::quiet_NaN());
4097 DataOps::setValue(m_inceptionVoltageMinu, std::numeric_limits<Real>::quiet_NaN());
4099 MayDay::Warning(
"DischargeInceptionStepper::computeInceptionVoltageVolume -- not enough voltages for estimating "
4100 "inception voltage");
4104 constexpr
int comp = 0;
4107 auto calcUincInterp = [Kinc = this->m_inceptionK,
4108 &V = this->m_voltageSweeps](
const std::vector<Real>& K,
4109 const std::vector<Real>& T) -> std::array<Real, 3> {
4110 Real streamerInc = std::numeric_limits<Real>::quiet_NaN();
4111 Real townsendInc = std::numeric_limits<Real>::quiet_NaN();
4113 bool foundInception =
false;
4116 for (
size_t i = 0; i < K.size() - 1; i++) {
4117 if (K[i] <= Kinc && K[i + 1] > Kinc) {
4118 streamerInc = V[i] + (Kinc - K[i]) * (V[i + 1] - V[i]) / (K[i + 1] - K[i]);
4122 else if (K[i] == Kinc) {
4130 for (
size_t i = 0; i < T.size() - 1; i++) {
4131 if (T[i] <= 1.0 && T[i + 1] > 1) {
4132 townsendInc = V[i] + (1.0 - T[i]) * (V[i + 1] - V[i]) / (T[i + 1] - T[i]);
4136 else if (T[i] == 1.0) {
4145 if (std::isnan(streamerInc) && std::isnan(townsendInc)) {
4146 Uinc = std::numeric_limits<Real>::quiet_NaN();
4148 else if (std::isnan(streamerInc) && !std::isnan(townsendInc)) {
4151 else if (!std::isnan(streamerInc) && std::isnan(townsendInc)) {
4155 Uinc =
std::min(streamerInc, townsendInc);
4158 return std::array<Real, 3>{Uinc, streamerInc, townsendInc};
4162 auto calcUincNoInterp = [Kinc = this->m_inceptionK,
4163 &V = this->m_voltageSweeps](
const std::vector<Real>& K,
4164 const std::vector<Real>& T) -> std::array<Real, 3> {
4165 Real streamerInc = std::numeric_limits<Real>::quiet_NaN();
4166 Real townsendInc = std::numeric_limits<Real>::quiet_NaN();
4169 for (
size_t i = 0; i < K.size() - 1; i++) {
4170 if (K[i] <= Kinc && K[i + 1] >= Kinc) {
4178 for (
size_t i = 0; i < T.size() - 1; i++) {
4179 if (T[i] <= 1.0 && T[i + 1] >= 1) {
4188 if (std::isnan(streamerInc) && std::isnan(townsendInc)) {
4189 Uinc = std::numeric_limits<Real>::quiet_NaN();
4191 else if (std::isnan(streamerInc) && !std::isnan(townsendInc)) {
4194 else if (!std::isnan(streamerInc) && std::isnan(townsendInc)) {
4198 Uinc =
std::min(streamerInc, townsendInc);
4201 return std::array<Real, 3>{Uinc, streamerInc, townsendInc};
4205 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); ++lvl) {
4206 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
4207 const DataIterator& dit = dbl.dataIterator();
4209 const int nbox = dit.size();
4211 #pragma omp parallel for schedule(runtime)
4212 for (
int mybox = 0; mybox < nbox; mybox++) {
4213 const DataIndex& din = dit[mybox];
4215 EBCellFAB& inceptionVoltagePlus = (*m_inceptionVoltagePlus[lvl])[din];
4216 EBCellFAB& inceptionVoltageMinu = (*m_inceptionVoltageMinu[lvl])[din];
4218 EBCellFAB& streamerInceptionVoltagePlus = (*m_streamerInceptionVoltagePlus[lvl])[din];
4219 EBCellFAB& streamerInceptionVoltageMinu = (*m_streamerInceptionVoltageMinu[lvl])[din];
4221 EBCellFAB& townsendInceptionVoltagePlus = (*m_townsendInceptionVoltagePlus[lvl])[din];
4222 EBCellFAB& townsendInceptionVoltageMinu = (*m_townsendInceptionVoltageMinu[lvl])[din];
4224 FArrayBox& inceptionVoltagePlusReg = inceptionVoltagePlus.getFArrayBox();
4225 FArrayBox& inceptionVoltageMinuReg = inceptionVoltageMinu.getFArrayBox();
4227 FArrayBox& streamerInceptionVoltagePlusReg = streamerInceptionVoltagePlus.getFArrayBox();
4228 FArrayBox& streamerInceptionVoltageMinuReg = streamerInceptionVoltageMinu.getFArrayBox();
4230 FArrayBox& townsendInceptionVoltagePlusReg = townsendInceptionVoltagePlus.getFArrayBox();
4231 FArrayBox& townsendInceptionVoltageMinuReg = townsendInceptionVoltageMinu.getFArrayBox();
4233 const EBCellFAB& inceptionIntegralPlus = (*m_inceptionIntegralPlus[lvl])[din];
4234 const EBCellFAB& inceptionIntegralMinu = (*m_inceptionIntegralMinu[lvl])[din];
4236 const FArrayBox& inceptionIntegralPlusReg = inceptionIntegralPlus.getFArrayBox();
4237 const FArrayBox& inceptionIntegralMinuReg = inceptionIntegralMinu.getFArrayBox();
4239 const EBCellFAB& townsendCriterionPlus = (*m_townsendCriterionPlus[lvl])[din];
4240 const EBCellFAB& townsendCriterionMinu = (*m_townsendCriterionMinu[lvl])[din];
4242 const FArrayBox& townsendCriterionPlusReg = townsendCriterionPlus.getFArrayBox();
4243 const FArrayBox& townsendCriterionMinuReg = townsendCriterionMinu.getFArrayBox();
4246 auto regularKernel = [&](
const IntVect& iv) ->
void {
4247 std::vector<Real> Kplus;
4248 std::vector<Real> Kminu;
4250 std::vector<Real> Tplus;
4251 std::vector<Real> Tminu;
4253 for (
size_t i = 0; i < m_voltageSweeps.size(); i++) {
4254 Kplus.emplace_back(inceptionIntegralPlusReg(iv, i));
4255 Kminu.emplace_back(inceptionIntegralMinuReg(iv, i));
4257 Tplus.emplace_back(townsendCriterionPlusReg(iv, i));
4258 Tminu.emplace_back(townsendCriterionMinuReg(iv, i));
4261 std::array<Real, 3> inceptionVoltagesPlus;
4262 std::array<Real, 3> inceptionVoltagesMinu;
4264 if (m_fullIntegration) {
4265 inceptionVoltagesPlus = calcUincInterp(Kplus, Tplus);
4266 inceptionVoltagesMinu = calcUincInterp(Kminu, Tminu);
4269 inceptionVoltagesPlus = calcUincNoInterp(Kplus, Tplus);
4270 inceptionVoltagesMinu = calcUincNoInterp(Kminu, Tminu);
4273 inceptionVoltagePlusReg(iv, comp) = std::get<0>(inceptionVoltagesPlus);
4274 inceptionVoltageMinuReg(iv, comp) = std::get<0>(inceptionVoltagesMinu);
4276 streamerInceptionVoltagePlusReg(iv, comp) = std::get<1>(inceptionVoltagesPlus);
4277 streamerInceptionVoltageMinuReg(iv, comp) = std::get<1>(inceptionVoltagesMinu);
4279 townsendInceptionVoltagePlusReg(iv, comp) = std::get<2>(inceptionVoltagesPlus);
4280 townsendInceptionVoltageMinuReg(iv, comp) = std::get<2>(inceptionVoltagesMinu);
4284 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
4285 std::vector<Real> Kplus;
4286 std::vector<Real> Kminu;
4288 std::vector<Real> Tplus;
4289 std::vector<Real> Tminu;
4291 for (
size_t i = 0; i < m_voltageSweeps.size(); i++) {
4292 Kplus.emplace_back(inceptionIntegralPlus(vof, i));
4293 Kminu.emplace_back(inceptionIntegralMinu(vof, i));
4295 Tplus.emplace_back(townsendCriterionPlus(vof, i));
4296 Tminu.emplace_back(townsendCriterionMinu(vof, i));
4299 std::array<Real, 3> inceptionVoltagesPlus;
4300 std::array<Real, 3> inceptionVoltagesMinu;
4302 if (m_fullIntegration) {
4303 inceptionVoltagesPlus = calcUincInterp(Kplus, Tplus);
4304 inceptionVoltagesMinu = calcUincInterp(Kminu, Tminu);
4307 inceptionVoltagesPlus = calcUincNoInterp(Kplus, Tplus);
4308 inceptionVoltagesMinu = calcUincNoInterp(Kminu, Tminu);
4311 inceptionVoltagePlus(vof, comp) = std::get<0>(inceptionVoltagesPlus);
4312 inceptionVoltageMinu(vof, comp) = std::get<0>(inceptionVoltagesMinu);
4314 streamerInceptionVoltagePlus(vof, comp) = std::get<1>(inceptionVoltagesPlus);
4315 streamerInceptionVoltageMinu(vof, comp) = std::get<1>(inceptionVoltagesMinu);
4317 townsendInceptionVoltagePlus(vof, comp) = std::get<2>(inceptionVoltagesPlus);
4318 townsendInceptionVoltageMinu(vof, comp) = std::get<2>(inceptionVoltagesMinu);
4322 const Box& cellBox = dbl[din];
4323 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
4331 m_amr->conservativeAverage(m_inceptionVoltagePlus, m_realm, m_phase);
4332 m_amr->interpGhost(m_inceptionVoltageMinu, m_realm, m_phase);
4336 template <
typename P,
typename F,
typename C>
4337 std::pair<Real, RealVect>
4340 CH_TIME(
"DischargeInceptionStepper::computeMinimumInceptionVoltage");
4341 if (m_verbosity > 5) {
4342 pout() <<
"DischargeInceptionStepper::computeMinimumInceptionVoltage" << endl;
4345 const RealVect probLo = m_amr->getProbLo();
4347 std::pair<Real, RealVect> UxInc;
4350 UxInc.second = RealVect::Zero;
4352 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
4353 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
4354 const DataIterator& dit = dbl.dataIterator();
4355 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
4356 const Real& dx = m_amr->getDx()[lvl];
4358 const int nbox = dit.size();
4360 #pragma omp parallel for schedule(runtime) reduction(pairmin : UxInc)
4361 for (
int mybox = 0; mybox < nbox; mybox++) {
4362 const DataIndex& din = dit[mybox];
4364 const BaseFab<bool>& validCells = (*m_amr->getValidCells(m_realm)[lvl])[din];
4365 const EBISBox& ebisBox = ebisl[din];
4367 const EBCellFAB& voltage = (*a_Uinc[lvl])[din];
4368 const FArrayBox& voltageReg = voltage.getFArrayBox();
4370 auto regularKernel = [&](
const IntVect& iv) ->
void {
4371 if (validCells(iv, 0) && ebisBox.isRegular(iv)) {
4372 const Real& U = voltageReg(iv, 0);
4373 const RealVect pos = probLo + (0.5 * RealVect::Unit + RealVect(iv)) * dx;
4375 if (!(std::isnan(U))) {
4376 if (std::abs(U) < UxInc.first) {
4377 UxInc.first = std::abs(U);
4384 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
4385 const IntVect iv = vof.gridIndex();
4386 if (validCells(iv, 0) && ebisBox.isIrregular(iv)) {
4387 const Real& U = voltage(vof, 0);
4388 const RealVect centroid = ebisBox.centroid(vof);
4389 const RealVect pos = probLo + (0.5 * RealVect::Unit + RealVect(iv) + centroid) * dx;
4391 if (!(std::isnan(U))) {
4392 if (std::abs(U) < UxInc.first) {
4393 UxInc.first = std::abs(U);
4400 Box cellBox = dbl[din];
4401 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
4411 template <
typename P,
typename F,
typename C>
4415 CH_TIME(
"DischargeInceptionStepper::computeCriticalVolumeStationary");
4416 if (m_verbosity > 5) {
4417 pout() <<
"DischargeInceptionStepper::computeCriticalVolumeStationary" << endl;
4421 for (
size_t i = 0; i < m_voltageSweeps.size(); i++) {
4422 Real criticalVolumePlus = 0.0;
4423 Real criticalVolumeMinu = 0.0;
4425 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); ++lvl) {
4426 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
4427 const DataIterator& dit = dbl.dataIterator();
4428 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
4430 const LevelData<BaseFab<bool>>& validCellsLD = *m_amr->getValidCells(m_realm)[lvl];
4432 const Real dx = m_amr->getDx()[lvl];
4434 const int nbox = dit.size();
4436 #pragma omp parallel for schedule(runtime) reduction(+ : criticalVolumePlus, criticalVolumeMinu)
4437 for (
int mybox = 0; mybox < nbox; mybox++) {
4438 const DataIndex& din = dit[mybox];
4440 const EBISBox& ebisbox = ebisl[din];
4441 const BaseFab<bool>& validCells = validCellsLD[din];
4443 const EBCellFAB& inceptionIntegralPlus = (*m_inceptionIntegralPlus[lvl])[din];
4444 const EBCellFAB& inceptionIntegralMinu = (*m_inceptionIntegralMinu[lvl])[din];
4446 const FArrayBox& inceptionIntegralPlusReg = inceptionIntegralPlus.getFArrayBox();
4447 const FArrayBox& inceptionIntegralMinuReg = inceptionIntegralMinu.getFArrayBox();
4449 const EBCellFAB& townsendCritPlus = (*m_townsendCriterionPlus[lvl])[din];
4450 const EBCellFAB& townsendCritMinu = (*m_townsendCriterionMinu[lvl])[din];
4452 const FArrayBox& townsendCritPlusReg = townsendCritPlus.getFArrayBox();
4453 const FArrayBox& townsendCritMinuReg = townsendCritMinu.getFArrayBox();
4455 auto regularKernel = [&](
const IntVect& iv) ->
void {
4456 if (validCells(iv, 0) && ebisbox.isRegular(iv)) {
4457 if (inceptionIntegralPlusReg(iv, i) >= m_inceptionK || townsendCritPlusReg(iv, i) >= 1.0) {
4458 criticalVolumePlus += std::pow(dx, SpaceDim);
4460 if (inceptionIntegralMinuReg(iv, i) >= m_inceptionK || townsendCritMinuReg(iv, i) >= 1.0) {
4461 criticalVolumeMinu += std::pow(dx, SpaceDim);
4466 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
4467 if (validCells(vof.gridIndex())) {
4468 const Real kappa = ebisbox.volFrac(vof);
4470 if (inceptionIntegralPlus(vof, i) >= m_inceptionK || townsendCritPlus(vof, i) >= 1.0) {
4471 criticalVolumePlus += kappa * std::pow(dx, SpaceDim);
4473 if (inceptionIntegralMinu(vof, i) >= m_inceptionK || townsendCritMinu(vof, i) >= 1.0) {
4474 criticalVolumeMinu += kappa * std::pow(dx, SpaceDim);
4480 const Box cellBox = dbl[din];
4481 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
4493 template <
typename P,
typename F,
typename C>
4497 CH_TIME(
"DischargeInceptionStepper::computeCriticalVolumeTransient");
4498 if (m_verbosity > 5) {
4499 pout() <<
"DischargeInceptionStepper::computeCriticalVolumeTransient" << endl;
4504 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); ++lvl) {
4505 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
4506 const DataIterator& dit = dbl.dataIterator();
4507 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
4509 const LevelData<BaseFab<bool>>& validCellsLD = *m_amr->getValidCells(m_realm)[lvl];
4511 const Real dx = m_amr->getDx()[lvl];
4512 const Real vol = std::pow(dx, SpaceDim);
4514 const int nbox = dit.size();
4516 #pragma omp parallel for schedule(runtime) reduction(+ : Vcr)
4517 for (
int mybox = 0; mybox < nbox; mybox++) {
4518 const DataIndex& din = dit[mybox];
4520 const EBISBox& ebisbox = ebisl[din];
4521 const BaseFab<bool>& validCells = validCellsLD[din];
4523 const EBCellFAB& inceptionIntegral = (*m_inceptionIntegral[lvl])[din];
4524 const FArrayBox& inceptionIntegralReg = inceptionIntegral.getFArrayBox();
4526 const EBCellFAB& townsendCriterion = (*m_townsendCriterion[lvl])[din];
4527 const FArrayBox& townsendCriterionReg = townsendCriterion.getFArrayBox();
4529 auto regularKernel = [&](
const IntVect& iv) ->
void {
4530 if (validCells(iv, 0) && ebisbox.isRegular(iv)) {
4531 if (inceptionIntegralReg(iv, 0) >= m_inceptionK || townsendCriterionReg(iv, 0) >= 1.0) {
4537 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
4538 if (validCells(vof.gridIndex())) {
4539 if (inceptionIntegral(vof, 0) >= m_inceptionK || townsendCriterion(vof, 0) >= 1.0) {
4540 Vcr += ebisbox.volFrac(vof) * vol;
4546 const Box cellBox = dbl[din];
4547 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
4557 template <
typename P,
typename F,
typename C>
4561 CH_TIME(
"DischargeInceptionStepper::computeCriticalAreaStationary");
4562 if (m_verbosity > 5) {
4563 pout() <<
"DischargeInceptionStepper::computeCriticalAreaStationary" << endl;
4567 for (
size_t i = 0; i < m_voltageSweeps.size(); ++i) {
4568 Real criticalAreaPlus = 0.0;
4569 Real criticalAreaMinu = 0.0;
4571 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); ++lvl) {
4572 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
4573 const DataIterator& dit = dbl.dataIterator();
4574 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
4576 const LevelData<BaseFab<bool>>& validCellsLD = *m_amr->getValidCells(m_realm)[lvl];
4578 const Real dx = m_amr->getDx()[lvl];
4580 const int nbox = dit.size();
4582 #pragma omp parallel for schedule(runtime) reduction(+ : criticalAreaPlus, criticalAreaMinu)
4583 for (
int mybox = 0; mybox < nbox; mybox++) {
4584 const DataIndex& din = dit[mybox];
4586 const EBISBox& ebisbox = ebisl[din];
4587 const BaseFab<bool>& validCells = validCellsLD[din];
4589 const EBCellFAB& inceptionIntegralPlus = (*m_inceptionIntegralPlus[lvl])[din];
4590 const EBCellFAB& inceptionIntegralMinu = (*m_inceptionIntegralMinu[lvl])[din];
4592 const EBCellFAB& townsendCriterionPlus = (*m_townsendCriterionPlus[lvl])[din];
4593 const EBCellFAB& townsendCriterionMinu = (*m_townsendCriterionMinu[lvl])[din];
4595 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
4596 if (validCells(vof.gridIndex())) {
4597 const Real boundaryArea = ebisbox.bndryArea(vof);
4599 if (inceptionIntegralPlus(vof, i) >= m_inceptionK || townsendCriterionPlus(vof, i) >= 1.0) {
4600 criticalAreaPlus += boundaryArea * std::pow(dx, SpaceDim - 1);
4602 if (inceptionIntegralMinu(vof, i) >= m_inceptionK || townsendCriterionMinu(vof, i) >= 1.0) {
4603 criticalAreaMinu += boundaryArea * std::pow(dx, SpaceDim - 1);
4609 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
4620 template <
typename P,
typename F,
typename C>
4624 CH_TIME(
"DischargeInceptionStepper::computeCriticalAreaTransient");
4625 if (m_verbosity > 5) {
4626 pout() <<
"DischargeInceptionStepper::computeCriticalAreaTransient" << endl;
4631 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); ++lvl) {
4632 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
4633 const DataIterator& dit = dbl.dataIterator();
4634 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
4636 const LevelData<BaseFab<bool>>& validCellsLD = *m_amr->getValidCells(m_realm)[lvl];
4638 const Real dx = m_amr->getDx()[lvl];
4639 const Real area = std::pow(dx, SpaceDim - 1);
4641 const int nbox = dit.size();
4643 #pragma omp parallel for schedule(runtime) reduction(+ : Acr)
4644 for (
int mybox = 0; mybox < nbox; mybox++) {
4645 const DataIndex& din = dit[mybox];
4647 const EBISBox& ebisbox = ebisl[din];
4648 const BaseFab<bool>& validCells = validCellsLD[din];
4650 const EBCellFAB& inceptionIntegral = (*m_inceptionIntegral[lvl])[din];
4651 const EBCellFAB& townsendCriterion = (*m_townsendCriterion[lvl])[din];
4653 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
4654 if (validCells(vof.gridIndex())) {
4655 if (inceptionIntegral(vof, 0) >= m_inceptionK || townsendCriterion(vof, 0) >= 1.0) {
4656 Acr += ebisbox.bndryArea(vof) * area;
4662 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
4671 template <
typename P,
typename F,
typename C>
4675 CH_TIME(
"DischargeInceptionStepper::computeIonizationVolumeStationary");
4676 if (m_verbosity > 5) {
4677 pout() <<
"DischargeInceptionStepper::computeIonizationVolumeStationary" << endl;
4682 m_amr->allocate(scratch, m_realm, m_phase, SpaceDim);
4685 for (
size_t i = 0; i < m_voltageSweeps.size(); ++i) {
4686 Real ionizationVolume = 0.0;
4688 this->superposition(scratch, m_voltageSweeps[i]);
4690 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); ++lvl) {
4691 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
4692 const DataIterator& dit = dbl.dataIterator();
4693 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
4695 const LevelData<BaseFab<bool>>& validCellsLD = *m_amr->getValidCells(m_realm)[lvl];
4697 const Real dx = m_amr->getDx()[lvl];
4698 const RealVect probLo = m_amr->getProbLo();
4700 const int nbox = dit.size();
4702 #pragma omp parallel for schedule(runtime) reduction(+ : ionizationVolume)
4703 for (
int mybox = 0; mybox < nbox; mybox++) {
4704 const DataIndex& din = dit[mybox];
4706 const EBISBox& ebisbox = ebisl[din];
4707 const BaseFab<bool>& validCells = validCellsLD[din];
4709 const EBCellFAB& electricField = (*scratch[lvl])[din];
4710 const FArrayBox& electricFieldReg = electricField.getFArrayBox();
4712 auto regularKernel = [&](
const IntVect& iv) ->
void {
4713 if (validCells(iv, 0) && ebisbox.isRegular(iv)) {
4714 const RealVect x = probLo + dx * (0.5 * RealVect::Unit + RealVect(iv));
4715 const RealVect EE = RealVect(
4716 D_DECL(electricFieldReg(iv, 0), electricFieldReg(iv, 1), electricFieldReg(iv, 2)));
4717 const Real E = EE.vectorLength();
4719 const Real alpha = m_alpha(E, x);
4720 const Real eta = m_eta(E, x);
4723 ionizationVolume += std::pow(dx, SpaceDim);
4728 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
4729 if (validCells(vof.gridIndex())) {
4731 const RealVect x = probLo +
Location::position(Location::Cell::Center, vof, ebisbox, dx);
4732 const RealVect EE = RealVect(D_DECL(electricField(vof, 0), electricField(vof, 1), electricField(vof, 2)));
4733 const Real E = EE.vectorLength();
4735 const Real alpha = m_alpha(E, x);
4736 const Real eta = m_eta(E, x);
4738 const Real kappa = ebisbox.volFrac(vof);
4741 ionizationVolume += kappa * std::pow(dx, SpaceDim);
4747 const Box cellBox = dbl[din];
4748 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
4759 template <
typename P,
typename F,
typename C>
4763 CH_TIME(
"DischargeInceptionStepper::computeIonizationVolumeTransient");
4764 if (m_verbosity > 5) {
4765 pout() <<
"DischargeInceptionStepper::computeIonizationVolumeTransient" << endl;
4772 m_amr->allocate(scratch, m_realm, m_phase, SpaceDim);
4773 this->superposition(scratch, a_voltage);
4775 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); ++lvl) {
4776 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
4777 const DataIterator& dit = dbl.dataIterator();
4778 const EBISLayout& ebisl = m_amr->getEBISLayout(m_realm, m_phase)[lvl];
4780 const LevelData<BaseFab<bool>>& validCellsLD = *m_amr->getValidCells(m_realm)[lvl];
4782 const Real dx = m_amr->getDx()[lvl];
4783 const Real vol = std::pow(dx, SpaceDim);
4784 const RealVect probLo = m_amr->getProbLo();
4786 const int nbox = dit.size();
4788 #pragma omp parallel for schedule(runtime) reduction(+ : Vion)
4789 for (
int mybox = 0; mybox < nbox; mybox++) {
4790 const DataIndex& din = dit[mybox];
4792 const EBISBox& ebisbox = ebisl[din];
4793 const BaseFab<bool>& validCells = validCellsLD[din];
4795 const EBCellFAB& electricField = (*scratch[lvl])[din];
4796 const FArrayBox& electricFieldReg = electricField.getFArrayBox();
4798 auto regularKernel = [&](
const IntVect& iv) ->
void {
4799 if (validCells(iv, 0) && ebisbox.isRegular(iv)) {
4801 const RealVect x = probLo + dx * (0.5 * RealVect::Unit + RealVect(iv));
4802 const RealVect EE = RealVect(
4803 D_DECL(electricFieldReg(iv, 0), electricFieldReg(iv, 1), electricFieldReg(iv, 2)));
4804 const Real E = EE.vectorLength();
4806 const Real alpha = m_alpha(E, x);
4807 const Real eta = m_eta(E, x);
4814 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
4815 if (validCells(vof.gridIndex())) {
4817 const RealVect x = probLo +
Location::position(Location::Cell::Centroid, vof, ebisbox, dx);
4818 const RealVect EE = RealVect(D_DECL(electricField(vof, 0), electricField(vof, 1), electricField(vof, 2)));
4819 const Real E = EE.vectorLength();
4821 const Real alpha = m_alpha(E, x);
4822 const Real eta = m_eta(E, x);
4824 Vion = ebisbox.volFrac(vof) * vol;
4830 const Box cellBox = dbl[din];
4831 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
4841 template <
typename P,
typename F,
typename C>
4845 CH_TIME(
"DischargeInceptionStepper::writeReportStationary");
4846 if (m_verbosity > 5) {
4847 pout() <<
"DischargeInceptionStepper::writeReportStationary" << endl;
4850 const std::pair<Real, RealVect> UIncPlus = this->computeMinimumInceptionVoltage(m_inceptionVoltagePlus);
4851 const std::pair<Real, RealVect> UIncMinu = this->computeMinimumInceptionVoltage(m_inceptionVoltageMinu);
4853 const std::pair<Real, RealVect> streamerUIncPlus = this->computeMinimumInceptionVoltage(
4854 m_streamerInceptionVoltagePlus);
4855 const std::pair<Real, RealVect> streamerUIncMinu = this->computeMinimumInceptionVoltage(
4856 m_streamerInceptionVoltageMinu);
4858 const std::pair<Real, RealVect> townsendUIncPlus = this->computeMinimumInceptionVoltage(
4859 m_townsendInceptionVoltagePlus);
4860 const std::pair<Real, RealVect> townsendUIncMinu = this->computeMinimumInceptionVoltage(
4861 m_townsendInceptionVoltageMinu);
4864 if (procID() == 0) {
4867 std::ofstream output(m_outputFile, std::ofstream::out);
4869 const std::string lineBreak =
"# " + std::string(178,
'=');
4872 output << lineBreak <<
"\n";
4873 if (std::isnan(UIncPlus.first) || std::isnan(UIncMinu.first)) {
4874 output <<
"# Could not compute inception voltage\n";
4877 if(m_fullIntegration){
4878 output <<
"# Minimum inception voltage(+) = " << UIncPlus.first <<
",\t x = " << UIncPlus.second <<
"\n";
4879 output <<
"# Minimum inception voltage(-) = " << UIncMinu.first <<
",\t x = " << UIncMinu.second <<
"\n";
4881 output <<
"# Streamer inception voltage(+) = " << streamerUIncPlus.first <<
",\t x = " << streamerUIncPlus.second <<
"\n";
4882 output <<
"# Streamer inception voltage(-) = " << streamerUIncMinu.first <<
",\t x = " << streamerUIncMinu.second <<
"\n";
4884 output <<
"# Townsend inception voltage(+) = " << townsendUIncPlus.first <<
",\t x = " << townsendUIncPlus.second <<
"\n";
4885 output <<
"# Townsend inception voltage(-) = " << townsendUIncMinu.first <<
",\t x = " << townsendUIncMinu.second <<
"\n";
4888 output <<
"# Minimum inception voltage(+) >= " << UIncPlus.first <<
",\t x = " << UIncPlus.second <<
"\n";
4889 output <<
"# Minimum inception voltage(-) >= " << UIncMinu.first <<
",\t x = " << UIncMinu.second <<
"\n";
4891 output <<
"# Streamer inception voltage(+) >= " << streamerUIncPlus.first <<
",\t x = " << streamerUIncPlus.second <<
"\n";
4892 output <<
"# Streamer inception voltage(-) >= " << streamerUIncMinu.first <<
",\t x = " << streamerUIncMinu.second <<
"\n";
4894 output <<
"# Townsend inception voltage(+) >= " << townsendUIncPlus.first <<
",\t x = " << townsendUIncPlus.second <<
"\n";
4895 output <<
"# Townsend inception voltage(-) >= " << townsendUIncMinu.first <<
",\t x = " << townsendUIncMinu.second <<
"\n";
4900 output << lineBreak <<
"\n";
4901 output << left << setw(15) << setfill(
' ') <<
"# +/- Voltage";
4902 output << left << setw(15) << setfill(
' ') <<
"Max K(+)";
4903 output << left << setw(15) << setfill(
' ') <<
"Max K(-)";
4904 output << left << setw(20) << setfill(
' ') <<
"Max T(+)";
4905 output << left << setw(20) << setfill(
' ') <<
"Max T(-)";
4906 output << left << setw(20) << setfill(
' ') <<
"Crit. vol(+)";
4907 output << left << setw(20) << setfill(
' ') <<
"Crit. vol(-)";
4908 output << left << setw(20) << setfill(
' ') <<
"Crit. area(+)";
4909 output << left << setw(20) << setfill(
' ') <<
"Crit. area(-)";
4910 output << left << setw(20) << setfill(
' ') <<
"Ionization vol." <<
"\n";
4911 output << lineBreak <<
"\n";
4913 for (
int i = 0; i < m_voltageSweeps.size(); i++) {
4914 output << left << setw(15) << setfill(
' ') << m_voltageSweeps[i];
4915 output << left << setw(15) << setfill(
' ') << m_maxKPlus[i];
4916 output << left << setw(15) << setfill(
' ') << m_maxKMinu[i];
4917 output << left << setw(20) << setfill(
' ') << m_maxTPlus[i];
4918 output << left << setw(20) << setfill(
' ') << m_maxTMinu[i];
4919 output << left << setw(20) << setfill(
' ') << m_criticalVolumePlus[i];
4920 output << left << setw(20) << setfill(
' ') << m_criticalVolumeMinu[i];
4921 output << left << setw(20) << setfill(
' ') << m_criticalAreaPlus[i];
4922 output << left << setw(20) << setfill(
' ') << m_criticalAreaMinu[i];
4923 output << left << setw(20) << setfill(
' ') << m_ionizationVolume[i];
4926 output << lineBreak <<
"\n";
4933 template <
typename P,
typename F,
typename C>
4937 CH_TIME(
"DischargeInceptionStepper::writeReportTransient");
4938 if (m_verbosity > 5) {
4939 pout() <<
"DischargeInceptionStepper::writeReportTransient" << endl;
4943 if (procID() == 0) {
4945 std::ofstream output(m_outputFile, std::ofstream::out);
4947 output << std::left << std::setw(15) << setfill(
' ') <<
"# Time t";
4948 output << std::left << std::setw(15) << setfill(
' ') <<
"V(t)";
4949 output << std::left << std::setw(15) << setfill(
' ') <<
"max K(t)";
4950 output << std::left << std::setw(15) << setfill(
' ') <<
"max T(t)";
4951 output << std::left << std::setw(15) << setfill(
' ') <<
"Vcr(t)";
4952 output << std::left << std::setw(15) << setfill(
' ') <<
"Acr(t)";
4953 output << std::left << std::setw(15) << setfill(
' ') <<
"Vion(t)";
4954 output << std::left << std::setw(15) << setfill(
' ') <<
"lambda(t)";
4955 output << std::left << std::setw(15) << setfill(
' ') <<
"P(t)";
4956 output << std::left << std::setw(15) << setfill(
' ') <<
"dP(t, t+dt)";
4957 output << std::left << std::setw(15) << setfill(
' ') <<
"Time lag";
4961 std::vector<Real> dProb;
4962 for (
size_t i = 0; i < m_Rdot.size() - 1; i++) {
4963 const Real t = m_Rdot[i].first;
4964 const Real dt = m_Rdot[i + 1].first - m_Rdot[i].first;
4965 const Real prob = m_inceptionProbability[i].second;
4966 const Real Rdot = m_Rdot[i].second;
4968 dProb.emplace_back((1.0 - prob) * Rdot * dt);
4970 dProb.emplace_back(0.0);
4973 std::vector<Real> tau(m_Rdot.size(), 0.0);
4974 for (
size_t i = 0; i < m_Rdot.size() - 1; i++) {
4975 const Real t1 = m_Rdot[i].first;
4976 const Real t2 = m_Rdot[i + 1].first;
4977 const Real dt = t2 - t1;
4978 const Real prob = m_inceptionProbability[i].second;
4979 const Real lambda = m_Rdot[i].second;
4981 tau[i + 1] = tau[i] + t1 * (1 - prob) * lambda * dt;
4983 for (
int i = 0; i < tau.size(); i++) {
4984 const Real prob = m_inceptionProbability[i].second;
4986 tau[i] = prob > 0.0 ? tau[i] / prob : std::numeric_limits<Real>::infinity();
4989 for (
size_t i = 0; i < m_Rdot.size(); i++) {
4990 const Real time = m_Rdot[i].first;
4992 output << std::left << std::setw(15) << time;
4993 output << std::left << std::setw(15) << m_voltageCurve(time);
4994 output << std::left << std::setw(15) << m_maxK[i].second;
4995 output << std::left << std::setw(15) << m_maxT[i].second;
4996 output << std::left << std::setw(15) << m_criticalVolume[i].second;
4997 output << std::left << std::setw(15) << m_criticalArea[i].second;
4998 output << std::left << std::setw(15) << m_ionizationVolumeTransient[i].second;
4999 output << std::left << std::setw(15) << m_Rdot[i].second;
5000 output << std::left << std::setw(15) << m_inceptionProbability[i].second;
5001 output << std::left << std::setw(15) << dProb[i];
5002 output << std::left << std::setw(15) << tau[i];
5013 template <
typename P,
typename F,
typename C>
5016 const RealVect& a_probLo,
5017 const RealVect& a_probHi)
const noexcept
5020 CH_TIME(
"DischargeInceptionStepper::particleOutsideGrid");
5021 if (m_verbosity > 5) {
5022 pout() <<
"DischargeInceptionStepper::particleOutsideGrid" << endl;
5026 bool isOutside =
false;
5028 for (
int dir = 0; dir < SpaceDim; dir++) {
5029 if (a_pos[dir] <= a_probLo[dir] || a_pos[dir] >= a_probHi[dir]) {
5037 template <
typename P,
typename F,
typename C>
5042 CH_TIME(
"DischargeInceptionStepper::particleInsideEB");
5043 if (m_verbosity > 5) {
5044 pout() <<
"DischargeInceptionStepper::particleInsideEB" << endl;
5048 const RefCountedPtr<BaseIF>& implicitFunction = m_amr->getBaseImplicitFunction(m_phase);
5050 return (implicitFunction->value(a_pos) >= 0.0) ? true :
false;
5053 template <
typename P,
typename F,
typename C>
5057 CH_TIME(
"DischargeInceptionStepper::computeIonVelocity");
5058 if (m_verbosity > 5) {
5059 pout() <<
"DischargeInceptionStepper::computeIonVelocity" << endl;
5062 CH_assert(!(m_ionSolver.isNull()));
5063 CH_assert(m_ionSolver->isMobile());
5065 EBAMRCellData& vel = m_ionSolver->getCellCenteredVelocity();
5068 this->superposition(vel, a_voltage);
5073 m_amr->allocate(mu, m_realm, m_phase, 1);
5075 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
5076 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
5077 const DataIterator& dit = dbl.dataIterator();
5079 const int nbox = dit.
size();
5081 #pragma omp parallel for schedule(runtime)
5082 for (
int mybox = 0; mybox < nbox; mybox++) {
5083 const DataIndex& din = dit[mybox];
5085 const EBCellFAB& v = (*vel[lvl])[din];
5086 const FArrayBox& vReg = v.getFArrayBox();
5088 EBCellFAB& MU = (*mu[lvl])[din];
5089 FArrayBox& MUREG = MU.getFArrayBox();
5091 auto regularKernel = [&](
const IntVect& iv) ->
void {
5092 const RealVect EE = RealVect(D_DECL(vReg(iv, 0), vReg(iv, 1), vReg(iv, 2)));
5093 const Real E = EE.vectorLength();
5095 MUREG(iv, 0) = m_ionMobility(E);
5098 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
5099 const RealVect EE = RealVect(D_DECL(v(vof, 0), v(vof, 1), v(vof, 2)));
5100 const Real E = EE.vectorLength();
5102 MU(vof, 0) = m_ionMobility(E);
5105 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
5106 Box cellBox = dbl[din];
5115 m_amr->arithmeticAverage(vel, m_realm, m_phase);
5116 m_amr->interpGhostPwl(vel, m_realm, m_phase);
5119 template <
typename P,
typename F,
typename C>
5123 CH_TIME(
"DischargeInceptionStepper::computeIonDiffusion");
5124 if (m_verbosity > 5) {
5125 pout() <<
"DischargeInceptionStepper::computeIonDiffusion" << endl;
5128 CH_assert(!(m_ionSolver.isNull()));
5129 CH_assert(m_ionSolver->isMobile());
5133 m_amr->allocate(scratch, m_realm, m_phase, SpaceDim);
5134 this->superposition(scratch, a_voltage);
5138 m_amr->allocate(diffCoCell, m_realm, m_phase, 1);
5140 for (
int lvl = 0; lvl <= m_amr->getFinestLevel(); lvl++) {
5141 const DisjointBoxLayout& dbl = m_amr->getGrids(m_realm)[lvl];
5142 const DataIterator& dit = dbl.dataIterator();
5144 const int nbox = dit.
size();
5146 #pragma omp parallel for schedule(runtime)
5147 for (
int mybox = 0; mybox < nbox; mybox++) {
5148 const DataIndex& din = dit[mybox];
5150 const EBCellFAB& electricField = (*scratch[lvl])[din];
5151 const FArrayBox& electricFieldReg = electricField.getFArrayBox();
5153 EBCellFAB& dCo = (*diffCoCell[lvl])[din];
5154 FArrayBox& dCoReg = dCo.getFArrayBox();
5156 auto regularKernel = [&](
const IntVect& iv) ->
void {
5157 const RealVect EE = RealVect(D_DECL(electricFieldReg(iv, 0), electricFieldReg(iv, 1), electricFieldReg(iv, 2)));
5158 const Real E = EE.vectorLength();
5160 dCoReg(iv, 0) = m_ionDiffusion(E);
5163 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
5164 const RealVect EE = RealVect(D_DECL(electricField(vof, 0), electricField(vof, 1), electricField(vof, 2)));
5165 const Real E = EE.vectorLength();
5167 dCo(vof, 0) = m_ionDiffusion(E);
5170 VoFIterator& vofit = (*m_amr->getVofIterator(m_realm, m_phase)[lvl])[din];
5171 Box cellBox = dbl[din];
5179 m_amr->arithmeticAverage(diffCoCell, m_realm, m_phase);
5180 m_amr->interpGhostPwl(diffCoCell, m_realm, m_phase);
5183 EBAMRFluxData& diffCoFace = m_ionSolver->getFaceCenteredDiffusionCoefficient();
5184 EBAMRIVData& diffCoEB = m_ionSolver->getEbCenteredDiffusionCoefficient();
5191 m_amr->getDomains(),
5195 Average::Arithmetic);
5198 template <
typename P,
typename F,
typename C>
5203 const Real a_voltage)
const noexcept
5205 CH_TIME(
"DischargeInceptionStepper::superposition(full)");
5207 const EBAMRCellData homogeneousField = m_amr->alias(phase::gas, a_homogeneousField);
5208 const EBAMRCellData inhomogeneousField = m_amr->alias(phase::gas, a_inhomogeneousField);
5214 m_amr->arithmeticAverage(a_sumField, m_realm, m_phase);
5215 m_amr->interpGhostPwl(a_sumField, m_realm, m_phase);
5216 m_amr->interpToCentroids(a_sumField, m_realm, m_phase);
5219 template <
typename P,
typename F,
typename C>
5223 CH_TIME(
"DischargeInceptionStepper::superposition(short)");
5225 this->superposition(a_sumField, m_electricFieldInho, m_electricFieldHomo, a_voltage);
5228 template <
typename P,
typename F,
typename C>
5233 const std::string a_outputRealm,
5235 const bool a_interpToCentroids,
5236 const bool a_interpGhost)
const noexcept
5239 CH_TIMERS(
"DischargeInceptionStepper::writeData");
5240 CH_TIMER(
"DischargeInceptionStepper::writeData::allocate", t1);
5241 CH_TIMER(
"DischargeInceptionStepper::writeData::local_copy", t2);
5242 CH_TIMER(
"DischargeInceptionStepper::writeData::interp_ghost", t3);
5243 CH_TIMER(
"DischargeInceptionStepper::writeData::interp_centroid", t4);
5244 CH_TIMER(
"DischargeInceptionStepper::writeData::final_copy", t5);
5245 if (m_verbosity > 5) {
5246 pout() <<
"DischargeInceptionStepper::writeData" << endl;
5250 const int numComp = a_data[a_level]->nComp();
5253 const Interval srcInterv(0, numComp - 1);
5254 const Interval dstInterv(a_comp, a_comp + numComp - 1);
5257 LevelData<EBCellFAB> scratch;
5258 m_amr->allocate(scratch, m_realm, m_phase, a_level, numComp);
5262 m_amr->copyData(scratch, *a_data[a_level], a_level, m_realm, m_realm);
5267 if (a_level > 0 && a_interpGhost) {
5268 m_amr->interpGhost(scratch, *a_data[a_level - 1], a_level, m_realm, m_phase);
5273 if (a_interpToCentroids) {
5274 m_amr->interpToCentroids(scratch, m_realm, m_phase, a_level);
5281 m_amr->copyData(a_output, scratch, a_level, a_outputRealm, m_realm, dstInterv, srcInterv);
5287 template <
typename P,
typename F,
typename C>
5291 CH_TIMERS(
"DischargeInceptionStepper::getElectricField");
5293 return &m_homogeneousFieldGas;
5296 #include <CD_NamespaceFooter.H>
Simple species for DischargeInception test problem.
TimeStepper class for evaluating the streamer inception criterion.
Mode
For specifying whether the module is run in stationary or transient mode.
Definition: CD_DischargeInceptionStepper.H:65
Declaration of various useful OpenMP-related utilities.
Declaration of various useful units.
static void scale(MFAMRCellData &a_lhs, const Real &a_scale) noexcept
Scale data by factor.
Definition: CD_DataOps.cpp:2384
static void compute(EBAMRCellData &a_data, const std::function< Real(const Real a_cellValue)> &a_func) noexcept
Compute a new value given the old cell value.
Definition: CD_DataOps.cpp:480
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 squareRoot(EBAMRFluxData &a_lhs)
Compute the square root of the input data.
Definition: CD_DataOps.cpp:3275
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 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 multiply(EBAMRCellData &a_lhs, const EBAMRCellData &a_rhs)
Multiply data holder by another data holder.
Definition: CD_DataOps.cpp:2142
static void kappaScale(EBAMRCellData &a_data) noexcept
Scale data by volume fraction.
Definition: CD_DataOps.cpp:2044
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 dotProduct(MFAMRCellData &a_result, const MFAMRCellData &a_data1, const MFAMRCellData &a_data2)
Compote the cell-wise dot product between two data holders.
Definition: CD_DataOps.cpp:533
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
int size() const noexcept
Get size of m_data.
Definition: CD_EBAMRDataImplem.H:66
Type
Type of interpolation methods supported. PWC = Piecewise constant, ignoring the embedded boundary....
Definition: CD_EBCoarseToFineInterp.H:42
Templated class for holding particles on an AMR hierarchy with particle remapping.
Definition: CD_ParticleContainer.H:50
const RealVect getProbLo() const noexcept
Get lower-left corner.
Definition: CD_ParticleContainerImplem.H:256
void remap()
Remap over the entire AMR hierarchy.
Definition: CD_ParticleContainerImplem.H:973
void clearParticles()
Clear all particles.
Definition: CD_ParticleContainerImplem.H:1670
unsigned long long getNumberOfValidParticlesGlobal() const
Get global number of particles.
Definition: CD_ParticleContainerImplem.H:1436
AMRParticles< P > & getParticles()
Get all particles on all levels.
Definition: CD_ParticleContainerImplem.H:270
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:173
static void copyDestructive(ParticleContainer< P > &a_dst, ParticleContainer< P > &a_src) noexcept
Copy all the particles from the a_src to a_dst. This destroys the source particles.
Definition: CD_ParticleOpsImplem.H:291
static bool domainIntersection(const RealVect &a_oldPos, const RealVect &a_newPos, const RealVect &a_probLo, const RealVect &a_probHi, Real &a_s)
Compute the intersection point between a particle path and a domain side.
Definition: CD_ParticleOpsImplem.H:127
Advection and diffused species for DischargeInceptionStepper.
Definition: CD_DischargeInceptionSpecies.H:27
Class for streamer inception integral evaluations.
Definition: CD_DischargeInceptionStepper.H:90
virtual const std::function< Real(const Real &E, const RealVect &x)> & getAlpha() const noexcept
Get ionization coefficient.
Definition: CD_DischargeInceptionStepperImplem.H:2063
void parseRuntimeOptions() override
Parse runtime options.
Definition: CD_DischargeInceptionStepperImplem.H:406
virtual const EBAMRCellData * getElectricField() const noexcept
Get the electric field.
Definition: CD_DischargeInceptionStepperImplem.H:5289
void parseMode() noexcept
Parse simulation mode.
Definition: CD_DischargeInceptionStepperImplem.H:436
void computeIonVelocity(const Real &a_voltage) noexcept
Set the negative ion velocity. Note.
Definition: CD_DischargeInceptionStepperImplem.H:5055
virtual void setIonMobility(const std::function< Real(const Real E)> &a_mobility) noexcept
Set the negative ion mobility (field-dependent)
Definition: CD_DischargeInceptionStepperImplem.H:2014
virtual void writeReportStationary() const noexcept
Print report to the terminal.
Definition: CD_DischargeInceptionStepperImplem.H:4843
virtual Real advance(const Real a_dt) override
Advancement method. Swaps between various kernels.
Definition: CD_DischargeInceptionStepperImplem.H:1585
virtual void townsendTrackTrapezoidal(const Real &a_voltage) noexcept
Track particles (positive ions) using a trapezoidal rule and check if the collide with a cathode.
Definition: CD_DischargeInceptionStepperImplem.H:3338
virtual void seedUniformParticles() noexcept
Distribute particles in every grid cell.
Definition: CD_DischargeInceptionStepperImplem.H:2136
virtual void resetTracerParticles() noexcept
Reset particles.
Definition: CD_DischargeInceptionStepperImplem.H:3687
virtual void setIonDensity(const std::function< Real(const RealVect x)> &a_density) noexcept
Set the negative ion density.
Definition: CD_DischargeInceptionStepperImplem.H:2002
virtual void computeCriticalVolumeStationary() noexcept
Compute the critical volume of the K values for each voltage.
Definition: CD_DischargeInceptionStepperImplem.H:4413
virtual void postRegrid() override
Perform post-regrid operations.
Definition: CD_DischargeInceptionStepperImplem.H:1953
virtual void inceptionIntegrateTrapezoidal(const Real &a_voltage) noexcept
K integral: Add integration parts after particles move.
Definition: CD_DischargeInceptionStepperImplem.H:2738
virtual void setBackgroundRate(const std::function< Real(const Real &E, const RealVect &x)> &a_backgroundRate) noexcept
Set the background ionization rate (e.g. from cosmic radiation etc).
Definition: CD_DischargeInceptionStepperImplem.H:2077
void computeIonDiffusion(const Real &a_voltage) noexcept
Set the negative ion diffusion coefficient.
Definition: CD_DischargeInceptionStepperImplem.H:5121
virtual std::pair< Real, RealVect > computeMinimumInceptionVoltage(const EBAMRCellData &a_Uinc) const noexcept
Compute the minimum inception voltage and the starting electron position.
Definition: CD_DischargeInceptionStepperImplem.H:4338
virtual void computeTownsendCriterionStationary() noexcept
Solve for the Townsend criterion for each particle in each voltage.
Definition: CD_DischargeInceptionStepperImplem.H:3038
virtual void synchronizeSolverTimes(const int a_step, const Real a_time, const Real a_dt) override
Synchronize solver times and time steps.
Definition: CD_DischargeInceptionStepperImplem.H:1783
virtual void inceptionIntegrateEuler(const Real &a_voltage) noexcept
Integrate the inception integral using the Euler rule.
Definition: CD_DischargeInceptionStepperImplem.H:2549
virtual void computeInceptionVoltageVolume() noexcept
Interpolate between K values to find voltage giving K_inception and store values in m_inceptionVoltag...
Definition: CD_DischargeInceptionStepperImplem.H:4083
virtual Real computeIonizationVolumeTransient(const Real &a_voltage) const noexcept
Compute the ionization volume for each voltage.
Definition: CD_DischargeInceptionStepperImplem.H:4761
virtual void computeFieldEmission(EBAMRCellData &a_emissionRate, const Real &a_voltage) const noexcept
Compute field emission rates.
Definition: CD_DischargeInceptionStepperImplem.H:3937
virtual int getNumberOfPlotVariables() const override
Get the number of plot variables for this time stepper.
Definition: CD_DischargeInceptionStepperImplem.H:702
virtual Real computeCriticalVolumeTransient() const noexcept
Compute the critical volume of the K values for each voltage.
Definition: CD_DischargeInceptionStepperImplem.H:4495
void registerOperators() override
Register operators.
Definition: CD_DischargeInceptionStepperImplem.H:377
virtual void evaluateFunction(EBAMRCellData &a_data, const Real &a_voltage, const std::function< Real(const Real E, const RealVect x)> &a_func) const noexcept
Evaluate a function f = f(E, x) in a volume.
Definition: CD_DischargeInceptionStepperImplem.H:3996
void allocate() override
Allocate storage for solvers and time stepper.
Definition: CD_DischargeInceptionStepperImplem.H:166
virtual Vector< std::string > getTransientPlotVariableNames() const noexcept
Get plot variable names for transient mode.
Definition: CD_DischargeInceptionStepperImplem.H:1040
virtual Mode getMode() const noexcept
Get the solver mode.
Definition: CD_DischargeInceptionStepperImplem.H:2129
void parseInceptionAlgorithm() noexcept
Parse the inception algorithm.
Definition: CD_DischargeInceptionStepperImplem.H:515
virtual ~DischargeInceptionStepper()
Destructor.
Definition: CD_DischargeInceptionStepperImplem.H:106
void solvePoisson() noexcept
Solve the Poisson equation.
Definition: CD_DischargeInceptionStepperImplem.H:268
virtual void setAlpha(const std::function< Real(const Real &E, const RealVect &x)> &a_alpha) noexcept
Set the ionization coefficient.
Definition: CD_DischargeInceptionStepperImplem.H:2038
virtual void regrid(const int a_lmin, const int a_oldFinestLevel, const int a_newFinestLevel) override
Time stepper regrid method.
Definition: CD_DischargeInceptionStepperImplem.H:1874
bool particleOutsideGrid(const RealVect &a_pos, const RealVect &a_probLo, const RealVect &a_probHi) const noexcept
Check if particle is outside grid boundaries.
Definition: CD_DischargeInceptionStepperImplem.H:5015
virtual void writeReportTransient() const noexcept
Print report to the terminal.
Definition: CD_DischargeInceptionStepperImplem.H:4935
virtual void rewindTracerParticles() noexcept
Move particles back to their original position.
Definition: CD_DischargeInceptionStepperImplem.H:3655
virtual void townsendTrackEuler(const Real &a_voltage) noexcept
Track particles (positive ions) using an Euler rule and check if the collide with a cathode.
Definition: CD_DischargeInceptionStepperImplem.H:3198
virtual void writePlotData(LevelData< EBCellFAB > &a_output, int &a_icomp, const std::string a_outputRealm, const int a_level) const override
Write plot data to output holder.
Definition: CD_DischargeInceptionStepperImplem.H:1105
void superposition(EBAMRCellData &a_sumField, const MFAMRCellData &a_inhomogeneousField, const MFAMRCellData &a_homogeneousField, const Real a_voltage) const noexcept
Calculate the total electric field = inhomogeneous + V * homogeneous.
Definition: CD_DischargeInceptionStepperImplem.H:5200
void parseOptions()
Parse options.
Definition: CD_DischargeInceptionStepperImplem.H:391
void setupSolvers() override
Instantiate the tracer particle solver.
Definition: CD_DischargeInceptionStepperImplem.H:116
virtual void setEta(const std::function< Real(const Real &E, const RealVect &x)> &a_eta) noexcept
Set the attachment coefficient.
Definition: CD_DischargeInceptionStepperImplem.H:2051
virtual void writePlotDataTransient(LevelData< EBCellFAB > &a_output, int &a_icomp, const std::string a_outputRealm, const int a_level) const noexcept
Write plot data for the 'transient' mode.
Definition: CD_DischargeInceptionStepperImplem.H:1328
virtual Vector< std::string > getStationaryPlotVariableNames() const noexcept
Get plot variable names for stationary mode.
Definition: CD_DischargeInceptionStepperImplem.H:895
virtual void setDetachmentRate(const std::function< Real(const Real &E, const RealVect &x)> &a_detachmentRate) noexcept
Set the detachment rate for negative ions.
Definition: CD_DischargeInceptionStepperImplem.H:2090
virtual void computeTownsendCriterionTransient(const Real &a_voltage) noexcept
Solve for the Townsend criterion for each particle in each voltage.
Definition: CD_DischargeInceptionStepperImplem.H:3145
virtual void computeIonizationVolumeStationary() noexcept
Compute the ionization volume for each voltage.
Definition: CD_DischargeInceptionStepperImplem.H:4673
virtual void computeFieldEmissionStationary() noexcept
Compute field emission rates.
Definition: CD_DischargeInceptionStepperImplem.H:3858
void parseOutput() noexcept
Parse output settings.
Definition: CD_DischargeInceptionStepperImplem.H:501
virtual void computeInceptionIntegralStationary() noexcept
Solve streamer inception integral for each particle in each voltage and store K values in m_inception...
Definition: CD_DischargeInceptionStepperImplem.H:2403
virtual Real computeCriticalAreaTransient() const noexcept
Compute the critical area of the K values for each voltage.
Definition: CD_DischargeInceptionStepperImplem.H:4622
virtual Vector< std::string > getPlotVariableNames() const override
Get plot variable names.
Definition: CD_DischargeInceptionStepperImplem.H:839
virtual void computeDetachmentStationary() noexcept
Compute the detachment ionization rate for all voltages.
Definition: CD_DischargeInceptionStepperImplem.H:3784
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 used for IO.
Definition: CD_DischargeInceptionStepperImplem.H:5230
void parseVoltages() noexcept
Parse voltage levels.
Definition: CD_DischargeInceptionStepperImplem.H:461
virtual void setIonDiffusion(const std::function< Real(const Real E)> &a_diffCo) noexcept
Set the negative ion diffusion coefficient (field-dependent)
Definition: CD_DischargeInceptionStepperImplem.H:2026
void postInitialize() override
Perform any post-initialization steps.
Definition: CD_DischargeInceptionStepperImplem.H:2319
virtual void setSigma(const std::function< Real(const RealVect &x)> &a_sigma) noexcept
Set surface charge distribution.
Definition: CD_DischargeInceptionStepperImplem.H:1990
void parseTransportAlgorithm() noexcept
Parse the transport algorithm.
Definition: CD_DischargeInceptionStepperImplem.H:565
virtual void seedIonizationParticles(const Real a_voltage) noexcept
Add particles to every cell where alpha - eta > 0.0.
Definition: CD_DischargeInceptionStepperImplem.H:2213
DischargeInceptionStepper()
Default constructor.
Definition: CD_DischargeInceptionStepperImplem.H:35
void parsePlotVariables() noexcept
Parse plot variables.
Definition: CD_DischargeInceptionStepperImplem.H:605
void initialData() override
Fill problem with initial data.
Definition: CD_DischargeInceptionStepperImplem.H:256
virtual const std::function< Real(const Real &E, const RealVect &x)> & getEta() const noexcept
Get attachment coefficient.
Definition: CD_DischargeInceptionStepperImplem.H:2070
virtual void setSecondaryEmission(const std::function< Real(const Real &E, const RealVect &x)> &a_coeff) noexcept
Set the secondary emission coefficient.
Definition: CD_DischargeInceptionStepperImplem.H:2116
virtual Real computeDt() override
Compute a time step to be used by Driver.
Definition: CD_DischargeInceptionStepperImplem.H:1498
virtual void preRegrid(const int a_lmin, const int a_oldFinestLevel) override
Perform pre-regrid operations.
Definition: CD_DischargeInceptionStepperImplem.H:1854
virtual void printStepReport() override
Print a step report. Used in transient simulations.
Definition: CD_DischargeInceptionStepperImplem.H:1801
virtual void setRho(const std::function< Real(const RealVect &x)> &a_rho) noexcept
Set space charge distribution.
Definition: CD_DischargeInceptionStepperImplem.H:1978
virtual void writePlotDataStationary(LevelData< EBCellFAB > &a_output, int &a_icomp, const std::string a_outputRealm, const int a_level) const noexcept
Write plot data for the 'stationary' mode.
Definition: CD_DischargeInceptionStepperImplem.H:1148
void parseVerbosity() noexcept
Parse class verbosity.
Definition: CD_DischargeInceptionStepperImplem.H:421
void registerRealms() override
Register realms. Primal is the only realm we need.
Definition: CD_DischargeInceptionStepperImplem.H:365
virtual void computeBackgroundIonizationStationary() noexcept
Compute the background ionization rate for all voltages.
Definition: CD_DischargeInceptionStepperImplem.H:3717
virtual void computeInceptionIntegralTransient(const Real &a_voltage) noexcept
Solve streamer inception integral.
Definition: CD_DischargeInceptionStepperImplem.H:2514
virtual void setVoltageCurve(const std::function< Real(const Real &a_time)> &a_voltageCurve) noexcept
Set the voltage curve (used for transient mode)
Definition: CD_DischargeInceptionStepperImplem.H:1966
virtual void computeCriticalAreaStationary() noexcept
Compute the critical area of the K values for each voltage.
Definition: CD_DischargeInceptionStepperImplem.H:4559
virtual void advanceIons(const Real a_dt) noexcept
Advance negative ions.
Definition: CD_DischargeInceptionStepperImplem.H:1697
bool particleInsideEB(const RealVect a_pos) const noexcept
Check if particle is inside electrode.
Definition: CD_DischargeInceptionStepperImplem.H:5039
virtual Real computeRdot(const Real &a_voltage) const noexcept
Compute integral_Vcr(dne/dt * (1 - eta/alpha) dV)
Definition: CD_DischargeInceptionStepperImplem.H:3553
virtual void setFieldEmission(const std::function< Real(const Real &E, const RealVect &x)> &a_currentDensity) noexcept
Set the field emission current.
Definition: CD_DischargeInceptionStepperImplem.H:2103
static const std::string Primal
Identifier for perimal realm.
Definition: CD_Realm.H:47
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
Base class for a tracer particle solver. This solver can advance particles in a pre-defined velocity ...
Definition: CD_TracerParticleSolver.H:37
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
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
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
Real sum(const Real &a_value) noexcept
Compute the sum across all MPI ranks.
Definition: CD_ParallelOpsImplem.H:353
constexpr Real Qe
Elementary charge.
Definition: CD_Units.H:34