Cantera  4.0.0a1
Loading...
Searching...
No Matches
ElectronCollisionPlasmaRate.cpp
Go to the documentation of this file.
1//! @file ElectronCollisionPlasmaRate.cpp
2
3// This file is part of Cantera. See License.txt in the top-level directory or
4// at https://cantera.org/license.txt for license and copyright information.
5
11
12namespace Cantera
13{
14
15ElectronCollisionPlasmaData::ElectronCollisionPlasmaData()
16{
17 energyLevels.assign(1, 0.0);
18 distribution.assign(1, 0.0);
19}
20
22{
23 const PlasmaPhase& pp = dynamic_cast<const PlasmaPhase&>(phase);
24
25 // The distribution number dictates whether the rate should be updated.
26 // Three scenarios involving changes of the distribution number:
27 // 1. Change of the electron energy levels
28 // 2. Change of the electron energy distribution
29 // 3. Combined changes of one and two
31 return false;
32 }
33
34 // Update distribution
38
39 // Update energy levels
40 if (pp.levelNumber() != levelNumber || energyLevels.empty()) {
44 }
45 return true;
46}
47
49{
50 ReactionRate::setParameters(node, rate_units);
51 if (!node.hasKey("energy-levels") && !node.hasKey("cross-sections")) {
52 return;
53 }
54
55 if (node.hasKey("kind")) {
56 m_kind = node["kind"].asString();
57 }
58 if (node.hasKey("target")) {
59 m_target = node["target"].asString();
60 }
61 if (node.hasKey("product")) {
62 m_product = node["product"].asString();
63 }
64
65 m_energyLevels = node["energy-levels"].asVector<double>();
66 m_crossSections = node["cross-sections"].asVector<double>(m_energyLevels.size());
67 m_threshold = node.getDouble("threshold", 0.0);
68}
69
71 node["type"] = type();
72 node["energy-levels"] = m_energyLevels;
73 node["cross-sections"] = m_crossSections;
74 if (!m_kind.empty()) {
75 node["kind"] = m_kind;
76 }
77}
78
80 span<const double> sharedLevels)
81{
83 m_crossSectionsInterpolated.reserve(sharedLevels.size());
84 for (double level : sharedLevels) {
87 }
88}
89
91 const ElectronCollisionPlasmaData& shared_data)
92{
93 // Interpolate cross-sections data to the energy levels of
94 // the electron energy distribution function when the EEDF from the phase changes
95 if (m_levelNumber != shared_data.levelNumber) {
97 for (double level : shared_data.energyLevels) {
100 }
101 m_levelNumber = shared_data.levelNumber;
102 }
103
104 AssertThrowMsg(m_crossSectionsInterpolated.size() == shared_data.distribution.size(),
105 "ECPR:evalFromStruct", "Size mismatch: len(interp) = {}, len(distrib) = {}",
106 m_crossSectionsInterpolated.size(), shared_data.distribution.size());
107
108 // Map cross sections to Eigen::ArrayXd
109 auto cs_array = Eigen::Map<const Eigen::ArrayXd>(
111 );
112
113 // Map energyLevels in Eigen::ArrayXd
114 auto eps = Eigen::Map<const Eigen::ArrayXd>(
115 shared_data.energyLevels.data(), shared_data.energyLevels.size()
116 );
117
118 // Map energyLevels in Eigen::ArrayXd
119 auto distribution = Eigen::Map<const Eigen::ArrayXd>(
120 shared_data.distribution.data(), shared_data.distribution.size()
121 );
122
123 // unit in kmol/m3/s
124 return pow(2.0 * ElectronCharge / ElectronMass, 0.5) * Avogadro *
125 simpson(eps.cwiseProduct(distribution.cwiseProduct(cs_array)), eps);
126}
127
129 const ElectronCollisionPlasmaData& shared_data, double& kf, double& kr)
130{
131 if (kr == 0.0) {
132 // The reverse rate constant is only for reversible reactions
133 // kr = 0.0 indicates that the reaction is irreversible
134 return;
135 }
136
137 // Interpolate cross-sections data to the energy levels of
138 // the electron energy distribution function
139 if (m_levelNumberSuperelastic != shared_data.levelNumber) {
140 // super elastic collision energy levels and cross-sections
141 vector<double> superElasticEnergyLevels{0.0};
142 m_crossSectionsOffset.resize(shared_data.energyLevels.size());
143 for (size_t i = 1; i < m_energyLevels.size(); i++) {
144 // The energy levels are offset by the first energy level (threshold)
145 superElasticEnergyLevels.push_back(m_energyLevels[i] - m_energyLevels[0]);
146 }
147 for (size_t i = 0; i < shared_data.energyLevels.size(); i++) {
148 // The interpolated super-elastic cross section is evaluated
149 // at the shared energy grid
151 superElasticEnergyLevels,
153 }
155 }
156
157 // Map energyLevels in Eigen::ArrayXd
158 auto eps = Eigen::Map<const Eigen::ArrayXd>(
159 shared_data.energyLevels.data(), shared_data.energyLevels.size()
160 );
161
162 // Map energyLevels in Eigen::ArrayXd
163 auto distribution = Eigen::Map<const Eigen::ArrayXd>(
164 shared_data.distribution.data(), shared_data.distribution.size()
165 );
166
167 // unit in kmol/m3/s
168 kr = pow(2.0 * ElectronCharge / ElectronMass, 0.5) * Avogadro *
169 simpson((eps + m_energyLevels[0]).cwiseProduct(
170 distribution.cwiseProduct(m_crossSectionsOffset)), eps);
171}
172
174{
175 const ThermoPhase& thermo = kin.thermo();
176 // get electron species name
177 string electronName;
178 if (thermo.type() == "plasma") {
179 electronName = dynamic_cast<const PlasmaPhase&>(thermo).electronSpeciesName();
180 } else {
181 throw CanteraError("ElectronCollisionPlasmaRate::setContext",
182 "ElectronCollisionPlasmaRate requires plasma phase");
183 }
184
185 // Number of reactants needs to be two
186 if (rxn.reactants.size() != 2) {
187 throw InputFileError("ElectronCollisionPlasmaRate::setContext", rxn.input,
188 "ElectronCollisionPlasmaRate requires exactly two reactants");
189 }
190
191 // Must have only one electron
192 // @todo add electron-electron collision rate
193 if (rxn.reactants.at(electronName) != 1) {
194 throw InputFileError("ElectronCollisionPlasmaRate::setContext", rxn.input,
195 "ElectronCollisionPlasmaRate requires one and only one electron");
196 }
197
198 // Determine the "kind" of collision if not specified explicitly
199 if (m_kind.empty()) {
200 m_kind = "excitation"; // default
201 if (rxn.reactants == rxn.products) {
202 m_kind = "effective";
203 } else {
204 for (const auto& [p, stoich] : rxn.products) {
205 if (p == electronName) {
206 continue;
207 }
208 double q = thermo.charge(thermo.speciesIndex(p, true));
209 if (q > 0) {
210 m_kind = "ionization";
211 } else if (q < 0) {
212 m_kind = "attachment";
213 }
214 }
215 }
216 }
217
218 if (m_threshold == 0.0 &&
219 (m_kind == "excitation" || m_kind == "ionization" || m_kind == "attachment"))
220 {
221 for (size_t i = 0; i < m_energyLevels.size(); i++) {
222 if (m_energyLevels[i] > 0.0) { // Look for first non-zero cross-section
224 break;
225 }
226 }
227 }
228
229 if (!rxn.reversible) {
230 return; // end checking of forward reaction
231 }
232
233 // For super-elastic collisions
234 if (rxn.products.size() != 2) {
235 throw InputFileError("ElectronCollisionPlasmaRate::setContext", rxn.input,
236 "ElectronCollisionPlasmaRate requires exactly two products"
237 " if the reaction is reversible (super-elastic collisions)");
238 }
239
240 // Must have only one electron
241 if (rxn.products.at(electronName) != 1) {
242 throw InputFileError("ElectronCollisionPlasmaRate::setContext", rxn.input,
243 "ElectronCollisionPlasmaRate requires one and only one electron in products"
244 " if the reaction is reversible (super-elastic collisions)");
245 }
246}
247
248}
Header for plasma reaction rates parameterized by electron collision cross section and electron energ...
Base class for kinetics managers and also contains the kineticsmgr module documentation (see Kinetics...
Header file for class PlasmaPhase.
A map of string keys to values whose type can vary at runtime.
Definition AnyMap.h:431
double getDouble(const string &key, double default_) const
If key exists, return it as a double, otherwise return default_.
Definition AnyMap.cpp:1580
bool hasKey(const string &key) const
Returns true if the map contains an item named key.
Definition AnyMap.cpp:1477
Base class for exceptions thrown by Cantera classes.
void updateInterpolatedCrossSection(span< const double >)
Update the value of m_crossSectionsInterpolated [m2].
vector< double > m_crossSectionsInterpolated
collision cross sections [m2] after interpolation
virtual void setContext(const Reaction &rxn, const Kinetics &kin) override
Set context of reaction rate evaluation.
int m_levelNumberSuperelastic
Counter used to indicate when m_crossSectionsOffset needs to be synced with the phase.
string m_product
The product of electron collision.
int m_levelNumber
Counter used to indicate when m_energyLevels needs to be synced with the phase.
string m_target
The name of the target of electron collision.
vector< double > m_crossSections
collision cross sections [m2] at m_energyLevels
double m_threshold
The energy threshold of electron collision.
string m_kind
The name of the kind of electron collision.
virtual void getParameters(AnyMap &node) const override
Get parameters.
void modifyRateConstants(const ElectronCollisionPlasmaData &shared_data, double &kf, double &kr)
Calculate the reverse rate coefficient for super-elastic collisions.
Eigen::ArrayXd m_crossSectionsOffset
collision cross section [m2] interpolated on m_energyLevels offset by the threshold energy (the first...
vector< double > m_energyLevels
electron energy levels [eV]
virtual void setParameters(const AnyMap &node, const UnitStack &units) override
Set parameters.
virtual const std::string type() const override
String identifying reaction rate specialization.
double evalFromStruct(const ElectronCollisionPlasmaData &shared_data)
Evaluate reaction rate.
Error thrown for problems processing information contained in an AnyMap or AnyValue.
Definition AnyMap.h:749
Public interface for kinetics managers.
Definition Kinetics.h:126
ThermoPhase & thermo(size_t n=0)
This method returns a reference to the nth ThermoPhase object defined in this kinetics mechanism.
Definition Kinetics.h:239
size_t speciesIndex(const string &name, bool raise=true) const
Returns the index of a species named 'name' within the Phase object.
Definition Phase.cpp:127
double charge(size_t k) const
Dimensionless electrical charge of a single molecule of species k The charge is normalized by the the...
Definition Phase.h:561
Base class for handling plasma properties, specifically focusing on the electron energy distribution.
Definition PlasmaPhase.h:84
int distributionNumber() const
Return the distribution Number m_distNum.
int levelNumber() const
Return the electron energy level Number m_levelNum.
size_t nElectronEnergyLevels() const
Number of electron levels.
void getElectronEnergyDistribution(span< double > distrb) const
Get electron energy distribution.
void getElectronEnergyLevels(span< double > levels) const
Get electron energy levels.
virtual void setParameters(const AnyMap &node, const UnitStack &units)
Set parameters.
Abstract base class which stores data about a reaction and its rate parameterization so that it can b...
Definition Reaction.h:25
bool reversible
True if the current reaction is reversible. False otherwise.
Definition Reaction.h:126
Composition products
Product species and stoichiometric coefficients.
Definition Reaction.h:114
Composition reactants
Reactant species and stoichiometric coefficients.
Definition Reaction.h:111
AnyMap input
Input data used for specific models.
Definition Reaction.h:139
Base class for a phase with thermodynamic properties.
string type() const override
String indicating the thermodynamic model implemented.
Header for a file containing miscellaneous numerical functions.
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
double simpson(const Eigen::ArrayXd &f, const Eigen::ArrayXd &x)
Numerical integration of a function using Simpson's rule with flexibility of taking odd and even numb...
Definition funcs.cpp:91
double linearInterp(double x, span< const double > xpts, span< const double > fpts)
Linearly interpolate a function defined on a discrete grid.
Definition funcs.cpp:13
const double Avogadro
Avogadro's Number [number/kmol].
Definition ct_defs.h:84
const double ElectronCharge
Elementary charge [C].
Definition ct_defs.h:93
const double ElectronMass
Electron Mass [kg].
Definition ct_defs.h:114
Namespace for the Cantera kernel.
Definition AnyMap.cpp:595
Data container holding shared data specific to ElectronCollisionPlasmaRate.
vector< double > energyLevels
electron energy levels
virtual bool update(const ThermoPhase &phase, const Kinetics &kin) override
Update data container based on thermodynamic phase state.
int levelNumber
integer that is incremented when electron energy levels change
vector< double > distribution
electron energy distribution
int m_dist_number
integer that is incremented when electron energy distribution changes
Unit aggregation utility.
Definition Units.h:105