Cantera  3.0.0
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 StFlow(ph, nsp, 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") != npos ) {
37 m_kElectron = m_thermo->speciesIndex("E");
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-14, 1.0);
48 }
49 setBounds(c_offset_Y + m_kElectron, -1e-18, 1.0);
50
51 m_refiner->setActive(c_offset_E, false);
52 m_mobility.resize(m_nsp*m_points);
53 m_do_electric_field.resize(m_points,false);
54}
55
56IonFlow::IonFlow(shared_ptr<Solution> sol, const string& id, size_t points)
57 : IonFlow(sol->thermo().get(), sol->thermo()->nSpecies(), points)
58{
59 m_solution = sol;
60 m_id = id;
61 m_kin = m_solution->kinetics().get();
62 m_trans = m_solution->transport().get();
63 if (m_trans->transportModel() == "none") {
64 // @deprecated
65 warn_deprecated("IonFlow",
66 "An appropriate transport model\nshould be set when instantiating the "
67 "Solution ('gas') object.\nImplicit setting of the transport model "
68 "is deprecated and\nwill be removed after Cantera 3.0.");
69 setTransportModel("ionized-gas");
70 }
71 m_solution->registerChangedCallback(this, [this]() {
72 setKinetics(m_solution->kinetics());
73 setTransport(m_solution->transport());
74 });
75}
76
77string IonFlow::type() const {
78 if (m_isFree) {
79 return "free-ion-flow";
80 }
81 if (m_usesLambda) {
82 return "axisymmetric-ion-flow";
83 }
84 return "unstrained-ion-flow";
85}
86
87void IonFlow::resize(size_t components, size_t points){
88 StFlow::resize(components, points);
90 m_do_species.resize(m_nsp,true);
91 m_do_electric_field.resize(m_points,false);
92}
93
94bool IonFlow::componentActive(size_t n) const
95{
96 if (n == c_offset_E) {
97 return true;
98 } else {
100 }
101}
102
103void IonFlow::updateTransport(double* x, size_t j0, size_t j1)
104{
106 for (size_t j = j0; j < j1; j++) {
107 setGasAtMidpoint(x,j);
108 m_trans->getMobilities(&m_mobility[j*m_nsp]);
110 size_t k = m_kElectron;
111 double tlog = log(m_thermo->temperature());
112 m_mobility[k+m_nsp*j] = poly5(tlog, m_mobi_e_fix.data());
113 m_diff[k+m_nsp*j] = poly5(tlog, m_diff_e_fix.data());
114 }
115 }
116}
117
118void IonFlow::updateDiffFluxes(const double* x, size_t j0, size_t j1)
119{
120 if (m_stage == 1) {
121 frozenIonMethod(x,j0,j1);
122 }
123 if (m_stage == 2) {
124 electricFieldMethod(x,j0,j1);
125 }
126}
127
128void IonFlow::frozenIonMethod(const double* x, size_t j0, size_t j1)
129{
130 for (size_t j = j0; j < j1; j++) {
131 double wtm = m_wtm[j];
132 double rho = density(j);
133 double dz = z(j+1) - z(j);
134 double sum = 0.0;
135 for (size_t k : m_kNeutral) {
136 m_flux(k,j) = m_wt[k]*(rho*m_diff[k+m_nsp*j]/wtm);
137 m_flux(k,j) *= (X(x,k,j) - X(x,k,j+1))/dz;
138 sum -= m_flux(k,j);
139 }
140
141 // correction flux to insure that \sum_k Y_k V_k = 0.
142 for (size_t k : m_kNeutral) {
143 m_flux(k,j) += sum*Y(x,k,j);
144 }
145
146 // flux for ions
147 // Set flux to zero to prevent some fast charged species (such electrons)
148 // to run away
149 for (size_t k : m_kCharge) {
150 m_flux(k,j) = 0;
151 }
152 }
153}
154
155void IonFlow::electricFieldMethod(const double* x, size_t j0, size_t j1)
156{
157 for (size_t j = j0; j < j1; j++) {
158 double wtm = m_wtm[j];
159 double rho = density(j);
160 double dz = z(j+1) - z(j);
161
162 // mixture-average diffusion
163 for (size_t k = 0; k < m_nsp; k++) {
164 m_flux(k,j) = m_wt[k]*(rho*m_diff[k+m_nsp*j]/wtm);
165 m_flux(k,j) *= (X(x,k,j) - X(x,k,j+1))/dz;
166 }
167
168 // ambipolar diffusion
169 double E_ambi = E(x,j);
170 for (size_t k : m_kCharge) {
171 double Yav = 0.5 * (Y(x,k,j) + Y(x,k,j+1));
172 double drift = rho * Yav * E_ambi
173 * m_speciesCharge[k] * m_mobility[k+m_nsp*j];
174 m_flux(k,j) += drift;
175 }
176
177 // correction flux
178 double sum_flux = 0.0;
179 for (size_t k = 0; k < m_nsp; k++) {
180 sum_flux -= m_flux(k,j); // total net flux
181 }
182 double sum_ion = 0.0;
183 for (size_t k : m_kCharge) {
184 sum_ion += Y(x,k,j);
185 }
186 // The portion of correction for ions is taken off
187 for (size_t k : m_kNeutral) {
188 m_flux(k,j) += Y(x,k,j) / (1-sum_ion) * sum_flux;
189 }
190 }
191}
192
193void IonFlow::setSolvingStage(const size_t stage)
194{
195 if (stage == 1 || stage == 2) {
196 m_stage = stage;
197 } else {
198 throw CanteraError("IonFlow::setSolvingStage",
199 "solution stage must be set to: "
200 "1) frozenIonMethod, "
201 "2) electricFieldEqnMethod");
202 }
203}
204
205void IonFlow::evalResidual(double* x, double* rsd, int* diag,
206 double rdt, size_t jmin, size_t jmax)
207{
208 StFlow::evalResidual(x, rsd, diag, rdt, jmin, jmax);
209 if (m_stage != 2) {
210 return;
211 }
212
213 for (size_t j = jmin; j <= jmax; j++) {
214 if (j == 0) {
215 // enforcing the flux for charged species is difficult
216 // since charged species are also affected by electric
217 // force, so Neumann boundary condition is used.
218 for (size_t k : m_kCharge) {
219 rsd[index(c_offset_Y + k, 0)] = Y(x,k,0) - Y(x,k,1);
220 }
221 rsd[index(c_offset_E, j)] = E(x,0);
222 diag[index(c_offset_E, j)] = 0;
223 } else if (j == m_points - 1) {
224 rsd[index(c_offset_E, j)] = dEdz(x,j) - rho_e(x,j) / epsilon_0;
225 diag[index(c_offset_E, j)] = 0;
226 } else {
227 //-----------------------------------------------
228 // Electric field by Gauss's law
229 //
230 // dE/dz = e/eps_0 * sum(q_k*n_k)
231 //
232 // E = -dV/dz
233 //-----------------------------------------------
234 rsd[index(c_offset_E, j)] = dEdz(x,j) - rho_e(x,j) / epsilon_0;
235 diag[index(c_offset_E, j)] = 0;
236 }
237 }
238}
239
241{
242 bool changed = false;
243 if (j == npos) {
244 for (size_t i = 0; i < m_points; i++) {
245 if (!m_do_electric_field[i]) {
246 changed = true;
247 }
248 m_do_electric_field[i] = true;
249 }
250 } else {
251 if (!m_do_electric_field[j]) {
252 changed = true;
253 }
254 m_do_electric_field[j] = true;
255 }
256 m_refiner->setActive(c_offset_U, true);
257 m_refiner->setActive(c_offset_V, true);
258 m_refiner->setActive(c_offset_T, true);
259 m_refiner->setActive(c_offset_E, true);
260 if (changed) {
262 }
263}
264
266{
267 bool changed = false;
268 if (j == npos) {
269 for (size_t i = 0; i < m_points; i++) {
270 if (m_do_electric_field[i]) {
271 changed = true;
272 }
273 m_do_electric_field[i] = false;
274 }
275 } else {
276 if (m_do_electric_field[j]) {
277 changed = true;
278 }
279 m_do_electric_field[j] = false;
280 }
281 m_refiner->setActive(c_offset_U, false);
282 m_refiner->setActive(c_offset_V, false);
283 m_refiner->setActive(c_offset_T, false);
284 m_refiner->setActive(c_offset_E, false);
285 if (changed) {
287 }
288}
289
290void IonFlow::setElectronTransport(vector<double>& tfix, vector<double>& diff_e,
291 vector<double>& mobi_e)
292{
294 size_t degree = 5;
295 size_t n = tfix.size();
296 vector<double> tlog;
297 for (size_t i = 0; i < n; i++) {
298 tlog.push_back(log(tfix[i]));
299 }
300 vector<double> w(n, -1.0);
301 m_diff_e_fix.resize(degree + 1);
302 m_mobi_e_fix.resize(degree + 1);
303 polyfit(n, degree, tlog.data(), diff_e.data(), w.data(), m_diff_e_fix.data());
304 polyfit(n, degree, tlog.data(), mobi_e.data(), w.data(), m_mobi_e_fix.data());
305}
306
307void IonFlow::_finalize(const double* x)
308{
310
311 bool p = m_do_electric_field[0];
312 if (p) {
314 }
315}
316
317}
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:609
size_t m_points
Number of grid points.
Definition Domain1D.h:578
string m_id
Identity tag for the domain.
Definition Domain1D.h:602
void needJacUpdate()
Set this if something has changed in the governing equations (for example, the value of a constant ha...
Definition Domain1D.cpp:102
This class models the ion transportation in a flame.
Definition IonFlow.h:29
vector< size_t > m_kCharge
index of species with charges
Definition IonFlow.h:93
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:155
double E(const double *x, size_t j) const
electric field
Definition IonFlow.h:112
void evalResidual(double *x, double *rsd, int *diag, double rdt, size_t jmin, size_t jmax) override
Definition IonFlow.cpp:205
vector< bool > m_do_electric_field
flag for solving electric field or not
Definition IonFlow.h:84
size_t m_kElectron
index of electron
Definition IonFlow.h:109
void frozenIonMethod(const double *x, size_t j0, size_t j1)
Solving phase one: the fluxes of charged species are turned off.
Definition IonFlow.cpp:128
void resize(size_t components, size_t points) override
Resize the domain to have nv components and np grid points.
Definition IonFlow.cpp:87
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:290
string type() const override
String indicating the domain implemented.
Definition IonFlow.cpp:77
double rho_e(double *x, size_t j) const
total charge density
Definition IonFlow.h:126
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:103
vector< double > m_mobility
mobility
Definition IonFlow.h:103
void updateDiffFluxes(const double *x, size_t j0, size_t j1) override
Update the diffusive mass fluxes.
Definition IonFlow.cpp:118
size_t m_stage
solving stage
Definition IonFlow.h:106
void _finalize(const double *x) override
In some cases, a domain may need to set parameters that depend on the initial solution estimate.
Definition IonFlow.cpp:307
void setSolvingStage(const size_t stage) override
Solving stage mode for handling ionized species (used by IonFlow specialization)
Definition IonFlow.cpp:193
bool m_import_electron_transport
flag for importing transport of electron
Definition IonFlow.h:87
void solveElectricField(size_t j=npos) override
Set to solve electric field in a point (used by IonFlow specialization)
Definition IonFlow.cpp:240
void fixElectricField(size_t j=npos) override
Set to fix voltage in a point (used by IonFlow specialization)
Definition IonFlow.cpp:265
vector< size_t > m_kNeutral
index of neutral species
Definition IonFlow.h:96
vector< double > m_mobi_e_fix
coefficients of polynomial fitting of fixed electron transport profile
Definition IonFlow.h:99
bool componentActive(size_t n) const override
Returns true if the specified component is an active part of the solver state.
Definition IonFlow.cpp:94
vector< double > m_speciesCharge
electrical properties
Definition IonFlow.h:90
double temperature() const
Temperature (K).
Definition Phase.h:662
virtual void evalResidual(double *x, double *rsd, int *diag, double rdt, size_t jmin, size_t jmax)
Evaluate the residual function.
Definition StFlow.cpp:404
void setTransportModel(const string &trans)
Set the transport model.
Definition StFlow.cpp:237
void setTransport(shared_ptr< Transport > trans) override
Set transport model to existing instance.
Definition StFlow.cpp:161
void setKinetics(shared_ptr< Kinetics > kin) override
Set the kinetics manager.
Definition StFlow.cpp:143
void resize(size_t components, size_t points) override
Change the grid size. Called after grid refinement.
Definition StFlow.cpp:186
virtual bool componentActive(size_t n) const
Returns true if the specified component is an active part of the solver state.
Definition StFlow.cpp:722
void _finalize(const double *x) override
In some cases, a domain may need to set parameters that depend on the initial solution estimate.
Definition StFlow.cpp:306
size_t m_nsp
Number of species in the mechanism.
Definition StFlow.h:516
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 StFlow.cpp:288
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 StFlow.cpp:588
virtual string transportModel() const
Identifies the model represented by this Transport object.
Definition Transport.h:173
virtual void getMobilities(double *const mobil_e)
Get the Electrical mobilities (m^2/V/s).
Definition Transport.h:345
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:564
const size_t npos
index returned by functions to indicate "no position"
Definition ct_defs.h:195
@ c_offset_U
axial velocity
Definition StFlow.h:25
@ c_offset_V
strain rate
Definition StFlow.h:26
@ c_offset_E
electric poisson's equation
Definition StFlow.h:29
@ c_offset_Y
mass fractions
Definition StFlow.h:30
@ c_offset_T
temperature
Definition StFlow.h:27
void warn_deprecated(const string &source, const AnyBase &node, const string &message)
A deprecation warning for syntax in an input file.
Definition AnyMap.cpp:1926
Various templated functions that carry out common vector and polynomial operations (see Templated Arr...