35 bool NonlinearSolver::s_TurnOffTiming(
false);
38 bool NonlinearSolver::s_print_NumJac(
true);
40 bool NonlinearSolver::s_print_NumJac(
false);
44 bool NonlinearSolver::s_print_DogLeg(
false);
50 bool NonlinearSolver::s_doBothSolvesAndCompare(
false);
56 bool NonlinearSolver::s_alwaysAssumeNewtonGood(
false);
62 m_manualDeltaStepSet(0),
64 m_normResid_Bound(0.0),
66 m_normDeltaSoln_Newton(0.0),
67 m_normDeltaSoln_CP(0.0),
68 m_normResidTrial(0.0),
69 m_resid_scaled(false),
76 m_numTotalLinearSolves(0),
80 m_jacFormMethod(NSOLN_JAC_NUM),
83 m_matrixConditioning(0),
87 userResidRtol_(1.0E-3),
88 checkUserResidualTols_(0),
90 m_ScaleSolnNormToResNorm(0.001),
93 residNorm2Cauchy_(0.0),
100 norm_deltaX_trust_(0.0),
102 trustRegionInitializationMethod_(2),
103 trustRegionInitializationFactor_(1.0),
110 normTrust_Newton_(0.0),
114 CurrentTrustFactor_(1.0),
115 NextTrustFactor_(1.0),
116 ResidWtsReevaluated_(false),
117 ResidDecreaseSDExp_(0.0),
118 ResidDecreaseSD_(0.0),
119 ResidDecreaseNewtExp_(0.0),
120 ResidDecreaseNewt_(0.0)
122 warn_deprecated(
"class NonlinearSolver",
"To be removed after Cantera 2.2.");
145 doublereal hb = std::numeric_limits<double>::max();
149 for (
size_t i = 0; i <
neq_; i++) {
155 Jd_.resize(neq_, 0.0);
160 m_func(right.m_func),
163 m_manualDeltaStepSet(0),
165 m_normResid_Bound(0.0),
167 m_normDeltaSoln_Newton(0.0),
168 m_normDeltaSoln_CP(0.0),
169 m_normResidTrial(0.0),
170 m_resid_scaled(false),
177 m_numTotalLinearSolves(0),
178 m_numTotalNewtIts(0),
181 m_jacFormMethod(NSOLN_JAC_NUM),
184 m_matrixConditioning(0),
188 userResidRtol_(1.0E-3),
189 checkUserResidualTols_(0),
191 m_ScaleSolnNormToResNorm(0.001),
194 residNorm2Cauchy_(0.0),
199 norm_deltaX_trust_(0.0),
201 trustRegionInitializationMethod_(2),
202 trustRegionInitializationFactor_(1.0),
209 normTrust_Newton_(0.0),
213 CurrentTrustFactor_(1.0),
214 NextTrustFactor_(1.0),
215 ResidWtsReevaluated_(false),
216 ResidDecreaseSDExp_(0.0),
217 ResidDecreaseSD_(0.0),
218 ResidDecreaseNewtExp_(0.0),
219 ResidDecreaseNewt_(0.0)
232 if (
this == &right) {
333 for (
size_t i = 0; i <
neq_; i++) {
335 if (DEBUG_MODE_ENABLED &&
m_ewt[i] <= 0.0) {
336 throw CanteraError(
" NonlinearSolver::createSolnWeights()",
"ewts <= 0.0");
342 const doublereal*
const y_high_bounds)
344 for (
size_t i = 0; i <
neq_; i++) {
367 const doublereal dampFactor)
const
369 doublereal sum_norm = 0.0,
error;
370 for (
size_t i = 0; i <
neq_; i++) {
374 sum_norm = sqrt(sum_norm / neq_);
378 printf(
"\t\t solnErrorNorm(): ");
382 printf(
" Delta soln norm ");
384 printf(
" = %-11.4E\n", sum_norm);
389 const int num_entries = printLargest;
392 printf(
"\t\t solnErrorNorm(): ");
396 printf(
" Delta soln norm ");
398 printf(
" = %-11.4E\n", sum_norm);
400 doublereal dmax1, normContrib;
402 std::vector<size_t> imax(num_entries,
npos);
403 printf(
"\t\t Printout of Largest Contributors: (damp = %g)\n", dampFactor);
404 printf(
"\t\t I weightdeltaY/sqtN| deltaY "
405 "ysolnOld ysolnNew Soln_Weights\n");
409 for (
int jnum = 0; jnum < num_entries; jnum++) {
411 for (
size_t i = 0; i <
neq_; i++) {
413 for (j = 0; j < jnum; j++) {
421 if (normContrib > dmax1) {
427 size_t i = imax[jnum];
431 printf(
"\t\t %4s %12.4e | %12.4e %12.4e %12.4e %12.4e\n",
int2str(i).c_str(), normContrib/sqrt((
double)neq_),
444 const doublereal*
const y)
const
446 doublereal sum_norm = 0.0,
error;
448 for (
size_t i = 0; i <
neq_; i++) {
449 if (DEBUG_MODE_ENABLED) {
453 if (DEBUG_MODE_ENABLED) {
458 sum_norm = sqrt(sum_norm / neq_);
459 if (DEBUG_MODE_ENABLED) {
463 const int num_entries = printLargest;
464 doublereal dmax1, normContrib;
466 std::vector<size_t> imax(num_entries,
npos);
469 printf(
"\t\t residErrorNorm():");
471 printf(
" %s ", title);
473 printf(
" residual L2 norm ");
475 printf(
"= %12.4E\n", sum_norm);
480 printf(
"\t\t residErrorNorm(): ");
482 printf(
" %s ", title);
484 printf(
" residual L2 norm ");
486 printf(
"= %12.4E\n", sum_norm);
487 printf(
"\t\t Printout of Largest Contributors to norm:\n");
488 printf(
"\t\t I |Resid/ResWt| UnsclRes ResWt | y_curr\n");
491 for (
int jnum = 0; jnum < num_entries; jnum++) {
493 for (
size_t i = 0; i <
neq_; i++) {
495 for (j = 0; j < jnum; j++) {
503 if (normContrib > dmax1) {
509 size_t i = imax[jnum];
513 printf(
"\t\t %4s %12.4e %12.4e %12.4e | %12.4e\n",
int2str(i).c_str(), normContrib, resid[i],
m_residWts[i], y[i]);
529 for (
size_t i = 0; i <
neq_; i++) {
532 throw CanteraError(
"NonlinearSolver::setColumnScaling() ERROR",
"Bad column scale factor");
551 for (
size_t i = 0; i <
neq_; i++) {
555 for (
size_t i = 0; i <
neq_; i++) {
574 doublereal time_curr,
int num_newt_its)
597 doublereal* jptr = &(*(jac.
begin()));
598 for (jcol = 0; jcol < (int)
neq_; jcol++) {
599 for (irow = 0; irow < (int)
neq_; irow++) {
605 int kl =
static_cast<int>(ivec[0]);
606 int ku =
static_cast<int>(ivec[1]);
607 for (jcol = 0; jcol < (int)
neq_; jcol++) {
608 colP_j = (doublereal*) jac.
ptrColumn(jcol);
609 for (irow = jcol - ku; irow <= jcol + kl; irow++) {
610 if (irow >= 0 && irow < (
int)
neq_) {
611 colP_j[kl + ku + irow - jcol] *=
m_colScales[jcol];
628 doublereal* jptr = &(*(jac.
begin()));
629 for (irow = 0; irow < (int)
neq_; irow++) {
634 for (jcol = 0; jcol < (int)
neq_; jcol++) {
635 for (irow = 0; irow < (int)
neq_; irow++) {
646 if (DEBUG_MODE_ENABLED) {
653 int kl =
static_cast<int>(ivec[0]);
654 int ku =
static_cast<int>(ivec[1]);
655 for (jcol = 0; jcol < (int)
neq_; jcol++) {
656 colP_j = (doublereal*) jac.
ptrColumn(jcol);
657 for (irow = jcol - ku; irow <= jcol + kl; irow++) {
658 if (irow >= 0 && irow < (
int)
neq_) {
659 double vv = fabs(colP_j[kl + ku + irow - jcol]);
670 if (DEBUG_MODE_ENABLED) {
678 for (irow = 0; irow < (int)
neq_; irow++) {
682 for (irow = 0; irow < (int)
neq_; irow++) {
691 jptr = &(*(jac.
begin()));
692 for (jcol = 0; jcol < (int)
neq_; jcol++) {
693 for (irow = 0; irow < (int)
neq_; irow++) {
699 int kl =
static_cast<int>(ivec[0]);
700 int ku =
static_cast<int>(ivec[1]);
701 for (jcol = 0; jcol < (int)
neq_; jcol++) {
702 colP_j = (doublereal*) jac.
ptrColumn(jcol);
703 for (irow = jcol - ku; irow <= jcol + kl; irow++) {
704 if (irow >= 0 && irow < (
int)
neq_) {
705 colP_j[kl + ku + irow - jcol] *=
m_rowScales[irow];
712 if (num_newt_its % 5 == 1) {
724 doublereal sum = 0.0;
725 for (
size_t irow = 0; irow <
neq_; irow++) {
730 for (
size_t irow = 0; irow <
neq_; irow++) {
734 for (
size_t irow = 0; irow <
neq_; irow++) {
739 for (
size_t irow = 0; irow <
neq_; irow++) {
745 for (
size_t irow = 0; irow <
neq_; irow++) {
748 doublereal* jptr = &((*jacCopyPtr_)(0,0));
749 for (
size_t jcol = 0; jcol <
neq_; jcol++) {
750 for (
size_t irow = 0; irow <
neq_; irow++) {
755 doublereal resNormOld = 0.0;
758 for (
size_t irow = 0; irow <
neq_; irow++) {
760 resNormOld += error *
error;
762 resNormOld = sqrt(resNormOld / neq_);
764 if (resNormOld > 0.0) {
772 throw CanteraError(
"NonlinearSolver::calcSolnToResNormVector()" ,
"Logic error");
777 const doublereal*
const ydot_curr, doublereal*
const delta_y,
782 for (
size_t n = 0; n <
neq_; n++) {
787 for (
size_t n = 0; n <
neq_; n++) {
805 for (
size_t irow = 0; irow <
neq_; irow++) {
811 if (printJacContributions) {
812 for (
size_t iNum = 0; iNum < numRows; iNum++) {
816 doublereal dsum = 0.0;
818 doublereal dRow = Jdata[
neq_ * focusRow + focusRow];
819 printf(
"\n Details on delta_Y for row %d \n", focusRow);
820 printf(
" Value before = %15.5e, delta = %15.5e,"
821 "value after = %15.5e\n", y_curr[focusRow],
822 delta_y[focusRow], y_curr[focusRow] + delta_y[focusRow]);
824 printf(
" Old Jacobian\n");
826 printf(
" col delta_y aij "
828 printf(
"--------------------------------------------------"
829 "---------------------------------------------\n");
830 printf(
" Res(%d) %15.5e %15.5e %15.5e (Res = %g)\n",
831 focusRow, delta_y[focusRow],
832 dRow, RRow[iNum] / dRow, RRow[iNum]);
833 dsum += RRow[iNum] / dRow;
834 for (
size_t ii = 0; ii <
neq_; ii++) {
835 if (ii != focusRow) {
836 doublereal aij = Jdata[neq_ * ii + focusRow];
837 doublereal contrib = aij * delta_y[ii] * (-1.0) / dRow;
839 if (fabs(contrib) > Pcutoff) {
840 printf(
"%6d %15.5e %15.5e %15.5e\n", ii,
841 delta_y[ii] , aij, contrib);
845 printf(
"--------------------------------------------------"
846 "---------------------------------------------\n");
847 printf(
" %15.5e %15.5e\n",
848 delta_y[focusRow], dsum);
868 bool newtonGood =
true;
875 for (
size_t n = 0; n <
neq_; n++) {
880 for (
size_t n = 0; n <
neq_; n++) {
900 doublereal rcond = 0.0;
904 doublereal a1norm = jac.
oneNorm();
905 rcond = jac.
rcond(a1norm);
914 printf(
"\t\t doAffineNewtonSolve: ");
916 printf(
"factorQR()");
920 printf(
" returned with info = %d, indicating a zero row or column\n", info);
923 bool doHessian =
false;
929 printf(
"\t\t doAffineNewtonSolve: Condition number = %g during regular solve\n",
m_conditionNumber);
938 printf(
"\t\t doAffineNewtonSolve() ERROR: QRSolve returned INFO = %d. Switching to Hessian solve\n", info);
947 for (
size_t irow = 0; irow <
neq_; irow++) {
956 printf(
"\t\t doAffineNewtonSolve() WARNING: Condition number too large, %g, But Banded Hessian solve "
963 printf(
"\t\t doAffineNewtonSolve() WARNING: Condition number too large, %g. Doing a Hessian solve \n",
m_conditionNumber);
971 for (
size_t irow = 0; irow <
neq_; irow++) {
972 delyNewton[irow] = delta_y[irow];
987 for (
size_t i = 0; i <
neq_; i++) {
988 for (
size_t j = i; j <
neq_; j++) {
989 for (
size_t k = 0; k <
neq_; k++) {
992 hessian(j,i) = hessian(i,j);
996 for (
size_t i = 0; i <
neq_; i++) {
997 for (
size_t j = i; j <
neq_; j++) {
998 for (
size_t k = 0; k <
neq_; k++) {
999 hessian(i,j) += jacCopy(k,i) * jacCopy(k,j);
1001 hessian(j,i) = hessian(i,j);
1009 doublereal hnorm = 0.0;
1010 doublereal hcol = 0.0;
1012 for (
size_t i = 0; i <
neq_; i++) {
1013 for (
size_t j = i; j <
neq_; j++) {
1016 for (
size_t j = i+1; j <
neq_; j++) {
1025 for (
size_t i = 0; i <
neq_; i++) {
1026 for (
size_t j = i; j <
neq_; j++) {
1027 hcol += fabs(hessian(j,i));
1029 for (
size_t j = i+1; j <
neq_; j++) {
1030 hcol += fabs(hessian(i,j));
1041 hcol = sqrt(static_cast<double>(neq_)) * 1.0E-7 * hnorm;
1042 #ifdef DEBUG_HKM_NOT
1048 for (
size_t i = 0; i <
neq_; i++) {
1052 for (
size_t i = 0; i <
neq_; i++) {
1053 hessian(i,i) += hcol;
1064 printf(
"\t\t doAffineNewtonSolve() ERROR: Hessian isn't positive definite DPOTRF returned INFO = %d\n", info);
1072 for (
size_t n = 0; n <
neq_; n++) {
1076 for (
size_t n = 0; n <
neq_; n++) {
1082 for (
size_t j = 0; j <
neq_; j++) {
1084 for (
size_t i = 0; i <
neq_; i++) {
1085 delta_y[j] += delyH[i] * jacCopy(i,j) *
m_rowScales[i];
1089 for (
size_t j = 0; j <
neq_; j++) {
1091 for (
size_t i = 0; i <
neq_; i++) {
1092 delta_y[j] += delyH[i] * jacCopy(i,j);
1101 ct_dpotrs(ctlapack::UpperTriangular, neq_, 1,&(*(hessian.
begin())),
neq_, delta_y,
neq_, info);
1104 printf(
"\t\t NonlinearSolver::doAffineNewtonSolve() ERROR: DPOTRS returned INFO = %d\n", info);
1112 for (
size_t irow = 0; irow <
neq_; irow++) {
1113 delta_y[irow] = delta_y[irow] *
m_colScales[irow];
1121 printf(
"\t\t doAffineNewtonSolve(): Printout Comparison between Hessian deltaX and Newton deltaX\n");
1123 printf(
"\t\t I Hessian+Junk Newton");
1125 printf(
" (USING NEWTON DIRECTION)\n");
1127 printf(
" (USING HESSIAN DIRECTION)\n");
1129 printf(
"\t\t Norm: %12.4E %12.4E\n", normHess, normNewt);
1131 printf(
"\t\t --------------------------------------------------------\n");
1132 for (
size_t i = 0; i <
neq_; i++) {
1133 printf(
"\t\t %3s %13.5E %13.5E\n",
int2str(i).c_str(), delta_y[i], delyNewton[i]);
1135 printf(
"\t\t --------------------------------------------------------\n");
1139 printf(
"\t\t doAffineNewtonSolve(): Hessian update norm = %12.4E \n"
1140 "\t\t Newton update norm = %12.4E \n", normHess, normNewt);
1142 printf(
"\t\t (USING NEWTON DIRECTION)\n");
1144 printf(
"\t\t (USING HESSIAN DIRECTION)\n");
1152 copy(delyNewton.begin(), delyNewton.end(), delta_y);
1157 if (printJacContributions) {
1158 for (
int iNum = 0; iNum < numRows; iNum++) {
1162 doublereal dsum = 0.0;
1164 doublereal dRow = Jdata[
neq_ * focusRow + focusRow];
1165 printf(
"\n Details on delta_Y for row %d \n", focusRow);
1166 printf(
" Value before = %15.5e, delta = %15.5e,"
1167 "value after = %15.5e\n", y_curr[focusRow],
1168 delta_y[focusRow], y_curr[focusRow] + delta_y[focusRow]);
1170 printf(
" Old Jacobian\n");
1172 printf(
" col delta_y aij "
1174 printf(
"-----------------------------------------------------------------------------------------------\n");
1175 printf(
" Res(%d) %15.5e %15.5e %15.5e (Res = %g)\n",
1176 focusRow, delta_y[focusRow],
1177 dRow, RRow[iNum] / dRow, RRow[iNum]);
1178 dsum += RRow[iNum] / dRow;
1179 for (
int ii = 0; ii <
neq_; ii++) {
1180 if (ii != focusRow) {
1181 doublereal aij = Jdata[neq_ * ii + focusRow];
1182 doublereal contrib = aij * delta_y[ii] * (-1.0) / dRow;
1184 if (fabs(contrib) > Pcutoff) {
1185 printf(
"%6d %15.5e %15.5e %15.5e\n", ii,
1186 delta_y[ii] , aij, contrib);
1190 printf(
"-----------------------------------------------------------------------------------------------\n");
1191 printf(
" %15.5e %15.5e\n",
1192 delta_y[focusRow], dsum);
1206 doublereal rowFac = 1.0;
1207 doublereal colFac = 1.0;
1208 doublereal normSoln;
1219 for (
size_t j = 0; j <
neq_; j++) {
1224 for (
size_t i = 0; i <
neq_; i++) {
1230 if (DEBUG_MODE_ENABLED) {
1239 for (
size_t i = 0; i <
neq_; i++) {
1246 for (
size_t j = 0; j <
neq_; j++) {
1260 for (
size_t i = 0; i <
neq_; i++) {
1268 throw CanteraError(
"NonlinearSolver::doCauchyPointSolve()",
"Unexpected condition: norms are zero");
1279 for (
size_t i = 0; i <
neq_; i++) {
1299 doublereal residCauchy = 0.0;
1316 printf(
"\t\t doCauchyPointSolve: Steepest descent to Cauchy point: \n");
1318 printf(
"\t\t\t Rpred = %g\n", residCauchy);
1321 printf(
"\t\t\t deltaX = %g\n", normSoln);
1333 doublereal ff = 1.0E-5;
1334 doublereal ffNewt = 1.0E-5;
1337 if (cauchyDistanceNorm < 1.0E-2) {
1338 ff = 1.0E-9 / cauchyDistanceNorm;
1343 for (
size_t i = 0; i <
neq_; i++) {
1358 doublereal residSteep2 = residSteep * residSteep *
neq_;
1359 doublereal funcDecreaseSD = 0.5 * (residSteep2 - normResid02) / (ff * cauchyDistanceNorm);
1363 ffNewt = ffNewt / sNewt;
1365 for (
size_t i = 0; i <
neq_; i++) {
1381 doublereal residNewt2 = residNewt * residNewt *
neq_;
1383 doublereal funcDecreaseNewt2 = 0.5 * (residNewt2 - normResid02) / (ffNewt * sNewt);
1389 doublereal funcDecreaseNewtExp2 = - normResid02 / sNewt;
1415 printf(
"\t\t descentComparison: initial rate of decrease of func in Cauchy dir (expected) = %g\n", funcDecreaseSDExp);
1416 printf(
"\t\t descentComparison: initial rate of decrease of func in Cauchy dir = %g\n", funcDecreaseSD);
1417 printf(
"\t\t descentComparison: initial rate of decrease of func in Newton dir (expected) = %g\n", funcDecreaseNewtExp2);
1418 printf(
"\t\t descentComparison: initial rate of decrease of func in Newton dir = %g\n", funcDecreaseNewt2);
1421 printf(
"\t\t descentComparison: initial rate of decrease of Resid in Cauchy dir (expected) = %g\n",
ResidDecreaseSDExp_);
1422 printf(
"\t\t descentComparison: initial rate of decrease of Resid in Cauchy dir = %g\n",
ResidDecreaseSD_);
1423 printf(
"\t\t descentComparison: initial rate of decrease of Resid in Newton dir (expected) = %g\n",
ResidDecreaseNewtExp_);
1424 printf(
"\t\t descentComparison: initial rate of decrease of Resid in Newton dir = %g\n",
ResidDecreaseNewt_);
1428 if (funcDecreaseNewt2 >= 0.0) {
1429 printf(
"\t\t %13.5E %22.16E\n", funcDecreaseNewtExp2,
m_normResid_0);
1430 double ff = ffNewt * 1.0E-5;
1431 for (
int ii = 0; ii < 13; ii++) {
1436 for (
size_t i = 0; i <
neq_; i++) {
1446 residNewt2 = residNewt * residNewt *
neq_;
1447 funcDecreaseNewt2 = 0.5 * (residNewt2 - normResid02) / (ff * sNewt);
1448 printf(
"\t\t %10.3E %13.5E %22.16E\n", ff, funcDecreaseNewt2, residNewt);
1476 doublereal Nres2CP = residSteepLin * residSteepLin *
neq_;
1478 doublereal a = Nres2CP / Nres2_o;
1479 doublereal betaEqual = (2.0 - sqrt(4.0 - 4 * (1.0 - a))) / 2.0;
1480 doublereal beta = (1.0 + betaEqual) / 2.0;
1486 for (
size_t i = 0; i <
neq_; i++) {
1516 doublereal resD2, res2, resNorm;
1526 doublereal tmp = - 2.0 * alpha + alpha * alpha;
1530 }
else if (leg == 1) {
1536 doublereal RdotJS = - tmp2;
1537 doublereal JsJs = tmp2;
1542 res2 = res0_2 + (1.0 - alpha) * 2 * RdotJS - 2 * alpha *
Nuu_ * res0_2
1543 + (1.0 - alpha) * (1.0 - alpha) * JsJs
1544 + alpha * alpha *
Nuu_ *
Nuu_ * res0_2
1545 - 2 * alpha *
Nuu_ * (1.0 - alpha) * RdotJS;
1547 return sqrt(res2 / neq_);
1550 doublereal beta =
Nuu_ + alpha * (1.0 -
Nuu_);
1551 doublereal tmp2 = normResid02;
1552 doublereal tmp = 1.0 - 2.0 * beta + 1.0 * beta * beta - 1.0;
1560 resNorm = sqrt(res2 / neq_);
1568 doublereal& alphaBest)
const
1573 doublereal alpha = 0;
1575 doublereal residSteepBest = 1.0E300;
1576 doublereal residSteepLinBest = 0.0;
1578 printf(
"\t\t residualComparisonLeg() \n");
1579 printf(
"\t\t Point StepLen Residual_Actual Residual_Linear RelativeMatch\n");
1582 std::vector<doublereal> alphaT;
1583 alphaT.push_back(0.00);
1584 alphaT.push_back(0.01);
1585 alphaT.push_back(0.1);
1586 alphaT.push_back(0.25);
1587 alphaT.push_back(0.50);
1588 alphaT.push_back(0.75);
1589 alphaT.push_back(1.0);
1590 for (
size_t iteration = 0; iteration < alphaT.size(); iteration++) {
1591 alpha = alphaT[iteration];
1592 for (
size_t i = 0; i <
neq_; i++) {
1612 if (residSteep < residSteepBest) {
1615 residSteepBest = residSteep;
1616 residSteepLinBest = residSteepLin;
1619 doublereal relFit = (residSteep - residSteepLin) / (fabs(residSteepLin) + 1.0E-10);
1621 printf(
"\t\t (%2d - % 10.3g) % 15.8E % 15.8E % 15.8E % 15.8E\n", 0, alpha, sLen, residSteep, residSteepLin , relFit);
1625 for (
size_t iteration = 0; iteration < alphaT.size(); iteration++) {
1626 doublereal alpha = alphaT[iteration];
1627 for (
size_t i = 0; i <
neq_; i++) {
1644 for (
size_t i = 0; i <
neq_; i++) {
1651 if (residSteep < residSteepBest) {
1654 residSteepBest = residSteep;
1655 residSteepLinBest = residSteepLin;
1658 doublereal relFit = (residSteep - residSteepLin) / (fabs(residSteepLin) + 1.0E-10);
1660 printf(
"\t\t (%2d - % 10.3g) % 15.8E % 15.8E % 15.8E % 15.8E\n", 1, alpha, sLen, residSteep, residSteepLin , relFit);
1664 for (
size_t iteration = 0; iteration < alphaT.size(); iteration++) {
1665 doublereal alpha = alphaT[iteration];
1666 for (
size_t i = 0; i <
neq_; i++) {
1687 if (residSteep < residSteepBest) {
1690 residSteepBest = residSteep;
1691 residSteepLinBest = residSteepLin;
1693 doublereal relFit = (residSteep - residSteepLin) / (fabs(residSteepLin) + 1.0E-10);
1695 printf(
"\t\t (%2d - % 10.3g) % 15.8E % 15.8E % 15.8E % 15.8E\n", 2, alpha, sLen, residSteep, residSteepLin , relFit);
1699 printf(
"\t\t Best Result: \n");
1700 doublereal relFit = (residSteepBest - residSteepLinBest) / (fabs(residSteepLinBest) + 1.0E-10);
1702 printf(
"\t\t Leg %2d alpha %5g: NonlinResid = %g LinResid = %g, relfit = %g\n",
1703 legBest, alphaBest, residSteepBest, residSteepLinBest, relFit);
1707 }
else if (legBest == 1) {
1708 for (
size_t i = 0; i <
neq_; i++) {
1716 printf(
"\t\t (%2d - % 10.3g) % 15.8E % 15.8E % 15.8E % 15.8E\n", legBest, alphaBest, sLen,
1717 residSteepBest, residSteepLinBest , relFit);
1731 for (
size_t i = 0; i <
neq_; i++) {
1739 for (
size_t i = 0; i <
neq_; i++) {
1750 for (
size_t i = 0; i <
neq_; i++) {
1759 size_t i_fbounds = 0;
1762 doublereal UPFAC = 2.0;
1764 doublereal sameSign = 0.0;
1766 doublereal f_delta_bounds = 1.0;
1768 for (
size_t i = 0; i <
neq_; i++) {
1769 doublereal y_new = y_n_curr[i] + step_1[i];
1770 sameSign = y_new * y_n_curr[i];
1780 if (sameSign >= 0.0) {
1781 if ((fabs(y_new) > UPFAC * fabs(y_n_curr[i])) &&
1783 ff = (UPFAC - 1.0) * fabs(y_n_curr[i]/(y_new - y_n_curr[i]));
1785 ff = std::max(ff, ff_alt);
1788 if ((fabs(2.0 * y_new) < fabs(y_n_curr[i])) &&
1790 ff = y_n_curr[i]/(y_new - y_n_curr[i]) * (1.0 - 2.0)/2.0;
1792 ff = std::max(ff, ff_alt);
1801 ff = y_n_curr[i]/(y_new - y_n_curr[i]) * (1.0 - 2.0)/2.0;
1803 ff = std::max(ff, ff_alt);
1804 if (y_n_curr[i] >= 0.0) {
1813 else if (fabs(y_new) > 0.5 * fabs(y_n_curr[i])) {
1814 ff = y_n_curr[i]/(y_new - y_n_curr[i]) * (-1.5);
1816 ff = std::max(ff, ff_alt);
1821 if (ff < f_delta_bounds) {
1822 f_delta_bounds = ff;
1835 if (f_delta_bounds < 1.0) {
1837 printf(
"\t\tdeltaBoundStep: Increase of Variable %s causing "
1838 "delta damping of %g: origVal = %10.3g, undampedNew = %10.3g, dampedNew = %10.3g\n",
1839 int2str(i_fbounds).c_str(), f_delta_bounds, y_n_curr[i_fbounds], y_n_curr[i_fbounds] + step_1[i_fbounds],
1840 y_n_curr[i_fbounds] + f_delta_bounds * step_1[i_fbounds]);
1842 printf(
"\t\tdeltaBoundStep: Decrease of variable %s causing"
1843 "delta damping of %g: origVal = %10.3g, undampedNew = %10.3g, dampedNew = %10.3g\n",
1844 int2str(i_fbounds).c_str(), f_delta_bounds, y_n_curr[i_fbounds], y_n_curr[i_fbounds] + step_1[i_fbounds],
1845 y_n_curr[i_fbounds] + f_delta_bounds * step_1[i_fbounds]);
1851 return f_delta_bounds;
1857 doublereal wtSum = 0.0;
1858 for (
size_t i = 0; i <
neq_; i++) {
1863 doublereal deltaXSizeOld = trustNorm;
1864 doublereal trustNormGoal = trustNorm *
trustDelta_;
1869 for (
size_t i = 0; i <
neq_; i++) {
1874 doublereal newValue = trustNormGoal *
m_ewt[i];
1875 if (newValue > 0.5 * fabsy) {
1882 if (newValue > 4.0 * oldVal) {
1883 newValue = 4.0 * oldVal;
1884 }
else if (newValue < 0.25 * oldVal) {
1885 newValue = 0.25 * oldVal;
1900 doublereal sum = trustNormGoal / trustNorm;
1901 for (
size_t i = 0; i <
neq_; i++) {
1908 printf(
"\t\t reajustTrustVector(): Trust size = %11.3E: Old deltaX size = %11.3E trustDelta_ = %11.3E\n"
1909 "\t\t new deltaX size = %11.3E trustdelta_ = %11.3E\n",
1920 for (
size_t i = 0; i <
neq_; i++) {
1926 for (
size_t i = 0; i <
neq_; i++) {
1931 printf(
"\t\t initializeTrustRegion(): Relative Distance of Cauchy Vector wrt Trust Vector = %g\n", cpd);
1937 printf(
"\t\t initializeTrustRegion(): Relative Distance of Cauchy Vector wrt Trust Vector = %g\n", cpd);
1941 for (
size_t i = 0; i <
neq_; i++) {
1946 printf(
"\t\t initializeTrustRegion(): Relative Distance of Newton Vector wrt Trust Vector = %g\n", cpd);
1952 printf(
"\t\t initializeTrustRegion(): Relative Distance of Newton Vector wrt Trust Vector = %g\n", cpd);
1960 for (
size_t i = 0; i <
neq_; i++) {
1963 }
else if (leg == 2) {
1964 for (
size_t i = 0; i <
neq_; i++) {
1968 for (
size_t i = 0; i <
neq_; i++) {
1976 doublereal sum = 0.0;
1977 doublereal tmp = 0.0;
1978 for (
size_t i = 0; i <
neq_; i++) {
2007 doublereal sumv = 0.0;
2008 for (
size_t i = 0; i <
neq_; i++) {
2013 doublereal b = 2.0 * Nuu_ * sumv;
2016 alpha =(-b + sqrt(b * b - 4.0 * a * c)) / (2.0 * a);
2026 size_t i_lower =
npos;
2027 doublereal f_bounds = 1.0;
2028 doublereal ff, y_new;
2030 for (
size_t i = 0; i <
neq_; i++) {
2031 y_new = y[i] + step0[i];
2035 if (step0[i] < 0.0) {
2038 ff = legalDelta / step0[i];
2039 if (ff < f_bounds) {
2048 if (step0[i] > 0.0) {
2051 ff = legalDelta / step0[i];
2052 if (ff < f_bounds) {
2065 if (f_bounds != 1.0) {
2066 printf(
"\t\tboundStep: Variable %s causing bounds damping of %g\n",
int2str(i_lower).c_str(), f_bounds);
2071 return std::min(f_bounds, f_delta_bounds);
2075 const doublereal*
const ydot_n_curr, doublereal*
const step_1,
2076 doublereal*
const y_n_1, doublereal*
const ydot_n_1, doublereal*
const step_2,
2077 doublereal& stepNorm_2,
GeneralMatrix& jac,
bool writetitle,
int& num_backtracks)
2086 for (
size_t j = 0; j <
neq_; j++) {
2087 step_1_orig[j] = step_1[j];
2100 printf(
"\t\t\tdampStep(): At limits.\n");
2114 for (m = 0; m <
NDAMP; m++) {
2123 for (
size_t j = 0; j <
neq_; j++) {
2124 step_1[j] = ff * step_1_orig[j];
2125 y_n_1[j] = y_n_curr[j] + step_1[j];
2142 printf(
"\t\t\tdampStep(): current trial step and damping led to Residual Calc ERROR %d. Bailing\n", info);
2157 printf(
"\t dampStep(): Current trial step and damping"
2158 " coefficient accepted because residTrial test step < 1:\n");
2160 }
else if (steepEnough) {
2161 printf(
"\t dampStep(): Current trial step and damping"
2162 " coefficient accepted because resid0 > residTrial and steep enough:\n");
2165 printf(
"\t dampStep(): Current trial step and damping"
2166 " coefficient accepted because residual solution damping is turned off:\n");
2190 info =
doNewtonSolve(time_curr, y_n_1, ydot_n_1, step_2, jac);
2192 info =
doNewtonSolve(time_curr, y_n_1, ydot_n_curr, step_2, jac);
2196 printf(
"\t\t\tdampStep: current trial step and damping led to LAPACK ERROR %d. Bailing\n", info);
2207 (
const doublereal*) step_2,
"DeltaSolnTrial",
2208 "dampNewt: Important Entries for Weighted Soln Updates:",
2209 y_n_curr, y_n_1, ff, 5);
2212 printf(
"\t\t\tdampStep(): s1 = %g, s2 = %g, dampBound = %g,"
2213 "dampRes = %g\n", stepNorm_1, stepNorm_2,
m_dampBound, m_dampRes);
2222 if (stepNorm_2 < 0.8 || stepNorm_2 < stepNorm_1) {
2223 if (stepNorm_2 < 1.0) {
2225 if (stepNorm_2 < 1.0) {
2226 printf(
"\t\t\tdampStep: current trial step and damping coefficient accepted because test step < 1\n");
2227 printf(
"\t\t\t s2 = %g, s1 = %g\n", stepNorm_2, stepNorm_1);
2237 printf(
"\t\t\tdampStep: current step rejected: (s1 = %g > "
2238 "s0 = %g)", stepNorm_2, stepNorm_1);
2239 if (m < (NDAMP-1)) {
2240 printf(
" Decreasing damping factor and retrying");
2242 printf(
" Giving up!!!");
2257 printf(
"\t dampStep(): current trial step accepted retnTrial = %d, its = %d, damp = %g\n", retnTrial, m+1, ff);
2261 if (stepNorm_2 < 0.5 && (stepNorm_1 < 0.5)) {
2263 printf(
"\t dampStep(): current trial step accepted kindof retnTrial = %d, its = %d, damp = %g\n", 2, m+1, ff);
2267 if (stepNorm_2 < 1.0) {
2269 printf(
"\t dampStep(): current trial step accepted and soln converged retnTrial ="
2270 "%d, its = %d, damp = %g\n", 0, m+1, ff);
2276 printf(
"\t dampStep(): current direction is rejected! retnTrial = %d, its = %d, damp = %g\n",
2283 const doublereal* ydot_n_curr, std::vector<doublereal> & step_1,
2284 doublereal*
const y_n_1, doublereal*
const ydot_n_1,
2285 doublereal& stepNorm_1, doublereal& stepNorm_2,
GeneralMatrix& jac,
int& numTrials)
2290 bool success =
false;
2291 bool haveASuccess =
false;
2304 for (m = 0; m <
NDAMP; m++) {
2312 printf(
"\t\t dampDogLeg: trust region with length %13.5E has intersection at leg = %d, alpha = %g, lambda = %g\n",
2329 for (
size_t j = 0; j <
neq_; j++) {
2336 for (
size_t j = 0; j <
neq_; j++) {
2337 y_n_1[j] = y_n_curr[j] + step_1[j];
2350 y_n_1, ydot_n_1, trustDeltaOld);
2360 printf(
"\t\t dampDogLeg: Current direction rejected, update became too small %g\n", stepNorm);
2367 printf(
"\t\t dampDogLeg: current trial step and damping led to LAPACK ERROR %d. Bailing\n", info);
2378 haveASuccess =
true;
2380 copy(step_1.begin(), step_1.end(), stepLastGood);
2391 copy(stepLastGood, stepLastGood+neq_, step_1.begin());
2392 for (
size_t j = 0; j <
neq_; j++) {
2393 y_n_1[j] = y_n_curr[j] + step_1[j];
2410 stepNorm_2 = stepNorm_1;
2414 stepNorm_2 /= lambda;
2432 const doublereal*
const y_n_curr,
2433 const doublereal*
const ydot_n_curr,
const std::vector<doublereal> & step_1,
2434 const doublereal*
const y_n_1,
const doublereal*
const ydot_n_1,
2435 doublereal trustDeltaOld)
2452 if (funcDecreaseSDExp > 0.0) {
2454 printf(
"\t\tdecideStep(): Unexpected condition -> Cauchy slope is positive\n");
2473 printf(
"\t\tdecideStep: current trial step and damping led to Residual Calc ERROR %d. Bailing\n", info);
2488 doublereal funcDecrease = 0.5 * (normResidTrial_2 - normResid0_2);
2489 doublereal acceptableDelF = funcDecreaseSDExp * stepNorm * 1.0E-4;
2490 if (funcDecrease < acceptableDelF) {
2495 printf(
"\t\t decideStep: Norm Residual(leg=%1d, alpha=%10.2E) = %11.4E passes\n",
2500 printf(
"\t\t decideStep: Norm Residual(leg=%1d, alpha=%10.2E) = %11.4E failes\n",
2507 if (
rtol_ * stepNorm < 1.0E-6) {
2523 doublereal expectedFuncDecrease = 0.5 * (neq_ * expectedNormRes * expectedNormRes - normResid0_2);
2524 if (funcDecrease > 0.1 * expectedFuncDecrease) {
2525 if ((m_normResidTrial > 0.5 *
m_normResid_0) && (m_normResidTrial > 0.1)) {
2530 printf(
"\t\t decideStep: Trust region decreased from %g to %g due to bad quad approximation\n",
2538 if (funcDecrease < 0.8 * expectedFuncDecrease || (m_normResidTrial < 0.33 *
m_normResid_0)) {
2539 if (
trustDelta_ <= trustDeltaOld && (leg != 2 || alpha < 0.75)) {
2546 printf(
"\t\t decideStep: Redo line search with trust region increased from %g to %g due to good nonlinear behavior\n",
2549 printf(
"\t\t decideStep: Redi line search with trust region increased from %g to %g due to good linear model approximation\n",
2558 if (m_normResidTrial < 0.99 * expectedNormRes || (m_normResidTrial < 0.20 *
m_normResid_0) ||
2559 (funcDecrease < -1.0E-50 && (funcDecrease < 0.9 *expectedFuncDecrease))) {
2560 if (leg == 2 && alpha == 1.0) {
2568 printf(
"\t\t decideStep: Trust region further increased from %g to %g next step due to good linear model behavior\n",
2579 printf(
"\t\t decideStep: Trust region further increased from %g to %g next step due to good linear model behavior\n",
2593 int& num_newt_its,
int& num_linear_solves,
2594 int& num_backtracks,
int loglevelInput)
2607 bool forceNewJac =
false;
2612 doublereal stepNorm_1;
2613 doublereal stepNorm_2;
2615 doublereal alphaBest;
2616 bool trInit =
false;
2644 printf(
"\tsolve_nonlinear_problem():\n\n");
2646 printf(
"\tWt Iter Resid NewJac log(CN)| dRdS_CDexp dRdS_CD dRdS_Newtexp dRdS_Newt |"
2647 "DS_Cauchy DS_Newton DS_Trust | legID legAlpha Fbound | CTF NTF | nTr|"
2648 "DS_Final ResidLag ResidFull\n");
2649 printf(
"\t---------------------------------------------------------------------------------------------------"
2650 "--------------------------------------------------------------------------------\n");
2652 printf(
"\t Wt Iter Resid NewJac | Fbound ResidBound | DampIts Fdamp DS_Step1 DS_Step2"
2653 "ResidLag | DS_Damp DS_Newton ResidFull\n");
2654 printf(
"\t--------------------------------------------------------------------------------------------------"
2655 "----------------------------------\n");
2674 writeline(
'=', 119);
2675 printf(
"\tsolve_nonlinear_problem(): iteration %d:\n",
2683 if (trInit && (DEBUG_MODE_ENABLED ||
doDogLeg_)) {
2701 printf(
"\t solve_nonlinear_problem(): Getting a new Jacobian\n");
2707 printf(
"\t solve_nonlinear_problem(): Jacobian Formation Error: %d Bailing\n", info);
2714 printf(
"\t solve_nonlinear_problem(): Solving system with old Jacobian\n");
2727 printf(
"\t solve_nonlinear_problem(): Calculate the base residual\n");
2732 printf(
"\t solve_nonlinear_problem(): Residual Calc ERROR %d. Bailing\n", info);
2753 printf(
"\t solve_nonlinear_problem(): Initial Residual Norm = %13.4E\n",
m_normResid_0);
2759 printf(
"\t solve_nonlinear_problem(): Calculate the steepest descent direction and Cauchy Point\n");
2767 printf(
"\t solve_nonlinear_problem(): Calculate the Newton direction via an Affine solve\n");
2772 printf(
"\t solve_nonlinear_problem(): Calculate the Newton direction via a Newton solve\n");
2780 printf(
"\t solve_nonlinear_problem(): Matrix Inversion Error: %d Bailing\n", info);
2796 printf(
"\t solve_nonlinear_problem(): Initialize the trust region size as the length of the Cauchy Vector times %f\n",
2799 printf(
"\t solve_nonlinear_problem(): Initialize the trust region size as the length of the Newton Vector times %f\n",
2811 printf(
"\t\t Newton's method step size, %g trustVectorUnits, larger than trust region, %g trustVectorUnits\n",
2813 printf(
"\t\t Newton's method step size, %g trustVectorUnits, larger than trust region, %g trustVectorUnits\n",
2816 printf(
"\t\t Newton's method step size, %g trustVectorUnits, smaller than trust region, %g trustVectorUnits\n",
2829 printf(
"\t solve_nonlinear_problem(): Compare descent rates for Cauchy and Newton directions\n");
2842 printf(
"\t solve_nonlinear_problem(): Compare Linear and nonlinear residuals along double dog-leg path\n");
2846 printf(
"\t solve_nonlinear_problem(): Calculate damping along dog-leg path to ensure residual decrease\n");
2851 printf(
"\t solve_nonlinear_problem(): Compare Linear and nonlinear residuals along double dog-leg path\n");
2870 num_backtracks += i_numTrials;
2881 printf(
"\t solve_nonlinear_problem(): Damped Newton successful (m=%d) but minimum Newton"
2882 "iterations not attained. Resolving ...\n", retnDamp);
2894 printf(
"\t solve_nonlinear_problem(): Damped Newton unsuccessful (max newts exceeded) sfinal = %g\n",
2906 printf(
"\t solve_nonlinear_problem(): current trial step and damping led to Residual Calc "
2907 "ERROR %d. Bailing\n", info);
2916 printf(
"\t solve_nonlinear_problem(): Full residual norm changed from %g to %g due to "
2935 bool m_filterIntermediate =
false;
2936 if (m_filterIntermediate) {
2958 bool m_jacAge =
false;
2972 printf(
" %2d ", i_numTrials);
2977 printf(
"%2d %10.2E %10.3E %10.3E %10.3E", i_numTrials + 1,
m_dampRes,
2987 printf(
"\t solve_nonlinear_problem(): Problem Converged, stepNorm = %11.3E, reduction of res from %11.3E to %11.3E\n",
2990 writeline(
'=', 119);
2992 printf(
"\t solve_nonlinear_problem(): Successfull step taken with stepNorm = %11.3E, reduction of res from %11.3E to %11.3E\n",
2997 printf(
"\t solve_nonlinear_problem(): Damped Newton iteration successful, nonlin "
2998 "converged, final estimate of the next solution update norm = %-12.4E\n", stepNorm_2);
3000 writeline(
'=', 119);
3002 printf(
"\t solve_nonlinear_problem(): Damped Newton iteration successful, "
3003 "estimate of the next solution update norm = %-12.4E\n", stepNorm_2);
3005 printf(
"\t solve_nonlinear_problem(): Damped Newton unsuccessful, final estimate "
3006 "of the next solution update norm = %-12.4E\n", stepNorm_2);
3019 printf(
"\t solve_nonlinear_problem(): Final ShowSolution residual eval returned an error! "
3020 "ERROR %d. Bailing\n", info);
3049 " | | converged = 3 |(%11.3E) \n", stepNorm_2);
3052 " | | converged = %1d | %10.3E %10.3E\n", convRes,
3055 printf(
"\t-----------------------------------------------------------------------------------------------------"
3056 "------------------------------------------------------------------------------\n");
3060 " | converged = 3 | (%11.3E) \n", stepNorm_2);
3063 " | converged = %1d | %10.3E %10.3E\n", convRes,
3066 printf(
"\t------------------------------------------------------------------------------------"
3067 "-----------------------------------------------\n");
3082 doublereal time_elapsed = wc.
secondsWC();
3086 printf(
"\tNonlinear problem solved successfully in %d its\n",
3089 printf(
"\tNonlinear problem solved successfully in %d its, time elapsed = %g sec\n",
3090 num_newt_its, time_elapsed);
3093 printf(
"\tNonlinear problem failed to solve after %d its\n", num_newt_its);
3096 retnCode = retnDamp;
3106 const std::vector<doublereal>& ydot_nm1)
3113 const char*
const stepNorm_1,
3114 const doublereal*
const step_2,
3115 const char*
const stepNorm_2,
3116 const char*
const title,
3117 const doublereal*
const y_n_curr,
3118 const doublereal*
const y_n_1,
3123 doublereal dmax0, dmax1,
error, rel_norm;
3124 printf(
"\t\t%s currentDamp = %g\n", title, damp);
3125 printf(
"\t\t I ysolnOld %13s ysolnNewRaw | ysolnNewTrial "
3126 "%10s ysolnNewTrialRaw | solnWeight wtDelSoln wtDelSolnTrial\n", stepNorm_1, stepNorm_2);
3127 std::vector<size_t> imax(num_entries,
npos);
3129 writeline(
'-', 125);
3130 for (
size_t jnum = 0; jnum < num_entries; jnum++) {
3132 for (
size_t i = 0; i <
neq_; i++) {
3134 for (
size_t j = 0; j < jnum; j++) {
3140 error = step_1[i] /
m_ewt[i];
3141 rel_norm = sqrt(error * error);
3142 error = step_2[i] /
m_ewt[i];
3143 rel_norm += sqrt(error * error);
3144 if (rel_norm > dmax1) {
3150 if (imax[jnum] !=
npos) {
3151 size_t i = imax[jnum];
3152 error = step_1[i] /
m_ewt[i];
3153 dmax0 = sqrt(error * error);
3154 error = step_2[i] /
m_ewt[i];
3155 dmax1 = sqrt(error * error);
3156 printf(
"\t\t %4s %12.4e %12.4e %12.4e | %12.4e %12.4e %12.4e |%12.4e %12.4e %12.4e\n",
3157 int2str(i).c_str(), y_n_curr[i], step_1[i], y_n_curr[i] + step_1[i], y_n_1[i],
3158 step_2[i], y_n_1[i]+ step_2[i],
m_ewt[i], dmax0, dmax1);
3162 writeline(
'-', 125);
3184 static inline doublereal
subtractRD(doublereal a, doublereal b)
3186 doublereal diff = a - b;
3187 doublereal d = std::min(fabs(a), fabs(b));
3189 doublereal ad = fabs(diff);
3190 if (ad < 1.0E-300) {
3200 doublereal time_curr, doublereal CJ,
3201 doublereal*
const y, doublereal*
const ydot,
3206 doublereal ysave, dy;
3207 doublereal ydotsave = 0;
3240 if (DEBUG_MODE_ENABLED) {
3241 for (
size_t ii = 0; ii <
neq_; ii++) {
3256 printf(
"\t\t beuler_jac ERROR! calcDeltaSolnVariables() returned an error flag\n");
3257 printf(
"\t\t We will bail from the nonlinear solver after calculating the Jacobian");
3260 printf(
"\t\tUnk m_ewt y dyVector ResN\n");
3261 for (
size_t iii = 0; iii <
neq_; iii++) {
3262 printf(
"\t\t %4s %16.8e %16.8e %16.8e %16.8e \n",
3263 int2str(iii).c_str(),
m_ewt[iii], y[iii], dyVector[iii], f[iii]);
3280 for (
size_t j = 0; j <
neq_; j++) {
3307 if (DEBUG_MODE_ENABLED) {
3308 if (fabs(dy) < 1.0E-300) {
3309 throw CanteraError(
"NonlinearSolver::beuler_jac",
"dy is equal to zero");
3311 for (
size_t ii = 0; ii <
neq_; ii++) {
3321 for (
size_t i = 0; i <
neq_; i++) {
3323 col_j[i] = diff / dy;
3335 kl =
static_cast<int>(ivec[0]);
3336 ku =
static_cast<int>(ivec[1]);
3338 printf(
"we have probs\n");
3356 printf(
"\t\t beuler_jac ERROR! calcDeltaSolnVariables() returned an error flag\n");
3357 printf(
"\t\t We will bail from the nonlinear solver after calculating the Jacobian");
3360 printf(
"\t\tUnk m_ewt y dyVector ResN\n");
3361 for (
size_t iii = 0; iii <
neq_; iii++) {
3362 printf(
"\t\t %4s %16.8e %16.8e %16.8e %16.8e \n",
3363 int2str(iii).c_str(),
m_ewt[iii], y[iii], dyVector[iii], f[iii]);
3370 for (
size_t j = 0; j <
neq_; j++) {
3387 if (DEBUG_MODE_ENABLED) {
3388 if (fabs(dy) < 1.0E-300) {
3389 throw CanteraError(
"NonlinearSolver::beuler_jac",
"dy is equal to zero");
3391 for (
size_t ii = 0; ii <
neq_; ii++) {
3403 for (
int i = (
int) j - ku; i <= (int) j + kl; i++) {
3404 if (i >= 0 && i < (
int)
neq_) {
3406 col_j[kl + ku + i - j] = diff / dy;
3418 if (vSmall < 1.0E-100) {
3419 printf(
"WE have a zero row, %s\n",
int2str(ismall).c_str());
3423 if (vSmall < 1.0E-100) {
3424 printf(
"WE have a zero column, %s\n",
int2str(ismall).c_str());
3434 printf(
"\t\tCurrent Matrix and Residual:\n");
3435 printf(
"\t\t I,J | ");
3436 for (
size_t j = 0; j <
neq_; j++) {
3437 printf(
" %5s ",
int2str(j).c_str());
3439 printf(
"| Residual \n");
3441 for (
size_t j = 0; j <
neq_; j++) {
3442 printf(
"------------");
3444 printf(
"| -----------\n");
3447 for (
size_t i = 0; i <
neq_; i++) {
3448 printf(
"\t\t %4s |",
int2str(i).c_str());
3449 for (
size_t j = 0; j <
neq_; j++) {
3450 printf(
" % 11.4E", J(i,j));
3452 printf(
" | % 11.4E\n", f[i]);
3456 for (
size_t j = 0; j <
neq_; j++) {
3457 printf(
"------------");
3459 printf(
"--------------\n");
3472 const doublereal*
const y_curr,
3473 doublereal*
const ydot_curr)
const
3483 for (
size_t i = 0; i <
neq_; i++) {
3484 ydot_curr[i] = c1 * (y_curr[i] -
m_y_nm1[i]);
3489 for (
size_t i = 0; i <
neq_; i++) {
3500 const doublereal*
const ybase, doublereal*
const step0)
3506 doublereal*
const y_current, doublereal*
const ydot_current)
3515 for (
size_t i = 0; i <
neq_; i++) {
3517 if (DEBUG_MODE_ENABLED) {
3522 doublereal sum = 0.0;
3523 for (
size_t i = 0; i <
neq_; i++) {
3525 if (DEBUG_MODE_ENABLED) {
3531 for (
size_t i = 0; i <
neq_; i++) {
3535 for (
size_t i = 0; i <
neq_; i++) {
3545 for (
size_t i = 0; i <
neq_; i++) {
3559 if (dampCode <= 0) {
3562 if (dampCode == 3) {
3576 if (dampCode == 4) {
3591 if (dampCode == 1 || dampCode == 2) {
3603 for (
size_t i = 0; i <
neq_; i++) {
3604 if (atol[i] <= 0.0) {
3606 "Atol is less than or equal to zero");
3623 if (residNormHandling < 0 || residNormHandling > 2) {
3624 throw CanteraError(
"NonlinearSolver::setResidualTols()",
3625 "Unknown int for residNormHandling");
3631 for (
size_t i = 0; i <
neq_; i++) {
3635 if (residNormHandling ==1 || residNormHandling == 2) {
3636 throw CanteraError(
"NonlinearSolver::setResidualTols()",
3637 "Must set residATol vector");
static bool s_alwaysAssumeNewtonGood
This toggle turns off the use of the Hessian when it is warranted by the condition number...
virtual doublereal * ptrColumn(size_t j)=0
Return a pointer to the top of column j, columns are assumed to be contiguous in memory.
int matrixType_
Matrix type.
int trustRegionInitializationMethod_
Method for handling the trust region initialization.
void computeResidWts()
Compute the Residual Weights.
std::vector< doublereal > m_y_low_bounds
Lower bounds vector for each species.
doublereal ResidDecreaseSDExp_
Expected DResid_dS for the steepest descent path - output variable.
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
#define NSOLN_RETN_SUCCESS
The nonlinear solve is successful.
void readjustTrustVector()
Readjust the trust region vectors.
int beuler_jac(GeneralMatrix &J, doublereal *const f, doublereal time_curr, doublereal CJ, doublereal *const y, doublereal *const ydot, int num_newt_its)
Function called to evaluate the Jacobian matrix and the current residual vector at the current time s...
int m_matrixConditioning
Boolean indicating matrix conditioning.
Base residual calculation for the showSolution routine.
void checkFinite(const double tmp)
Check to see that a number is finite (not NaN, +Inf or -Inf)
doublereal Nuu_
Relative distance down the Newton step that the second dogleg starts.
int m_rowScaling
int indicating whether row scaling is turned on (1) or not (0)
virtual int nEquations() const
Return the number of equations in the equation system.
int convergenceCheck(int dampCode, doublereal s1)
Check to see if the nonlinear problem has converged.
doublereal solnErrorNorm(const doublereal *const delta_y, const char *title=0, int printLargest=0, const doublereal dampFactor=1.0) const
L2 norm of the delta of the solution vector.
std::vector< doublereal > atolk_
absolute tolerance in the solution unknown
doublereal boundStep(const doublereal *const y, const doublereal *const step0)
Bound the step.
doublereal m_normResidTrial
Norm of the residual for a trial calculation which may or may not be used.
doublereal lambdaStar_
Value of lambdaStar_ which is used to calculate the Cauchy point.
doublereal ResidDecreaseNewtExp_
Expected DResid_dS for the Newton path - output variable.
std::vector< doublereal > m_colScales
Vector of column scaling factors.
doublereal normTrust_Newton_
Norm of the Newton Step wrt trust region.
std::vector< doublereal > userResidAtol_
absolute tolerance in the unscaled solution unknowns
Declarations for a simple class that implements an Ansi C wall clock timer (see Cantera::clockWC).
virtual GeneralMatrix * duplMyselfAsGeneralMatrix() const =0
Duplicator member function.
doublereal userResidRtol_
absolute tolerance in the unscaled solution unknowns
doublereal m_normResid_Bound
Norm of the residual after it has been bounded.
const size_t npos
index returned by functions to indicate "no position"
virtual doublereal oneNorm() const =0
Calculate the one norm of the matrix.
virtual void clearFactorFlag()
clear the factored flag
virtual void setPreviousTimeStep(const std::vector< doublereal > &y_nm1, const std::vector< doublereal > &ydot_nm1)
Set the values for the previous time step.
#define NSOLN_RETN_MATRIXINVERSIONERROR
The nonlinear problem's Jacobian is singular.
int doResidualCalc(const doublereal time_curr, const int typeCalc, const doublereal *const y_curr, const doublereal *const ydot_curr, const ResidEval_Type_Enum evalType=Base_ResidEval) const
Compute the current residual.
virtual int evalResidNJ(const doublereal t, const doublereal delta_t, const doublereal *const y, const doublereal *const ydot, doublereal *const resid, const ResidEval_Type_Enum evalType=Base_ResidEval, const int id_x=-1, const doublereal delta_x=0.0)
Evaluate the residual function.
int dogLegID_
Current leg.
virtual doublereal rcond(doublereal a1norm)=0
Returns an estimate of the inverse of the condition number for the matrix.
virtual int evalJacobian(const doublereal t, const doublereal delta_t, doublereal cj, const doublereal *const y, const doublereal *const ydot, GeneralMatrix &J, doublereal *const resid)
Calculate an analytical Jacobian and the residual at the current time and values. ...
std::vector< doublereal > m_ydot_nm1
Vector containing the solution derivative at the previous time step.
void setupDoubleDogleg()
Setup the parameters for the double dog leg.
#define NSOLN_RETN_CONTINUE
Problem isn't solved yet.
virtual vector_fp::iterator begin()=0
Return an iterator pointing to the first element.
void calcSolnToResNormVector()
Calculate the scaling factor for translating residual norms into solution norms.
#define NSOLN_TYPE_STEADY_STATE
The nonlinear problem is part of a steady state calculation.
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
std::vector< doublereal > deltaX_trust_
Vector of trust region values.
const double DampFactor
Dampfactor is the factor by which the damping factor is reduced by when a reduction in step length is...
int dampStep(const doublereal time_curr, const doublereal *const y_n_curr, const doublereal *const ydot_n_curr, doublereal *const step_1, doublereal *const y_n_1, doublereal *const ydot_n_1, doublereal *step_2, doublereal &stepNorm_2, GeneralMatrix &jac, bool writetitle, int &num_backtracks)
Find a damping coefficient through a look-ahead mechanism.
Base residual calculation for the Jacobian calculation.
#define NSOLN_RETN_FAIL_DAMPSTEP
The nonlinear problem didn't solve the problem.
virtual int factorQR()
Factors the A matrix using the QR algorithm, overwriting A.
The class provides the wall clock timer in seconds.
int m_print_flag
Determines the level of printing for each time step.
int m_nfe
Counter for the total number of function evaluations.
virtual int factorAlgorithm() const =0
Return the factor algorithm used.
NonlinearSolver & operator=(const NonlinearSolver &right)
Assignment operator.
doublereal m_normDeltaSoln_CP
Norm of the distance to the Cauchy point using the solution norm.
std::vector< doublereal > deltaX_Newton_
Newton Step - This is the Newton step determined from the straight Jacobian.
doublereal residErrorNorm(const doublereal *const resid, const char *title=0, const int printLargest=0, const doublereal *const y=0) const
L2 norm of the residual of the equation system.
doublereal NextTrustFactor_
Factor indicating how much trust region has been changed next iteration - output variable.
doublereal filterNewSolution(const doublereal timeCurrent, doublereal *const y_current, doublereal *const ydot_current)
Apply a filter to the solution.
#define NSOLN_JAC_ANAL
The Jacobian is calculated from an analytical function.
virtual int factor()=0
Factors the A matrix, overwriting A.
#define NSOLN_RETN_MAXIMUMITERATIONSEXCEEDED
The nonlinear problem's max number of iterations has been exceeded.
double subtractRD(double a, double b)
This routine subtracts two numbers for one another.
std::vector< doublereal > m_rowScales
Weights for normalizing the values of the residuals.
virtual ResidJacEval * duplMyselfAsResidJacEval() const
Duplication routine for objects derived from residJacEval.
std::vector< doublereal > m_ewt
Soln error weights.
ResidEval_Type_Enum
Differentiates the type of residual evaluations according to functionality.
doublereal dogLegAlpha_
Current Alpha param along the leg.
int m_min_newt_its
Minimum number of Newton iterations to use.
void setDefaultDeltaBoundsMagnitudes()
Set default deulta bounds amounts.
std::vector< doublereal > Jd_
Jacobian times the steepest descent direction in the normalized coordinates.
doublereal m_normDeltaSoln_Newton
Norm of the solution update created by the iteration in its raw, undamped form, using the solution no...
static bool s_print_NumJac
Turn on or off printing of the Jacobian.
int checkUserResidualTols_
Check the residual tolerances explicitly against user input.
NonlinearSolver(ResidJacEval *func)
Default constructor.
Wrappers for the function evaluators for Nonlinear solvers and Time steppers.
std::vector< doublereal > deltaX_CP_
Steepest descent direction. This is also the distance to the Cauchy Point.
doublereal m_dampBound
Damping factor imposed by hard bounds and by delta bounds.
doublereal trustDelta_
Current value of trust radius.
int m_colScaling
The type of column scaling used in the matrix inversion of the problem.
virtual int calcDeltaSolnVariables(const doublereal t, const doublereal *const y, const doublereal *const ydot, doublereal *const delta_y, const doublereal *const solnWeights=0)
Return a vector of delta y's for calculation of the numerical Jacobian.
void createSolnWeights(const doublereal *const y)
Create solution weights for convergence criteria.
std::vector< doublereal > m_deltaStepMaximum
Value of the delta step magnitudes.
int m_numLocalLinearSolves
Number of local linear solves done during the current iteration.
virtual void zero()=0
Zero the matrix elements.
void print_solnDelta_norm_contrib(const doublereal *const step_1, const char *const stepNorm_1, const doublereal *const step_2, const char *const stepNorm_2, const char *const title, const doublereal *const y_n_curr, const doublereal *const y_n_1, doublereal damp, size_t num_entries)
Print solution norm contribution.
int doNewtonSolve(const doublereal time_curr, const doublereal *const y_curr, const doublereal *const ydot_curr, doublereal *const delta_y, GeneralMatrix &jac)
Compute the undamped Newton step.
void adjustUpStepMinimums()
Adjust the step minimums.
doublereal calcTrustDistance(std::vector< doublereal > const &deltaX) const
Calculate the trust distance of a step in the solution variables.
Class that calculates the solution to a nonlinear, dense, set of equations (see Numerical Utilities w...
std::vector< doublereal > m_residWts
Vector of residual weights.
doublereal trustRegionLength() const
Calculate the length of the current trust region in terms of the solution error norm.
void calcColumnScales()
Set the column scaling vector at the current time.
bool m_resid_scaled
Boolean indicating whether we should scale the residual.
doublereal ResidDecreaseNewt_
Actual DResid_dS for the Newton path - output variable.
void setAtol(const doublereal *const atol)
Set the absolute tolerances for the solution variables.
int dampDogLeg(const doublereal time_curr, const doublereal *y_n_curr, const doublereal *ydot_n_curr, std::vector< doublereal > &step_1, doublereal *const y_n_1, doublereal *const ydot_n_1, doublereal &stepNorm_1, doublereal &stepNorm_2, GeneralMatrix &jac, int &num_backtracks)
Damp using the dog leg approach.
double secondsWC()
Returns the wall clock time in seconds since the last reset.
void error(const std::string &msg)
Write an error message and quit.
void initializeTrustRegion()
Initialize the size of the trust vector.
int m_nJacEval
Number of Jacobian evaluations.
std::vector< doublereal > m_y_n_curr
Vector containing the current solution vector within the nonlinear solver.
doublereal ResidDecreaseSD_
Actual DResid_dS for the steepest descent path - output variable.
void setDeltaBoundsMagnitudes(const doublereal *const deltaBoundsMagnitudes)
Set the delta Bounds magnitudes by hand.
size_t neq_
Local copy of the number of equations.
int doAffineNewtonSolve(const doublereal *const y_curr, const doublereal *const ydot_curr, doublereal *const delta_y, GeneralMatrix &jac)
Compute the Newton step, either by direct Newton's or by solving a close problem that is represented ...
std::vector< doublereal > m_ydot_trial
Value of the solution time derivative at the new point that is to be considered.
void fillDogLegStep(int leg, doublereal alpha, std::vector< doublereal > &deltaX) const
Fill a dogleg solution step vector.
virtual size_t checkRows(doublereal &valueSmall) const =0
Check to see if we have any zero rows in the Jacobian.
Base class for exceptions thrown by Cantera classes.
Class that calculates the solution to a nonlinear system.
doublereal m_dampRes
Additional damping factor due to bounds on the residual and solution norms.
#define NSOLN_RETN_JACOBIANFORMATIONERROR
The nonlinear problem's Jacobian formation produced an error.
void setResidualTols(double residRtol, double *residAtol, int residNormHandling=2)
Set the relative and absolute tolerances for the Residual norm comparisons, if used.
std::vector< doublereal > m_y_high_bounds
Bounds vector for each species.
doublereal rtol_
value of the relative tolerance to use in solving the equation set
const int NDAMP
Number of damping steps that are carried out before the solution is deemed a failure.
static bool s_print_DogLeg
Turn on extra printing of dogleg information.
doublereal dist_R2_
Distance of the second leg of the dogleg in terms of the solution norm.
doublereal dist_R1_
Distance of the first leg of the dogleg in terms of the solution norm.
void scaleMatrix(GeneralMatrix &jac, doublereal *const y_comm, doublereal *const ydot_comm, doublereal time_curr, int num_newt_its)
Scale the matrix.
bool ResidWtsReevaluated_
Boolean indicating that the residual weights have been reevaluated this iteration - output variable...
doublereal RJd_norm_
Residual dot Jd norm.
void setRowScaling(bool useRowScaling)
Set the rowscaling that are used for the inversion of the matrix.
std::vector< doublereal > m_ydot_n_curr
Vector containing the time derivative of the current solution vector within the nonlinear solver (whe...
void descentComparison(doublereal time_curr, doublereal *ydot0, doublereal *ydot1, int &numTrials)
This is a utility routine that can be used to print out the rates of the initial residual decline...
doublereal filterNewStep(const doublereal timeCurrent, const doublereal *const ybase, doublereal *const step0)
Apply a filtering process to the step.
static bool s_TurnOffTiming
Turn off printing of time.
int m_numTotalLinearSolves
Total number of linear solves taken by the solver object.
virtual void calcSolnScales(const doublereal t, const doublereal *const y, const doublereal *const y_old, doublereal *const yScales)
Returns a vector of column scale factors that can be used to column scale Jacobians.
int m_manualDeltaStepSet
Boolean indicating whether a manual delta bounds has been input.
Cantera::GeneralMatrix * jacCopyPtr_
Copy of the Jacobian that doesn't get overwritten when the inverse is determined. ...
#define NSOLN_RETN_RESIDUALFORMATIONERROR
The nonlinear problem's base residual produced an error.
virtual ~NonlinearSolver()
Destructor.
virtual bool factored() const
true if the current factorization is up to date with the matrix
std::vector< doublereal > m_resid
Value of the residual for the nonlinear problem.
int m_jacFormMethod
Jacobian formation method.
int solve_nonlinear_problem(int SolnType, doublereal *const y_comm, doublereal *const ydot_comm, doublereal CJ, doublereal time_curr, GeneralMatrix &jac, int &num_newt_its, int &num_linear_solves, int &num_backtracks, int loglevelInput)
Find the solution to F(X) = 0 by damped Newton iteration.
int lambdaToLeg(const doublereal lambda, doublereal &alpha) const
Change the global lambda coordinate into the (leg,alpha) coordinate for the double dogleg...
std::vector< doublereal > m_deltaStepMinimum
Soln Delta bounds magnitudes.
std::vector< doublereal > m_y_n_trial
Vector containing the solution at the new point that is to be considered.
std::vector< doublereal > m_y_nm1
Vector containing the solution at the previous time step.
doublereal m_normResid_full
Norm of the residual at the end of the first leg of the current iteration.
doublereal m_normResid_0
Norm of the residual at the start of each nonlinear iteration.
doublereal time_n
Current system time.
virtual int solve(doublereal *b, size_t nrhs=1, size_t ldb=0)=0
Solves the Ax = b system returning x in the b spot.
int decideStep(const doublereal time_curr, int leg, doublereal alpha, const doublereal *const y_n_curr, const doublereal *const ydot_n_curr, const std::vector< doublereal > &step_1, const doublereal *const y_n_1, const doublereal *const ydot_n_1, doublereal trustDeltaOld)
Decide whether the current step is acceptable and adjust the trust region size.
int m_numTotalNewtIts
Total number of Newton iterations.
virtual size_t nRowsAndStruct(size_t *const iStruct=0) const =0
Return the size and structure of the matrix.
int m_order
Order of the time step method = 1.
Cantera::GeneralMatrix * HessianPtr_
Hessian.
virtual size_t checkColumns(doublereal &valueSmall) const =0
Check to see if we have any zero columns in the Jacobian.
doublereal delta_t_n
Delta t for the current step.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
int solnType_
Solution type.
void residualComparisonLeg(const doublereal time_curr, const doublereal *const ydot0, int &legBest, doublereal &alphaBest) const
Here we print out the residual at various points along the double dogleg, comparing against the quadr...
doublereal expectedResidLeg(int leg, doublereal alpha) const
Calculated the expected residual along the double dogleg curve.
void setRtol(const doublereal rtol)
Set the relative tolerances for the solution variables.
void setBoundsConstraints(const doublereal *const y_low_bounds, const doublereal *const y_high_bounds)
Set bounds constraints for all variables in the problem.
Delta residual calculation for the Jacbobian calculation.
void calc_ydot(const int order, const doublereal *const y_curr, doublereal *const ydot_curr) const
Internal function to calculate the time derivative of the solution at the new step.
doublereal normTrust_CP_
Norm of the Cauchy Step direction wrt trust region.
doublereal CurrentTrustFactor_
Factor indicating how much trust region has been changed this iteration - output variable.
doublereal JdJd_norm_
Dot product of the Jd_ variable defined above with itself.
Contains declarations for string manipulation functions within Cantera.
void getResidWts(doublereal *const residWts) const
Return the residual weights.
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
int calcTrustIntersection(doublereal trustVal, doublereal &lambda, doublereal &alpha) const
Given a trust distance, this routine calculates the intersection of the this distance with the double...
doublereal m_conditionNumber
Condition number of the matrix.
std::vector< doublereal > m_wksp_2
Workspace of length neq_.
virtual doublereal filterSolnPrediction(const doublereal t, doublereal *const y)
Filter the solution predictions.
void setSolverScheme(int doDogLeg, int doAffineSolve)
Parameter to turn on solution solver schemes.
doublereal norm_deltaX_trust_
Current norm of the vector deltaX_trust_ in terms of the solution norm.
int doAffineSolve_
General toggle for turning on Affine solve with Hessian.
ResidJacEval * m_func
Pointer to the residual and Jacobian evaluator for the function.
doublereal deltaBoundStep(const doublereal *const y, const doublereal *const step0)
Return the factor by which the undamped Newton step 'step0' must be multiplied in order to keep the u...
doublereal trustRegionInitializationFactor_
Factor used to set the initial trust region.
doublereal m_normResid_1
Norm of the residual at the end of the first leg of the current iteration.
std::vector< doublereal > m_rowWtScales
Weights for normalizing the values of the residuals.
void setPrintLvl(int printLvl)
Set the print level from the nonlinear solver.
static bool s_doBothSolvesAndCompare
Turn on solving both the Newton and Hessian systems and comparing the results.
doublereal residNorm2Cauchy_
Expected value of the residual norm at the Cauchy point if the quadratic model were valid...
doublereal dist_R0_
Distance of the zeroeth leg of the dogleg in terms of the solution norm.
doublereal atolBase_
Base value of the absolute tolerance.
std::vector< doublereal > m_wksp
Workspace of length neq_.
int maxNewtIts_
Maximum number of Newton iterations.
doublereal m_ScaleSolnNormToResNorm
Scale factor for turning residual norms into solution norms.
virtual doublereal filterNewStep(const doublereal t, const doublereal *const ybase, doublereal *const step)
Filter the solution predictions.
Base residual calculation containing any lagged components.
virtual doublereal rcondQR()
Returns an estimate of the inverse of the condition number for the matrix.
int doDogLeg_
General toggle for turning on dog leg damping.
doublereal dist_Total_
Distance of the sum of all legs of the doglegs in terms of the solution norm.
std::vector< doublereal > & lowBoundsConstraintVector()
Return an editable vector of the low bounds constraints.
std::vector< doublereal > m_step_1
Value of the step to be taken in the solution.
std::vector< doublereal > & highBoundsConstraintVector()
Return an editable vector of the high bounds constraints.
virtual void useFactorAlgorithm(int fAlgorithm)
Change the way the matrix is factored.
doublereal doCauchyPointSolve(GeneralMatrix &jac)
Calculate the steepest descent direction and the Cauchy Point where the quadratic formulation of the ...
void setColumnScaling(bool useColScaling, const double *const scaleFactors=0)
Set the column scaling that are used for the inversion of the matrix.