Cantera  3.3.0a1
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(shared_ptr<Solution> phase, const string& id, size_t points)
19 : Flow1D(phase, id, points)
20{
21 // make a local copy of species charge
22 for (size_t k = 0; k < m_nsp; k++) {
23 m_speciesCharge.push_back(m_thermo->charge(k));
24 }
25
26 // Find indices for charge of species
27 for (size_t k = 0; k < m_nsp; k++){
28 if (m_speciesCharge[k] != 0){
29 m_kCharge.push_back(k);
30 } else {
31 m_kNeutral.push_back(k);
32 }
33 }
34
35 // Find the index of electron
36 if (m_thermo->speciesIndex("E", false) != npos ) {
37 m_kElectron = m_thermo->speciesIndex("E", true);
38 }
39
40 // no bound for electric potential
41 setBounds(c_offset_E, -1.0e20, 1.0e20);
42
43 // Set tighter negative species limit on charged species to avoid
44 // instabilities. Tolerance on electrons is even tighter to account for the
45 // low "molecular" weight.
46 for (size_t k : m_kCharge) {
47 setBounds(c_offset_Y + k, -1e-10, 1.0);
48 }
49 setBounds(c_offset_Y + m_kElectron, -1e-14, 1.0);
50
51 m_refiner->setActive(c_offset_E, false);
53
55 m_solution->thermo()->addSpeciesLock();
56 m_id = id;
57 m_kin = m_solution->kinetics().get();
58 m_trans = m_solution->transport().get();
59 if (m_trans->transportModel() == "none") {
60 throw CanteraError("IonFlow::IonFlow",
61 "An appropriate transport model\nshould be set when instantiating the "
62 "Solution ('gas') object.");
63 }
64 m_solution->registerChangedCallback(this, [this]() {
65 _setKinetics(m_solution->kinetics());
66 _setTransport(m_solution->transport());
67 });
68}
69
70string IonFlow::domainType() const {
71 if (m_isFree) {
72 return "free-ion-flow";
73 }
74 if (m_usesLambda) {
75 return "axisymmetric-ion-flow";
76 }
77 return "unstrained-ion-flow";
78}
79
80void IonFlow::resize(size_t components, size_t points){
81 Flow1D::resize(components, points);
83}
84
85bool IonFlow::componentActive(size_t n) const
86{
87 if (n == c_offset_E) {
88 return true;
89 } else {
91 }
92}
93
94void IonFlow::updateTransport(double* x, size_t j0, size_t j1)
95{
97 for (size_t j = j0; j < j1; j++) {
101 size_t k = m_kElectron;
102 double tlog = log(m_thermo->temperature());
103 m_mobility[k+m_nsp*j] = poly5(tlog, m_mobi_e_fix.data());
104 double rho = m_thermo->density();
105 double wtm = m_thermo->meanMolecularWeight();
106 m_diff[k+m_nsp*j] = m_wt[k]*rho*poly5(tlog, m_diff_e_fix.data())/wtm;
107 }
108 }
109}
110
111void IonFlow::updateDiffFluxes(const double* x, size_t j0, size_t j1)
112{
114 electricFieldMethod(x,j0,j1);
115 } else {
116 frozenIonMethod(x,j0,j1);
117 }
118}
119
120void IonFlow::frozenIonMethod(const double* x, size_t j0, size_t j1)
121{
122 for (size_t j = j0; j < j1; j++) {
123 double dz = z(j+1) - z(j);
124 double sum = 0.0;
125 for (size_t k : m_kNeutral) {
126 m_flux(k,j) = m_diff[k+m_nsp*j];
127 m_flux(k,j) *= (X(x,k,j) - X(x,k,j+1))/dz;
128 sum -= m_flux(k,j);
129 }
130
131 // correction flux to insure that \sum_k Y_k V_k = 0.
132 for (size_t k : m_kNeutral) {
133 m_flux(k,j) += sum*Y(x,k,j);
134 }
135
136 // flux for ions
137 // Set flux to zero to prevent some fast charged species (such electrons)
138 // to run away
139 for (size_t k : m_kCharge) {
140 m_flux(k,j) = 0;
141 }
142 }
143}
144
145void IonFlow::electricFieldMethod(const double* x, size_t j0, size_t j1)
146{
147 for (size_t j = j0; j < j1; j++) {
148 double rho = density(j);
149 double dz = z(j+1) - z(j);
150
151 // mixture-average diffusion
152 for (size_t k = 0; k < m_nsp; k++) {
153 m_flux(k,j) = m_diff[k+m_nsp*j];
154 m_flux(k,j) *= (X(x,k,j) - X(x,k,j+1))/dz;
155 }
156
157 // ambipolar diffusion
158 double E_ambi = E(x,j);
159 for (size_t k : m_kCharge) {
160 double Yav = 0.5 * (Y(x,k,j) + Y(x,k,j+1));
161 double drift = rho * Yav * E_ambi
162 * m_speciesCharge[k] * m_mobility[k+m_nsp*j];
163 m_flux(k,j) += drift;
164 }
165
166 // correction flux
167 double sum_flux = 0.0;
168 for (size_t k = 0; k < m_nsp; k++) {
169 sum_flux -= m_flux(k,j); // total net flux
170 }
171 double sum_ion = 0.0;
172 for (size_t k : m_kCharge) {
173 sum_ion += Y(x,k,j);
174 }
175 // The portion of correction for ions is taken off
176 for (size_t k : m_kNeutral) {
177 m_flux(k,j) += Y(x,k,j) / (1-sum_ion) * sum_flux;
178 }
179 }
180}
181
182//! Evaluate the electric field equation residual
183void IonFlow::evalElectricField(double* x, double* rsd, int* diag,
184 double rdt, size_t jmin, size_t jmax)
185{
186 Flow1D::evalElectricField(x, rsd, diag, rdt, jmin, jmax);
187 if (!m_do_electric_field) {
188 return;
189 }
190
191 if (jmin == 0) { // left boundary
192 rsd[index(c_offset_E, jmin)] = E(x,jmin);
193 }
194
195 if (jmax == m_points - 1) { // right boundary
196 rsd[index(c_offset_E, jmax)] = dEdz(x,jmax) - rho_e(x,jmax) / epsilon_0;
197 }
198
199 // j0 and j1 are constrained to only interior points
200 size_t j0 = std::max<size_t>(jmin, 1);
201 size_t j1 = std::min(jmax, m_points - 2);
202 for (size_t j = j0; j <= j1; j++) {
203 rsd[index(c_offset_E, j)] = dEdz(x,j) - rho_e(x,j) / epsilon_0;
204 diag[index(c_offset_E, j)] = 0;
205 }
206}
207
208void IonFlow::evalSpecies(double* x, double* rsd, int* diag,
209 double rdt, size_t jmin, size_t jmax)
210{
211 Flow1D::evalSpecies(x, rsd, diag, rdt, jmin, jmax);
212 if (!m_do_electric_field) {
213 return;
214 }
215
216 if (jmin == 0) { // left boundary
217 // enforcing the flux for charged species is difficult
218 // since charged species are also affected by electric
219 // force, so Neumann boundary condition is used.
220 for (size_t k : m_kCharge) {
221 rsd[index(c_offset_Y + k, jmin)] = Y(x,k,jmin) - Y(x,k,jmin + 1);
222 }
223 }
224}
225
227{
228 if (!m_do_electric_field) {
230 }
231 m_refiner->setActive(c_offset_U, true);
232 m_refiner->setActive(c_offset_V, true);
233 m_refiner->setActive(c_offset_T, true);
234 m_refiner->setActive(c_offset_E, true);
235 m_do_electric_field = true;
236}
237
239{
242 }
243 m_refiner->setActive(c_offset_U, false);
244 m_refiner->setActive(c_offset_V, false);
245 m_refiner->setActive(c_offset_T, false);
246 m_refiner->setActive(c_offset_E, false);
247 m_do_electric_field = false;
248}
249
250void IonFlow::setElectronTransport(vector<double>& tfix, vector<double>& diff_e,
251 vector<double>& mobi_e)
252{
254 size_t degree = 5;
255 size_t n = tfix.size();
256 vector<double> tlog;
257 for (size_t i = 0; i < n; i++) {
258 tlog.push_back(log(tfix[i]));
259 }
260 vector<double> w(n, -1.0);
261 m_diff_e_fix.resize(degree + 1);
262 m_mobi_e_fix.resize(degree + 1);
263 polyfit(n, degree, tlog.data(), diff_e.data(), w.data(), m_diff_e_fix.data());
264 polyfit(n, degree, tlog.data(), mobi_e.data(), w.data(), m_mobi_e_fix.data());
265}
266
267}
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:713
string id() const
Returns the identifying tag for this domain.
Definition Domain1D.h:575
double z(size_t jlocal) const
Get the coordinate [m] of the point with local index jlocal
Definition Domain1D.h:588
size_t m_points
Number of grid points.
Definition Domain1D.h:676
string m_id
Identity tag for the domain.
Definition Domain1D.h:706
unique_ptr< Refiner > m_refiner
Refiner object used for placing grid points.
Definition Domain1D.h:707
void setBounds(size_t n, double lower, double upper)
Set the upper and lower bounds for a solution component, n.
Definition Domain1D.h:190
void needJacUpdate()
Set this if something has changed in the governing equations (for example, the value of a constant ha...
Definition Domain1D.cpp:119
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:330
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:914
double density(size_t j) const
Get the density [kg/m³] at point j
Definition Flow1D.h:377
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:727
ThermoPhase & phase()
Access the phase object used to compute thermodynamic properties for points in this domain.
Definition Flow1D.h:69
Kinetics * m_kin
Kinetics object used for calculating species production rates.
Definition Flow1D.h:917
void resize(size_t components, size_t points) override
Change the grid size. Called after grid refinement.
Definition Flow1D.cpp:149
bool m_usesLambda
Flag that is true for counterflow configurations that use the pressure eigenvalue in the radial mome...
Definition Flow1D.h:971
void _setTransport(shared_ptr< Transport > trans) override
Update transport model to existing instance.
Definition Flow1D.cpp:129
vector< double > m_diff
Coefficient used in diffusion calculations for each species at each grid point.
Definition Flow1D.h:890
Array2D m_flux
Array of size m_nsp by m_points for saving diffusive mass fluxes.
Definition Flow1D.h:900
Transport * m_trans
Transport object used for calculating transport properties.
Definition Flow1D.h:920
virtual bool componentActive(size_t n) const
Returns true if the specified component is an active part of the solver state.
Definition Flow1D.cpp:856
void _setKinetics(shared_ptr< Kinetics > kin) override
Update transport model to existing instance.
Definition Flow1D.cpp:123
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:730
vector< double > m_wt
Molecular weight of each species.
Definition Flow1D.h:877
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:710
bool m_isFree
Flag that is true for freely propagating flames anchored by a temperature fixed point.
Definition Flow1D.h:966
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:770
size_t m_nsp
Number of species in the mechanism.
Definition Flow1D.h:911
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:241
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:368
vector< size_t > m_kCharge
index of species with charges
Definition IonFlow.h:117
vector< double > m_diff_e_fix
Coefficients of polynomial fit for electron diffusivity as a function of temperature.
Definition IonFlow.h:130
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:145
double E(const double *x, size_t j) const
electric field [V/m]
Definition IonFlow.h:139
IonFlow(shared_ptr< Solution > phase, const string &id="", size_t points=1)
Create a new IonFlow domain.
Definition IonFlow.cpp:18
size_t m_kElectron
index of electron
Definition IonFlow.h:136
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:120
void resize(size_t components, size_t points) override
Change the grid size. Called after grid refinement.
Definition IonFlow.cpp:80
bool m_do_electric_field
flag for solving electric field or not
Definition IonFlow.h:108
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:250
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:183
double rho_e(double *x, size_t j) const
total charge density
Definition IonFlow.h:154
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:94
vector< double > m_mobility
mobility
Definition IonFlow.h:133
double dEdz(const double *x, size_t j) const
Axial gradient of the electric field [V/m²].
Definition IonFlow.h:144
void fixElectricField() override
Set to fix voltage in a point (used by IonFlow specialization)
Definition IonFlow.cpp:238
void updateDiffFluxes(const double *x, size_t j0, size_t j1) override
Update the diffusive mass fluxes.
Definition IonFlow.cpp:111
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:208
bool m_import_electron_transport
flag for importing transport of electron
Definition IonFlow.h:111
string domainType() const override
Domain type flag.
Definition IonFlow.cpp:70
vector< size_t > m_kNeutral
index of neutral species
Definition IonFlow.h:120
vector< double > m_mobi_e_fix
Coefficients of polynomial fit for electron mobility as a function of temperature.
Definition IonFlow.h:125
void solveElectricField() override
Set to solve electric field in a point (used by IonFlow specialization)
Definition IonFlow.cpp:226
bool componentActive(size_t n) const override
Returns true if the specified component is an active part of the solver state.
Definition IonFlow.cpp:85
vector< double > m_speciesCharge
electrical properties
Definition IonFlow.h:114
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 temperature() const
Temperature (K).
Definition Phase.h:598
double meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition Phase.h:691
virtual double density() const
Density (kg/m^3).
Definition Phase.h:623
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:574
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:179
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
Various templated functions that carry out common vector and polynomial operations (see Templated Arr...