18 static doublereal calc_damping(doublereal* x, doublereal* dx,
size_t dim,
int*);
19 static doublereal calcWeightedNorm(
const doublereal [],
const doublereal dx[],
size_t);
24 m_SurfChemPtr(surfChemPtr),
25 m_objects(surfChemPtr->getObjects()),
29 m_numTotSurfSpecies(0),
31 m_numTotBulkSpeciesSS(0),
39 for (
size_t n = 0; n <
m_objects.size(); n++) {
42 if (surfPhaseIndex !=
npos) {
48 "InterfaceKinetics object has no surface phase");
53 "Inconsistent ThermoPhase object within "
54 "InterfaceKinetics object");
73 size_t tsp =
m_objects[n]->nTotalSpecies();
96 for (
size_t k = 0; k < nsp; k++, kindexSP++) {
103 size_t dim1 = std::max<size_t>(1,
m_neq);
114 doublereal PGas, doublereal reltol, doublereal abstol)
116 doublereal EXTRA_ACCURACY = 0.001;
118 EXTRA_ACCURACY *= 0.001;
123 doublereal label_factor = 1.0;
126 doublereal deltaT = 1.0E-10;
128 doublereal inv_t = 0.0;
129 doublereal t_real = 0.0, update_norm = 1.0E6;
130 bool do_time =
false, not_converged =
true;
131 m_ioflag = std::min(m_ioflag, 1);
155 print_header(m_ioflag, ifunc, time_scale,
true, reltol, abstol);
160 not_converged =
false;
165 while (not_converged && iter < iter_max) {
185 &label_t, &label_t_old, &label_factor, m_ioflag);
188 }
else if (tmp > 2.0*inv_t) {
196 tmp = t_real + 1.0/inv_t;
197 if (tmp > time_scale) {
198 inv_t = 1.0/(time_scale - t_real);
237 for (
size_t irow = 0; irow <
m_neq; irow++) {
240 for (
size_t irow = 0; irow <
m_neq; irow++) {
246 t_real += damp/inv_t;
250 printIteration(m_ioflag, damp, label_d, label_t, inv_t, t_real, iter,
251 update_norm, resid_norm, do_time);
255 not_converged = (t_real < time_scale);
258 if (t_real > time_scale ||
259 (resid_norm < 1.0e-7 &&
260 update_norm*time_scale/t_real < EXTRA_ACCURACY)) {
264 not_converged = ((update_norm > EXTRA_ACCURACY) ||
265 (resid_norm > EXTRA_ACCURACY));
272 if (not_converged && m_ioflag) {
273 writelog(
"#$#$#$# Error in solveSP $#$#$#$ \n");
274 writelogf(
"Newton iter on surface species did not converge, "
275 "update_norm = %e \n", update_norm);
285 printIteration(m_ioflag, damp, label_d, label_t, inv_t, t_real, iter,
286 update_norm, resid_norm, do_time,
true);
290 if (update_norm > 1.0) {
316 for (
size_t iph = 0; iph < kin->
nPhases(); iph++) {
326 doublereal Clarge = CSolnSP[kindexSP];
330 if (CSolnSP[kindexSP] > Clarge) {
331 Clarge = CSolnSP[kindexSP];
339 const doublereal* CSolnOld,
const bool do_time,
340 const doublereal deltaT)
343 doublereal lenScale = 1.0E-9;
361 size_t kins = kindexSP;
363 for (k = 0; k < nsp; k++, kindexSP++) {
365 (CSoln[kindexSP] - CSolnOld[kindexSP]) / deltaT
371 resid[kspecial] = sd;
372 for (k = 0; k < nsp; k++) {
373 resid[kspecial] -= CSoln[kins + k];
383 size_t kins = kindexSP;
385 for (k = 0; k < nsp; k++, kindexSP++) {
390 resid[kspecial] = sd;
391 for (k = 0; k < nsp; k++) {
392 resid[kspecial] -= CSoln[kins + k];
406 for (k = 0; k < nsp; k++) {
412 for (k = 0; k < nsp; k++) {
413 resid[kindexSP] -= CSoln[kindexSP + k];
416 for (k = 1; k < nsp; k++) {
418 resid[kindexSP + k] = XBlk[k] * grRate
421 resid[kindexSP + k] = XBlk[k] * grRate;
428 for (k = 1; k < nsp; k++) {
429 resid[kindexSP + k] = grRate * (XBlk[k] - 1.0/nsp);
433 for (k = 1; k < nsp; k++) {
434 resid[kindexSP + k] +=
436 (CSoln[kindexSP + k]- CSolnOld[kindexSP + k]);
446 doublereal resid[], doublereal CSoln[],
447 const doublereal CSolnOld[],
const bool do_time,
448 const doublereal deltaT)
450 size_t kColIndex = 0;
452 fun_eval(resid, CSoln, CSolnOld, do_time, deltaT);
457 for (
size_t kCol = 0; kCol < nsp; kCol++) {
458 double cSave = CSoln[kColIndex];
459 double dc = std::max(1.0E-10 * sd, fabs(cSave) * 1.0E-7);
460 CSoln[kColIndex] += dc;
462 for (
size_t i = 0; i <
m_neq; i++) {
463 jac(i, kColIndex) = (
m_numEqn2[i] - resid[i])/dc;
465 CSoln[kColIndex] = cSave;
474 for (
size_t kCol = 0; kCol < nsp; kCol++) {
475 double cSave = CSoln[kColIndex];
476 double dc = std::max(1.0E-10 * sd, fabs(cSave) * 1.0E-7);
477 CSoln[kColIndex] += dc;
479 for (
size_t i = 0; i <
m_neq; i++) {
480 jac(i, kColIndex) = (
m_numEqn2[i] - resid[i])/dc;
482 CSoln[kColIndex] = cSave;
500 static doublereal calc_damping(doublereal x[], doublereal dxneg[],
size_t dim,
int* label)
502 const doublereal APPROACH = 0.80;
503 doublereal damp = 1.0;
504 static doublereal damp_old = 1.0;
507 for (
size_t i = 0; i < dim; i++) {
509 double xnew = x[i] - damp * dxneg[i];
514 double xtop = 1.0 - 0.1*fabs(1.0-x[i]);
515 double xbot = fabs(x[i]*0.1) - 1.0e-16;
517 damp = - APPROACH * (1.0 - x[i]) / dxneg[i];
519 }
else if (xnew < xbot) {
520 damp = APPROACH * x[i] / dxneg[i];
522 }
else if (xnew > 3.0*std::max(x[i], 1.0E-10)) {
523 damp = - 2.0 * std::max(x[i], 1.0E-10) / dxneg[i];
527 damp = std::max(damp, 1e-2);
531 if (damp > damp_old*3) {
546 static doublereal calcWeightedNorm(
const doublereal wtX[],
const doublereal dx[],
size_t dim)
548 doublereal norm = 0.0;
552 for (
size_t i = 0; i < dim; i++) {
553 norm += pow(dx[i] / wtX[i], 2);
555 return sqrt(norm/dim);
559 const Array2D& Jac,
const doublereal CSoln[],
560 const doublereal abstol,
const doublereal reltol)
568 wtSpecies[kindex] = abstol * sd + reltol * fabs(CSoln[kindex]);
575 wtSpecies[kindex] = abstol * sd + reltol * fabs(CSoln[kindex]);
583 for (
size_t k = 0; k <
m_neq; k++) {
585 for (
size_t jcol = 0; jcol <
m_neq; jcol++) {
586 wtResid[k] += fabs(Jac(k,jcol) * wtSpecies[jcol]);
592 doublereal XMolSolnSP[],
593 int* label,
int* label_old,
594 doublereal* label_factor,
int ioflag)
596 doublereal inv_timeScale = 1.0E-10;
611 size_t kspindex = kstart + k;
612 netProdRateSolnSP[kindexSP] =
m_numEqn1[kspindex];
613 double tmp = std::max(XMolSolnSP[kindexSP], 1.0e-10);
615 tmp = fabs(netProdRateSolnSP[kindexSP]/ tmp);
616 if (netProdRateSolnSP[kindexSP]> 0.0) {
619 if (tmp > inv_timeScale) {
621 *label = int(kindexSP);
628 if (*label == *label_old) {
629 *label_factor *= 1.5;
634 return inv_timeScale / *label_factor;
638 int damping, doublereal reltol, doublereal abstol)
641 writelog(
"\n================================ SOLVESP CALL SETUP "
642 "========================================\n");
644 writelog(
"\n SOLVESP Called with Initialization turned on\n");
645 writelogf(
" Time scale input = %9.3e\n", time_scale);
647 writelog(
"\n SOLVESP Called to calculate steady state residual\n");
648 writelog(
" from a good initial guess\n");
650 writelog(
"\n SOLVESP Called to calculate steady state Jacobian\n");
651 writelog(
" from a good initial guess\n");
653 writelog(
"\n SOLVESP Called to integrate surface in time\n");
654 writelogf(
" for a total of %9.3e sec\n", time_scale);
657 "Unknown ifunc flag = {}", ifunc);
661 writelog(
" The composition of the Bulk Phases will be calculated\n");
663 writelog(
" Bulk Phases have fixed compositions\n");
675 writelogf(
" Reltol = %9.3e, Abstol = %9.3e\n", reltol, abstol);
679 writelog(
"\n\n\t Iter Time Del_t Damp DelX "
680 " Resid Name-Time Name-Damp\n");
681 writelog(
"\t -----------------------------------------------"
682 "------------------------------------\n");
687 int label_t, doublereal inv_t, doublereal t_real,
688 size_t iter, doublereal update_norm,
689 doublereal resid_norm,
bool do_time,
bool final)
698 writelogf(
"%9.4e %9.4e ", t_real, 1.0/inv_t);
700 writeline(
' ', 22,
false);
705 writeline(
' ', 11,
false);
707 writelogf(
"%9.4e %9.4e", update_norm, resid_norm);
713 writeline(
' ', 16,
false);