Cantera  3.2.0a5
Loading...
Searching...
No Matches
IonFlow.cpp
Go to the documentation of this file.
1//! @file IonFlow.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
8#include "cantera/oneD/refine.h"
13#include "cantera/base/global.h"
14
15namespace Cantera
16{
17
18IonFlow::IonFlow(ThermoPhase* ph, size_t nsp, size_t points) :
19 Flow1D(ph, nsp, points)
20{
21 warn_deprecated("IonFlow::IonFlow(ThermoPhase*, size_t, size_t)",
22 "To be removed after Cantera 3.2. Use constructor using Solution instead.");
23 _init(ph, nsp, points);
24}
25
26void IonFlow::_init(ThermoPhase* ph, size_t nsp, size_t points)
27{
28 // make a local copy of species charge
29 for (size_t k = 0; k < m_nsp; k++) {
30 m_speciesCharge.push_back(m_thermo->charge(k));
31 }
32
33 // Find indices for charge of species
34 for (size_t k = 0; k < m_nsp; k++){
35 if (m_speciesCharge[k] != 0){
36 m_kCharge.push_back(k);
37 } else {
38 m_kNeutral.push_back(k);
39 }
40 }
41
42 // Find the index of electron
43 if (m_thermo->speciesIndex("E", false) != npos ) {
44 m_kElectron = m_thermo->speciesIndex("E", true);
45 }
46
47 // no bound for electric potential
48 setBounds(c_offset_E, -1.0e20, 1.0e20);
49
50 // Set tighter negative species limit on charged species to avoid
51 // instabilities. Tolerance on electrons is even tighter to account for the
52 // low "molecular" weight.
53 for (size_t k : m_kCharge) {
54 setBounds(c_offset_Y + k, -1e-10, 1.0);
55 }
56 setBounds(c_offset_Y + m_kElectron, -1e-14, 1.0);
57
58 m_refiner->setActive(c_offset_E, false);
60}
61
62IonFlow::IonFlow(shared_ptr<Solution> phase, const string& id, size_t points)
63 : Flow1D(phase, id, points)
64{
65 _init(phase->thermo().get(), phase->thermo()->nSpecies(), points);
67 m_solution->thermo()->addSpeciesLock();
68 m_id = id;
69 m_kin = m_solution->kinetics().get();
70 m_trans = m_solution->transport().get();
71 if (m_trans->transportModel() == "none") {
72 throw CanteraError("IonFlow::IonFlow",
73 "An appropriate transport model\nshould be set when instantiating the "
74 "Solution ('gas') object.");
75 }
76 m_solution->registerChangedCallback(this, [this]() {
77 _setKinetics(m_solution->kinetics());
78 _setTransport(m_solution->transport());
79 });
80}
81
82string IonFlow::domainType() const {
83 if (m_isFree) {
84 return "free-ion-flow";
85 }
86 if (m_usesLambda) {
87 return "axisymmetric-ion-flow";
88 }
89 return "unstrained-ion-flow";
90}
91
92void IonFlow::resize(size_t components, size_t points){
93 Flow1D::resize(components, points);
95}
96
97bool IonFlow::componentActive(size_t n) const
98{
99 if (n == c_offset_E) {
100 return true;
101 } else {
102 return Flow1D::componentActive(n);
103 }
104}
105
106void IonFlow::updateTransport(double* x, size_t j0, size_t j1)
107{
109 for (size_t j = j0; j < j1; j++) {
110 setGasAtMidpoint(x,j);
113 size_t k = m_kElectron;
114 double tlog = log(m_thermo->temperature());
115 m_mobility[k+m_nsp*j] = poly5(tlog, m_mobi_e_fix.data());
116 double rho = m_thermo->density();
117 double wtm = m_thermo->meanMolecularWeight();
118 m_diff[k+m_nsp*j] = m_wt[k]*rho*poly5(tlog, m_diff_e_fix.data())/wtm;
119 }
120 }
121}
122
123void IonFlow::updateDiffFluxes(const double* x, size_t j0, size_t j1)
124{
126 electricFieldMethod(x,j0,j1);
127 } else {
128 frozenIonMethod(x,j0,j1);
129 }
130}
131
132void IonFlow::frozenIonMethod(const double* x, size_t j0, size_t j1)
133{
134 for (size_t j = j0; j < j1; j++) {
135 double dz = z(j+1) - z(j);
136 double sum = 0.0;
137 for (size_t k : m_kNeutral) {
138 m_flux(k,j) = m_diff[k+m_nsp*j];
139 m_flux(k,j) *= (X(x,k,j) - X(x,k,j+1))/dz;
140 sum -= m_flux(k,j);
141 }
142
143 // correction flux to insure that \sum_k Y_k V_k = 0.
144 for (size_t k : m_kNeutral) {
145 m_flux(k,j) += sum*Y(x,k,j);
146 }
147
148 // flux for ions
149 // Set flux to zero to prevent some fast charged species (such electrons)
150 // to run away
151 for (size_t k : m_kCharge) {
152 m_flux(k,j) = 0;
153 }
154 }
155}
156
157void IonFlow::electricFieldMethod(const double* x, size_t j0, size_t j1)
158{
159 for (size_t j = j0; j < j1; j++) {
160 double rho = density(j);
161 double dz = z(j+1) - z(j);
162
163 // mixture-average diffusion
164 for (size_t k = 0; k < m_nsp; k++) {
165 m_flux(k,j) = m_diff[k+m_nsp*j];
166 m_flux(k,j) *= (X(x,k,j) - X(x,k,j+1))/dz;
167 }
168
169 // ambipolar diffusion
170 double E_ambi = E(x,j);
171 for (size_t k : m_kCharge) {
172 double Yav = 0.5 * (Y(x,k,j) + Y(x,k,j+1));
173 double drift = rho * Yav * E_ambi
174 * m_speciesCharge[k] * m_mobility[k+m_nsp*j];
175 m_flux(k,j) += drift;
176 }
177
178 // correction flux
179 double sum_flux = 0.0;
180 for (size_t k = 0; k < m_nsp; k++) {
181 sum_flux -= m_flux(k,j); // total net flux
182 }
183 double sum_ion = 0.0;
184 for (size_t k : m_kCharge) {
185 sum_ion += Y(x,k,j);
186 }
187 // The portion of correction for ions is taken off
188 for (size_t k : m_kNeutral) {
189 m_flux(k,j) += Y(x,k,j) / (1-sum_ion) * sum_flux;
190 }
191 }
192}
193
194void IonFlow::setSolvingStage(const size_t stage)
195{
196 warn_deprecated("IonFlow::setSolvingStage", "To be removed after Cantera 3.2. ",
197 "Use solveElectricField() or fixElectricField() instead");
198 if (stage == 1) {
199 m_do_electric_field = false;
200 } else if (stage == 2) {
201 m_do_electric_field = true;
202 } else {
203 throw CanteraError("IonFlow::setSolvingStage",
204 "solution stage must be set to: "
205 "1) frozenIonMethod, "
206 "2) electricFieldEqnMethod");
207 }
208}
209
210//! Evaluate the electric field equation residual
211void IonFlow::evalElectricField(double* x, double* rsd, int* diag,
212 double rdt, size_t jmin, size_t jmax)
213{
214 Flow1D::evalElectricField(x, rsd, diag, rdt, jmin, jmax);
215 if (!m_do_electric_field) {
216 return;
217 }
218
219 if (jmin == 0) { // left boundary
220 rsd[index(c_offset_E, jmin)] = E(x,jmin);
221 }
222
223 if (jmax == m_points - 1) { // right boundary
224 rsd[index(c_offset_E, jmax)] = dEdz(x,jmax) - rho_e(x,jmax) / epsilon_0;
225 }
226
227 // j0 and j1 are constrained to only interior points
228 size_t j0 = std::max<size_t>(jmin, 1);
229 size_t j1 = std::min(jmax, m_points - 2);
230 for (size_t j = j0; j <= j1; j++) {
231 rsd[index(c_offset_E, j)] = dEdz(x,j) - rho_e(x,j) / epsilon_0;
232 diag[index(c_offset_E, j)] = 0;
233 }
234}
235
236void IonFlow::evalSpecies(double* x, double* rsd, int* diag,
237 double rdt, size_t jmin, size_t jmax)
238{
239 Flow1D::evalSpecies(x, rsd, diag, rdt, jmin, jmax);
240 if (!m_do_electric_field) {
241 return;
242 }
243
244 if (jmin == 0) { // left boundary
245 // enforcing the flux for charged species is difficult
246 // since charged species are also affected by electric
247 // force, so Neumann boundary condition is used.
248 for (size_t k : m_kCharge) {
249 rsd[index(c_offset_Y + k, jmin)] = Y(x,k,jmin) - Y(x,k,jmin + 1);
250 }
251 }
252}
253
255{
256 if (j != npos) {
257 warn_deprecated("IonFlow::solveElectricField", "Argument to be removed after "
258 "Cantera 3.2.");
259 }
260 if (!m_do_electric_field) {
262 }
263 m_refiner->setActive(c_offset_U, true);
264 m_refiner->setActive(c_offset_V, true);
265 m_refiner->setActive(c_offset_T, true);
266 m_refiner->setActive(c_offset_E, true);
267 m_do_electric_field = true;
268}
269
271{
272 if (j != npos) {
273 warn_deprecated("IonFlow::fixElectricField", "Argument to be removed after "
274 "Cantera 3.2.");
275 }
278 }
279 m_refiner->setActive(c_offset_U, false);
280 m_refiner->setActive(c_offset_V, false);
281 m_refiner->setActive(c_offset_T, false);
282 m_refiner->setActive(c_offset_E, false);
283 m_do_electric_field = false;
284}
285
286void IonFlow::setElectronTransport(vector<double>& tfix, vector<double>& diff_e,
287 vector<double>& mobi_e)
288{
290 size_t degree = 5;
291 size_t n = tfix.size();
292 vector<double> tlog;
293 for (size_t i = 0; i < n; i++) {
294 tlog.push_back(log(tfix[i]));
295 }
296 vector<double> w(n, -1.0);
297 m_diff_e_fix.resize(degree + 1);
298 m_mobi_e_fix.resize(degree + 1);
299 polyfit(n, degree, tlog.data(), diff_e.data(), w.data(), m_diff_e_fix.data());
300 polyfit(n, degree, tlog.data(), mobi_e.data(), w.data(), m_mobi_e_fix.data());
301}
302
303}
Headers for the Transport object, which is the virtual base class for all transport property evaluato...
Base class for exceptions thrown by Cantera classes.
shared_ptr< Solution > m_solution
Composite thermo/kinetics/transport handler.
Definition Domain1D.h:862
string id() const
Returns the identifying tag for this domain.
Definition Domain1D.h:718
double z(size_t jlocal) const
Get the coordinate [m] of the point with local index jlocal
Definition Domain1D.h:731
size_t m_points
Number of grid points.
Definition Domain1D.h:825
string m_id
Identity tag for the domain.
Definition Domain1D.h:855
unique_ptr< Refiner > m_refiner
Refiner object used for placing grid points.
Definition Domain1D.h:856
void setBounds(size_t n, double lower, double upper)
Set the upper and lower bounds for a solution component, n.
Definition Domain1D.h:268
void needJacUpdate()
Set this if something has changed in the governing equations (for example, the value of a constant ha...
Definition Domain1D.cpp:135
size_t index(size_t n, size_t j) const
Returns the index of the solution vector, which corresponds to component n at grid point j.
Definition Domain1D.h:408
This class represents 1D flow domains that satisfy the one-dimensional similarity solution for chemic...
Definition Flow1D.h:47
ThermoPhase * m_thermo
Phase object used for calculating thermodynamic properties.
Definition Flow1D.h:969
double density(size_t j) const
Get the density [kg/m³] at point j
Definition Flow1D.h:425
double X(const double *x, size_t k, size_t j) const
Get the mole fraction of species k at point j from the local state vector x.
Definition Flow1D.h:780
ThermoPhase & phase()
Access the phase object used to compute thermodynamic properties for points in this domain.
Definition Flow1D.h:93
Kinetics * m_kin
Kinetics object used for calculating species production rates.
Definition Flow1D.h:972
void resize(size_t components, size_t points) override
Change the grid size. Called after grid refinement.
Definition Flow1D.cpp:205
bool m_usesLambda
Flag that is true for counterflow configurations that use the pressure eigenvalue in the radial mome...
Definition Flow1D.h:1026
void _setTransport(shared_ptr< Transport > trans) override
Update transport model to existing instance.
Definition Flow1D.cpp:185
vector< double > m_diff
Coefficient used in diffusion calculations for each species at each grid point.
Definition Flow1D.h:945
Array2D m_flux
Array of size m_nsp by m_points for saving diffusive mass fluxes.
Definition Flow1D.h:955
Transport * m_trans
Transport object used for calculating transport properties.
Definition Flow1D.h:975
virtual bool componentActive(size_t n) const
Returns true if the specified component is an active part of the solver state.
Definition Flow1D.cpp:912
void _setKinetics(shared_ptr< Kinetics > kin) override
Update transport model to existing instance.
Definition Flow1D.cpp:171
virtual void evalSpecies(double *x, double *rsd, int *diag, double rdt, size_t jmin, size_t jmax)
Evaluate the species equations' residuals.
Definition Flow1D.cpp:786
vector< double > m_wt
Molecular weight of each species.
Definition Flow1D.h:932
double Y(const double *x, size_t k, size_t j) const
Get the mass fraction of species k at point j from the local state vector x.
Definition Flow1D.h:763
bool m_isFree
Flag that is true for freely propagating flames anchored by a temperature fixed point.
Definition Flow1D.h:1021
virtual void evalElectricField(double *x, double *rsd, int *diag, double rdt, size_t jmin, size_t jmax)
Evaluate the electric field equation residual to be zero everywhere.
Definition Flow1D.cpp:826
size_t m_nsp
Number of species in the mechanism.
Definition Flow1D.h:966
void setGasAtMidpoint(const double *x, size_t j)
Set the gas state to be consistent with the solution at the midpoint between j and j + 1.
Definition Flow1D.cpp:297
virtual void updateTransport(double *x, size_t j0, size_t j1)
Update the transport properties at grid points in the range from j0 to j1, based on solution x.
Definition Flow1D.cpp:424
vector< size_t > m_kCharge
index of species with charges
Definition IonFlow.h:143
vector< double > m_diff_e_fix
Coefficients of polynomial fit for electron diffusivity as a function of temperature.
Definition IonFlow.h:156
void electricFieldMethod(const double *x, size_t j0, size_t j1)
Solving phase two: the electric field equation is added coupled by the electrical drift.
Definition IonFlow.cpp:157
double E(const double *x, size_t j) const
electric field [V/m]
Definition IonFlow.h:165
size_t m_kElectron
index of electron
Definition IonFlow.h:162
void frozenIonMethod(const double *x, size_t j0, size_t j1)
Solving phase one: the fluxes of charged species are turned off and the electric field is not solved.
Definition IonFlow.cpp:132
void resize(size_t components, size_t points) override
Change the grid size. Called after grid refinement.
Definition IonFlow.cpp:92
bool m_do_electric_field
flag for solving electric field or not
Definition IonFlow.h:134
void setElectronTransport(vector< double > &tfix, vector< double > &diff_e, vector< double > &mobi_e)
Sometimes it is desired to carry out the simulation using a specified electron transport profile,...
Definition IonFlow.cpp:286
void evalElectricField(double *x, double *rsd, int *diag, double rdt, size_t jmin, size_t jmax) override
Evaluate the electric field equation residual by Gauss's law.
Definition IonFlow.cpp:211
double rho_e(double *x, size_t j) const
total charge density
Definition IonFlow.h:180
void updateTransport(double *x, size_t j0, size_t j1) override
Update the transport properties at grid points in the range from j0 to j1, based on solution x.
Definition IonFlow.cpp:106
void _init(ThermoPhase *ph, size_t nsp, size_t points)
Initialize arrays.
Definition IonFlow.cpp:26
vector< double > m_mobility
mobility
Definition IonFlow.h:159
double dEdz(const double *x, size_t j) const
Axial gradient of the electric field [V/m²].
Definition IonFlow.h:170
void updateDiffFluxes(const double *x, size_t j0, size_t j1) override
Update the diffusive mass fluxes.
Definition IonFlow.cpp:123
void evalSpecies(double *x, double *rsd, int *diag, double rdt, size_t jmin, size_t jmax) override
Evaluate the species equations' residual.
Definition IonFlow.cpp:236
void setSolvingStage(const size_t stage) override
Solving stage mode for handling ionized species (used by IonFlow specialization)
Definition IonFlow.cpp:194
bool m_import_electron_transport
flag for importing transport of electron
Definition IonFlow.h:137
void solveElectricField(size_t j=npos) override
Set to solve electric field in a point (used by IonFlow specialization)
Definition IonFlow.cpp:254
void fixElectricField(size_t j=npos) override
Set to fix voltage in a point (used by IonFlow specialization)
Definition IonFlow.cpp:270
string domainType() const override
Domain type flag.
Definition IonFlow.cpp:82
vector< size_t > m_kNeutral
index of neutral species
Definition IonFlow.h:146
vector< double > m_mobi_e_fix
Coefficients of polynomial fit for electron mobility as a function of temperature.
Definition IonFlow.h:151
IonFlow(ThermoPhase *ph=0, size_t nsp=1, size_t points=1)
Create a new IonFlow domain.
Definition IonFlow.cpp:18
bool componentActive(size_t n) const override
Returns true if the specified component is an active part of the solver state.
Definition IonFlow.cpp:97
vector< double > m_speciesCharge
electrical properties
Definition IonFlow.h:140
size_t nSpecies() const
Returns the number of species in the phase.
Definition Phase.h:270
double temperature() const
Temperature (K).
Definition Phase.h:629
double meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition Phase.h:722
size_t speciesIndex(const string &name) const
Returns the index of a species named 'name' within the Phase object.
Definition Phase.cpp:147
virtual double density() const
Density (kg/m^3).
Definition Phase.h:654
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:605
Base class for a phase with thermodynamic properties.
virtual string transportModel() const
Identifies the model represented by this Transport object.
Definition Transport.h:101
virtual void getMobilities(double *const mobil_e)
Get the electrical mobilities [m²/V/s].
Definition Transport.h:185
Header for a file containing miscellaneous numerical functions.
This file contains definitions for utility functions and text for modules, inputfiles and logging,...
R poly5(D x, R *c)
Templated evaluation of a polynomial of order 5.
Definition utilities.h:141
double polyfit(size_t n, size_t deg, const double *xp, const double *yp, const double *wp, double *pp)
Fits a polynomial function to a set of data points.
Definition polyfit.cpp:14
const double epsilon_0
Permittivity of free space [F/m].
Definition ct_defs.h:137
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:180
@ c_offset_U
axial velocity [m/s]
Definition Flow1D.h:26
@ c_offset_V
strain rate
Definition Flow1D.h:27
@ c_offset_E
electric field
Definition Flow1D.h:30
@ c_offset_Y
mass fractions
Definition Flow1D.h:32
@ c_offset_T
temperature [kelvin]
Definition Flow1D.h:28
void warn_deprecated(const string &source, const AnyBase &node, const string &message)
A deprecation warning for syntax in an input file.
Definition AnyMap.cpp:1997
Various templated functions that carry out common vector and polynomial operations (see Templated Arr...