31 static doublereal calcWeightedNorm(
const doublereal [],
const doublereal dx[],
size_t);
46 size_t dim1 = std::max<size_t>(1,
m_neq);
48 m_atol.resize(dim1, 1.0E-9);
65 for (
size_t k = 0; k < dim1; k++) {
86 doublereal EXTRA_ACCURACY = 0.001;
87 if (ifunc == SOLVEPROB_JACOBIAN) {
88 EXTRA_ACCURACY *= 0.001;
91 size_t label_t =
npos;
93 size_t label_t_old =
npos;
94 doublereal label_factor = 1.0;
98 doublereal deltaT = 1.0E-10;
99 doublereal damp=1.0, tmp;
103 doublereal resid_norm;
104 doublereal inv_t = 0.0;
105 doublereal t_real = 0.0, update_norm = 1.0E6;
107 bool do_time =
false, not_converged =
true;
109 #ifdef DEBUG_SOLVEPROB
110 #ifdef DEBUG_SOLVEPROB_TIME
119 #ifdef DEBUG_SOLVEPROB
120 #ifdef DEBUG_SOLVEPROB_TIME
157 not_converged =
false;
165 while (not_converged && iter < iter_max) {
190 &label_t, &label_t_old, &label_factor, m_ioflag);
193 }
else if (tmp > 2.0*inv_t) {
203 if (ifunc == SOLVEPROB_TRANSIENT) {
204 tmp = t_real + 1.0/inv_t;
205 if (tmp > time_scale) {
206 inv_t = 1.0/(time_scale - t_real);
237 #ifdef DEBUG_SOLVEPROB
239 printIterationHeader(m_ioflag, damp, inv_t, t_real, iter, do_time);
264 printf(
"solveSurfSS: Zero pivot, assuming converged: %g (%d)\n",
267 for (
size_t jcol = 0; jcol <
m_neq; jcol++) {
274 printf(
"solveSurfProb: iter %d t_real %g delta_t %g\n\n",
275 iter,t_real, 1.0/inv_t);
276 printf(
"solveSurfProb: init guess, current concentration,"
282 t_real += time_scale;
284 #ifdef DEBUG_SOLVEPROB
286 printf(
"\nResidual is small, forcing convergence!\n");
312 for (
size_t irow = 0; irow <
m_neq; irow++) {
318 t_real += damp/inv_t;
322 printIteration(m_ioflag, damp, label_d, label_t, inv_t, t_real, iter,
323 update_norm, resid_norm,
329 if (ifunc == SOLVEPROB_TRANSIENT) {
330 not_converged = (t_real < time_scale);
333 if (t_real > time_scale ||
334 (resid_norm < 1.0e-7 &&
335 update_norm*time_scale/t_real < EXTRA_ACCURACY)) {
337 #ifdef DEBUG_SOLVEPROB
339 printf(
"\t\tSwitching to steady solve.\n");
344 not_converged = ((update_norm > EXTRA_ACCURACY) ||
345 (resid_norm > EXTRA_ACCURACY));
356 printf(
"#$#$#$# Error in solveProb $#$#$#$ \n");
357 printf(
"Newton iter on surface species did not converge, "
358 "update_norm = %e \n", update_norm);
359 printf(
"Continuing anyway\n");
362 #ifdef DEBUG_SOLVEPROB
363 #ifdef DEBUG_SOLVEPROB_TIME
365 printf(
"\nEnd of solve, time used: %e\n", wc.
secondsWC()-t1);
380 printFinal(m_ioflag, damp, label_d, label_t, inv_t, t_real, iter,
390 if (update_norm > 1.0) {
415 const doublereal*
const CSolnOld,
const bool do_time,
416 const doublereal deltaT)
419 m_residFunc->evalSimpleTD(0.0, CSoln, CSolnOld, deltaT, resid);
433 doublereal resid[], doublereal CSoln[],
434 const doublereal CSolnOld[],
const bool do_time,
435 const doublereal deltaT)
437 doublereal dc, cSave, sd;
442 fun_eval(resid, CSoln, CSolnOld, do_time, deltaT);
447 for (
size_t kCol = 0; kCol <
m_neq; kCol++) {
449 sd = fabs(cSave) + fabs(CSoln[kCol]) +
m_atol[kCol] * 1.0E6;
453 dc =
std::max(1.0E-11 * sd, fabs(cSave) * 1.0E-6);
456 col_j = JacCol[kCol];
457 for (
size_t i = 0; i <
m_neq; i++) {
465 #define APPROACH 0.50
486 doublereal damp = 1.0, xnew, xtop, xbot;
487 static doublereal damp_old = 1.0;
490 for (
size_t i = 0; i < dim; i++) {
496 double delta_x = - dxneg[i];
497 xnew = x[i] - damp * dxneg[i];
504 bool canCrossOrigin =
false;
505 if (topBounds > 0.0 && botBounds < 0.0) {
506 canCrossOrigin =
true;
509 xtop = topBounds - 0.1 * fabs(topBounds - x[i]);
511 xbot = botBounds + 0.1 * fabs(x[i] - botBounds);
514 damp = - APPROACH * (xtop - x[i]) / dxneg[i];
516 }
else if (xnew < xbot) {
517 damp = APPROACH * (x[i] - xbot) / dxneg[i];
524 double denom = fabs(x[i]) + 1.0E5 *
m_atol[i];
525 if ((fabs(delta_x) / denom) > 0.3) {
526 double newdamp = 0.3 * denom / fabs(delta_x);
527 if (canCrossOrigin) {
528 if (xnew * x[i] < 0.0) {
529 if (fabs(x[i]) < 1.0E8 *
m_atol[i]) {
530 newdamp = 2.0 * fabs(x[i]) / fabs(delta_x);
543 if (damp > damp_old*3) {
562 static doublereal calcWeightedNorm(
const doublereal wtX[],
const doublereal dx[],
size_t dim)
564 doublereal norm = 0.0;
569 for (
size_t i = 0; i < dim; i++) {
570 tmp = dx[i] / wtX[i];
573 return (sqrt(norm/dim));
582 const doublereal CSoln[])
588 for (
size_t k = 0; k <
m_neq; k++) {
597 for (
size_t k = 0; k <
m_neq; k++) {
599 for (
size_t jcol = 0; jcol <
m_neq; jcol++) {
600 wtResid[k] += fabs(
m_Jac(k,jcol) * wtSpecies[jcol]);
617 calc_t(doublereal netProdRateSolnSP[], doublereal Csoln[],
618 size_t* label,
size_t* label_old, doublereal* label_factor,
int ioflag)
620 doublereal tmp, inv_timeScale=0.0;
621 for (
size_t k = 0; k <
m_neq; k++) {
622 if (Csoln[k] <= 1.0E-10) {
627 tmp = fabs(netProdRateSolnSP[k]/ tmp);
630 if (netProdRateSolnSP[k]> 0.0) {
633 if (tmp > inv_timeScale) {
643 if (*label == *label_old) {
644 *label_factor *= 1.5;
649 inv_timeScale = inv_timeScale / *label_factor;
650 #ifdef DEBUG_SOLVEPROB
652 if (*label_factor > 1.0) {
653 printf(
"Delta_t increase due to repeated controlling species = %e\n",
656 int kkin = m_kinSpecIndex[*label];
659 printf(
"calc_t: spec=%d(%s) sf=%e pr=%e dt=%e\n",
660 *label, sn.c_str(), XMolSolnSP[*label],
661 netProdRateSolnSP[*label], 1.0/inv_timeScale);
665 return (inv_timeScale);
678 for (
size_t k = 0; k <
m_neq; k++) {
688 #ifdef DEBUG_SOLVEPROB
689 void solveProb::printResJac(
int ioflag,
int neq,
const Array2D& Jac,
690 doublereal resid[], doublereal wtRes[],
702 doublereal netProdRate[])
706 printf(
"\n================================ SOLVEPROB CALL SETUP "
707 "========================================\n");
709 printf(
"\n SOLVEPROB Called with Initialization turned on\n");
710 printf(
" Time scale input = %9.3e\n", time_scale);
711 }
else if (ifunc == SOLVEPROB_RESIDUAL) {
712 printf(
"\n SOLVEPROB Called to calculate steady state residual\n");
713 printf(
" from a good initial guess\n");
714 }
else if (ifunc == SOLVEPROB_JACOBIAN) {
715 printf(
"\n SOLVEPROB Called to calculate steady state jacobian\n");
716 printf(
" from a good initial guess\n");
717 }
else if (ifunc == SOLVEPROB_TRANSIENT) {
718 printf(
"\n SOLVEPROB Called to integrate surface in time\n");
719 printf(
" for a total of %9.3e sec\n", time_scale);
721 fprintf(stderr,
"Unknown ifunc flag = %d\n", ifunc);
728 printf(
" Damping is ON \n");
730 printf(
" Damping is OFF \n");
733 printf(
" Reltol = %9.3e, Abstol = %9.3e\n", reltol,
m_atol[0]);
739 #ifdef DEBUG_SOLVEPROB
741 printf(
"\n================================ INITIAL GUESS "
742 "========================================\n");
744 for (
int isp = 0; isp < m_numSurfPhases; isp++) {
747 int nPhases = m_kin->
nPhases();
749 updateMFKinSpecies(XMolKinSpecies, isp);
751 printf(
"\n IntefaceKinetics Object # %d\n\n", isp);
753 printf(
"\t Number of Phases = %d\n", nPhases);
754 printf(
"\t Phase:SpecName Prod_Rate MoleFraction kindexSP\n");
755 printf(
"\t -------------------------------------------------------"
759 bool inSurfacePhase =
false;
760 for (
int ip = 0; ip < nPhases; ip++) {
761 if (ip == surfIndex) {
762 inSurfacePhase =
true;
764 inSurfacePhase =
false;
768 string pname = THref.
id();
769 for (
int k = 0; k < nsp; k++) {
771 string cname = pname +
":" + sname;
772 if (inSurfacePhase) {
773 printf(
"\t %-24s %10.3e %10.3e %d\n", cname.c_str(),
774 netProdRate[kspindex], XMolKinSpecies[kspindex],
778 printf(
"\t %-24s %10.3e %10.3e\n", cname.c_str(),
779 netProdRate[kspindex], XMolKinSpecies[kspindex]);
784 printf(
"=========================================================="
785 "=================================\n");
790 printf(
"\n\n\t Iter Time Del_t Damp DelX "
791 " Resid Name-Time Name-Damp\n");
792 printf(
"\t -----------------------------------------------"
793 "------------------------------------\n");
799 doublereal inv_t, doublereal t_real,
int iter,
800 doublereal update_norm, doublereal resid_norm,
801 doublereal netProdRate[], doublereal CSolnSP[],
803 doublereal wtSpecies[],
size_t dim,
bool do_time)
809 printf(
"\t%6d ", iter);
811 printf(
"%9.4e %9.4e ", t_real, 1.0/inv_t);
813 for (i = 0; i < 22; i++) {
817 printf(
"%9.4e ", damp);
819 for (i = 0; i < 11; i++) {
822 printf(
"%9.4e %9.4e", update_norm, resid_norm);
825 printf(
" %s",
int2str(k).c_str());
827 for (i = 0; i < 16; i++) {
831 if (label_d !=
npos) {
833 printf(
" %s",
int2str(k).c_str());
837 #ifdef DEBUG_SOLVEPROB
838 else if (ioflag > 1) {
840 updateMFSolnSP(XMolSolnSP);
841 printf(
"\n\t Weighted norm of update = %10.4e\n", update_norm);
843 printf(
"\t Name Prod_Rate XMol Conc "
846 printf(
" UnDamped_Conc");
849 printf(
"\t---------------------------------------------------------"
850 "-----------------------------\n");
852 for (
int isp = 0; isp < m_numSurfPhases; isp++) {
853 int nsp = m_nSpeciesSurfPhase[isp];
857 for (
int k = 0; k < nsp; k++, kindexSP++) {
858 int kspIndex = m_kinSpecIndex[kindexSP];
860 printf(
"\t%-16s %10.3e %10.3e %10.3e %10.3e %10.3e ",
863 XMolSolnSP[kindexSP],
864 CSolnSP[kindexSP], CSolnSP[kindexSP]+damp*resid[kindexSP],
865 wtSpecies[kindexSP]);
867 printf(
"%10.4e ", CSolnSP[kindexSP]+(damp-1.0)*resid[kindexSP]);
868 if (label_d == kindexSP) {
872 if (label_t == kindexSP) {
880 printf(
"\t--------------------------------------------------------"
881 "------------------------------\n");
888 doublereal inv_t, doublereal t_real,
int iter,
889 doublereal update_norm, doublereal resid_norm,
890 doublereal netProdRateKinSpecies[],
const doublereal CSolnSP[],
891 const doublereal resid[],
892 const doublereal wtSpecies[],
const doublereal wtRes[],
893 size_t dim,
bool do_time)
899 printf(
"\tFIN%3d ", iter);
901 printf(
"%9.4e %9.4e ", t_real, 1.0/inv_t);
903 for (i = 0; i < 22; i++) {
907 printf(
"%9.4e ", damp);
909 for (i = 0; i < 11; i++) {
912 printf(
"%9.4e %9.4e", update_norm, resid_norm);
915 printf(
" %s",
int2str(k).c_str());
917 for (i = 0; i < 16; i++) {
921 if (label_d !=
npos) {
924 printf(
" %s",
int2str(k).c_str());
926 printf(
" -- success\n");
928 #ifdef DEBUG_SOLVEPROB
929 else if (ioflag > 1) {
932 printf(
"\n================================== FINAL RESULT ========="
933 "==================================================\n");
935 printf(
"\n Weighted norm of solution update = %10.4e\n", update_norm);
936 printf(
" Weighted norm of residual update = %10.4e\n\n", resid_norm);
938 printf(
" Name Prod_Rate XMol Conc "
939 " wtConc Resid Resid/wtResid wtResid");
941 printf(
" UnDamped_Conc");
944 printf(
"---------------------------------------------------------------"
945 "---------------------------------------------\n");
947 for (
int k = 0; k <
m_neq; k++, k++) {
948 printf(
"%-16s %10.3e %10.3e %10.3e %10.3e %10.3e %10.3e %10.3e",
955 resid[k]/wtRes[k], wtRes[k]);
957 printf(
"%10.4e ", CSolnSP[k]+(damp-1.0)*resid[k]);
969 printf(
"==============================================================="
970 "============================================\n\n");
975 #ifdef DEBUG_SOLVEPROB
977 printIterationHeader(
int ioflag, doublereal damp,doublereal inv_t, doublereal t_real,
978 int iter,
bool do_time)
981 printf(
"\n===============================Iteration %5d "
982 "=================================\n", iter);
984 printf(
" Transient step with: Real Time_n-1 = %10.4e sec,", t_real);
985 printf(
" Time_n = %10.4e sec\n", t_real + 1.0/inv_t);
986 printf(
" Delta t = %10.4e sec", 1.0/inv_t);
988 printf(
" Steady Solve ");
991 printf(
", Damping value = %10.4e\n", damp);
999 void solveProb::setAtol(
const doublereal atol[])
1001 for (
size_t k = 0; k <
m_neq; k++, k++) {
1006 void solveProb::setAtolConst(
const doublereal atolconst)
1008 for (
size_t k = 0; k <
m_neq; k++, k++) {