Cantera  2.3.0
ImplicitSurfChem.cpp
Go to the documentation of this file.
1 /**
2  * @file ImplicitSurfChem.cpp
3  * Definitions for the implicit integration of surface site density equations
4  * (see \ref kineticsmgr and class
5  * \link Cantera::ImplicitSurfChem ImplicitSurfChem\endlink).
6  */
7 
8 // This file is part of Cantera. See License.txt in the top-level directory or
9 // at http://www.cantera.org/license.txt for license and copyright information.
10 
14 
15 using namespace std;
16 
17 namespace Cantera
18 {
19 
20 ImplicitSurfChem::ImplicitSurfChem(vector<InterfaceKinetics*> k) :
21  m_nv(0),
22  m_numTotalBulkSpecies(0),
23  m_numTotalSpecies(0),
24  m_atol(1.e-14),
25  m_rtol(1.e-7),
26  m_maxstep(0.0),
27  m_mediumSpeciesStart(-1),
28  m_bulkSpeciesStart(-1),
29  m_surfSpeciesStart(-1),
30  m_commonTempPressForPhases(true),
31  m_ioFlag(0)
32 {
33  size_t ntmax = 0;
34  size_t kinSpIndex = 0;
35  // Loop over the number of surface kinetics objects
36  for (size_t n = 0; n < k.size(); n++) {
37  InterfaceKinetics* kinPtr = k[n];
38  m_vecKinPtrs.push_back(kinPtr);
39  size_t ns = k[n]->surfacePhaseIndex();
40  if (ns == npos) {
41  throw CanteraError("ImplicitSurfChem",
42  "kinetics manager contains no surface phase");
43  }
44  m_surfindex.push_back(ns);
45  m_surf.push_back((SurfPhase*)&k[n]->thermo(ns));
46  size_t nsp = m_surf.back()->nSpecies();
47  m_nsp.push_back(nsp);
48  m_nv += m_nsp.back();
49  size_t nt = k[n]->nTotalSpecies();
50  ntmax = std::max(nt, ntmax);
51  m_specStartIndex.push_back(kinSpIndex);
52  kinSpIndex += nsp;
53  size_t nPhases = kinPtr->nPhases();
54  vector_int pLocTmp(nPhases);
55  size_t imatch = npos;
56  for (size_t ip = 0; ip < nPhases; ip++) {
57  if (ip != ns) {
58  ThermoPhase* thPtr = & kinPtr->thermo(ip);
59  if ((imatch = checkMatch(m_bulkPhases, thPtr)) == npos) {
60  m_bulkPhases.push_back(thPtr);
61  nsp = thPtr->nSpecies();
62  m_numTotalBulkSpecies += nsp;
63  imatch = m_bulkPhases.size() - 1;
64  }
65  pLocTmp[ip] = int(imatch);
66  } else {
67  pLocTmp[ip] = -int(n);
68  }
69  }
70  pLocVec.push_back(pLocTmp);
71  }
72  m_numTotalSpecies = m_nv + m_numTotalBulkSpecies;
73  m_concSpecies.resize(m_numTotalSpecies, 0.0);
74  m_concSpeciesSave.resize(m_numTotalSpecies, 0.0);
75 
76  m_integ.reset(newIntegrator("CVODE"));
77 
78  // use backward differencing, with a full Jacobian computed
79  // numerically, and use a Newton linear iterator
80  m_integ->setMethod(BDF_Method);
81  m_integ->setProblemType(DENSE + NOJAC);
82  m_integ->setIterator(Newton_Iter);
83  m_work.resize(ntmax);
84 }
85 
86 int ImplicitSurfChem::checkMatch(std::vector<ThermoPhase*> m_vec, ThermoPhase* thPtr)
87 {
88  int retn = -1;
89  for (int i = 0; i < (int) m_vec.size(); i++) {
90  ThermoPhase* th = m_vec[i];
91  if (th == thPtr) {
92  return i;
93  }
94  }
95  return retn;
96 }
97 
98 void ImplicitSurfChem::getInitialConditions(doublereal t0, size_t lenc,
99  doublereal* c)
100 {
101  warn_deprecated("ImplicitSurfChem::getInitialConditions",
102  "Use getState instead. To be removed after Cantera 2.3.");
103  getState(c);
104 }
105 
106 void ImplicitSurfChem::getState(doublereal* c)
107 {
108  size_t loc = 0;
109  for (size_t n = 0; n < m_surf.size(); n++) {
110  m_surf[n]->getCoverages(c + loc);
111  loc += m_nsp[n];
112  }
113 }
114 
115 void ImplicitSurfChem::initialize(doublereal t0)
116 {
117  m_integ->setTolerances(m_rtol, m_atol);
118  m_integ->initialize(t0, *this);
119 }
120 
121 void ImplicitSurfChem::integrate(doublereal t0, doublereal t1)
122 {
123  m_integ->initialize(t0, *this);
124  m_integ->setMaxStepSize(t1 - t0);
125  m_integ->integrate(t1);
126  updateState(m_integ->solution());
127 }
128 
129 void ImplicitSurfChem::integrate0(doublereal t0, doublereal t1)
130 {
131  m_integ->integrate(t1);
132  updateState(m_integ->solution());
133 }
134 
135 void ImplicitSurfChem::updateState(doublereal* c)
136 {
137  size_t loc = 0;
138  for (size_t n = 0; n < m_surf.size(); n++) {
139  m_surf[n]->setCoverages(c + loc);
140  loc += m_nsp[n];
141  }
142 }
143 
144 void ImplicitSurfChem::eval(doublereal time, doublereal* y,
145  doublereal* ydot, doublereal* p)
146 {
147  updateState(y); // synchronize the surface state(s) with y
148  size_t loc = 0;
149  for (size_t n = 0; n < m_surf.size(); n++) {
150  double rs0 = 1.0/m_surf[n]->siteDensity();
151  m_vecKinPtrs[n]->getNetProductionRates(m_work.data());
152  size_t kstart = m_vecKinPtrs[n]->kineticsSpeciesIndex(0,m_surfindex[n]);
153  double sum = 0.0;
154  for (size_t k = 1; k < m_nsp[n]; k++) {
155  ydot[k + loc] = m_work[kstart + k] * rs0 * m_surf[n]->size(k);
156  sum -= ydot[k];
157  }
158  ydot[loc] = sum;
159  loc += m_nsp[n];
160  }
161 }
162 
164  doublereal timeScaleOverride)
165 {
166  int ifunc;
167  // set bulkFunc. We assume that the bulk concentrations are constant.
168  int bulkFunc = BULK_ETCH;
169  // time scale - time over which to integrate equations
170  doublereal time_scale = timeScaleOverride;
171  if (!m_surfSolver) {
172  m_surfSolver.reset(new solveSP(this, bulkFunc));
173  // set ifunc, which sets the algorithm.
174  ifunc = SFLUX_INITIALIZE;
175  } else {
176  ifunc = SFLUX_RESIDUAL;
177  }
178 
179  // Possibly override the ifunc value
180  if (ifuncOverride >= 0) {
181  ifunc = ifuncOverride;
182  }
183 
184  // Get the specifications for the problem from the values
185  // in the ThermoPhase objects for all phases.
186  //
187  // 1) concentrations of all species in all phases, m_concSpecies[]
188  // 2) Temperature and pressure
191  ThermoPhase& tp = ik->thermo(0);
192  doublereal TKelvin = tp.temperature();
193  doublereal PGas = tp.pressure();
194 
195  // Make sure that there is a common temperature and pressure for all
196  // ThermoPhase objects belonging to the interfacial kinetics object, if it
197  // is required by the problem statement.
199  setCommonState_TP(TKelvin, PGas);
200  }
201 
202  doublereal reltol = 1.0E-6;
203  doublereal atol = 1.0E-20;
204 
205  // Install a filter for negative concentrations. One of the few ways solveSS
206  // can fail is if concentrations on input are below zero.
207  bool rset = false;
208  for (size_t k = 0; k < m_nv; k++) {
209  if (m_concSpecies[k] < 0.0) {
210  rset = true;
211  m_concSpecies[k] = 0.0;
212  }
213  }
214  if (rset) {
216  }
217 
218  m_surfSolver->m_ioflag = m_ioFlag;
219 
220  // Save the current solution
221  m_concSpeciesSave = m_concSpecies;
222 
223  int retn = m_surfSolver->solveSurfProb(ifunc, time_scale, TKelvin, PGas,
224  reltol, atol);
225  if (retn != 1) {
226  // reset the concentrations
227  m_concSpecies = m_concSpeciesSave;
228  setConcSpecies(m_concSpeciesSave.data());
229  ifunc = SFLUX_INITIALIZE;
230  retn = m_surfSolver->solveSurfProb(ifunc, time_scale, TKelvin, PGas,
231  reltol, atol);
232  if (retn != 1) {
233  throw CanteraError("ImplicitSurfChem::solvePseudoSteadyStateProblem",
234  "solveSP return an error condition!");
235  }
236  }
237 }
238 
239 void ImplicitSurfChem::getConcSpecies(doublereal* const vecConcSpecies) const
240 {
241  size_t kstart;
242  for (size_t ip = 0; ip < m_surf.size(); ip++) {
243  ThermoPhase* TP_ptr = m_surf[ip];
244  kstart = m_specStartIndex[ip];
245  TP_ptr->getConcentrations(vecConcSpecies + kstart);
246  }
247  kstart = m_nv;
248  for (size_t ip = 0; ip < m_bulkPhases.size(); ip++) {
249  ThermoPhase* TP_ptr = m_bulkPhases[ip];
250  TP_ptr->getConcentrations(vecConcSpecies + kstart);
251  kstart += TP_ptr->nSpecies();
252  }
253 }
254 
255 void ImplicitSurfChem::setConcSpecies(const doublereal* const vecConcSpecies)
256 {
257  size_t kstart;
258  for (size_t ip = 0; ip < m_surf.size(); ip++) {
259  ThermoPhase* TP_ptr = m_surf[ip];
260  kstart = m_specStartIndex[ip];
261  TP_ptr->setConcentrations(vecConcSpecies + kstart);
262  }
263  kstart = m_nv;
264  for (size_t ip = 0; ip < m_bulkPhases.size(); ip++) {
265  ThermoPhase* TP_ptr = m_bulkPhases[ip];
266  TP_ptr->setConcentrations(vecConcSpecies + kstart);
267  kstart += TP_ptr->nSpecies();
268  }
269 }
270 
271 void ImplicitSurfChem::setCommonState_TP(doublereal TKelvin, doublereal PresPa)
272 {
273  for (size_t ip = 0; ip < m_surf.size(); ip++) {
274  ThermoPhase* TP_ptr = m_surf[ip];
275  TP_ptr->setState_TP(TKelvin, PresPa);
276  }
277  for (size_t ip = 0; ip < m_bulkPhases.size(); ip++) {
278  ThermoPhase* TP_ptr = m_bulkPhases[ip];
279  TP_ptr->setState_TP(TKelvin, PresPa);
280  }
281 }
282 
283 }
Backward Differentiation.
Definition: Integrator.h:33
Header for a simple thermodynamics model of a surface phase derived from ThermoPhase, assuming an ideal solution model (see Thermodynamic Properties and class SurfPhase).
std::vector< size_t > m_surfindex
index of the surface phase in each InterfaceKinetics object
doublereal temperature() const
Temperature (K).
Definition: Phase.h:601
virtual void getState(doublereal *y)
Get the current state of the solution vector.
thermo_t & thermo(size_t n=0)
This method returns a reference to the nth ThermoPhase object defined in this kinetics mechanism...
Definition: Kinetics.h:276
std::unique_ptr< Integrator > m_integ
Pointer to the CVODE integrator.
void solvePseudoSteadyStateProblem(int ifuncOverride=-1, doublereal timeScaleOverride=1.0)
Solve for the pseudo steady-state of the surface problem.
std::vector< ThermoPhase * > m_bulkPhases
Vector of pointers to bulk phases.
Method to solve a pseudo steady state surface problem.
Definition: solveSP.h:138
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
std::unique_ptr< solveSP > m_surfSolver
Pointer to the helper method, Placid, which solves the surface problem.
std::vector< size_t > m_nsp
Vector of number of species in each Surface Phase.
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:54
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:262
STL namespace.
const int BULK_ETCH
Etching of a bulk phase is to be expected.
Definition: solveSP.h:56
size_t nPhases() const
The number of phases participating in the reaction mechanism.
Definition: Kinetics.h:216
std::vector< SurfPhase * > m_surf
vector of pointers to surface phases.
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:93
std::vector< int > vector_int
Vector of ints.
Definition: ct_defs.h:159
A simple thermodynamic model for a surface phase, assuming an ideal solution model.
Definition: SurfPhase.h:143
int m_ioFlag
Controls the amount of printing from this routine and underlying routines.
bool m_commonTempPressForPhases
If true, a common temperature and pressure for all surface and bulk phases associated with the surfac...
const int SFLUX_INITIALIZE
This assumes that the initial guess supplied to the routine is far from the correct one...
Definition: solveSP.h:21
A kinetics manager for heterogeneous reaction mechanisms.
const int SFLUX_RESIDUAL
Need to solve the surface problem in order to calculate the surface fluxes of gas-phase species...
Definition: solveSP.h:28
virtual void getInitialConditions(doublereal t0, size_t leny, doublereal *y)
Set the initial conditions for the solution vector.
size_t m_nv
Total number of surface species in all surface phases.
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
virtual void eval(doublereal t, doublereal *y, doublereal *ydot, doublereal *p)
Evaluate the value of ydot[k] at the current conditions.
virtual void setConcentrations(const doublereal *const conc)
Set the concentrations to the specified values within the phase.
Definition: Phase.cpp:600
void integrate0(doublereal t0, doublereal t1)
Integrate from t0 to t1 without reinitializing the integrator.
void setConcSpecies(const doublereal *const vecConcSpecies)
Sets the concentrations within phases that are unknowns in the surface problem.
Declarations for the implicit integration of surface site density equations (see Kinetics Managers an...
virtual void setState_TP(doublereal t, doublereal p)
Set the temperature (K) and pressure (Pa)
virtual doublereal pressure() const
Return the thermodynamic pressure (Pa).
Definition: ThermoPhase.h:278
void getConcSpecies(doublereal *const vecConcSpecies) const
virtual void initialize(doublereal t0=0.0)
void setCommonState_TP(doublereal TKelvin, doublereal PresPa)
Sets the state variable in all thermodynamic phases (surface and surrounding bulk phases) to the inpu...
Newton Iteration.
Definition: Integrator.h:43
void updateState(doublereal *y)
Set the mixture to a state consistent with solution vector y.
Header file for implicit surface problem solver (see Chemical Kinetics and class solveSP).
std::vector< InterfaceKinetics * > m_vecKinPtrs
vector of pointers to InterfaceKinetics objects
Namespace for the Cantera kernel.
Definition: application.cpp:29
void getConcentrations(doublereal *const c) const
Get the species concentrations (kmol/m^3).
Definition: Phase.cpp:595
vector_fp m_concSpecies
Temporary vector - length num species in the Kinetics object.
void integrate(doublereal t0, doublereal t1)
Integrate from t0 to t1. The integrator is reinitialized first.