25 static doublereal calcWeightedNorm(
const doublereal [],
const doublereal dx[],
size_t);
39 size_t dim1 = std::max<size_t>(1,
m_neq);
41 m_atol.resize(dim1, 1.0E-9);
55 m_Jac.resize(dim1, dim1, 0.0);
57 for (
size_t k = 0; k < dim1; k++) {
72 doublereal EXTRA_ACCURACY = 0.001;
73 if (ifunc == SOLVEPROB_JACOBIAN) {
74 EXTRA_ACCURACY *= 0.001;
77 size_t label_t =
npos;
79 size_t label_t_old =
npos;
80 doublereal label_factor = 1.0;
83 doublereal deltaT = 1.0E-10;
84 doublereal damp=1.0, tmp;
88 doublereal resid_norm;
89 doublereal inv_t = 0.0;
90 doublereal t_real = 0.0, update_norm = 1.0E6;
92 bool do_time =
false, not_converged =
true;
94 #ifdef DEBUG_SOLVEPROB
95 #ifdef DEBUG_SOLVEPROB_TIME
104 #ifdef DEBUG_SOLVEPROB
105 #ifdef DEBUG_SOLVEPROB_TIME
142 not_converged =
false;
150 while (not_converged && iter < iter_max) {
167 &label_t, &label_t_old, &label_factor, m_ioflag);
170 }
else if (tmp > 2.0*inv_t) {
180 if (ifunc == SOLVEPROB_TRANSIENT) {
181 tmp = t_real + 1.0/inv_t;
182 if (tmp > time_scale) {
183 inv_t = 1.0/(time_scale - t_real);
214 #ifdef DEBUG_SOLVEPROB
216 printIterationHeader(m_ioflag, damp, inv_t, t_real, iter, do_time);
238 printf(
"solveSurfSS: Zero pivot, assuming converged: %g (%d)\n",
241 for (
size_t jcol = 0; jcol <
m_neq; jcol++) {
248 printf(
"solveSurfProb: iter %d t_real %g delta_t %g\n\n",
249 iter,t_real, 1.0/inv_t);
250 printf(
"solveSurfProb: init guess, current concentration,"
256 t_real += time_scale;
258 #ifdef DEBUG_SOLVEPROB
260 printf(
"\nResidual is small, forcing convergence!\n");
286 for (
size_t irow = 0; irow <
m_neq; irow++) {
292 t_real += damp/inv_t;
296 printIteration(m_ioflag, damp, label_d, label_t, inv_t, t_real, iter,
297 update_norm, resid_norm,
303 if (ifunc == SOLVEPROB_TRANSIENT) {
304 not_converged = (t_real < time_scale);
307 if (t_real > time_scale ||
308 (resid_norm < 1.0e-7 &&
309 update_norm*time_scale/t_real < EXTRA_ACCURACY)) {
311 #ifdef DEBUG_SOLVEPROB
313 printf(
"\t\tSwitching to steady solve.\n");
318 not_converged = ((update_norm > EXTRA_ACCURACY) ||
319 (resid_norm > EXTRA_ACCURACY));
330 printf(
"#$#$#$# Error in solveProb $#$#$#$ \n");
331 printf(
"Newton iter on surface species did not converge, "
332 "update_norm = %e \n", update_norm);
333 printf(
"Continuing anyway\n");
336 #ifdef DEBUG_SOLVEPROB
337 #ifdef DEBUG_SOLVEPROB_TIME
339 printf(
"\nEnd of solve, time used: %e\n", wc.
secondsWC()-t1);
354 printFinal(m_ioflag, damp, label_d, label_t, inv_t, t_real, iter,
364 if (update_norm > 1.0) {
376 const doublereal*
const CSolnOld,
const bool do_time,
377 const doublereal deltaT)
384 m_residFunc->evalSimpleTD(0.0, CSoln, CSolnOld, deltaT, resid);
391 doublereal resid[], doublereal CSoln[],
392 const doublereal CSolnOld[],
const bool do_time,
393 const doublereal deltaT)
395 doublereal dc, cSave, sd;
400 fun_eval(resid, CSoln, CSolnOld, do_time, deltaT);
405 for (
size_t kCol = 0; kCol <
m_neq; kCol++) {
407 sd = fabs(cSave) + fabs(CSoln[kCol]) +
m_atol[kCol] * 1.0E6;
411 dc = std::max(1.0E-11 * sd, fabs(cSave) * 1.0E-6);
415 col_j = JacCol[kCol];
416 for (
size_t i = 0; i <
m_neq; i++) {
426 const doublereal APPROACH = 0.50;
427 doublereal damp = 1.0, xnew, xtop, xbot;
428 static doublereal damp_old = 1.0;
431 for (
size_t i = 0; i < dim; i++) {
437 double delta_x = - dxneg[i];
438 xnew = x[i] - damp * dxneg[i];
445 bool canCrossOrigin =
false;
446 if (topBounds > 0.0 && botBounds < 0.0) {
447 canCrossOrigin =
true;
450 xtop = topBounds - 0.1 * fabs(topBounds - x[i]);
452 xbot = botBounds + 0.1 * fabs(x[i] - botBounds);
455 damp = - APPROACH * (xtop - x[i]) / dxneg[i];
457 }
else if (xnew < xbot) {
458 damp = APPROACH * (x[i] - xbot) / dxneg[i];
461 double denom = fabs(x[i]) + 1.0E5 *
m_atol[i];
462 if ((fabs(delta_x) / denom) > 0.3) {
463 double newdamp = 0.3 * denom / fabs(delta_x);
464 if (canCrossOrigin) {
465 if (xnew * x[i] < 0.0) {
466 if (fabs(x[i]) < 1.0E8 *
m_atol[i]) {
467 newdamp = 2.0 * fabs(x[i]) / fabs(delta_x);
471 damp = std::min(damp, newdamp);
480 if (damp > damp_old*3) {
498 static doublereal calcWeightedNorm(
const doublereal wtX[],
const doublereal dx[],
size_t dim)
500 doublereal norm = 0.0;
505 for (
size_t i = 0; i < dim; i++) {
506 tmp = dx[i] / wtX[i];
509 return sqrt(norm/dim);
513 const doublereal CSoln[])
519 for (
size_t k = 0; k <
m_neq; k++) {
528 for (
size_t k = 0; k <
m_neq; k++) {
530 for (
size_t jcol = 0; jcol <
m_neq; jcol++) {
531 wtResid[k] += fabs(
m_Jac(k,jcol) * wtSpecies[jcol]);
537 size_t* label,
size_t* label_old,
538 doublereal* label_factor,
int ioflag)
540 doublereal tmp, inv_timeScale=0.0;
541 for (
size_t k = 0; k <
m_neq; k++) {
542 if (Csoln[k] <= 1.0E-10) {
547 tmp = fabs(netProdRateSolnSP[k]/ tmp);
550 if (netProdRateSolnSP[k]> 0.0) {
553 if (tmp > inv_timeScale) {
563 if (*label == *label_old) {
564 *label_factor *= 1.5;
569 inv_timeScale = inv_timeScale / *label_factor;
570 #ifdef DEBUG_SOLVEPROB
572 if (*label_factor > 1.0) {
573 printf(
"Delta_t increase due to repeated controlling species = %e\n",
576 int kkin = m_kinSpecIndex[*label];
579 printf(
"calc_t: spec=%d(%s) sf=%e pr=%e dt=%e\n",
580 *label, sn.c_str(), XMolSolnSP[*label],
581 netProdRateSolnSP[*label], 1.0/inv_timeScale);
585 return inv_timeScale;
591 for (
size_t k = 0; k <
m_neq; k++) {
597 #ifdef DEBUG_SOLVEPROB
598 void solveProb::printResJac(
int ioflag,
int neq,
const Array2D& Jac,
599 doublereal resid[], doublereal wtRes[],
608 doublereal netProdRate[])
612 printf(
"\n================================ SOLVEPROB CALL SETUP "
613 "========================================\n");
615 printf(
"\n SOLVEPROB Called with Initialization turned on\n");
616 printf(
" Time scale input = %9.3e\n", time_scale);
617 }
else if (ifunc == SOLVEPROB_RESIDUAL) {
618 printf(
"\n SOLVEPROB Called to calculate steady state residual\n");
619 printf(
" from a good initial guess\n");
620 }
else if (ifunc == SOLVEPROB_JACOBIAN) {
621 printf(
"\n SOLVEPROB Called to calculate steady state Jacobian\n");
622 printf(
" from a good initial guess\n");
623 }
else if (ifunc == SOLVEPROB_TRANSIENT) {
624 printf(
"\n SOLVEPROB Called to integrate surface in time\n");
625 printf(
" for a total of %9.3e sec\n", time_scale);
628 "Unknown ifunc flag = " +
int2str(ifunc));
634 printf(
" Damping is ON \n");
636 printf(
" Damping is OFF \n");
639 printf(
" Reltol = %9.3e, Abstol = %9.3e\n", reltol,
m_atol[0]);
645 #ifdef DEBUG_SOLVEPROB
647 printf(
"\n================================ INITIAL GUESS "
648 "========================================\n");
650 for (
int isp = 0; isp < m_numSurfPhases; isp++) {
653 int nPhases = m_kin->
nPhases();
655 updateMFKinSpecies(XMolKinSpecies, isp);
657 printf(
"\n IntefaceKinetics Object # %d\n\n", isp);
659 printf(
"\t Number of Phases = %d\n", nPhases);
660 printf(
"\t Phase:SpecName Prod_Rate MoleFraction kindexSP\n");
661 printf(
"\t -------------------------------------------------------"
665 bool inSurfacePhase =
false;
666 for (
int ip = 0; ip < nPhases; ip++) {
667 if (ip == surfIndex) {
668 inSurfacePhase =
true;
670 inSurfacePhase =
false;
674 string pname = THref.
id();
675 for (
int k = 0; k < nsp; k++) {
677 string cname = pname +
":" + sname;
678 if (inSurfacePhase) {
679 printf(
"\t %-24s %10.3e %10.3e %d\n", cname.c_str(),
680 netProdRate[kspindex], XMolKinSpecies[kspindex],
684 printf(
"\t %-24s %10.3e %10.3e\n", cname.c_str(),
685 netProdRate[kspindex], XMolKinSpecies[kspindex]);
690 printf(
"=========================================================="
691 "=================================\n");
696 printf(
"\n\n\t Iter Time Del_t Damp DelX "
697 " Resid Name-Time Name-Damp\n");
698 printf(
"\t -----------------------------------------------"
699 "------------------------------------\n");
705 doublereal inv_t, doublereal t_real,
int iter,
706 doublereal update_norm, doublereal resid_norm,
707 doublereal netProdRate[], doublereal CSolnSP[],
709 doublereal wtSpecies[],
size_t dim,
bool do_time)
715 printf(
"\t%6d ", iter);
717 printf(
"%9.4e %9.4e ", t_real, 1.0/inv_t);
719 for (i = 0; i < 22; i++) {
723 printf(
"%9.4e ", damp);
725 for (i = 0; i < 11; i++) {
728 printf(
"%9.4e %9.4e", update_norm, resid_norm);
731 printf(
" %s",
int2str(k).c_str());
733 for (i = 0; i < 16; i++) {
737 if (label_d !=
npos) {
739 printf(
" %s",
int2str(k).c_str());
743 #ifdef DEBUG_SOLVEPROB
744 else if (ioflag > 1) {
746 updateMFSolnSP(XMolSolnSP);
747 printf(
"\n\t Weighted norm of update = %10.4e\n", update_norm);
749 printf(
"\t Name Prod_Rate XMol Conc "
752 printf(
" UnDamped_Conc");
755 printf(
"\t---------------------------------------------------------"
756 "-----------------------------\n");
758 for (
int isp = 0; isp < m_numSurfPhases; isp++) {
759 int nsp = m_nSpeciesSurfPhase[isp];
762 for (
int k = 0; k < nsp; k++, kindexSP++) {
763 int kspIndex = m_kinSpecIndex[kindexSP];
765 printf(
"\t%-16s %10.3e %10.3e %10.3e %10.3e %10.3e ",
768 XMolSolnSP[kindexSP],
769 CSolnSP[kindexSP], CSolnSP[kindexSP]+damp*resid[kindexSP],
770 wtSpecies[kindexSP]);
772 printf(
"%10.4e ", CSolnSP[kindexSP]+(damp-1.0)*resid[kindexSP]);
773 if (label_d == kindexSP) {
777 if (label_t == kindexSP) {
785 printf(
"\t--------------------------------------------------------"
786 "------------------------------\n");
792 doublereal inv_t, doublereal t_real,
int iter,
793 doublereal update_norm, doublereal resid_norm,
794 doublereal netProdRateKinSpecies[],
const doublereal CSolnSP[],
795 const doublereal resid[],
796 const doublereal wtSpecies[],
const doublereal wtRes[],
797 size_t dim,
bool do_time)
803 printf(
"\tFIN%3d ", iter);
805 printf(
"%9.4e %9.4e ", t_real, 1.0/inv_t);
807 for (i = 0; i < 22; i++) {
811 printf(
"%9.4e ", damp);
813 for (i = 0; i < 11; i++) {
816 printf(
"%9.4e %9.4e", update_norm, resid_norm);
819 printf(
" %s",
int2str(k).c_str());
821 for (i = 0; i < 16; i++) {
825 if (label_d !=
npos) {
828 printf(
" %s",
int2str(k).c_str());
830 printf(
" -- success\n");
832 #ifdef DEBUG_SOLVEPROB
833 else if (ioflag > 1) {
834 printf(
"\n================================== FINAL RESULT ========="
835 "==================================================\n");
837 printf(
"\n Weighted norm of solution update = %10.4e\n", update_norm);
838 printf(
" Weighted norm of residual update = %10.4e\n\n", resid_norm);
840 printf(
" Name Prod_Rate XMol Conc "
841 " wtConc Resid Resid/wtResid wtResid");
843 printf(
" UnDamped_Conc");
846 printf(
"---------------------------------------------------------------"
847 "---------------------------------------------\n");
849 for (
int k = 0; k <
m_neq; k++, k++) {
850 printf(
"%-16s %10.3e %10.3e %10.3e %10.3e %10.3e %10.3e %10.3e",
857 resid[k]/wtRes[k], wtRes[k]);
859 printf(
"%10.4e ", CSolnSP[k]+(damp-1.0)*resid[k]);
871 printf(
"==============================================================="
872 "============================================\n\n");
877 #ifdef DEBUG_SOLVEPROB
878 void solveProb::printIterationHeader(
int ioflag, doublereal damp,
879 doublereal inv_t, doublereal t_real,
880 int iter,
bool do_time)
883 printf(
"\n===============================Iteration %5d "
884 "=================================\n", iter);
886 printf(
" Transient step with: Real Time_n-1 = %10.4e sec,", t_real);
887 printf(
" Time_n = %10.4e sec\n", t_real + 1.0/inv_t);
888 printf(
" Delta t = %10.4e sec", 1.0/inv_t);
890 printf(
" Steady Solve ");
893 printf(
", Damping value = %10.4e\n", damp);
901 void solveProb::setAtol(
const doublereal atol[])
903 for (
size_t k = 0; k <
m_neq; k++, k++) {
908 void solveProb::setAtolConst(
const doublereal atolconst)
910 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.
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.
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
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.
This file contains definitions for utility functions and text for modules, inputfiles, logs, textlogs, (see Input File Handling, Diagnostic Output, and Writing messages to the screen).
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.
virtual void getNetProductionRates(doublereal *wdot)
Species net production rates [kmol/m^3/s or kmol/m^2/s].
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.
int solve(doublereal *b, size_t nrhs=1, size_t ldb=0)
Solves the Ax = b system returning x in the b spot.
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.
int factor()
Factors the A matrix, overwriting A.
std::string id() const
Return the string id for the phase.
Base class for exceptions thrown by Cantera classes.
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.
SquareMatrix m_Jac
Jacobian.
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 doublereal * ptrColumn(size_t j)
Return a pointer to the top of column j, columns are assumed to be contiguous in memory.
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.