25 static doublereal calc_damping(doublereal* x, doublereal* dx,
size_t dim,
int*);
26 static doublereal calcWeightedNorm(
const doublereal [],
const doublereal dx[],
size_t);
33 m_SurfChemPtr(surfChemPtr),
34 m_objects(surfChemPtr->getObjects()),
38 m_numTotSurfSpecies(0),
40 m_numTotBulkSpeciesSS(0),
48 size_t numPossibleSurfPhases =
m_objects.size();
49 for (
size_t n = 0; n < numPossibleSurfPhases; n++) {
52 if (surfPhaseIndex !=
npos) {
58 "InterfaceKinetics object has no surface phase");
64 "Inconsistent ThermoPhase object within "
65 "InterfaceKinetics object");
87 size_t tsp =
m_objects[n]->nTotalSpecies();
106 size_t isp, k, nsp, kstart;
114 for (k = 0; k < nsp; k++, kindexSP++) {
121 size_t dim1 = std::max<size_t>(1,
m_neq);
132 for (
size_t k = 0; k < dim1; k++) {
142 doublereal PGas, doublereal reltol, doublereal abstol)
144 doublereal EXTRA_ACCURACY = 0.001;
146 EXTRA_ACCURACY *= 0.001;
152 doublereal label_factor = 1.0;
156 doublereal deltaT = 1.0E-10;
157 doublereal damp=1.0, tmp;
160 doublereal resid_norm;
161 doublereal inv_t = 0.0;
162 doublereal t_real = 0.0, update_norm = 1.0E6;
164 bool do_time =
false, not_converged =
true;
186 for (
size_t k = 0; k <nsp; k++) {
202 print_header(m_ioflag, ifunc, time_scale,
true, reltol, abstol,
211 not_converged =
false;
219 while (not_converged && iter < iter_max) {
245 &label_t, &label_t_old, &label_factor, m_ioflag);
248 }
else if (tmp > 2.0*inv_t) {
259 tmp = t_real + 1.0/inv_t;
260 if (tmp > time_scale) {
261 inv_t = 1.0/(time_scale - t_real);
308 printf(
"solveSurfSS: Zero pivot, assuming converged: %g (%d)\n",
311 for (
size_t jcol = 0; jcol <
m_neq; jcol++) {
318 printf(
"solveSurfProb: iter %d t_real %g delta_t %g\n\n",
319 iter,t_real, 1.0/inv_t);
320 printf(
"solveSurfProb: init guess, current concentration,"
322 for (
size_t jcol = 0; jcol <
m_neq; jcol++) {
323 printf(
"\t%s %g %g %g\n",
int2str(jcol).c_str(),
330 t_real += time_scale;
353 for (
size_t irow = 0; irow <
m_neq; irow++) {
356 for (
size_t irow = 0; irow <
m_neq; irow++) {
362 t_real += damp/inv_t;
366 printIteration(m_ioflag, damp, label_d, label_t, inv_t, t_real, iter,
367 update_norm, resid_norm,
375 not_converged = (t_real < time_scale);
378 if (t_real > time_scale ||
379 (resid_norm < 1.0e-7 &&
380 update_norm*time_scale/t_real < EXTRA_ACCURACY)) {
384 not_converged = ((update_norm > EXTRA_ACCURACY) ||
385 (resid_norm > EXTRA_ACCURACY));
396 printf(
"#$#$#$# Error in solveSP $#$#$#$ \n");
397 printf(
"Newton iter on surface species did not converge, "
398 "update_norm = %e \n", update_norm);
399 printf(
"Continuing anyway\n");
413 printFinal(m_ioflag, damp, label_d, label_t, inv_t, t_real, iter,
424 if (update_norm > 1.0) {
451 for (
size_t iph = 0; iph < nph; iph++) {
463 doublereal Clarge = CSolnSP[kindexSP];
466 for (
size_t k = 1; k < nsp; k++, kindexSP++) {
467 if (CSolnSP[kindexSP] > Clarge) {
468 Clarge = CSolnSP[kindexSP];
476 const doublereal* CSolnOld,
const bool do_time,
477 const doublereal deltaT)
479 size_t isp, nsp, kstart, k, kindexSP, kins, kspecial;
480 doublereal lenScale = 1.0E-9;
506 for (k = 0; k < nsp; k++, kindexSP++) {
508 (CSoln[kindexSP] - CSolnOld[kindexSP]) / deltaT
514 resid[kspecial] = sd;
515 for (k = 0; k < nsp; k++) {
516 resid[kspecial] -= CSoln[kins + k];
528 for (k = 0; k < nsp; k++, kindexSP++) {
533 resid[kspecial] = sd;
534 for (k = 0; k < nsp; k++) {
535 resid[kspecial] -= CSoln[kins + k];
551 for (k = 0; k < nsp; k++) {
557 for (k = 0; k < nsp; k++) {
558 resid[kindexSP] -= CSoln[kindexSP + k];
561 for (k = 1; k < nsp; k++) {
563 resid[kindexSP + k] = XBlk[k] * grRate
566 resid[kindexSP + k] = XBlk[k] * grRate;
572 for (k = 1; k < nsp; k++) {
573 resid[kindexSP + k] = grRate * (XBlk[k] - 1.0/nsp);
577 for (k = 1; k < nsp; k++) {
578 resid[kindexSP + k] +=
580 (CSoln[kindexSP + k]- CSolnOld[kindexSP + k]);
590 doublereal resid[], doublereal CSoln[],
591 const doublereal CSolnOld[],
const bool do_time,
592 const doublereal deltaT)
594 size_t kColIndex = 0, nsp, jsp, i, kCol;
595 doublereal dc, cSave, sd;
600 fun_eval(resid, CSoln, CSolnOld, do_time, deltaT);
607 for (kCol = 0; kCol < nsp; kCol++) {
608 cSave = CSoln[kColIndex];
609 dc = std::max(1.0E-10 * sd, fabs(cSave) * 1.0E-7);
610 CSoln[kColIndex] += dc;
612 col_j = JacCol[kColIndex];
613 for (i = 0; i <
m_neq; i++) {
616 CSoln[kColIndex] = cSave;
625 for (kCol = 0; kCol < nsp; kCol++) {
626 cSave = CSoln[kColIndex];
627 dc = std::max(1.0E-10 * sd, fabs(cSave) * 1.0E-7);
628 CSoln[kColIndex] += dc;
630 col_j = JacCol[kColIndex];
631 for (i = 0; i <
m_neq; i++) {
634 CSoln[kColIndex] = cSave;
652 static doublereal calc_damping(doublereal x[], doublereal dxneg[],
size_t dim,
int* label)
654 const doublereal APPROACH = 0.80;
655 doublereal damp = 1.0, xnew, xtop, xbot;
656 static doublereal damp_old = 1.0;
660 for (
size_t i = 0; i < dim; i++) {
666 xnew = x[i] - damp * dxneg[i];
674 xtop = 1.0 - 0.1*fabs(1.0-x[i]);
675 xbot = fabs(x[i]*0.1) - 1.0e-16;
677 damp = - APPROACH * (1.0 - x[i]) / dxneg[i];
679 }
else if (xnew < xbot) {
680 damp = APPROACH * x[i] / dxneg[i];
682 }
else if (xnew > 3.0*std::max(x[i], 1.0E-10)) {
683 damp = - 2.0 * std::max(x[i], 1.0E-10) / dxneg[i];
696 if (damp > damp_old*3) {
715 static doublereal calcWeightedNorm(
const doublereal wtX[],
const doublereal dx[],
size_t dim)
717 doublereal norm = 0.0;
722 for (
size_t i = 0; i < dim; i++) {
723 tmp = dx[i] / wtX[i];
726 return sqrt(norm/dim);
730 const Array2D& Jac,
const doublereal CSoln[],
731 const doublereal abstol,
const doublereal reltol)
733 size_t k, jcol, kindex, isp, nsp;
743 for (k = 0; k < nsp; k++, kindex++) {
744 wtSpecies[kindex] = abstol * sd + reltol * fabs(CSoln[kindex]);
751 for (k = 0; k < nsp; k++, kindex++) {
752 wtSpecies[kindex] = abstol * sd + reltol * fabs(CSoln[kindex]);
762 for (k = 0; k <
m_neq; k++) {
764 for (jcol = 0; jcol <
m_neq; jcol++) {
765 wtResid[k] += fabs(Jac(k,jcol) * wtSpecies[jcol]);
771 calc_t(doublereal netProdRateSolnSP[], doublereal XMolSolnSP[],
772 int* label,
int* label_old, doublereal* label_factor,
int ioflag)
774 size_t k, isp, nsp, kstart;
775 doublereal inv_timeScale = 1.0E-10;
776 doublereal sden, tmp;
795 for (k = 0; k < nsp; k++, kindexSP++) {
796 size_t kspindex = kstart + k;
797 netProdRateSolnSP[kindexSP] =
m_numEqn1[kspindex];
798 if (XMolSolnSP[kindexSP] <= 1.0E-10) {
801 tmp = XMolSolnSP[kindexSP];
804 tmp = fabs(netProdRateSolnSP[kindexSP]/ tmp);
805 if (netProdRateSolnSP[kindexSP]> 0.0) {
808 if (tmp > inv_timeScale) {
810 *label = int(kindexSP);
819 if (*label == *label_old) {
820 *label_factor *= 1.5;
825 return inv_timeScale / *label_factor;
829 int damping, doublereal reltol, doublereal abstol,
831 doublereal PGas, doublereal netProdRate[],
832 doublereal XMolKinSpecies[])
835 printf(
"\n================================ SOLVESP CALL SETUP "
836 "========================================\n");
838 printf(
"\n SOLVESP Called with Initialization turned on\n");
839 printf(
" Time scale input = %9.3e\n", time_scale);
841 printf(
"\n SOLVESP Called to calculate steady state residual\n");
842 printf(
" from a good initial guess\n");
844 printf(
"\n SOLVESP Called to calculate steady state jacobian\n");
845 printf(
" from a good initial guess\n");
847 printf(
"\n SOLVESP Called to integrate surface in time\n");
848 printf(
" for a total of %9.3e sec\n", time_scale);
850 fprintf(stderr,
"Unknown ifunc flag = %d\n", ifunc);
855 printf(
" The composition of the Bulk Phases will be calculated\n");
857 printf(
" Bulk Phases have fixed compositions\n");
859 fprintf(stderr,
"Unknown bulkFunc flag = %d\n",
m_bulkFunc);
864 printf(
" Damping is ON \n");
866 printf(
" Damping is OFF \n");
869 printf(
" Reltol = %9.3e, Abstol = %9.3e\n", reltol, abstol);
873 printf(
"\n\n\t Iter Time Del_t Damp DelX "
874 " Resid Name-Time Name-Damp\n");
875 printf(
"\t -----------------------------------------------"
876 "------------------------------------\n");
882 doublereal inv_t, doublereal t_real,
size_t iter,
883 doublereal update_norm, doublereal resid_norm,
884 doublereal netProdRate[], doublereal CSolnSP[],
885 doublereal resid[], doublereal XMolSolnSP[],
886 doublereal wtSpecies[],
size_t dim,
bool do_time)
892 printf(
"\t%6s ",
int2str(iter).c_str());
894 printf(
"%9.4e %9.4e ", t_real, 1.0/inv_t);
896 for (i = 0; i < 22; i++) {
900 printf(
"%9.4e ", damp);
902 for (i = 0; i < 11; i++) {
905 printf(
"%9.4e %9.4e", update_norm, resid_norm);
911 printf(
" %-16s", nm.c_str());
913 for (i = 0; i < 16; i++) {
922 printf(
" %-16s", nm.c_str());
930 doublereal inv_t, doublereal t_real,
size_t iter,
931 doublereal update_norm, doublereal resid_norm,
932 doublereal netProdRateKinSpecies[],
const doublereal CSolnSP[],
933 const doublereal resid[], doublereal XMolSolnSP[],
934 const doublereal wtSpecies[],
const doublereal wtRes[],
935 size_t dim,
bool do_time,
936 doublereal TKelvin, doublereal PGas)
942 printf(
"\tFIN%3s ",
int2str(iter).c_str());
944 printf(
"%9.4e %9.4e ", t_real, 1.0/inv_t);
946 for (i = 0; i < 22; i++) {
950 printf(
"%9.4e ", damp);
952 for (i = 0; i < 11; i++) {
955 printf(
"%9.4e %9.4e", update_norm, resid_norm);
961 printf(
" %-16s", nm.c_str());
963 for (i = 0; i < 16; i++) {
972 printf(
" %-16s", nm.c_str());
974 printf(
" -- success\n");
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
int m_bulkFunc
This variable determines how the bulk phases are to be handled.
virtual void getNetProductionRates(doublereal *net)
Species net production rates [kmol/m^3/s or kmol/m^2/s].
std::vector< InterfaceKinetics * > & m_objects
Vector of interface kinetics objects.
void resize(size_t n, size_t m, doublereal v=0.0)
Resize the array, and fill the new entries with 'v'.
size_t m_neq
Total number of equations to solve in the implicit problem.
Declarations for a simple class that implements an Ansi C wall clock timer (see Cantera::clockWC).
std::vector< doublereal * > m_JacCol
Vector of pointers to the top of the columns of the Jacobian.
thermo_t & thermo(size_t n=0)
This method returns a reference to the nth ThermoPhase object defined in this kinetics mechanism...
const size_t npos
index returned by functions to indicate "no position"
std::string kineticsSpeciesName(size_t k) const
Return the name of the kth species in the kinetics manager.
vector_fp m_CSolnSPInit
Saved initial solution vector. length MAX(1, m_neq)
size_t m_numBulkPhasesSS
Total number of volumetric condensed phases included in the steady state problem handled by this rout...
void updateMFSolnSP(doublereal *XMolSolnSP)
Update mole fraction vector consisting of unknowns in surface problem.
vector_fp m_CSolnSP
Solution vector. length MAX(1, m_neq)
doublereal molarDensity() const
Molar density (kmol/m^3).
doublereal * ptrColumn(size_t j)
Return a pointer to the top of column j, columns are contiguous in memory.
const int BULK_ETCH
Etching of a bulk phase is to be expected.
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
void getConcentrations(doublereal *const c) const
Get the species concentrations (kmol/m^3).
A class for 2D arrays stored in column-major (Fortran-compatible) form.
Base class for a phase with thermodynamic properties.
void evalSurfLarge(const doublereal *CSolnSP)
Update the vector that keeps track of the largest species in each surface phase.
A simple thermodynamic model for a surface phase, assuming an ideal solution model.
size_t surfacePhaseIndex()
This returns the integer index of the phase which has ThermoPhase type cSurf.
size_t m_numTotSurfSpecies
Total number of surface species in all surface phases.
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.
const int SFLUX_INITIALIZE
This assumes that the initial guess supplied to the routine is far from the correct one...
void print_header(int ioflag, int ifunc, doublereal time_scale, int damping, doublereal reltol, doublereal abstol, doublereal TKelvin, doublereal PGas, doublereal netProdRate[], doublereal XMolKinSpecies[])
Printing routine that optionally gets called at the start of every invocation.
size_t nPhases() const
The number of phases participating in the reaction mechanism.
std::vector< size_t > m_eqnIndexStartSolnPhase
Index of the start of the unknowns for each solution phase.
A kinetics manager for heterogeneous reaction mechanisms.
vector_fp m_wtResid
Weights for the residual norm calculation. length MAX(1, m_neq)
const int SFLUX_RESIDUAL
Need to solve the surface problem in order to calculate the surface fluxes of gas-phase species...
vector_fp m_XMolKinSpecies
Vector of mole fractions. length m_maxTotSpecies.
doublereal calc_t(doublereal netProdRateSolnSP[], doublereal XMolSolnSP[], int *label, int *label_old, doublereal *label_factor, int ioflag)
Calculate a conservative delta T to use in a pseudo-steady state algorithm.
vector_fp m_numEqn1
Temporary vector with length equal to max m_maxTotSpecies.
const int BULK_DEPOSITION
Deposition of a bulk phase is to be expected.
const int SFLUX_JACOBIAN
Calculation of the surface problem is due to the need for a numerical jacobian for the gas-problem...
std::vector< size_t > m_spSurfLarge
Vector containing the indices of the largest species in each surface phase.
vector_fp m_CSolnSave
Temporary vector with length equal to max m_maxTotSpecies.
std::vector< size_t > m_nSpeciesSurfPhase
Vector of length number of surface phases containing the number of surface species in each phase...
vector_int m_ipiv
pivots. length MAX(1, m_neq)
void updateMFKinSpecies(doublereal *XMolKinSp, int isp)
Update the mole fraction vector for a specific kinetic species vector corresponding to one InterfaceK...
Base class for exceptions thrown by Cantera classes.
vector_fp m_numEqn2
Temporary vector with length equal to max m_maxTotSpecies.
const int SFLUX_TRANSIENT
The transient calculation is performed here for an amount of time specified by "time_scale".
size_t kineticsSpeciesIndex(size_t k, size_t n) const
The location of species k of phase n in species arrays.
std::vector< SurfPhase * > m_ptrsSurfPhase
Vector of surface phase pointers.
size_t nSpecies() const
Returns the number of species in the phase.
std::vector< size_t > m_kinObjPhaseIDSurfPhase
Phase ID in the InterfaceKinetics object of the surface phase.
vector_fp m_netProductionRatesSave
Temporary vector with length equal to max m_maxTotSpecies.
std::vector< size_t > m_kinObjIndex
Index between the equation index and the index of the InterfaceKinetics object.
Advances the surface coverages of the associated set of SurfacePhase objects in time.
size_t m_numSurfPhases
Number of surface phases in the surface problem.
std::vector< ThermoPhase * > m_bulkPhasePtrs
Vector of bulk phase pointers, length is equal to m_numBulkPhases.
~solveSP()
Destructor. Deletes the integrator.
std::vector< size_t > m_numBulkSpecies
Vector of number of species in the m_numBulkPhases phases.
vector_fp m_CSolnSPOld
Saved solution vector at the old time step. length MAX(1, m_neq)
vector_fp m_resid
Residual for the surface problem.
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.
std::vector< size_t > m_kinSpecIndex
Index between the equation index and the position in the kinetic species array for the appropriate ki...
size_t m_maxTotSpecies
Maximum number of species in any single kinetics operator -> also maxed wrt the total # of solution s...
std::vector< size_t > m_indexKinObjSurfPhase
Mapping between the surface phases and the InterfaceKinetics objects.
vector_fp m_wtSpecies
Weights for the species concentrations norm calculation.
void printFinal(int ioflag, doublereal damp, int label_d, int label_t, doublereal inv_t, doublereal t_real, size_t iter, doublereal update_norm, doublereal resid_norm, doublereal netProdRateKinSpecies[], const doublereal CSolnSP[], const doublereal resid[], doublereal XMolSolnSP[], const doublereal wtSpecies[], const doublereal wtRes[], size_t dim, bool do_time, doublereal TKelvin, doublereal PGas)
Print a summary of the solution.
void resjac_eval(std::vector< doublereal * > &JacCol, doublereal *resid, doublereal *CSolnSP, const doublereal *CSolnSPOld, const bool do_time, const doublereal deltaT)
Main routine that calculates the current residual and Jacobian.
void fun_eval(doublereal *resid, const doublereal *CSolnSP, const doublereal *CSolnOldSP, const bool do_time, const doublereal deltaT)
Main Function evaluation.
size_t m_numTotBulkSpeciesSS
Total number of species in all bulk phases.
void printIteration(int ioflag, doublereal damp, int label_d, int label_t, doublereal inv_t, doublereal t_real, size_t iter, doublereal update_norm, doublereal resid_norm, doublereal netProdRate[], doublereal CSolnSP[], doublereal resid[], doublereal XMolSolnSP[], doublereal wtSpecies[], size_t dim, bool do_time)
Printing routine that gets called after every iteration.
void updateState(const doublereal *cSurfSpec)
Update the surface states of the surface phases.
void calcWeights(doublereal wtSpecies[], doublereal wtResid[], const Array2D &Jac, const doublereal CSolnSP[], const doublereal abstol, const doublereal reltol)
Calculate the solution and residual weights.