31 static doublereal calc_damping(doublereal* x, doublereal* dx,
size_t dim,
int*);
32 static doublereal calcWeightedNorm(
const doublereal [],
const doublereal dx[],
size_t);
41 m_SurfChemPtr(surfChemPtr),
42 m_objects(surfChemPtr->getObjects()),
46 m_numTotSurfSpecies(0),
48 m_numTotBulkSpeciesSS(0),
57 size_t numPossibleSurfPhases =
m_objects.size();
58 for (
size_t n = 0; n < numPossibleSurfPhases; n++) {
61 if (surfPhaseIndex !=
npos) {
67 "InterfaceKinetics object has no surface phase");
73 "Inconsistent ThermoPhase object within "
74 "InterfaceKinetics object");
88 if (bulkFunc == BULK_DEPOSITION) {
96 size_t tsp =
m_objects[n]->nTotalSpecies();
115 size_t isp, k, nsp, kstart;
123 for (k = 0; k < nsp; k++, kindexSP++) {
130 size_t dim1 = std::max<size_t>(1,
m_neq);
141 for (
size_t k = 0; k < dim1; k++) {
159 doublereal PGas, doublereal reltol, doublereal abstol)
161 doublereal EXTRA_ACCURACY = 0.001;
162 if (ifunc == SFLUX_JACOBIAN) {
163 EXTRA_ACCURACY *= 0.001;
169 doublereal label_factor = 1.0;
173 doublereal deltaT = 1.0E-10;
174 doublereal damp=1.0, tmp;
177 doublereal resid_norm;
178 doublereal inv_t = 0.0;
179 doublereal t_real = 0.0, update_norm = 1.0E6;
181 bool do_time =
false, not_converged =
true;
203 for (
size_t k = 0; k <nsp; k++) {
219 print_header(m_ioflag, ifunc, time_scale,
true, reltol, abstol,
228 not_converged =
false;
236 while (not_converged && iter < iter_max) {
262 &label_t, &label_t_old, &label_factor, m_ioflag);
265 }
else if (tmp > 2.0*inv_t) {
275 if (ifunc == SFLUX_TRANSIENT) {
276 tmp = t_real + 1.0/inv_t;
277 if (tmp > time_scale) {
278 inv_t = 1.0/(time_scale - t_real);
325 printf(
"solveSurfSS: Zero pivot, assuming converged: %g (%d)\n",
328 for (
size_t jcol = 0; jcol <
m_neq; jcol++) {
335 printf(
"solveSurfProb: iter %d t_real %g delta_t %g\n\n",
336 iter,t_real, 1.0/inv_t);
337 printf(
"solveSurfProb: init guess, current concentration,"
339 for (
size_t jcol = 0; jcol <
m_neq; jcol++) {
340 printf(
"\t%s %g %g %g\n",
int2str(jcol).c_str(),
347 t_real += time_scale;
370 for (
size_t irow = 0; irow <
m_neq; irow++) {
373 for (
size_t irow = 0; irow <
m_neq; irow++) {
379 t_real += damp/inv_t;
383 printIteration(m_ioflag, damp, label_d, label_t, inv_t, t_real, iter,
384 update_norm, resid_norm,
391 if (ifunc == SFLUX_TRANSIENT) {
392 not_converged = (t_real < time_scale);
395 if (t_real > time_scale ||
396 (resid_norm < 1.0e-7 &&
397 update_norm*time_scale/t_real < EXTRA_ACCURACY)) {
401 not_converged = ((update_norm > EXTRA_ACCURACY) ||
402 (resid_norm > EXTRA_ACCURACY));
413 printf(
"#$#$#$# Error in solveSP $#$#$#$ \n");
414 printf(
"Newton iter on surface species did not converge, "
415 "update_norm = %e \n", update_norm);
416 printf(
"Continuing anyway\n");
430 printFinal(m_ioflag, damp, label_d, label_t, inv_t, t_real, iter,
441 if (update_norm > 1.0) {
478 for (
size_t iph = 0; iph < nph; iph++) {
494 doublereal Clarge = CSolnSP[kindexSP];
497 for (
size_t k = 1; k < nsp; k++, kindexSP++) {
498 if (CSolnSP[kindexSP] > Clarge) {
499 Clarge = CSolnSP[kindexSP];
517 const doublereal* CSolnOld,
const bool do_time,
518 const doublereal deltaT)
520 size_t isp, nsp, kstart, k, kindexSP, kins, kspecial;
521 doublereal lenScale = 1.0E-9;
547 for (k = 0; k < nsp; k++, kindexSP++) {
549 (CSoln[kindexSP] - CSolnOld[kindexSP]) / deltaT
555 resid[kspecial] = sd;
556 for (k = 0; k < nsp; k++) {
557 resid[kspecial] -= CSoln[kins + k];
569 for (k = 0; k < nsp; k++, kindexSP++) {
574 resid[kspecial] = sd;
575 for (k = 0; k < nsp; k++) {
576 resid[kspecial] -= CSoln[kins + k];
592 for (k = 0; k < nsp; k++) {
598 for (k = 0; k < nsp; k++) {
599 resid[kindexSP] -= CSoln[kindexSP + k];
602 for (k = 1; k < nsp; k++) {
604 resid[kindexSP + k] = XBlk[k] * grRate
607 resid[kindexSP + k] = XBlk[k] * grRate;
613 for (k = 1; k < nsp; k++) {
614 resid[kindexSP + k] = grRate * (XBlk[k] - 1.0/nsp);
618 for (k = 1; k < nsp; k++) {
619 resid[kindexSP + k] +=
621 (CSoln[kindexSP + k]- CSolnOld[kindexSP + k]);
638 doublereal resid[], doublereal CSoln[],
639 const doublereal CSolnOld[],
const bool do_time,
640 const doublereal deltaT)
642 size_t kColIndex = 0, nsp, jsp, i, kCol;
643 doublereal dc, cSave, sd;
648 fun_eval(resid, CSoln, CSolnOld, do_time, deltaT);
655 for (kCol = 0; kCol < nsp; kCol++) {
656 cSave = CSoln[kColIndex];
657 dc =
std::max(1.0E-10 * sd, fabs(cSave) * 1.0E-7);
658 CSoln[kColIndex] += dc;
660 col_j = JacCol[kColIndex];
661 for (i = 0; i <
m_neq; i++) {
664 CSoln[kColIndex] = cSave;
673 for (kCol = 0; kCol < nsp; kCol++) {
674 cSave = CSoln[kColIndex];
675 dc =
std::max(1.0E-10 * sd, fabs(cSave) * 1.0E-7);
676 CSoln[kColIndex] += dc;
678 col_j = JacCol[kColIndex];
679 for (i = 0; i <
m_neq; i++) {
682 CSoln[kColIndex] = cSave;
690 #define APPROACH 0.80
692 static doublereal calc_damping(doublereal x[], doublereal dxneg[],
size_t dim,
int* label)
706 doublereal damp = 1.0, xnew, xtop, xbot;
707 static doublereal damp_old = 1.0;
711 for (
size_t i = 0; i < dim; i++) {
717 xnew = x[i] - damp * dxneg[i];
725 xtop = 1.0 - 0.1*fabs(1.0-x[i]);
726 xbot = fabs(x[i]*0.1) - 1.0e-16;
728 damp = - APPROACH * (1.0 - x[i]) / dxneg[i];
730 }
else if (xnew < xbot) {
731 damp = APPROACH * x[i] / dxneg[i];
733 }
else if (xnew > 3.0*
std::max(x[i], 1.0E-10)) {
734 damp = - 2.0 *
std::max(x[i], 1.0E-10) / dxneg[i];
747 if (damp > damp_old*3) {
767 static doublereal calcWeightedNorm(
const doublereal wtX[],
const doublereal dx[],
size_t dim)
769 doublereal norm = 0.0;
774 for (
size_t i = 0; i < dim; i++) {
775 tmp = dx[i] / wtX[i];
778 return (sqrt(norm/dim));
787 const Array2D& Jac,
const doublereal CSoln[],
788 const doublereal abstol,
const doublereal reltol)
790 size_t k, jcol, kindex, isp, nsp;
800 for (k = 0; k < nsp; k++, kindex++) {
801 wtSpecies[kindex] = abstol * sd + reltol * fabs(CSoln[kindex]);
808 for (k = 0; k < nsp; k++, kindex++) {
809 wtSpecies[kindex] = abstol * sd + reltol * fabs(CSoln[kindex]);
819 for (k = 0; k <
m_neq; k++) {
821 for (jcol = 0; jcol <
m_neq; jcol++) {
822 wtResid[k] += fabs(Jac(k,jcol) * wtSpecies[jcol]);
839 calc_t(doublereal netProdRateSolnSP[], doublereal XMolSolnSP[],
840 int* label,
int* label_old, doublereal* label_factor,
int ioflag)
842 size_t k, isp, nsp, kstart;
843 doublereal inv_timeScale = 1.0E-10;
844 doublereal sden, tmp;
863 for (k = 0; k < nsp; k++, kindexSP++) {
864 size_t kspindex = kstart + k;
865 netProdRateSolnSP[kindexSP] =
m_numEqn1[kspindex];
866 if (XMolSolnSP[kindexSP] <= 1.0E-10) {
869 tmp = XMolSolnSP[kindexSP];
872 tmp = fabs(netProdRateSolnSP[kindexSP]/ tmp);
873 if (netProdRateSolnSP[kindexSP]> 0.0) {
876 if (tmp > inv_timeScale) {
878 *label = int(kindexSP);
887 if (*label == *label_old) {
888 *label_factor *= 1.5;
893 inv_timeScale = inv_timeScale / *label_factor;
894 return (inv_timeScale);
902 int damping, doublereal reltol, doublereal abstol,
904 doublereal PGas, doublereal netProdRate[],
905 doublereal XMolKinSpecies[])
908 printf(
"\n================================ SOLVESP CALL SETUP "
909 "========================================\n");
911 printf(
"\n SOLVESP Called with Initialization turned on\n");
912 printf(
" Time scale input = %9.3e\n", time_scale);
913 }
else if (ifunc == SFLUX_RESIDUAL) {
914 printf(
"\n SOLVESP Called to calculate steady state residual\n");
915 printf(
" from a good initial guess\n");
916 }
else if (ifunc == SFLUX_JACOBIAN) {
917 printf(
"\n SOLVESP Called to calculate steady state jacobian\n");
918 printf(
" from a good initial guess\n");
919 }
else if (ifunc == SFLUX_TRANSIENT) {
920 printf(
"\n SOLVESP Called to integrate surface in time\n");
921 printf(
" for a total of %9.3e sec\n", time_scale);
923 fprintf(stderr,
"Unknown ifunc flag = %d\n", ifunc);
928 printf(
" The composition of the Bulk Phases will be calculated\n");
930 printf(
" Bulk Phases have fixed compositions\n");
932 fprintf(stderr,
"Unknown bulkFunc flag = %d\n",
m_bulkFunc);
937 printf(
" Damping is ON \n");
939 printf(
" Damping is OFF \n");
942 printf(
" Reltol = %9.3e, Abstol = %9.3e\n", reltol, abstol);
946 printf(
"\n\n\t Iter Time Del_t Damp DelX "
947 " Resid Name-Time Name-Damp\n");
948 printf(
"\t -----------------------------------------------"
949 "------------------------------------\n");
955 doublereal inv_t, doublereal t_real,
size_t iter,
956 doublereal update_norm, doublereal resid_norm,
957 doublereal netProdRate[], doublereal CSolnSP[],
958 doublereal resid[], doublereal XMolSolnSP[],
959 doublereal wtSpecies[],
size_t dim,
bool do_time)
965 printf(
"\t%6s ",
int2str(iter).c_str());
967 printf(
"%9.4e %9.4e ", t_real, 1.0/inv_t);
969 for (i = 0; i < 22; i++) {
973 printf(
"%9.4e ", damp);
975 for (i = 0; i < 11; i++) {
978 printf(
"%9.4e %9.4e", update_norm, resid_norm);
984 printf(
" %-16s", nm.c_str());
986 for (i = 0; i < 16; i++) {
995 printf(
" %-16s", nm.c_str());
1003 doublereal inv_t, doublereal t_real,
size_t iter,
1004 doublereal update_norm, doublereal resid_norm,
1005 doublereal netProdRateKinSpecies[],
const doublereal CSolnSP[],
1006 const doublereal resid[], doublereal XMolSolnSP[],
1007 const doublereal wtSpecies[],
const doublereal wtRes[],
1008 size_t dim,
bool do_time,
1009 doublereal TKelvin, doublereal PGas)
1015 printf(
"\tFIN%3s ",
int2str(iter).c_str());
1017 printf(
"%9.4e %9.4e ", t_real, 1.0/inv_t);
1019 for (i = 0; i < 22; i++) {
1023 printf(
"%9.4e ", damp);
1025 for (i = 0; i < 11; i++) {
1028 printf(
"%9.4e %9.4e", update_norm, resid_norm);
1034 printf(
" %-16s", nm.c_str());
1036 for (i = 0; i < 16; i++) {
1045 printf(
" %-16s", nm.c_str());
1047 printf(
" -- success\n");