25 static doublereal calcWeightedNorm(
const doublereal [],
const doublereal dx[],
size_t);
38 size_t dim1 = std::max<size_t>(1,
m_neq);
40 m_atol.resize(dim1, 1.0E-9);
57 for (
size_t k = 0; k < dim1; k++) {
63 solveProb::~solveProb()
76 doublereal EXTRA_ACCURACY = 0.001;
77 if (ifunc == SOLVEPROB_JACOBIAN) {
78 EXTRA_ACCURACY *= 0.001;
81 size_t label_t =
npos;
83 size_t label_t_old =
npos;
84 doublereal label_factor = 1.0;
88 doublereal deltaT = 1.0E-10;
89 doublereal damp=1.0, tmp;
93 doublereal resid_norm;
94 doublereal inv_t = 0.0;
95 doublereal t_real = 0.0, update_norm = 1.0E6;
97 bool do_time =
false, not_converged =
true;
99 #ifdef DEBUG_SOLVEPROB
100 #ifdef DEBUG_SOLVEPROB_TIME
109 #ifdef DEBUG_SOLVEPROB
110 #ifdef DEBUG_SOLVEPROB_TIME
147 not_converged =
false;
155 while (not_converged && iter < iter_max) {
180 &label_t, &label_t_old, &label_factor, m_ioflag);
183 }
else if (tmp > 2.0*inv_t) {
193 if (ifunc == SOLVEPROB_TRANSIENT) {
194 tmp = t_real + 1.0/inv_t;
195 if (tmp > time_scale) {
196 inv_t = 1.0/(time_scale - t_real);
227 #ifdef DEBUG_SOLVEPROB
229 printIterationHeader(m_ioflag, damp, inv_t, t_real, iter, do_time);
254 printf(
"solveSurfSS: Zero pivot, assuming converged: %g (%d)\n",
257 for (
size_t jcol = 0; jcol <
m_neq; jcol++) {
264 printf(
"solveSurfProb: iter %d t_real %g delta_t %g\n\n",
265 iter,t_real, 1.0/inv_t);
266 printf(
"solveSurfProb: init guess, current concentration,"
272 t_real += time_scale;
274 #ifdef DEBUG_SOLVEPROB
276 printf(
"\nResidual is small, forcing convergence!\n");
302 for (
size_t irow = 0; irow <
m_neq; irow++) {
308 t_real += damp/inv_t;
312 printIteration(m_ioflag, damp, label_d, label_t, inv_t, t_real, iter,
313 update_norm, resid_norm,
319 if (ifunc == SOLVEPROB_TRANSIENT) {
320 not_converged = (t_real < time_scale);
323 if (t_real > time_scale ||
324 (resid_norm < 1.0e-7 &&
325 update_norm*time_scale/t_real < EXTRA_ACCURACY)) {
327 #ifdef DEBUG_SOLVEPROB
329 printf(
"\t\tSwitching to steady solve.\n");
334 not_converged = ((update_norm > EXTRA_ACCURACY) ||
335 (resid_norm > EXTRA_ACCURACY));
346 printf(
"#$#$#$# Error in solveProb $#$#$#$ \n");
347 printf(
"Newton iter on surface species did not converge, "
348 "update_norm = %e \n", update_norm);
349 printf(
"Continuing anyway\n");
352 #ifdef DEBUG_SOLVEPROB
353 #ifdef DEBUG_SOLVEPROB_TIME
355 printf(
"\nEnd of solve, time used: %e\n", wc.
secondsWC()-t1);
370 printFinal(m_ioflag, damp, label_d, label_t, inv_t, t_real, iter,
380 if (update_norm > 1.0) {
392 const doublereal*
const CSolnOld,
const bool do_time,
393 const doublereal deltaT)
400 m_residFunc->evalSimpleTD(0.0, CSoln, CSolnOld, deltaT, resid);
407 doublereal resid[], doublereal CSoln[],
408 const doublereal CSolnOld[],
const bool do_time,
409 const doublereal deltaT)
411 doublereal dc, cSave, sd;
416 fun_eval(resid, CSoln, CSolnOld, do_time, deltaT);
421 for (
size_t kCol = 0; kCol <
m_neq; kCol++) {
423 sd = fabs(cSave) + fabs(CSoln[kCol]) +
m_atol[kCol] * 1.0E6;
427 dc = std::max(1.0E-11 * sd, fabs(cSave) * 1.0E-6);
431 col_j = JacCol[kCol];
432 for (
size_t i = 0; i <
m_neq; i++) {
442 const doublereal APPROACH = 0.50;
443 doublereal damp = 1.0, xnew, xtop, xbot;
444 static doublereal damp_old = 1.0;
447 for (
size_t i = 0; i < dim; i++) {
453 double delta_x = - dxneg[i];
454 xnew = x[i] - damp * dxneg[i];
461 bool canCrossOrigin =
false;
462 if (topBounds > 0.0 && botBounds < 0.0) {
463 canCrossOrigin =
true;
466 xtop = topBounds - 0.1 * fabs(topBounds - x[i]);
468 xbot = botBounds + 0.1 * fabs(x[i] - botBounds);
471 damp = - APPROACH * (xtop - x[i]) / dxneg[i];
473 }
else if (xnew < xbot) {
474 damp = APPROACH * (x[i] - xbot) / dxneg[i];
481 double denom = fabs(x[i]) + 1.0E5 *
m_atol[i];
482 if ((fabs(delta_x) / denom) > 0.3) {
483 double newdamp = 0.3 * denom / fabs(delta_x);
484 if (canCrossOrigin) {
485 if (xnew * x[i] < 0.0) {
486 if (fabs(x[i]) < 1.0E8 *
m_atol[i]) {
487 newdamp = 2.0 * fabs(x[i]) / fabs(delta_x);
491 damp = std::min(damp, newdamp);
500 if (damp > damp_old*3) {
518 static doublereal calcWeightedNorm(
const doublereal wtX[],
const doublereal dx[],
size_t dim)
520 doublereal norm = 0.0;
525 for (
size_t i = 0; i < dim; i++) {
526 tmp = dx[i] / wtX[i];
529 return sqrt(norm/dim);
533 const doublereal CSoln[])
539 for (
size_t k = 0; k <
m_neq; k++) {
548 for (
size_t k = 0; k <
m_neq; k++) {
550 for (
size_t jcol = 0; jcol <
m_neq; jcol++) {
551 wtResid[k] += fabs(
m_Jac(k,jcol) * wtSpecies[jcol]);
557 calc_t(doublereal netProdRateSolnSP[], doublereal Csoln[],
558 size_t* label,
size_t* label_old, doublereal* label_factor,
int ioflag)
560 doublereal tmp, inv_timeScale=0.0;
561 for (
size_t k = 0; k <
m_neq; k++) {
562 if (Csoln[k] <= 1.0E-10) {
567 tmp = fabs(netProdRateSolnSP[k]/ tmp);
570 if (netProdRateSolnSP[k]> 0.0) {
573 if (tmp > inv_timeScale) {
583 if (*label == *label_old) {
584 *label_factor *= 1.5;
589 inv_timeScale = inv_timeScale / *label_factor;
590 #ifdef DEBUG_SOLVEPROB
592 if (*label_factor > 1.0) {
593 printf(
"Delta_t increase due to repeated controlling species = %e\n",
596 int kkin = m_kinSpecIndex[*label];
599 printf(
"calc_t: spec=%d(%s) sf=%e pr=%e dt=%e\n",
600 *label, sn.c_str(), XMolSolnSP[*label],
601 netProdRateSolnSP[*label], 1.0/inv_timeScale);
605 return inv_timeScale;
611 for (
size_t k = 0; k <
m_neq; k++) {
617 #ifdef DEBUG_SOLVEPROB
618 void solveProb::printResJac(
int ioflag,
int neq,
const Array2D& Jac,
619 doublereal resid[], doublereal wtRes[],
628 doublereal netProdRate[])
632 printf(
"\n================================ SOLVEPROB CALL SETUP "
633 "========================================\n");
635 printf(
"\n SOLVEPROB Called with Initialization turned on\n");
636 printf(
" Time scale input = %9.3e\n", time_scale);
637 }
else if (ifunc == SOLVEPROB_RESIDUAL) {
638 printf(
"\n SOLVEPROB Called to calculate steady state residual\n");
639 printf(
" from a good initial guess\n");
640 }
else if (ifunc == SOLVEPROB_JACOBIAN) {
641 printf(
"\n SOLVEPROB Called to calculate steady state jacobian\n");
642 printf(
" from a good initial guess\n");
643 }
else if (ifunc == SOLVEPROB_TRANSIENT) {
644 printf(
"\n SOLVEPROB Called to integrate surface in time\n");
645 printf(
" for a total of %9.3e sec\n", time_scale);
647 fprintf(stderr,
"Unknown ifunc flag = %d\n", ifunc);
654 printf(
" Damping is ON \n");
656 printf(
" Damping is OFF \n");
659 printf(
" Reltol = %9.3e, Abstol = %9.3e\n", reltol,
m_atol[0]);
665 #ifdef DEBUG_SOLVEPROB
667 printf(
"\n================================ INITIAL GUESS "
668 "========================================\n");
670 for (
int isp = 0; isp < m_numSurfPhases; isp++) {
673 int nPhases = m_kin->
nPhases();
675 updateMFKinSpecies(XMolKinSpecies, isp);
677 printf(
"\n IntefaceKinetics Object # %d\n\n", isp);
679 printf(
"\t Number of Phases = %d\n", nPhases);
680 printf(
"\t Phase:SpecName Prod_Rate MoleFraction kindexSP\n");
681 printf(
"\t -------------------------------------------------------"
685 bool inSurfacePhase =
false;
686 for (
int ip = 0; ip < nPhases; ip++) {
687 if (ip == surfIndex) {
688 inSurfacePhase =
true;
690 inSurfacePhase =
false;
694 string pname = THref.
id();
695 for (
int k = 0; k < nsp; k++) {
697 string cname = pname +
":" + sname;
698 if (inSurfacePhase) {
699 printf(
"\t %-24s %10.3e %10.3e %d\n", cname.c_str(),
700 netProdRate[kspindex], XMolKinSpecies[kspindex],
704 printf(
"\t %-24s %10.3e %10.3e\n", cname.c_str(),
705 netProdRate[kspindex], XMolKinSpecies[kspindex]);
710 printf(
"=========================================================="
711 "=================================\n");
716 printf(
"\n\n\t Iter Time Del_t Damp DelX "
717 " Resid Name-Time Name-Damp\n");
718 printf(
"\t -----------------------------------------------"
719 "------------------------------------\n");
725 doublereal inv_t, doublereal t_real,
int iter,
726 doublereal update_norm, doublereal resid_norm,
727 doublereal netProdRate[], doublereal CSolnSP[],
729 doublereal wtSpecies[],
size_t dim,
bool do_time)
735 printf(
"\t%6d ", iter);
737 printf(
"%9.4e %9.4e ", t_real, 1.0/inv_t);
739 for (i = 0; i < 22; i++) {
743 printf(
"%9.4e ", damp);
745 for (i = 0; i < 11; i++) {
748 printf(
"%9.4e %9.4e", update_norm, resid_norm);
751 printf(
" %s",
int2str(k).c_str());
753 for (i = 0; i < 16; i++) {
757 if (label_d !=
npos) {
759 printf(
" %s",
int2str(k).c_str());
763 #ifdef DEBUG_SOLVEPROB
764 else if (ioflag > 1) {
766 updateMFSolnSP(XMolSolnSP);
767 printf(
"\n\t Weighted norm of update = %10.4e\n", update_norm);
769 printf(
"\t Name Prod_Rate XMol Conc "
772 printf(
" UnDamped_Conc");
775 printf(
"\t---------------------------------------------------------"
776 "-----------------------------\n");
778 for (
int isp = 0; isp < m_numSurfPhases; isp++) {
779 int nsp = m_nSpeciesSurfPhase[isp];
783 for (
int k = 0; k < nsp; k++, kindexSP++) {
784 int kspIndex = m_kinSpecIndex[kindexSP];
786 printf(
"\t%-16s %10.3e %10.3e %10.3e %10.3e %10.3e ",
789 XMolSolnSP[kindexSP],
790 CSolnSP[kindexSP], CSolnSP[kindexSP]+damp*resid[kindexSP],
791 wtSpecies[kindexSP]);
793 printf(
"%10.4e ", CSolnSP[kindexSP]+(damp-1.0)*resid[kindexSP]);
794 if (label_d == kindexSP) {
798 if (label_t == kindexSP) {
806 printf(
"\t--------------------------------------------------------"
807 "------------------------------\n");
813 doublereal inv_t, doublereal t_real,
int iter,
814 doublereal update_norm, doublereal resid_norm,
815 doublereal netProdRateKinSpecies[],
const doublereal CSolnSP[],
816 const doublereal resid[],
817 const doublereal wtSpecies[],
const doublereal wtRes[],
818 size_t dim,
bool do_time)
824 printf(
"\tFIN%3d ", iter);
826 printf(
"%9.4e %9.4e ", t_real, 1.0/inv_t);
828 for (i = 0; i < 22; i++) {
832 printf(
"%9.4e ", damp);
834 for (i = 0; i < 11; i++) {
837 printf(
"%9.4e %9.4e", update_norm, resid_norm);
840 printf(
" %s",
int2str(k).c_str());
842 for (i = 0; i < 16; i++) {
846 if (label_d !=
npos) {
849 printf(
" %s",
int2str(k).c_str());
851 printf(
" -- success\n");
853 #ifdef DEBUG_SOLVEPROB
854 else if (ioflag > 1) {
857 printf(
"\n================================== FINAL RESULT ========="
858 "==================================================\n");
860 printf(
"\n Weighted norm of solution update = %10.4e\n", update_norm);
861 printf(
" Weighted norm of residual update = %10.4e\n\n", resid_norm);
863 printf(
" Name Prod_Rate XMol Conc "
864 " wtConc Resid Resid/wtResid wtResid");
866 printf(
" UnDamped_Conc");
869 printf(
"---------------------------------------------------------------"
870 "---------------------------------------------\n");
872 for (
int k = 0; k <
m_neq; k++, k++) {
873 printf(
"%-16s %10.3e %10.3e %10.3e %10.3e %10.3e %10.3e %10.3e",
880 resid[k]/wtRes[k], wtRes[k]);
882 printf(
"%10.4e ", CSolnSP[k]+(damp-1.0)*resid[k]);
894 printf(
"==============================================================="
895 "============================================\n\n");
900 #ifdef DEBUG_SOLVEPROB
902 printIterationHeader(
int ioflag, doublereal damp,doublereal inv_t, doublereal t_real,
903 int iter,
bool do_time)
906 printf(
"\n===============================Iteration %5d "
907 "=================================\n", iter);
909 printf(
" Transient step with: Real Time_n-1 = %10.4e sec,", t_real);
910 printf(
" Time_n = %10.4e sec\n", t_real + 1.0/inv_t);
911 printf(
" Delta t = %10.4e sec", 1.0/inv_t);
913 printf(
" Steady Solve ");
916 printf(
", Damping value = %10.4e\n", damp);
924 void solveProb::setAtol(
const doublereal atol[])
926 for (
size_t k = 0; k <
m_neq; k++, k++) {
931 void solveProb::setAtolConst(
const doublereal atolconst)
933 for (
size_t k = 0; k <
m_neq; k++, k++) {
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
virtual void setBounds(const doublereal botBounds[], const doublereal topBounds[])
Set the bottom and top bounds on the solution vector.
const int SOLVEPROB_INITIALIZE
Solution Methods.
virtual void getNetProductionRates(doublereal *net)
Species net production rates [kmol/m^3/s or kmol/m^2/s].
void resize(size_t n, size_t m, doublereal v=0.0)
Resize the array, and fill the new entries with 'v'.
Declarations for a simple class that implements an Ansi C wall clock timer (see Cantera::clockWC).
virtual doublereal calc_t(doublereal netProdRateSolnSP[], doublereal Csoln[], size_t *label, size_t *label_old, doublereal *label_factor, int ioflag)
Calculate a conservative delta T to use in a pseudo-steady state algorithm.
thermo_t & thermo(size_t n=0)
This method returns a reference to the nth ThermoPhase object defined in this kinetics mechanism...
virtual doublereal calc_damping(doublereal x[], doublereal dxneg[], size_t dim, size_t *label)
This function calculates a damping factor for the Newton iteration update vector, dxneg...
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_wtSpecies
Weights for the species concentrations norm calculation.
The class provides the wall clock timer in seconds.
int solve(int ifunc, doublereal time_scale, doublereal reltol)
Main routine that actually calculates the pseudo steady state of the surface problem.
virtual void printIteration(int ioflag, doublereal damp, size_t label_d, size_t label_t, doublereal inv_t, doublereal t_real, int iter, doublereal update_norm, doublereal resid_norm, doublereal netProdRate[], doublereal CSolnSP[], doublereal resid[], doublereal wtSpecies[], size_t dim, bool do_time)
Printing routine that gets called after every iteration.
doublereal * ptrColumn(size_t j)
Return a pointer to the top of column j, columns are contiguous in memory.
size_t m_neq
Total number of equations to solve in the implicit problem.
vector_fp m_numEqn1
Temporary vector with length MAX(1, m_neq)
A class for 2D arrays stored in column-major (Fortran-compatible) form.
ResidEval * m_residFunc
residual function pointer to be solved.
Base class for a phase with thermodynamic properties.
vector_fp m_botBounds
Bottom bounds for the solution vector.
vector_fp m_CSolnSPOld
Saved solution vector at the old time step.
size_t surfacePhaseIndex()
This returns the integer index of the phase which has ThermoPhase type cSurf.
virtual void reportState(doublereal *const CSoln) const
Report the current state of the solution.
virtual int getInitialConditions(const doublereal t0, doublereal *const y, doublereal *const ydot)
Fill in the initial conditions.
Virtual base class for DAE residual function evaluators.
size_t nPhases() const
The number of phases participating in the reaction mechanism.
A kinetics manager for heterogeneous reaction mechanisms.
double secondsWC()
Returns the wall clock time in seconds since the last reset.
doublereal m_rtol
m_rtol is the relative error tolerance.
vector_fp m_atol
m_atol is the absolute tolerance in real units.
vector_fp m_resid
Residual for the surface problem.
std::string id() const
Return the string id for the phase.
vector_fp m_CSolnSP
Solution vector.
virtual int nEquations() const =0
Return the number of equations in the equation system.
size_t nSpecies() const
Returns the number of species in the phase.
virtual void fun_eval(doublereal *const resid, const doublereal *const CSolnSP, const doublereal *const CSolnSPOld, const bool do_time, const doublereal deltaT)
Main Function evaluation.
virtual 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.
std::vector< doublereal * > m_JacCol
Vector of pointers to the top of the columns of the jacobians.
vector_fp m_CSolnSPInit
Saved initial solution vector.
Header file for implicit nonlinear solver with the option of a pseudotransient (see Numerical Utiliti...
Contains declarations for string manipulation functions within Cantera.
virtual void calcWeights(doublereal wtSpecies[], doublereal wtResid[], const doublereal CSolnSP[])
Calculate the solution and residual weights.
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
vector_fp m_netProductionRatesSave
Temporary vector with length MAX(1, m_neq)
virtual void print_header(int ioflag, int ifunc, doublereal time_scale, doublereal reltol, doublereal netProdRate[])
Printing routine that gets called at the start of every invocation.
vector_fp m_CSolnSave
Temporary vector with length MAX(1, m_neq)
vector_fp m_numEqn2
Temporary vector with length MAX(1, m_neq)
virtual void printFinal(int ioflag, doublereal damp, size_t label_d, size_t label_t, doublereal inv_t, doublereal t_real, int iter, doublereal update_norm, doublereal resid_norm, doublereal netProdRateKinSpecies[], const doublereal CSolnSP[], const doublereal resid[], const doublereal wtSpecies[], const doublereal wtRes[], size_t dim, bool do_time)
Print a summary of the solution.
vector_fp m_wtResid
Weights for the residual norm calculation.
vector_fp m_topBounds
Top bounds for the solution vector.
std::string speciesName(size_t k) const
Name of the species with index k.