Cantera  2.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 // Copyright 2001 California Institute of Technology
8 
12 
13 using namespace std;
14 
15 namespace Cantera
16 {
17 
18 ImplicitSurfChem::ImplicitSurfChem(vector<InterfaceKinetics*> k) :
19  m_nsurf(0),
20  m_nv(0),
21  m_numBulkPhases(0),
22  m_numTotalBulkSpecies(0),
23  m_numTotalSpecies(0),
24  m_integ(0),
25  m_atol(1.e-14),
26  m_rtol(1.e-7),
27  m_maxstep(0.0),
28  m_mediumSpeciesStart(-1),
29  m_bulkSpeciesStart(-1),
30  m_surfSpeciesStart(-1),
31  m_surfSolver(0),
32  m_commonTempPressForPhases(true),
33  m_ioFlag(0)
34 {
35  m_nsurf = k.size();
36  size_t ns, nsp;
37  size_t nt, ntmax = 0;
38  size_t kinSpIndex = 0;
39  // Loop over the number of surface kinetics objects
40  for (size_t n = 0; n < m_nsurf; n++) {
41  InterfaceKinetics* kinPtr = k[n];
42  m_vecKinPtrs.push_back(kinPtr);
43  ns = k[n]->surfacePhaseIndex();
44  if (ns == npos)
45  throw CanteraError("ImplicitSurfChem",
46  "kinetics manager contains no surface phase");
47  m_surfindex.push_back(ns);
48  m_surf.push_back((SurfPhase*)&k[n]->thermo(ns));
49  nsp = m_surf.back()->nSpecies();
50  m_nsp.push_back(nsp);
51  m_nv += m_nsp.back();
52  nt = k[n]->nTotalSpecies();
53  ntmax = std::max(nt, ntmax);
54  m_specStartIndex.push_back(kinSpIndex);
55  kinSpIndex += nsp;
56 
57  size_t nPhases = kinPtr->nPhases();
58  vector_int pLocTmp(nPhases);
59  size_t imatch = npos;
60  for (size_t ip = 0; ip < nPhases; ip++) {
61  if (ip != ns) {
62  ThermoPhase* thPtr = & kinPtr->thermo(ip);
63  if ((imatch = checkMatch(m_bulkPhases, thPtr)) == npos) {
64  m_bulkPhases.push_back(thPtr);
65  m_numBulkPhases++;
66  nsp = thPtr->nSpecies();
67  m_nspBulkPhases.push_back(nsp);
68  m_numTotalBulkSpecies += nsp;
69  imatch = m_bulkPhases.size() - 1;
70  }
71  pLocTmp[ip] = int(imatch);
72  } else {
73  pLocTmp[ip] = -int(n);
74  }
75  }
76  pLocVec.push_back(pLocTmp);
77 
78  }
79  m_numTotalSpecies = m_nv + m_numTotalBulkSpecies;
80  m_concSpecies.resize(m_numTotalSpecies, 0.0);
81  m_concSpeciesSave.resize(m_numTotalSpecies, 0.0);
82 
83  m_integ = newIntegrator("CVODE");
84 
85 
86 
87  // use backward differencing, with a full Jacobian computed
88  // numerically, and use a Newton linear iterator
89 
91  m_integ->setProblemType(DENSE + NOJAC);
93  m_work.resize(ntmax);
94 }
95 
96 int ImplicitSurfChem::checkMatch(std::vector<ThermoPhase*> m_vec, ThermoPhase* thPtr)
97 {
98  int retn = -1;
99  for (int i = 0; i < (int) m_vec.size(); i++) {
100  ThermoPhase* th = m_vec[i];
101  if (th == thPtr) {
102  return i;
103  }
104  }
105  return retn;
106 }
107 
109 {
110  delete m_integ;
111  delete m_surfSolver;
112 }
113 
114 void ImplicitSurfChem::getInitialConditions(doublereal t0, size_t lenc,
115  doublereal* c)
116 {
117  size_t loc = 0;
118  for (size_t n = 0; n < m_nsurf; n++) {
119  m_surf[n]->getCoverages(c + loc);
120  loc += m_nsp[n];
121  }
122 }
123 
124 void ImplicitSurfChem::initialize(doublereal t0)
125 {
126  m_integ->setTolerances(m_rtol, m_atol);
127  m_integ->initialize(t0, *this);
128 }
129 
130 void ImplicitSurfChem::integrate(doublereal t0, doublereal t1)
131 {
132  m_integ->initialize(t0, *this);
133  m_integ->setMaxStepSize(t1 - t0);
134  m_integ->integrate(t1);
136 }
137 
138 void ImplicitSurfChem::integrate0(doublereal t0, doublereal t1)
139 {
140  m_integ->integrate(t1);
142 }
143 
144 void ImplicitSurfChem::updateState(doublereal* c)
145 {
146  size_t loc = 0;
147  for (size_t n = 0; n < m_nsurf; n++) {
148  m_surf[n]->setCoverages(c + loc);
149  loc += m_nsp[n];
150  }
151 }
152 
153 void ImplicitSurfChem::eval(doublereal time, doublereal* y,
154  doublereal* ydot, doublereal* p)
155 {
156  updateState(y); // synchronize the surface state(s) with y
157  doublereal rs0, sum;
158  size_t loc = 0, kstart;
159  for (size_t n = 0; n < m_nsurf; n++) {
160  rs0 = 1.0/m_surf[n]->siteDensity();
161  m_vecKinPtrs[n]->getNetProductionRates(DATA_PTR(m_work));
162  kstart = m_vecKinPtrs[n]->kineticsSpeciesIndex(0,m_surfindex[n]);
163  sum = 0.0;
164  for (size_t k = 1; k < m_nsp[n]; k++) {
165  ydot[k + loc] = m_work[kstart + k] * rs0 * m_surf[n]->size(k);
166  sum -= ydot[k];
167  }
168  ydot[loc] = sum;
169  loc += m_nsp[n];
170  }
171 }
172 
174  doublereal timeScaleOverride)
175 {
176  int ifunc;
177  /*
178  * set bulkFunc
179  * -> We assume that the bulk concentrations are constant.
180  */
181  int bulkFunc = BULK_ETCH;
182  /*
183  * time scale - time over which to integrate equations
184  */
185  doublereal time_scale = timeScaleOverride;
186  if (!m_surfSolver) {
187  m_surfSolver = new solveSP(this, bulkFunc);
188  /*
189  * set ifunc, which sets the algorithm.
190  */
191  ifunc = SFLUX_INITIALIZE;
192  } else {
193  ifunc = SFLUX_RESIDUAL;
194  }
195 
196  // Possibly override the ifunc value
197  if (ifuncOverride >= 0) {
198  ifunc = ifuncOverride;
199  }
200 
201  /*
202  * Get the specifications for the problem from the values
203  * in the ThermoPhase objects for all phases.
204  *
205  * 1) concentrations of all species in all phases, m_concSpecies[]
206  * 2) Temperature and pressure
207  */
210  ThermoPhase& tp = ik->thermo(0);
211  doublereal TKelvin = tp.temperature();
212  doublereal PGas = tp.pressure();
213  /*
214  * Make sure that there is a common temperature and
215  * pressure for all ThermoPhase objects belonging to the
216  * interfacial kinetics object, if it is required by
217  * the problem statement.
218  */
220  setCommonState_TP(TKelvin, PGas);
221  }
222 
223  doublereal reltol = 1.0E-6;
224  doublereal atol = 1.0E-20;
225 
226  /*
227  * Install a filter for negative concentrations. One of the
228  * few ways solveSS can fail is if concentrations on input
229  * are below zero.
230  */
231  bool rset = false;
232  for (size_t k = 0; k < m_nv; k++) {
233  if (m_concSpecies[k] < 0.0) {
234  rset = true;
235  m_concSpecies[k] = 0.0;
236  }
237  }
238  if (rset) {
240  }
241 
242  m_surfSolver->m_ioflag = m_ioFlag;
243 
244  // Save the current solution
245  copy(m_concSpecies.begin(), m_concSpecies.end(), m_concSpeciesSave.begin());
246 
247 
248  int retn = m_surfSolver->solveSurfProb(ifunc, time_scale, TKelvin, PGas,
249  reltol, atol);
250  if (retn != 1) {
251  // reset the concentrations
252  copy(m_concSpeciesSave.begin(), m_concSpeciesSave.end(), m_concSpecies.begin());
253  setConcSpecies(DATA_PTR(m_concSpeciesSave));
254  ifunc = SFLUX_INITIALIZE;
255  retn = m_surfSolver->solveSurfProb(ifunc, time_scale, TKelvin, PGas,
256  reltol, atol);
257 
258  if (retn != 1) {
259  throw CanteraError("ImplicitSurfChem::solvePseudoSteadyStateProblem",
260  "solveSP return an error condition!");
261  }
262  }
263 }
264 
265 void ImplicitSurfChem::getConcSpecies(doublereal* const vecConcSpecies) const
266 {
267  size_t kstart;
268  for (size_t ip = 0; ip < m_nsurf; ip++) {
269  ThermoPhase* TP_ptr = m_surf[ip];
270  kstart = m_specStartIndex[ip];
271  TP_ptr->getConcentrations(vecConcSpecies + kstart);
272  }
273  kstart = m_nv;
274  for (size_t ip = 0; ip < m_numBulkPhases; ip++) {
275  ThermoPhase* TP_ptr = m_bulkPhases[ip];
276  TP_ptr->getConcentrations(vecConcSpecies + kstart);
277  kstart += TP_ptr->nSpecies();
278  }
279 }
280 
281 void ImplicitSurfChem::setConcSpecies(const doublereal* const vecConcSpecies)
282 {
283  size_t kstart;
284  for (size_t ip = 0; ip < m_nsurf; ip++) {
285  ThermoPhase* TP_ptr = m_surf[ip];
286  kstart = m_specStartIndex[ip];
287  TP_ptr->setConcentrations(vecConcSpecies + kstart);
288  }
289  kstart = m_nv;
290  for (size_t ip = 0; ip < m_numBulkPhases; ip++) {
291  ThermoPhase* TP_ptr = m_bulkPhases[ip];
292  TP_ptr->setConcentrations(vecConcSpecies + kstart);
293  kstart += TP_ptr->nSpecies();
294  }
295 }
296 
297 void ImplicitSurfChem::setCommonState_TP(doublereal TKelvin, doublereal PresPa)
298 {
299  for (size_t ip = 0; ip < m_nsurf; ip++) {
300  ThermoPhase* TP_ptr = m_surf[ip];
301  TP_ptr->setState_TP(TKelvin, PresPa);
302  }
303  for (size_t ip = 0; ip < m_numBulkPhases; ip++) {
304  ThermoPhase* TP_ptr = m_bulkPhases[ip];
305  TP_ptr->setState_TP(TKelvin, PresPa);
306  }
307 }
308 
309 }
Backward Differentiation.
Definition: Integrator.h:32
Integrator * m_integ
Pointer to the CVODE integrator.
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
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:285
void solvePseudoSteadyStateProblem(int ifuncOverride=-1, doublereal timeScaleOverride=1.0)
Solve for the pseudo steady-state of the surface problem.
virtual void setMaxStepSize(double hmax)
Set the maximum step size.
Definition: Integrator.h:175
virtual void integrate(doublereal tout)
Integrate the system of equations.
Definition: Integrator.h:121
std::vector< ThermoPhase * > m_bulkPhases
Vector of pointers to bulk phases.
Method to solve a pseudo steady state surface problem.
Definition: solveSP.h:142
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
std::vector< size_t > m_nsp
Vector of number of species in each Surface Phase.
virtual void setTolerances(doublereal reltol, size_t n, doublereal *abstol)
Set or reset the number of equations.
Definition: Integrator.h:72
const int BULK_ETCH
Etching of a bulk phase is to be expected.
Definition: solveSP.h:59
void getConcentrations(doublereal *const c) const
Get the species concentrations (kmol/m^3).
Definition: Phase.cpp:609
virtual void initialize(doublereal t0, FuncEval &func)
Initialize the integrator for a new problem.
Definition: Integrator.h:108
solveSP * m_surfSolver
Pointer to the helper method, Placid, which solves the surface problem.
std::vector< SurfPhase * > m_surf
vector of pointers to surface phases.
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:97
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 solveSurfProb(int ifunc, doublereal time_scale, doublereal TKelvin, doublereal PGas, doublereal reltol, doublereal abstol)
Main routine that actually calculates the pseudo steady state of the surface problem.
Definition: solveSP.cpp:131
int m_ioFlag
Controls the amount of printing from this routine and underlying routines.
virtual void setProblemType(int probtype)
Set the problem type.
Definition: Integrator.h:98
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:24
size_t nPhases() const
The number of phases participating in the reaction mechanism.
Definition: Kinetics.h:225
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:31
virtual ~ImplicitSurfChem()
Destructor.
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:99
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:614
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)
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:265
virtual doublereal pressure() const
Return the thermodynamic pressure (Pa).
Definition: ThermoPhase.h:278
doublereal temperature() const
Temperature (K).
Definition: Phase.h:602
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...
virtual doublereal & solution(size_t k)
The current value of the solution of equation k.
Definition: Integrator.h:136
Newton Iteration.
Definition: Integrator.h:42
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).
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
Definition: ct_defs.h:36
size_t m_nsurf
Total number of surface phases.
std::vector< InterfaceKinetics * > m_vecKinPtrs
vector of pointers to InterfaceKinetics objects
virtual void setIterator(IterType t)
Set the linear iterator.
Definition: Integrator.h:170
virtual void setMethod(MethodType t)
Set the solution method.
Definition: Integrator.h:165
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.