47 #include <Xyce_config.h>
52 #include <N_UTL_Misc.h>
72 #include <N_LOA_LoaderMgr.h>
73 #include <N_LOA_Loader.h>
78 #include <N_LAS_System.h>
79 #include <N_LAS_Vector.h>
80 #include <N_LAS_Matrix.h>
81 #include <N_LAS_Solver.h>
82 #include <N_LAS_Problem.h>
83 #include <N_LAS_Builder.h>
85 #include <N_ERH_ErrorMgr.h>
86 #include <N_UTL_Param.h>
87 #include <N_UTL_OptionBlock.h>
88 #include <N_UTL_Xyce.h>
90 #include <N_IO_CmdParse.h>
107 loadJacobianFlag_(true),
109 searchDirectionPtr_(0),
111 delta_(pow(N_UTL_MachineDependentParams::MachineEpsilon(), 0.67)),
115 maxNormRHSindex_(-1),
121 constraintFactor_(1.0),
128 initialDeltaXTol(0.0),
162 #ifdef Xyce_DEBUG_VOLTLIM
163 delete jdxVLVectorPtr_;
165 delete fdxVLVectorPtr_;
167 delete qdxVLVectorPtr_;
249 #ifdef Xyce_DEBUG_VOLTLIM
251 dxVoltlimVectorPtr_ =
lasSysPtr_->getDxVoltlimVector();
254 jdxVLVectorPtr_ =
lasSysPtr_->builder().createVector();
255 fdxVLVectorPtr_ =
lasSysPtr_->builder().createVector();
256 qdxVLVectorPtr_ =
lasSysPtr_->builder().createVector();
259 jacTestMatrixPtr_ =
lasSysPtr_->getJacTestMatrix();
260 dFdxTestMatrixPtr_ =
lasSysPtr_->getdFdxTestMatrix();
261 dQdxTestMatrixPtr_ =
lasSysPtr_->getdQdxTestMatrix();
280 <<
" Iter Step Wt DX Inf-Norm 2-Norm (rel)\n"
281 <<
" -------------------------------------------------------------------";
294 os << Xyce::section_divider << std::endl;
327 (*nextSolVectorPtrPtr_)->maxValue(&tmp);
328 double solnNorm = fabs(tmp);
330 if ((
iNumCalls_ == 0) && (solnNorm <= N_UTL_MachineDependentParams::DoubleMin()))
336 double newSoln, oldSoln;
338 int length = (*nextSolVectorPtrPtr_)->localLength();
339 for (
int i = 0; i < length; ++i)
341 newSoln = (*(*nextSolVectorPtrPtr_))[i];
342 oldSoln = (*(*currSolVectorPtrPtr_))[i];
376 static const char *trace =
"N_NLS_DampedNewton::solve: ";
378 #ifdef Xyce_DEBUG_NONLINEAR
399 #ifndef Xyce_SPICE_NORMS
410 #ifdef Xyce_VERBOSE_NONLINEAR
415 #ifdef Xyce_VERBOSE_NONLINEAR
418 Xyce::Report::UserWarning0() <<
"Use of the gradient strategy (1) is discouraged";
430 #ifdef Xyce_VERBOSE_NONLINEAR
442 std::vector<int> index(1, -1);
453 if (
normRHS_ < N_UTL_MachineDependentParams::MachineEpsilon())
489 int convergedStatus = 0;
490 while (convergedStatus == 0)
500 #ifdef Xyce_DEBUG_NONLINEAR
519 #ifdef Xyce_DEBUG_NONLINEAR
537 #ifdef Xyce_SPICE_NORMS
560 #ifdef Xyce_VERBOSE_NONLINEAR
597 #ifndef Xyce_SPICE_NORMS
608 #ifdef Xyce_VERBOSE_NONLINEAR
614 return convergedStatus;
632 static const char *trace =
"N_NLS_DampedNewton::takeFirstSolveStep: ";
634 #ifdef Xyce_DEBUG_NONLINEAR
650 #ifndef Xyce_SPICE_NORMS
663 #endif // figure this out later. Mainly, understand what is really meant
667 #ifdef Xyce_VERBOSE_NONLINEAR
673 #ifdef Xyce_VERBOSE_NONLINEAR
676 Xyce::Report::UserWarning0() <<
"Use of the gradient strategy (1) is discouraged";
688 #ifdef Xyce_VERBOSE_NONLINEAR
707 if (
normRHS_ < N_UTL_MachineDependentParams::MachineEpsilon())
return 1;
728 int convergedStatus = 0;
737 #ifdef Xyce_DEBUG_NONLINEAR
756 #ifdef Xyce_DEBUG_NONLINEAR
772 #ifdef Xyce_SPICE_NORMS
795 #ifdef Xyce_VERBOSE_NONLINEAR
817 #ifndef Xyce_SPICE_NORMS
832 return convergedStatus;
871 static const char *trace =
"N_NLS_DampedNewton::takeOneSolveStep";
873 #ifdef Xyce_DEBUG_NONLINEAR
897 int convergedStatus = 0;
907 #ifdef Xyce_DEBUG_NONLINEAR
926 #ifdef Xyce_DEBUG_NONLINEAR
942 #ifdef Xyce_SPICE_NORMS
965 #ifdef Xyce_VERBOSE_NONLINEAR
987 #ifdef Xyce_DEBUG_NONLINEAR
988 if (convergedStatus > 0)
1005 return convergedStatus;
1053 #ifdef Xyce_DEBUG_NONLINEAR
1102 static const char *trace =
"N_NLS_DampedNewton::direction_: ";
1104 #ifdef Xyce_DEBUG_NONLINEAR
1113 Xyce::dout() <<
"nonlinear strategy is Newton" << std::endl;
1116 Xyce::dout() <<
"nonlinear strategy is Modified-Newton" << std::endl;
1119 Xyce::dout() <<
"\tnonlinear strategy is Inexact Newton" << std::endl
1120 <<
"\t\tconvergence rate: " <<
resConvRate_ << std::endl;
1123 Xyce::dout() <<
"\tnonlinear strategy is Inexact Modified-Newton\n\t\tconvergence rate: " <<
resConvRate_ << std::endl;
1126 Xyce::dout() <<
"nonlinear strategy is Gradient" << std::endl;
1130 Xyce::Report::DevelFatal0().in(trace) <<
"Invalid nonlinear solver strategy: " <<
static_cast<int> (
nlParams.
getNLStrategy());
1150 const double minRedFac = 0.999;
1160 const double minRedFac = 0.999;
1218 #ifdef Xyce_DEBUG_NONLINEAR
1219 Xyce::Report::DevelFatal0().in(
"N_NLS_DampedNewton::direction_") <<
"Invalid search direction: " <<
static_cast<int>(
nlParams.
getDirection());
1245 static const char *trace =
"N_NLS_DampedNewton::computeStepLength_";
1302 static const char *trace =
"N_NLS_DampedNewton::divide__";
1304 #if defined(Xyce_DEBUG_NONLINEAR)
1310 const double oldNormRHS =
normRHS_;
1328 <<
"\toldNormRHS: " << oldNormRHS <<
", normRHS: " <<
normRHS_ << std::endl;
1332 bool searchDone = (
normRHS_ < oldNormRHS);
1339 if (
stepLength_ < N_UTL_MachineDependentParams::MachineEpsilon())
1341 #ifdef Xyce_DEBUG_NONLINEAR
1344 Xyce::Report::UserWarning0() <<
"\tStep size too small: " <<
stepLength_ <<
"\n\tTaking a full step.\n";
1360 searchDone = ((
normRHS_ < oldNormRHS) || (searchDone) ||
1366 <<
"\toldNormRHS: " << oldNormRHS <<
", normRHS: " <<
normRHS_ << std::endl;
1396 double sdotg = s.dotProduct(g);
1399 const double f = 0.5 * normrhs * normrhs;
1410 if (((sdotg >= 0) || (!issuffdec)) &&
1413 Xyce::lout() <<
"Switching to Cauchy!" << std::endl;
1415 s.scale(-1.0 / normrhs);
1416 sdotg = s.dotProduct(g);
1429 Xyce::lout() <<
"Linesearch failed!" << std::endl;
1453 double f = 0.5 * normrhs * normrhs;
1454 const double alpha = 1.0e-6;
1456 Xyce::dout().setf(std::ios::scientific);
1457 Xyce::dout().precision(10);
1459 Xyce::dout() <<
"\nIteration: " << 0
1461 <<
" F(X): " << finit
1462 <<
" gsinit: " << gsinit
1463 <<
" alpha * gsinit: " << alpha * gsinit
1467 const int nstepmax = 20;
1468 const double minstep = N_UTL_MachineDependentParams::MachineEpsilon();
1472 bool issuffdec =
false;
1476 if (nstep >= nstepmax)
1497 f = 0.5 * normrhs * normrhs;
1500 issuffdec = (f <= (finit + (alpha * step * gsinit)));
1505 Xyce::dout() <<
"Iteration: " << nstep
1506 <<
" Step: " << step
1508 <<
" Test: " << (finit + (alpha * step * gsinit))
1512 Xyce::dout().unsetf(std::ios::scientific);
1527 static const char *trace =
"N_NLS_DampedNewton::computeStepLength_";
1529 #if defined(Xyce_DEBUG_NONLINEAR)
1535 const double oldNormRHS =
normRHS_;
1551 double rho, delta, theta, lambda;
1552 const double t = 1.0e-04, thetaMin = 0.1, thetaMax = 0.5;
1553 const double minStep = pow(N_UTL_MachineDependentParams::MachineEpsilon(), 0.33);
1564 while ((rho > 1.0 - t * lambda) &&
1567 delta = rho * rho - 1.0 + 2.0 * lambda;
1572 theta = lambda / delta;
1574 if (theta > thetaMax)
1576 else if (theta < thetaMin)
1600 <<
"\toldNormRHS: " << oldNormRHS <<
", normRHS: " <<
normRHS_ << std::endl;
1608 return (rho <= 1.0 - t * lambda);
1664 (*nextSolVectorPtrPtr_)->putScalar(0.0);
1693 static const char * trace =
"N_NLS_DampedNewton::evalModNewton_";
1695 const double minConvFactor = 0.01;
1697 const double etaMax = 1.0;
1698 const double etaMin = 1.0e-12;
1699 const double etaInit = 1.0e-01;
1715 #ifdef Xyce_DEBUG_NONLINEAR
1718 N_UTL_Param linRes(
"RESIDUAL", 0.0 );
1720 Xyce::dout() <<
"\tnlResNorm: " << nlResNorm <<
" linRes: " << linRes.getImmutableValue<
double>()
1721 <<
"nlResNormOld: " <<
nlResNormOld <<
"calculated eta: " << eta << std::endl;
1728 #ifdef Xyce_DEBUG_NONLINEAR
1731 Xyce::dout() <<
"\t\teta:\t" << eta <<
"\n" << std::endl;
1740 if (eta < minConvFactor)
1747 #ifdef Xyce_VERBOSE_NONLINEAR
1749 Xyce::lout() <<
" ***** Calculating new Jacobian and preconditioner\n" << std::endl;
1751 Xyce::lout() <<
" ***** Using old Jacobian and preconditioner\n" << std::endl;
1790 static const char *trace =
"N_NLS_DampedNewton::converged_";
1792 const double rhsTol = N_UTL_MachineDependentParams::MachineEpsilon();
1793 const double convRateMax = 0.5 * N_UTL_MachineDependentParams::DoubleMax();
1795 const double minResReduct = 9.0e-1;
1796 const double stagnationTol = 1.0e-3;
1807 bool allDevicesConverged_ =
loaderPtr_->allDevsConverged();
1808 if (!allDevicesConverged_ &&
1816 bool innerDevicesConverged_ =
loaderPtr_->innerDevsConverged();
1817 if (!innerDevicesConverged_ )
1860 #ifdef Xyce_DEBUG_NONLINEAR
1863 Xyce::dout() <<
"\tcount:\t" <<
count << std::endl
1864 <<
"\tresConvRate_:\t" <<
resConvRate_ <<
"\n" << std::endl;
1876 #ifdef Xyce_DEBUG_NONLINEAR
1879 Xyce::dout() <<
"\ttmpConvRate: " <<
tmpConvRate << std::endl
1881 <<
"\tReturning 3\n" << std::endl;
1888 #ifdef Xyce_DEBUG_NONLINEAR
1891 Xyce::dout() <<
"\ttmpConvRate: " <<
tmpConvRate << std::endl
1893 <<
"\tReturning -3\n" << std::endl;
1939 if (Xyce::DEBUG_NONLINEAR)
1940 Xyce::dout() <<
"N_NLS_DampedNewton::constrain_: minValue: " << minValue << std::endl;
1942 #ifdef Xyce_VERBOSE_NONLINEAR
1944 Xyce::lout() <<
" ***** Constraining:\t" << minValue << std::endl;
1962 const double etaExp = 0.5 * (1.0 + sqrt(5.0));
1963 const double etaMax = 0.1;
1964 const double etaMin = 1.0e-12;
1965 const double etaInit = 1.0e-01;
1975 else if (
nlResNormOld > N_UTL_MachineDependentParams::DoubleMin())
1977 N_UTL_Param linRes(
"RESIDUAL", 0.0 );
1979 eta = fabs(nlResNorm - linRes.getImmutableValue<
double>()) /
nlResNormOld;
1983 etaSafe = pow(
etaOld, etaExp);
1985 eta = Xycemax(eta, etaSafe);
1988 eta = Xycemin(etaMax, eta);
1991 eta = Xycemax(etaMin, eta);
1993 #ifdef Xyce_DEBUG_NONLINEAR
1994 Xyce::dout() <<
"\tnlResNorm: " << nlResNorm
1995 <<
" linRes: " << linRes.getImmutableValue<
double>()
1997 <<
" calculated eta: " << fabs(nlResNorm - linRes.getImmutableValue<
double>())/
nlResNormOld << std::endl;
2007 #ifdef Xyce_VERBOSE_NONLINEAR
2008 Xyce::lout() <<
"\t\teta:\t" << eta <<
"\n" << std::endl;
2037 Xyce::lout() <<
"THIS IS BROKEN. DO NOT USE THIS METHOD" << std::endl;
2052 Xyce::lout() <<
"THIS IS BROKEN. DO NOT USE THIS METHOD" << std::endl;