Cantera  3.2.0a2
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 const vector<double>& sharedLevels) {
82 m_crossSectionsInterpolated.reserve(sharedLevels.size());
83 for (double level : sharedLevels) {
86 }
87}
88
90 const ElectronCollisionPlasmaData& shared_data)
91{
92 // Interpolate cross-sections data to the energy levels of
93 // the electron energy distribution function when the EEDF from the phase changes
94 if (m_levelNumber != shared_data.levelNumber) {
96 for (double level : shared_data.energyLevels) {
99 }
100 m_levelNumber = shared_data.levelNumber;
101 }
102
103 AssertThrowMsg(m_crossSectionsInterpolated.size() == shared_data.distribution.size(),
104 "ECPR:evalFromStruct", "Size mismatch: len(interp) = {}, len(distrib) = {}",
105 m_crossSectionsInterpolated.size(), shared_data.distribution.size());
106
107 // Map cross sections to Eigen::ArrayXd
108 auto cs_array = Eigen::Map<const Eigen::ArrayXd>(
110 );
111
112 // Map energyLevels in Eigen::ArrayXd
113 auto eps = Eigen::Map<const Eigen::ArrayXd>(
114 shared_data.energyLevels.data(), shared_data.energyLevels.size()
115 );
116
117 // Map energyLevels in Eigen::ArrayXd
118 auto distribution = Eigen::Map<const Eigen::ArrayXd>(
119 shared_data.distribution.data(), shared_data.distribution.size()
120 );
121
122 // unit in kmol/m3/s
123 return pow(2.0 * ElectronCharge / ElectronMass, 0.5) * Avogadro *
124 simpson(eps.cwiseProduct(distribution.cwiseProduct(cs_array)), eps);
125}
126
128 const ElectronCollisionPlasmaData& shared_data, double& kf, double& kr)
129{
130 if (kr == 0.0) {
131 // The reverse rate constant is only for reversible reactions
132 // kr = 0.0 indicates that the reaction is irreversible
133 return;
134 }
135
136 // Interpolate cross-sections data to the energy levels of
137 // the electron energy distribution function
138 if (m_levelNumberSuperelastic != shared_data.levelNumber) {
139 // super elastic collision energy levels and cross-sections
140 vector<double> superElasticEnergyLevels{0.0};
141 m_crossSectionsOffset.resize(shared_data.energyLevels.size());
142 for (size_t i = 1; i < m_energyLevels.size(); i++) {
143 // The energy levels are offset by the first energy level (threshold)
144 superElasticEnergyLevels.push_back(m_energyLevels[i] - m_energyLevels[0]);
145 }
146 for (size_t i = 0; i < shared_data.energyLevels.size(); i++) {
147 // The interpolated super-elastic cross section is evaluated
148 // at the shared energy grid
150 superElasticEnergyLevels,
152 }
154 }
155
156 // Map energyLevels in Eigen::ArrayXd
157 auto eps = Eigen::Map<const Eigen::ArrayXd>(
158 shared_data.energyLevels.data(), shared_data.energyLevels.size()
159 );
160
161 // Map energyLevels in Eigen::ArrayXd
162 auto distribution = Eigen::Map<const Eigen::ArrayXd>(
163 shared_data.distribution.data(), shared_data.distribution.size()
164 );
165
166 // unit in kmol/m3/s
167 kr = pow(2.0 * ElectronCharge / ElectronMass, 0.5) * Avogadro *
168 simpson((eps + m_energyLevels[0]).cwiseProduct(
169 distribution.cwiseProduct(m_crossSectionsOffset)), eps);
170}
171
173{
174 const ThermoPhase& thermo = kin.thermo();
175 // get electron species name
176 string electronName;
177 if (thermo.type() == "plasma") {
178 electronName = dynamic_cast<const PlasmaPhase&>(thermo).electronSpeciesName();
179 } else {
180 throw CanteraError("ElectronCollisionPlasmaRate::setContext",
181 "ElectronCollisionPlasmaRate requires plasma phase");
182 }
183
184 // Number of reactants needs to be two
185 if (rxn.reactants.size() != 2) {
186 throw InputFileError("ElectronCollisionPlasmaRate::setContext", rxn.input,
187 "ElectronCollisionPlasmaRate requires exactly two reactants");
188 }
189
190 // Must have only one electron
191 // @todo add electron-electron collision rate
192 if (rxn.reactants.at(electronName) != 1) {
193 throw InputFileError("ElectronCollisionPlasmaRate::setContext", rxn.input,
194 "ElectronCollisionPlasmaRate requires one and only one electron");
195 }
196
197 // Determine the "kind" of collision if not specified explicitly
198 if (m_kind.empty()) {
199 m_kind = "excitation"; // default
200 if (rxn.reactants == rxn.products) {
201 m_kind = "effective";
202 } else {
203 for (const auto& [p, stoich] : rxn.products) {
204 if (p == electronName) {
205 continue;
206 }
207 double q = thermo.charge(thermo.speciesIndex(p));
208 if (q > 0) {
209 m_kind = "ionization";
210 } else if (q < 0) {
211 m_kind = "attachment";
212 }
213 }
214 }
215 }
216
217 if (m_threshold == 0.0 &&
218 (m_kind == "excitation" || m_kind == "ionization" || m_kind == "attachment"))
219 {
220 for (size_t i = 0; i < m_energyLevels.size(); i++) {
221 if (m_energyLevels[i] > 0.0) { // Look for first non-zero cross-section
223 break;
224 }
225 }
226 }
227
228 if (!rxn.reversible) {
229 return; // end checking of forward reaction
230 }
231
232 // For super-elastic collisions
233 if (rxn.products.size() != 2) {
234 throw InputFileError("ElectronCollisionPlasmaRate::setContext", rxn.input,
235 "ElectronCollisionPlasmaRate requires exactly two products"
236 " if the reaction is reversible (super-elastic collisions)");
237 }
238
239 // Must have only one electron
240 if (rxn.products.at(electronName) != 1) {
241 throw InputFileError("ElectronCollisionPlasmaRate::setContext", rxn.input,
242 "ElectronCollisionPlasmaRate requires one and only one electron in products"
243 " if the reaction is reversible (super-elastic collisions)");
244 }
245}
246
247}
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.
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...
void updateInterpolatedCrossSection(const vector< double > &)
Update the value of m_crossSectionsInterpolated [m2].
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:240
size_t speciesIndex(const string &name) const
Returns the index of a species named 'name' within the Phase object.
Definition Phase.cpp:129
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:539
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(double *distrb) const
Get electron energy distribution.
void getElectronEnergyLevels(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 linearInterp(double x, const vector< double > &xpts, const vector< double > &fpts)
Linearly interpolate a function defined on a discrete grid.
Definition funcs.cpp:13
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
const double Avogadro
Avogadro's Number [number/kmol].
Definition ct_defs.h:81
const double ElectronCharge
Elementary charge [C].
Definition ct_defs.h:90
const double ElectronMass
Electron Mass [kg].
Definition ct_defs.h:111
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