Cantera  4.0.0a2
Loading...
Searching...
No Matches
PlasmaPhase.h
Go to the documentation of this file.
1/**
2 * @file PlasmaPhase.h
3 * Header file for class PlasmaPhase.
4 */
5
6// This file is part of Cantera. See License.txt in the top-level directory or
7// at https://cantera.org/license.txt for license and copyright information.
8
9#ifndef CT_PLASMAPHASE_H
10#define CT_PLASMAPHASE_H
11
14#include "cantera/numerics/eigen_sparse.h"
15
16namespace Cantera
17{
18
19class Reaction;
20class ElectronCollisionPlasmaRate;
21
22//! Base class for handling plasma properties, specifically focusing on the
23//! electron energy distribution.
24/*!
25 * This class provides functionality to manage the the electron energy distribution
26 * using two primary methods for defining the electron distribution and electron
27 * temperature.
28 *
29 * The first method utilizes setElectronTemperature(), which sets the electron
30 * temperature and calculates the electron energy distribution assuming an
31 * isotropic-velocity model. Note that all units in PlasmaPhase are in SI, except
32 * for electron energy, which is measured in volts.
33 *
34 * The generalized electron energy distribution for an isotropic-velocity
35 * distribution (as described by Gudmundsson @cite gudmundsson2001 and Khalilpour
36 * and Foroutan @cite khalilpour2020)
37 * is given by:
38 * @f[
39 * f(\epsilon) = c_1 \frac{\sqrt{\epsilon}}{\epsilon_m^{3/2}}
40 * \exp \left(-c_2 \left(\frac{\epsilon}{\epsilon_m}\right)^x \right),
41 * @f]
42 * where @f$ x = 1 @f$ corresponds to a Maxwellian distribution and
43 * @f$ x = 2 @f$ corresponds to a Druyvesteyn distribution.
44 * Here, @f$ \epsilon_m = \frac{3}{2} T_e @f$ [V] represents the
45 * mean electron energy.
46 *
47 * The total probability distribution integrates to one:
48 * @f[
49 * \int_0^{\infty} f(\epsilon) d\epsilon = 1.
50 * @f]
51 * According to Hagelaar and Pitchford @cite hagelaar2005, the electron energy
52 * probability function can be defined as
53 * @f$ F(\epsilon) = \frac{f(\epsilon)}{\sqrt{\epsilon}} @f$ with units of
54 * [V@f$^{-3/2}@f$]. The generalized form of the electron energy probability
55 * function for isotropic-velocity distributions is:
56 * @f[
57 * F(\epsilon) = c_1 \frac{1}{\epsilon_m^{3/2}}
58 * \exp\left(-c_2 \left(\frac{\epsilon}{\epsilon_m}\right)^x\right),
59 * @f]
60 * and this form is used to model the isotropic electron energy distribution
61 * in PlasmaPhase.
62 *
63 * The second method allows for manual definition of the electron energy
64 * distribution using setDiscretizedElectronEnergyDist(). In this approach,
65 * the electron temperature is derived from the mean electron energy,
66 * @f$ \epsilon_m @f$, which can be calculated as follows @cite hagelaar2005 :
67 * @f[
68 * \epsilon_m = \int_0^{\infty} \epsilon^{3/2} F(\epsilon) d\epsilon.
69 * @f]
70 * This integral can be approximated using the trapezoidal rule,
71 * @f[
72 * \epsilon_m = \sum_i \left(\epsilon_{i+1}^{5/2} - \epsilon_i^{5/2}\right)
73 * \frac{F(\epsilon_{i+1}) + F(\epsilon_i)}{2},
74 * @f]
75 * where @f$ i @f$ is the index of discrete energy levels, or Simpson's rule.
76 *
77 * ## Thermodynamic consistency of the two-temperature model
78 *
79 * When the electron temperature @f$ T_\text{e} @f$ differs from the heavy-species
80 * temperature @f$ T @f$, this phase does not satisfy all of Cantera's standard-state
81 * consistency relations simultaneously: one of them is deliberately left unsatisfied.
82 * This is a consequence of two design commitments that this implementation makes, both
83 * of which are individually reasonable but which cannot be reconciled once
84 * @f$ T_\text{e} \neq T @f$:
85 *
86 * 1. **Kinetics uses true concentrations.** The generalized (activity) concentrations
87 * that drive the law of mass action are kept equal to the true molar concentrations,
88 * @f$ C^a_k = C_k @f$, so that reaction rates depend on actual number densities.
89 * Together with the standard concentration @f$ C^0_k = P/RT @f$ (the gas
90 * temperature, for all species; see #standardConcentration()), this requires the
91 * reported activities to be
92 * @f[ a_k = \frac{C^a_k}{C^0_k} = X_k \frac{T}{\overline{T}}, @f]
93 * where @f$ \overline{T} @f$ is the mole-fraction-weighted mean temperature (see
94 * #meanTemperature()). This is what #getActivities() returns.
95 *
96 * 2. **Chemical potentials keep the ideal-gas form.** The chemical potentials retain
97 * the usual ideal-gas composition dependence,
98 * @f$ \mu_k = \mu^0_k(T_k) + R T_k \ln X_k @f$,
99 * with each species evaluated at its own temperature @f$ T_k @f$ (@f$ T @f$ for
100 * heavy species, @f$ T_\text{e} @f$ for electrons; see #getChemPotentials() and
101 * #getStandardChemPotentials()). This is equivalent to an activity of @f$ X_k @f$.
102 *
103 * When @f$ T_\text{e} \neq T @f$, these two demands imply different values for the
104 * activities -- @f$ X_k\,T/\overline{T} @f$ versus @f$ X_k @f$ -- which differ by the
105 * factor @f$ T/\overline{T} @f$. #getActivities() reports the first;
106 * #getChemPotentials() embodies the second; and the identity
107 * @f$ \mu_k = \mu^0_k + R T_k \ln a_k @f$ is therefore the relation left unsatisfied.
108 * This is why the consistency test `chem_potentials_to_activities` is a known failure
109 * for two-temperature states.
110 *
111 * The practical consequence of this inconsistency is limited. It formally perturbs any
112 * *chemical* equilibrium computed for the phase, but the concept of chemical
113 * equilibrium in the absence of *thermal* equilibrium (@f$ T_\text{e} \neq T @f$) is
114 * itself ill-posed, so the perturbed quantity has little physical meaning in exactly
115 * the regime where the inconsistency appears. The trade-offs and potential approaches
116 * for a fully-consistent implementation are documented in
117 * https://github.com/Cantera/enhancements/issues/258#issuecomment-4857093158.
118 *
119 * @warning This class is an experimental part of %Cantera and may be
120 * changed or removed without notice.
121 * @todo Implement electron Boltzmann equation solver to solve EEDF.
122 * https://github.com/Cantera/enhancements/issues/127
123 * @ingroup thermoprops
124 */
126{
127public:
128 //! Construct and initialize a PlasmaPhase object directly from an input file.
129 //! The constructor initializes the electron energy distribution to be a
130 //! Maxwellian distribution (#m_isotropicShapeFactor = 1.0).
131 //! The initial electron energy grid is set to a linear space which starts
132 //! at 0.01 eV and ends at 1 eV with 1000 points.
133 /*!
134 * @param inputFile Name of the input file containing the phase definition
135 * to set up the object. If blank, an empty phase will be
136 * created.
137 * @param id ID of the phase in the input file. Defaults to the
138 * empty string.
139 */
140 explicit PlasmaPhase(const string& inputFile="", const string& id="");
141
142 ~PlasmaPhase();
143
144 string type() const override {
145 return "plasma";
146 }
147
148 void initThermo() override;
149
150 //! @name Overridden from IdealGasPhase or ThermoPhase
151 //! @{
152 bool addSpecies(shared_ptr<Species> spec) override;
153 virtual void setSolution(std::weak_ptr<Solution> soln) override;
154 void getParameters(AnyMap& phaseNode) const override;
155 void setParameters(const AnyMap& phaseNode,
156 const AnyMap& rootNode=AnyMap()) override;
157 //! @}
158 //! @name Electron Species Information
159 //! @{
160
161 //! Electron Species Index
162 size_t electronSpeciesIndex() const {
164 }
165
166 //! Electron species name
167 string electronSpeciesName() const {
169 }
170
171 //! @}
172 //! @name Electron Energy Distribution Functions
173 //! @{
174
175 //! Set electron energy levels.
176 //! @param levels The vector of electron energy levels [eV].
177 //! Length: #m_nPoints.
178 void setElectronEnergyLevels(span<const double> levels);
179
180 //! Get electron energy levels.
181 //! @param levels The vector of electron energy levels [eV]. Length: #m_nPoints
182 void getElectronEnergyLevels(span<double> levels) const {
183 Eigen::Map<Eigen::ArrayXd>(levels.data(), levels.size()) = m_electronEnergyLevels;
184 }
185
186 //! Set discretized electron energy distribution.
187 //! @param levels The vector of electron energy levels [eV].
188 //! Length: #m_nPoints.
189 //! @param distrb The vector of electron energy distribution.
190 //! Length: #m_nPoints.
191 void setDiscretizedElectronEnergyDist(span<const double> levels,
192 span<const double> distrb);
193
194 //! Get electron energy distribution.
195 //! @param distrb The vector of electron energy distribution.
196 //! Length: #m_nPoints.
197 void getElectronEnergyDistribution(span<double> distrb) const {
198 Eigen::Map<Eigen::ArrayXd>(distrb.data(), distrb.size()) = m_electronEnergyDist;
199 }
200
201 //! Set the shape factor of isotropic electron energy distribution.
202 //! Note that @f$ x = 1 @f$ and @f$ x = 2 @f$ correspond to the
203 //! Maxwellian and Druyvesteyn distribution, respectively.
204 //! @param x The shape factor
205 void setIsotropicShapeFactor(double x);
206
207 //! The shape factor of isotropic electron energy distribution.
208 double isotropicShapeFactor() const {
209 return m_isotropicShapeFactor;
210 }
211
212 //! Electron Temperature [K].
213 //! @return The electron temperature of the phase.
214 double electronTemperature() const override {
215 return m_electronTemp;
216 }
217 //! Set the internally stored electron temperature of the phase [K].
218 //! @param Te Electron temperature in Kelvin.
219 void setElectronTemperature(double Te) override;
220
221 //! Mean electron energy [eV].
222 double meanElectronEnergy() const {
223 return 3.0 / 2.0 * electronTemperature() * Boltzmann / ElectronCharge;
224 }
225
226 //! Set mean electron energy [eV].
227 //! This method also sets electron temperature accordingly.
228 void setMeanElectronEnergy(double energy);
229
230 //! Get electron energy distribution type.
232 return m_distributionType;
233 }
234
235 //! Set electron energy distribution type.
236 void setElectronEnergyDistributionType(const string& type);
237
238 //! Numerical quadrature method. Method: #m_quadratureMethod
239 string quadratureMethod() const {
240 return m_quadratureMethod;
241 }
242
243 //! Set numerical quadrature method for integrating electron
244 //! energy distribution function. Method: #m_quadratureMethod
245 void setQuadratureMethod(const string& method) {
246 m_quadratureMethod = method;
247 }
248
249 //! Set flag of automatically normalize electron energy distribution.
250 //! Flag: #m_do_normalizeElectronEnergyDist
253 }
254
255 //! Flag of automatically normalize electron energy distribution.
256 //! Flag: #m_do_normalizeElectronEnergyDist
259 }
260
261 //! Number of electron levels.
262 size_t nElectronEnergyLevels() const {
263 return m_nPoints;
264 }
265
266 //! Number of electron collision cross sections.
267 size_t nCollisions() const {
268 return m_collisions.size();
269 }
270
271 //! Get the Reaction object associated with electron collision *i*.
272 //! @since New in %Cantera 3.2.
273 const shared_ptr<Reaction> collision(size_t i) const {
274 return m_collisions[i];
275 }
276
277 //! Get the ElectronCollisionPlasmaRate object associated with electron collision
278 //! *i*.
279 //! @since New in %Cantera 3.2.
280 const shared_ptr<ElectronCollisionPlasmaRate> collisionRate(size_t i) const {
281 return m_collisionRates[i];
282 }
283
284 //! Update the electron energy distribution.
286
287 //! Return the distribution number #m_distNum.
288 int distributionNumber() const {
289 return m_distNum;
290 }
291
292 //! Return the electron energy level number #m_levelNum.
293 int levelNumber() const {
294 return m_levelNum;
295 }
296
297 //! Get the indicies for inelastic electron collisions.
298 //! @since New in %Cantera 3.2.
299 const vector<size_t>& kInelastic() const {
300 return m_kInelastic;
301 }
302
303 //! Get the indices for elastic electron collisions.
304 //! @since New in %Cantera 3.2.
305 const vector<size_t>& kElastic() const {
306 return m_kElastic;
307 }
308
309 //! Return the target of a specific process.
310 //! @since New in %Cantera 3.2.
311 size_t targetIndex(size_t i) const {
312 return m_targetSpeciesIndices[i];
313 }
314
315 //! Get the frequency of the applied electric field [Hz].
316 //! @since New in %Cantera 3.2.
317 double electricFieldFrequency() const {
319 }
320
321 //! Get the applied electric field strength [V/m].
322 double electricField() const {
323 return m_electricField;
324 }
325
326 //! Set the absolute electric field strength [V/m].
327 void setElectricField(double E) {
328 m_electricField = E;
329 }
330
331 //! Calculate the degree of ionization
332 //double ionDegree() const {
333 // double ne = concentration(m_electronSpeciesIndex); // [kmol/m³]
334 // double n_total = molarDensity(); // [kmol/m³]
335 // return ne / n_total;
336 //}
337
338 //! Get the reduced electric field strength [V·m²].
339 double reducedElectricField() const {
341 }
342
343 //! Set reduced electric field given in [V·m²].
344 void setReducedElectricField(double EN) {
345 m_electricField = EN * molarDensity() * Avogadro; // [V/m]
346 }
347
348 /**
349 * The electron mobility (m²/V/s)
350 * @f[
351 * \mu = \nu_d / E,
352 * @f]
353 * where @f$ \nu_d @f$ is the drift velocity (m²/s), and @f$ E @f$ is the electric
354 * field strength (V/m).
355 */
356 double electronMobility() const;
357
358 /**
359 * The elastic power loss [J/s/m³]
360 * @f[
361 * P_k = N_A N_A C_e e \sum_k C_k K_k,
362 * @f]
363 * where @f$ C_k @f$ and @f$ C_e @f$ are the concentration (kmol/m³) of the
364 * target species and electrons, respectively. @f$ K_k @f$ is the elastic
365 * electron energy loss coefficient (eV-m³/s).
366 */
367 double elasticPowerLoss();
368
369 /**
370 * The joule heating power (W/m³)
371 * @f[
372 * q_J = \sigma * E^2,
373 * @f]
374 * where @f$ \sigma @f$ is the conductivity (S/m), defined by:
375 * @f[
376 * \sigma = e * n_e * \mu_e
377 * @f]
378 * and @f$ E @f$ is the electric field strength (V/m).
379 */
380 double jouleHeatingPower() const;
381
382 void beginEquilibrate() override;
383
384 void endEquilibrate() override;
385
386 double intrinsicHeating() override;
387
388 //! @}
389 //! @name Molar Thermodynamic Properties of the Solution
390 //! @{
391
392 //! Return the Molar enthalpy. Units: J/kmol.
393 /*!
394 * For an ideal gas mixture with electrons at a different temperature
395 * than the heavy species, the molar enthalpy is calculated as:
396 * @f[
397 * \begin{align}
398 * \hat h(T, T_\text{e})
399 * &= \sum_{k} X_k h^0_k(T_k) \\
400 * &= \sum_{k \neq e} X_k h^0_k(T) + X_\text{e} h_\text{e}^0(T_\text{e})
401 * \end{align}
402 * @f]
403 * where heavy-species properties are evaluated at @f$ T @f$, electron properties
404 * at @f$ T_\text{e} @f$, and @f$ P @f$ is the total pressure of the mixture.
405 * For an ideal gas, enthalpy is independent of pressure.
406 * The standard-state pure-species enthalpies @f$ h^0_k(T_k) @f$ are
407 * computed by the species thermodynamic property manager.
408 */
409 double enthalpy_mole() const override;
410
411 //! Return the molar entropy. Units: J/kmol/K.
412 /*!
413 * For an ideal gas mixture with electrons at a different temperature
414 * than the heavy species, the molar entropy is calculated as:
415 * @f[
416 * \hat s(T,T_\text{e},P) = \sum_k X_k \hat s^0_k(T_k) - \hat R \ln \frac{P}{P^0}
417 * @f]
418 * where heavy-species properties are evaluated at @f$ T @f$, electron properties
419 * at @f$ T_\text{e} @f$, and @f$ P @f$ is the total pressure of the mixture.
420 */
421 double entropy_mole() const override;
422
423 //! Return the molar Gibbs free energy. Units: J/kmol.
424 /*!
425 * For an ideal gas mixture with electrons at a different temperature
426 * than the heavy species, the molar Gibbs free energy is calculated as:
427 * @f[
428 * \begin{align}
429 * \hat g(T,T_\text{e},P)
430 * &= \sum_{k} X_k \tilde{g}_k(T_k, P)
431 * = \sum_{k} X_k \mu_k(T_k, P) \\
432 * &= \sum_{k} X_k \left[\mu^0_k(T_k)
433 * + R T_k \ln \left( \frac{X_k P}{P^0} \right) \right] \\
434 * \end{align}
435 * @f]
436 * where heavy-species properties are evaluated at @f$ T @f$, electron properties
437 * at @f$ T_\text{e} @f$, and @f$ P @f$ is the total pressure of the mixture.
438 */
439 double gibbs_mole() const override;
440
441 //! Return the molar internal energy. Units: J/kmol.
442 /*!
443 * For an ideal gas mixture with electrons at a different temperature
444 * than the heavy species, the molar internal energy is calculated as:
445 * @f[
446 * \hat u(T,T_\text{e},P)
447 * = \sum_{k} X_k \tilde{u}_k(T_k)
448 * = \sum_{k} X_k (\tilde{h}_k(T_k) - R T_k)
449 * @f]
450 * where heavy-species properties are evaluated at @f$ T @f$, electron properties
451 * at @f$ T_\text{e} @f$, and @f$ P @f$ is the total pressure of the mixture.
452 * For an ideal gas, internal energy is independent of pressure.
453 */
454 double intEnergy_mole() const override;
455
456 //! @}
457 //! @name Mechanical Equation of State
458 //! @{
459
460 //! Return the mean temperature of the plasma phase. Units: K.
461 /*!
462 * In a plasma phase, the electron temperature can differ from the
463 * heavy-species (gas) temperature. Therefore, the mean temperature is
464 * defined as a mole-fraction-weighted average of the electron and
465 * heavy-species temperatures:
466 * @f[
467 * \begin{align}
468 * \overline{T} &= \sum_{k \neq e} X_k T + X_\text{e} T_\text{e} \\
469 * &= (1 - X_\text{e}) T + X_\text{e} T_\text{e} \\
470 * &= T + X_\text{e} (T_\text{e} - T)
471 * \end{align}
472 * @f]
473 * See the #pressure() method for usage of the mean temperature in
474 * calculating the pressure of the plasma phase.
475 */
476 double meanTemperature() const;
477
478 //! Return the pressure of the plasma phase. Units: Pa.
479 /*!
480 * The pressure of the plasma phase is calculated using the mean temperature,
481 * which is a mole-fraction-weighted average of the electron and heavy-species
482 * temperatures.
483 * @f[
484 * \begin{align}
485 * P &= \sum_k n_k k_\text{B} T_k \\
486 * &= \sum_{k \neq e} n_k k_\text{B} T
487 * + n_\text{e} k_\text{B} T_\text{e} \\
488 * &= (n_\text{total} - n_\text{e}) k_\text{B} T
489 * + n_\text{e} k_\text{B} T_\text{e} \\
490 * &= n_\text{total} (1 - X_\text{e}) k_\text{B} T
491 * + n_\text{total} X_\text{e} k_\text{B} T_\text{e} \\
492 * &= n_\text{total} k_\text{B} \overline{T} \\
493 * \end{align}
494 * @f]
495 * where @f$ \overline{T} @f$ is the mean temperature of the plasma phase,
496 * defined in the #meanTemperature() method.
497 * Here, @f$ n_k @f$ is the number density of species *k* [in 1/m³],
498 * @f$ n_\text{total} @f$ is the total number density of the phase [in 1/m³],
499 * @f$ X_\text{e} @f$ is the mole fraction of electrons,
500 * @f$ T @f$ is the heavy-species (gas) temperature [K],
501 * @f$ T_\text{e} @f$ is the electron temperature [K],
502 * and @f$ k_\text{B} @f$ is the Boltzmann constant [J/K].
503 *
504 * The number density times Boltzmann constant can be expressed as
505 * @f$ n_\text{total} k_\text{B} = C_\text{total} R @f$, where
506 * @f$ C_\text{total} @f$ is the total molar concentration of the phase [kmol/m³]
507 * and @f$ R @f$ is the gas constant [J/kmol/K], so that:
508 * @f[
509 * P = C_\text{total} R \overline{T}.
510 * @f]
511 *
512 * Here, the pressure is set via the density, via:
513 * @f[
514 * P = R \overline{T} \frac{\rho}{\overline{W}}
515 * @f]
516 * where @f$ \overline{W} @f$ is the mean molecular weight.
517 */
518 double pressure() const override;
519
520 //! Set the pressure at constant temperature and composition. Units: Pa.
521 /*!
522 * This method is implemented by setting the mass density to
523 * @f[
524 * \rho = \frac{P \overline{W}}{\hat R \overline{T} }.
525 * @f]
526 *
527 * where @f$ \overline{W} @f$ is the mean molecular weight,
528 * and @f$ \overline{T} @f$ is the mean temperature (see #meanTemperature()).
529 *
530 * @param p Pressure [Pa].
531 */
532 void setPressure(double p) override {
534 }
535
536 //! Return the Gas Constant multiplied by the current electron temperature [J/kmol].
537 double RTe() const {
539 }
540
541 //! Return the electron pressure. Units: Pa.
542 /*!
543 * The partial pressure of electrons is calculated using the electron temperature:
544 * @f[
545 * P_\text{e} = n_\text{e} k_\text{B} T_\text{e} = C_\text{e} R T_\text{e},
546 * @f]
547 * where @f$ n_\text{e} @f$ is the particular density of electrons [in 1/m³],
548 * @f$ k_\text{B} @f$ is the Boltzmann constant [J/K],
549 * @f$ C_\text{e} @f$ is the molar concentration of electrons [in kmol/m³],
550 * @f$ R @f$ is the gas constant [J/kmol/K], and
551 * @f$ T_\text{e} @f$ is the electron temperature [K].
552 */
553 virtual double electronPressure() const {
556 }
557
558 //! Raise NotImplementedError, as there is an ambiguity on the temperature to use.
559 double thermalExpansionCoeff() const override {
560 throw NotImplementedError("PlasmaPhase::thermalExpansionCoeff");
561 }
562
563 //! Raise NotImplementedError, as there is an ambiguity on the temperature to use.
564 double soundSpeed() const override {
565 throw NotImplementedError("PlasmaPhase::soundSpeed");
566 }
567
568 //! @}
569 //! @name Chemical Potentials and Activities
570 //! @{
571
572 //! Returns the standard concentration @f$ C^0_k @f$, which is used to
573 //! normalize the generalized concentration. Units: m³/kmol.
574 /*!
575 * The standard concentration is chosen to be equal to @f[ C^0_k = \frac{P}{R T} @f]
576 * where @f$ P @f$ is the total pressure of the mixture,
577 * @f$ R @f$ is the gas constant, and @f$ T @f$ is the gas temperature.
578 *
579 * @note The gas temperature @f$ T @f$ (not the electron temperature or the
580 * mean temperature) is used for *all* species, including electrons.
581 * Consequently @f$ C^0_\text{e} = P/RT \neq 1/V^0_\text{e} = P/R T_\text{e} @f$
582 * when @f$ T_\text{e} \neq T @f$. This is intentional: the reciprocal
583 * relation @f$ C^0_k = 1/V^0_k @f$ is a coincidence of the
584 * single-temperature ideal gas and is not a thermodynamic requirement.
585 * See the class documentation.
586 *
587 * @param k Parameter indicating the species. The default
588 * is to assume this refers to species 0.
589 */
590 double standardConcentration(size_t k=0) const override;
591
592 //! Get the array of non-dimensional activities at the current solution
593 //! temperature, pressure, and solution concentration.
594 /*!
595 * Since @f$ a_k = C^a_k / C^0_k @f$, where @f$ C^a_k = C_k @f$ is the true molar
596 * concentration, and @f$ C^0_k @f$ is the standard concentration defined above,
597 * the activities are equal to @f$ a_k = X_k T / \overline{T} @f$.
598 *
599 * @note These activities are defined for consistency with the kinetics
600 * (law-of-mass-action) concentrations and, when @f$ T_\text{e} \neq T @f$,
601 * differ by a factor of @f$ T/\overline{T} @f$ from the activities implied by
602 * the chemical-potential model (@f$ a_k = X_k @f$). See the class documentation
603 * for a discussion of this intentional inconsistency.
604 *
605 * @param a Output vector of activities. Length: m_kk.
606 */
607 void getActivities(span<double> a) const override;
608
609 //! Get the array of non-dimensional activity coefficients at the current
610 //! solution temperature, pressure, and solution concentration.
611 /*!
612 * The activity coefficients are defined by @f$ \gamma_k = a_k / X_k @f$.
613 * With the current definition of the activities, the activity coefficients are
614 * equal to @f$ \gamma_k = T / \overline{T} @f$.
615 *
616 * @param ac Output vector of activity coefficients. Length: m_kk.
617 */
618 void getActivityCoefficients(span<double> ac) const override;
619
620 //! @}
621 //! @name Partial Molar Properties of the Solution
622 //! @{
623
624 //! Return the chemical potentials of the species in the solution. Units: J/kmol.
625 /*!
626 * The chemical potential of species *k* is calculated as:
627 * @f[
628 * \begin{align}
629 * \mu_k(T_k, X_k, P)
630 * &= \mu_k^o(T_k, P) + R T_k \ln(X_k) \\
631 * &= \mu^0_k(T_k)(T_k)
632 * + R T_k \ln\left(\frac{P}{P^0}\right)
633 * + R T_k \ln(X_k) \\
634 * &= h^0_k(T_k)
635 * - T_k s^0_k(T_k)
636 * + R T_k \ln\left(\frac{P X_k}{P^0}\right) \\
637 * \end{align}
638 * @f]
639 * Note that it is also equal to the partial molar Gibbs free energy.
640 */
641 void getChemPotentials(span<double> mu) const override;
642
643 //! Return the partial molar enthalpies of the species in the solution. Units: J/kmol.
644 /*!
645 * The partial molar enthalpy of species *k* is
646 * @f$ \tilde{h}_k(T_k,P) = h^o_k(T,P) = h^{ref}_k(T_k) @f$,
647 * where heavy-species properties are evaluated at the gas temperature @f$ T @f$,
648 * and electron properties are evaluated at the electron temperature @f$ T_e @f$.
649 */
650 void getPartialMolarEnthalpies(span<double> hbar) const override;
651
652 //! Return the partial molar entropies of the species in the solution. Units: J/kmol/K.
653 /*!
654 * The partial molar enthalpy of species *k* is:
655 * @f[
656 * \tilde{s}_k(T_k, P) = s^0_k(T_k) - R \ln \frac{X_k P}{P^0}
657 * @f]
658 * where heavy-species properties are evaluated at the gas temperature,
659 * and electron properties are evaluated at the electron temperature.
660 * Here, @f$ P @f$ is the total pressure of the mixture, as defined in #pressure().
661 */
662 void getPartialMolarEntropies(span<double> sbar) const override;
663
664 //! Return the partial molar internal energies of the species in the solution. Units: J/kmol.
665 /*!
666 * The partial molar internal energy of species *k* is calculated as:
667 * @f[
668 * \tilde{u}_k(T_k,P) = \tilde{h}_k(T_k,P) - R T_k = h^{ref}_k(T_k) - R T_k
669 * @f]
670 * where @f$ \tilde{h}_k @f$ is the partial molar enthalpy of species *k*, and
671 * @f$ T_k @f$ is the temperature at which the partial molar enthalpy is evaluated.
672 * For heavy species, the partial molar enthalpy is evaluated at the gas temperature,
673 * while for electrons, it is evaluated at the electron temperature.
674 */
675 void getPartialMolarIntEnergies(span<double> ubar) const override;
676
677 //! Return the partial molar volumes of the species in the solution. Units: m³/kmol.
678 /*!
679 * For a multitemperature system,
680 * @f[
681 * v_k = \frac{R T_k}{P}
682 * @f]
683 * where @f$ T_k @f$ is the temperature at which the
684 * partial molar enthalpy is evaluated.
685 */
686 void getPartialMolarVolumes(span<double> vbar) const override;
687
688 //! @}
689 //! @name Properties of the Standard State of the Species in the Solution
690 //! @{
691
692 //! Return the standard chemical potentials of the species. Units: J/kmol.
693 /*!
694 * The standard chemical potentials (or standard state Gibbs free energy)
695 * of species *k* is calculated as:
696 * @f[
697 * \begin{align}
698 * \mu^0_k(T_k, X_k, P)
699 * &= mu^0_k(T_k)(T_k)
700 * + R T_k \ln\left(\frac{P}{P^0}\right) \\
701 * &= h^0_k(T_k) - T_k s^0_k(T_k)
702 * + R T_k \ln\left(\frac{P X_k}{P^0}\right) \\
703 * \end{align}
704 * @f]
705 * Here, @f$ P @f$ is the total pressure of the mixture, as defined in #pressure().
706 */
707 void getStandardChemPotentials(span<double> muStar) const override;
708
709 //! Return the standard molar volumes of the species. Units: m³/kmol.
710 /*!
711 * For a multitemperature system,
712 * @f[
713 * v_k = \frac{R T_k}{P},
714 * @f]
715 * where @f$ T_k @f$ is the temperature at which
716 * the standard molar volume is evaluated.
717 */
718 void getStandardVolumes(span<double> vol) const override;
719
720 //! @}
721 //! @name Thermodynamic Values for the Species Reference States
722 //! @{
723
724 //! Return the reference chemical potentials of the species. Units: J/kmol.
725 /*!
726 * The reference chemical potentials (or reference state Gibbs free energy)
727 * of species *k* is calculated as:
728 * @f[
729 * \mu^0_k(T_k) = h^0_k(T_k) - T_k s^0_k(T_k)
730 * @f]
731 */
732 void getGibbs_ref(span<double> g) const override;
733
734 //! Return the molar volumes of the species reference states. Units: m³/kmol.
735 /*!
736 * The molar volumes of the species reference states of species *k*
737 * is calculated as:
738 * @f[
739 * v^o_k(T_k) = \frac{R T_k}{P^0}
740 * @f]
741 *
742 * @param vol Output vector containing the standard state volumes.
743 * Length: m_kk.
744
745 */
746 void getStandardVolumes_ref(span<double> vol) const override;
747
748 //! @}
749 //! @name Setting the State
750 //!
751 //! For a plasma phase, setting the state requires specifying both
752 //! the heavy-species (gas) temperature and the electron temperature.
753 //! @{
754
755 //! Set the state using an AnyMap containing any combination of properties
756 //! supported by the thermodynamic model
757 /*!
758 * Accepted keys are:
759 * * `X` (mole fractions)
760 * * `Y` (mass fractions)
761 * * `T` or `Tg` or `gas-temperature` [K]
762 * * `Te` or `electron-temperature` [K]
763 * * `P` or `pressure` [Pa]
764 * * `H` or `enthalpy` [J/kg]
765 * * `U` or `internal-energy` [J/kg]
766 * * `S` or `entropy` [J/kg/K]
767 * * `V` or `specific-volume` [m^3/kg]
768 * * `D` or `density` [kg/m^3]
769 *
770 * Composition can be specified as either an AnyMap of species names to
771 * values or as a composition string. All other values can be given as
772 * floating point values in Cantera's default units, or as strings with the
773 * units specified, which will be converted using the Units class.
774 *
775 * If no thermodynamic property pair is given, or only one of temperature or
776 * pressure is given, then 298.15 K and 101325 Pa will be used as necessary
777 * to fully set the state.
778 *
779 * Set the electron temperature first, and call ThermoPhase::setState.
780 */
781 void setState(const AnyMap& state) override;
782
783
784 //! @}
785
786
787protected:
788 //! Update the species reference state thermodynamic functions
789 /*!
790 * This method is called each time a thermodynamic property is requested,
791 * to check whether the internal species properties within the object
792 * need to be updated (like getPartialMolarCp, getEnthalpy_RT, getEntropy_R,
793 * getGibbs_RT, getIntEnergy_RT, getCp_R, and getEnthalpy_RT_ref and alike).
794 * Currently, this updates the species thermo polynomial values for the current
795 * value of the gas temperature for heavy species, and of the electron
796 * temperature for the electron species. A check is made to see if gas
797 * or electron temperatures have changed since the last evaluation.
798 * This object does not contain any persistent data that depends on the
799 * concentration, that needs to be updated. The state object modifies its
800 * concentration dependent information at the time the setMoleFractions()
801 * (or equivalent) call is made.
802 */
803 void updateThermo() const override;
804
805 //! When electron energy distribution changed, plasma properties such as
806 //! electron-collision reaction rates need to be re-evaluated.
808
809 //! When electron energy level changed, plasma properties such as
810 //! electron-collision reaction rates need to be re-evaluate.
811 //! In addition, the cross-sections need to be interpolated at
812 //! the new level.
814
815 //! Check the electron energy levels
816 /*!
817 * The values of electron energy levels need to be positive and
818 * monotonically increasing.
819 */
820 void checkElectronEnergyLevels() const;
821
822 //! Check the electron energy distribution
823 /*!
824 * This method check the electron energy distribution for the criteria
825 * below.
826 *
827 * 1. The values of electron energy distribution cannot be negative.
828 *
829 * 2. If the last value of electron energy distribution is larger
830 * than 0.01, it will raise a warning to suggest using a higher electron
831 * energy levels.
832 */
834
835 //! Set isotropic electron energy distribution
837
838 //! Update electron temperature (K) From energy distribution.
839 //! #m_electronTemp
841
842 //! Electron energy distribution norm
844
845 //! Update interpolated cross section of a collision
846 bool updateInterpolatedCrossSection(size_t k);
847
848 //! Update electron energy distribution difference
850
851 // Electron energy order in the exponential term
852 double m_isotropicShapeFactor = 1.0;
853
854 //! Number of points of electron energy levels
855 size_t m_nPoints = 1001;
856
857 //! electron energy levels [ev]. Length: #m_nPoints
859
860 //! Normalized electron energy distribution vector [-]
861 //! Length: #m_nPoints
862 Eigen::ArrayXd m_electronEnergyDist;
863
864 //! Index of electron species.
866
867 //! Electron temperature [K].
869
870 //! Electron energy distribution type. Can be "isotropic", "discretized" or "Boltzmann-two-term".
871 string m_distributionType = "isotropic";
872
873 //! Numerical quadrature method for electron energy distribution.
874 string m_quadratureMethod = "simpson";
875
876 //! Flag of normalizing electron energy distribution.
878
879 //! Indices of inelastic collisions in m_crossSections.
880 vector<size_t> m_kInelastic;
881
882 //! Indices of elastic collisions in m_crossSections.
883 vector<size_t> m_kElastic;
884
885 //! electric field [V/m].
886 double m_electricField = 0.0;
887
888 //! electric field freq [Hz].
890
891 //! Cross section data. m_crossSections[i][j], where i is the specific process,
892 //! j is the index of vector. Unit: [m^2]
893 vector<vector<double>> m_crossSections;
894
895 //! Electron energy levels corresponding to the cross section data. m_energyLevels[i][j],
896 //! where i is the specific process, j is the index of vector. Unit: [eV]
897 vector<vector<double>> m_energyLevels;
898
899 //! ionization degree for the electron-electron collisions (tmp is the previous one)
900 //double m_ionDegree = 0.0;
901
902 //! Electron energy distribution Difference dF/dε (V^-5/2)
904
905 //! Elastic electron energy loss coefficients (eV m3/s)
906 /*! The elastic electron energy loss coefficient for species k is,
907 * @f[
908 * K_k = \frac{2 m_e}{m_k} \sqrt{\frac{2 e}{m_e}} \int_0^{\infty} \sigma_k
909 * \epsilon^2 \left( F_0 + \frac{k_\text{B} T}{e}
910 * \frac{\partial F_0}{\partial \epsilon} \right) d \epsilon,
911 * @f]
912 * where @f$ m_e @f$ [kg] is the electron mass, @f$ \epsilon @f$ [V] is the
913 * electron energy, @f$ \sigma_k @f$ [m2] is the reaction collision cross section,
914 * @f$ F_0 @f$ [V^(-3/2)] is the normalized electron energy distribution function.
915 */
917
918 //! Updates the elastic electron energy loss coefficient for collision index i
919 /*! Calculates the elastic energy loss coefficient using the current electron
920 energy distribution and cross sections.
921 */
923
924 //! Update elastic electron energy loss coefficients
925 /*! Used by elasticPowerLoss() and other plasma property calculations that
926 depends on #m_elasticElectronEnergyLossCoefficients. This function calls
927 updateInterpolatedCrossSection() before calling
928 updateElasticElectronEnergyLossCoefficient()
929 */
931
932private:
933
934 //! Solver used to calculate the EEDF based on electron collision rates
935 unique_ptr<EEDFTwoTermApproximation> m_eedfSolver = nullptr;
936
937 //! Electron energy distribution change variable. Whenever
938 //! #m_electronEnergyDist changes, this int is incremented.
939 int m_distNum = -1;
940
941 //! Electron energy level change variable. Whenever
942 //! #m_electronEnergyLevels changes, this int is incremented.
943 int m_levelNum = -1;
944
945 //! The list of shared pointers of plasma collision reactions
946 vector<shared_ptr<Reaction>> m_collisions;
947
948 //! The list of shared pointers of collision rates
949 vector<shared_ptr<ElectronCollisionPlasmaRate>> m_collisionRates;
950
951 //! The collision-target species indices of #m_collisions
953
954 //! The list of whether the interpolated cross sections is ready
955 vector<bool> m_interp_cs_ready;
956
957 //! Set collisions. This function sets the list of collisions and
958 //! the list of target species using #addCollision.
959 void setCollisions();
960
961 //! Add a collision and record the target species
962 void addCollision(shared_ptr<Reaction> collision);
963
964 //! Saved electron temperature during an equilibrium solve
966
967 //! Lock flag (default off)
968 bool m_inEquilibrate = false;
969
970 //! Work array
971 mutable std::vector<double> m_work;
972};
973
974}
975
976#endif
EEDF Two-Term approximation solver.
ThermoPhase object for the ideal gas equation of state - workhorse for Cantera (see Thermodynamic Pro...
A map of string keys to values whose type can vary at runtime.
Definition AnyMap.h:431
Class IdealGasPhase represents low-density gases that obey the ideal gas equation of state.
An error indicating that an unimplemented function has been called.
virtual double molarDensity() const
Molar density (kmol/m^3).
Definition Phase.cpp:597
double meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition Phase.h:677
virtual double concentration(const size_t k) const
Concentration of species k.
Definition Phase.cpp:495
string speciesName(size_t k) const
Name of the species with index k.
Definition Phase.cpp:143
virtual void setDensity(const double density_)
Set the internally stored density (kg/m^3) of the phase.
Definition Phase.cpp:607
Base class for handling plasma properties, specifically focusing on the electron energy distribution.
void checkElectronEnergyDistribution() const
Check the electron energy distribution.
void getStandardChemPotentials(span< double > muStar) const override
Return the standard chemical potentials of the species. Units: J/kmol.
vector< vector< double > > m_energyLevels
Electron energy levels corresponding to the cross section data.
void setCollisions()
Set collisions.
double meanElectronEnergy() const
Mean electron energy [eV].
int distributionNumber() const
Return the distribution number m_distNum.
void getGibbs_ref(span< double > g) const override
Return the reference chemical potentials of the species. Units: J/kmol.
double m_electronTempEquil
Saved electron temperature during an equilibrium solve.
double enthalpy_mole() const override
Return the Molar enthalpy. Units: J/kmol.
void setQuadratureMethod(const string &method)
Set numerical quadrature method for integrating electron energy distribution function.
size_t m_nPoints
Number of points of electron energy levels.
void setState(const AnyMap &state) override
Set the state using an AnyMap containing any combination of properties supported by the thermodynamic...
int levelNumber() const
Return the electron energy level number m_levelNum.
void getActivities(span< double > a) const override
Get the array of non-dimensional activities at the current solution temperature, pressure,...
double thermalExpansionCoeff() const override
Raise NotImplementedError, as there is an ambiguity on the temperature to use.
void addCollision(shared_ptr< Reaction > collision)
Add a collision and record the target species.
virtual void setSolution(std::weak_ptr< Solution > soln) override
Set the link to the Solution object that owns this ThermoPhase.
void normalizeElectronEnergyDistribution()
Electron energy distribution norm.
void updateThermo() const override
Update the species reference state thermodynamic functions.
void getPartialMolarEnthalpies(span< double > hbar) const override
Return the partial molar enthalpies of the species in the solution. Units: J/kmol.
vector< size_t > m_targetSpeciesIndices
The collision-target species indices of m_collisions.
void setElectronTemperature(double Te) override
Set the internally stored electron temperature of the phase [K].
void electronEnergyLevelChanged()
When electron energy level changed, plasma properties such as electron-collision reaction rates need ...
double soundSpeed() const override
Raise NotImplementedError, as there is an ambiguity on the temperature to use.
double pressure() const override
Return the pressure of the plasma phase. Units: Pa.
double m_electricFieldFrequency
electric field freq [Hz].
string electronEnergyDistributionType() const
Get electron energy distribution type.
double elasticPowerLoss()
The elastic power loss [J/s/m³].
int m_levelNum
Electron energy level change variable.
bool updateInterpolatedCrossSection(size_t k)
Update interpolated cross section of a collision.
bool m_inEquilibrate
Lock flag (default off)
void electronEnergyDistributionChanged()
When electron energy distribution changed, plasma properties such as electron-collision reaction rate...
void setElectricField(double E)
Set the absolute electric field strength [V/m].
string quadratureMethod() const
Numerical quadrature method. Method: m_quadratureMethod.
double electricFieldFrequency() const
Get the frequency of the applied electric field [Hz].
size_t nElectronEnergyLevels() const
Number of electron levels.
size_t nCollisions() const
Number of electron collision cross sections.
void endEquilibrate() override
Hook called at the end of an equilibrium calculation on this phase.
Eigen::ArrayXd m_electronEnergyDist
Normalized electron energy distribution vector [-] Length: m_nPoints.
double electricField() const
Get the applied electric field strength [V/m].
Eigen::ArrayXd m_electronEnergyLevels
electron energy levels [ev]. Length: m_nPoints
void getActivityCoefficients(span< double > ac) const override
Get the array of non-dimensional activity coefficients at the current solution temperature,...
double meanTemperature() const
Return the mean temperature of the plasma phase. Units: K.
double intrinsicHeating() override
Intrinsic volumetric heating rate [W/m³].
double electronMobility() const
The electron mobility (m²/V/s)
void getParameters(AnyMap &phaseNode) const override
Store the parameters of a ThermoPhase object such that an identical one could be reconstructed using ...
void getElectronEnergyDistribution(span< double > distrb) const
Get electron energy distribution.
string type() const override
String indicating the thermodynamic model implemented.
void checkElectronEnergyLevels() const
Check the electron energy levels.
void initThermo() override
Initialize the ThermoPhase object after all species have been set up.
void updateElasticElectronEnergyLossCoefficients()
Update elastic electron energy loss coefficients.
void updateElectronTemperatureFromEnergyDist()
Update electron temperature (K) From energy distribution.
void setPressure(double p) override
Set the pressure at constant temperature and composition. Units: Pa.
string m_distributionType
Electron energy distribution type. Can be "isotropic", "discretized" or "Boltzmann-two-term".
const vector< size_t > & kElastic() const
Get the indices for elastic electron collisions.
const shared_ptr< ElectronCollisionPlasmaRate > collisionRate(size_t i) const
Get the ElectronCollisionPlasmaRate object associated with electron collision i.
void updateElectronEnergyDistribution()
Update the electron energy distribution.
vector< double > m_elasticElectronEnergyLossCoefficients
Elastic electron energy loss coefficients (eV m3/s)
string m_quadratureMethod
Numerical quadrature method for electron energy distribution.
double m_electricField
electric field [V/m].
void beginEquilibrate() override
Hook called at the beginning of an equilibrium calculation on this phase.
size_t electronSpeciesIndex() const
Electron Species Index.
void setDiscretizedElectronEnergyDist(span< const double > levels, span< const double > distrb)
Set discretized electron energy distribution.
double m_electronTemp
Electron temperature [K].
double RTe() const
Return the Gas Constant multiplied by the current electron temperature [J/kmol].
double intEnergy_mole() const override
Return the molar internal energy. Units: J/kmol.
double entropy_mole() const override
Return the molar entropy. Units: J/kmol/K.
bool m_do_normalizeElectronEnergyDist
Flag of normalizing electron energy distribution.
void updateElectronEnergyDistDifference()
Update electron energy distribution difference.
bool normalizeElectronEnergyDistEnabled() const
Flag of automatically normalize electron energy distribution.
void getElectronEnergyLevels(span< double > levels) const
Get electron energy levels.
void updateElasticElectronEnergyLossCoefficient(size_t i)
Updates the elastic electron energy loss coefficient for collision index i.
vector< size_t > m_kElastic
Indices of elastic collisions in m_crossSections.
void setReducedElectricField(double EN)
Set reduced electric field given in [V·m²].
unique_ptr< EEDFTwoTermApproximation > m_eedfSolver
Solver used to calculate the EEDF based on electron collision rates.
string electronSpeciesName() const
Electron species name.
void setIsotropicElectronEnergyDistribution()
Set isotropic electron energy distribution.
void getPartialMolarVolumes(span< double > vbar) const override
Return the partial molar volumes of the species in the solution. Units: m³/kmol.
Eigen::ArrayXd m_electronEnergyDistDiff
ionization degree for the electron-electron collisions (tmp is the previous one)
void getStandardVolumes(span< double > vol) const override
Return the standard molar volumes of the species. Units: m³/kmol.
double isotropicShapeFactor() const
The shape factor of isotropic electron energy distribution.
void getPartialMolarEntropies(span< double > sbar) const override
Return the partial molar entropies of the species in the solution. Units: J/kmol/K.
double gibbs_mole() const override
Return the molar Gibbs free energy. Units: J/kmol.
double standardConcentration(size_t k=0) const override
Returns the standard concentration , which is used to normalize the generalized concentration.
std::vector< double > m_work
Work array.
double reducedElectricField() const
Calculate the degree of ionization.
bool addSpecies(shared_ptr< Species > spec) override
Add a Species to this Phase.
const shared_ptr< Reaction > collision(size_t i) const
Get the Reaction object associated with electron collision i.
vector< bool > m_interp_cs_ready
The list of whether the interpolated cross sections is ready.
vector< shared_ptr< ElectronCollisionPlasmaRate > > m_collisionRates
The list of shared pointers of collision rates.
void getChemPotentials(span< double > mu) const override
Return the chemical potentials of the species in the solution. Units: J/kmol.
void setElectronEnergyLevels(span< const double > levels)
Set electron energy levels.
size_t targetIndex(size_t i) const
Return the target of a specific process.
vector< shared_ptr< Reaction > > m_collisions
The list of shared pointers of plasma collision reactions.
void setParameters(const AnyMap &phaseNode, const AnyMap &rootNode=AnyMap()) override
Set equation of state parameters from an AnyMap phase description.
void setMeanElectronEnergy(double energy)
Set mean electron energy [eV].
void getStandardVolumes_ref(span< double > vol) const override
Return the molar volumes of the species reference states. Units: m³/kmol.
size_t m_electronSpeciesIndex
Index of electron species.
const vector< size_t > & kInelastic() const
Get the indicies for inelastic electron collisions.
vector< vector< double > > m_crossSections
Cross section data.
void setElectronEnergyDistributionType(const string &type)
Set electron energy distribution type.
virtual double electronPressure() const
Return the electron pressure. Units: Pa.
double jouleHeatingPower() const
The joule heating power (W/m³)
vector< size_t > m_kInelastic
Indices of inelastic collisions in m_crossSections.
double electronTemperature() const override
Electron Temperature [K].
void setIsotropicShapeFactor(double x)
Set the shape factor of isotropic electron energy distribution.
void enableNormalizeElectronEnergyDist(bool enable)
Set flag of automatically normalize electron energy distribution.
void getPartialMolarIntEnergies(span< double > ubar) const override
Return the partial molar internal energies of the species in the solution. Units: J/kmol.
int m_distNum
Electron energy distribution change variable.
const double Boltzmann
Boltzmann constant [J/K].
Definition ct_defs.h:87
const double Avogadro
Avogadro's Number [number/kmol].
Definition ct_defs.h:84
const double GasConstant
Universal Gas Constant [J/kmol/K].
Definition ct_defs.h:123
const double ElectronCharge
Elementary charge [C].
Definition ct_defs.h:93
Namespace for the Cantera kernel.
Definition AnyMap.cpp:595
const size_t npos
index returned by functions to indicate "no position"
Definition ct_defs.h:183