47 #include <Xyce_config.h>
52 #include <N_UTL_Misc.h>
72 #include <N_LOA_Loader.h>
76 #include <N_LAS_System.h>
77 #include <N_LAS_Vector.h>
78 #include <N_LAS_Matrix.h>
79 #include <N_LAS_Solver.h>
80 #include <N_LAS_Problem.h>
81 #include <N_LAS_Builder.h>
83 #include <N_ERH_ErrorMgr.h>
84 #include <N_UTL_Param.h>
85 #include <N_UTL_OptionBlock.h>
86 #include <N_UTL_Xyce.h>
88 #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 <<
" -------------------------------------------------------------------\n";
294 os << Xyce::section_divider << std::endl;
307 os <<
"Niter: " << std::fixed << step
308 <<
" " << std::setprecision(4) << std::scientific <<
stepLength_
309 <<
" " << std::setprecision(4) << std::scientific <<
wtNormDX_
310 <<
" " << std::setprecision(4) << std::scientific <<
maxNormRHS_
311 <<
" " << std::setprecision(4) << std::scientific <<
normRHS_rel_
332 (*nextSolVectorPtrPtr_)->maxValue(&tmp);
333 double solnNorm = fabs(tmp);
335 if ((
iNumCalls_ == 0) && (solnNorm <= N_UTL_MachineDependentParams::DoubleMin()))
341 double newSoln, oldSoln;
343 int length = (*nextSolVectorPtrPtr_)->localLength();
344 for (
int i = 0; i < length; ++i)
346 newSoln = (*(*nextSolVectorPtrPtr_))[i];
347 oldSoln = (*(*currSolVectorPtrPtr_))[i];
381 static const char *trace =
"DampedNewton::solve: ";
383 #ifdef Xyce_DEBUG_NONLINEAR
404 #ifndef Xyce_SPICE_NORMS
415 #ifdef Xyce_VERBOSE_NONLINEAR
420 #ifdef Xyce_VERBOSE_NONLINEAR
423 Xyce::Report::UserWarning0() <<
"Use of the gradient strategy (1) is discouraged";
435 #ifdef Xyce_VERBOSE_NONLINEAR
447 std::vector<int> index(1, -1);
458 if (
normRHS_ < N_UTL_MachineDependentParams::MachineEpsilon())
494 int convergedStatus = 0;
495 while (convergedStatus == 0)
505 #ifdef Xyce_DEBUG_NONLINEAR
524 #ifdef Xyce_DEBUG_NONLINEAR
542 #ifdef Xyce_SPICE_NORMS
565 #ifdef Xyce_VERBOSE_NONLINEAR
602 #ifndef Xyce_SPICE_NORMS
613 #ifdef Xyce_VERBOSE_NONLINEAR
619 return convergedStatus;
637 static const char *trace =
"DampedNewton::takeFirstSolveStep: ";
639 #ifdef Xyce_DEBUG_NONLINEAR
655 #ifndef Xyce_SPICE_NORMS
668 #endif // figure this out later. Mainly, understand what is really meant
672 #ifdef Xyce_VERBOSE_NONLINEAR
678 #ifdef Xyce_VERBOSE_NONLINEAR
681 Xyce::Report::UserWarning0() <<
"Use of the gradient strategy (1) is discouraged";
693 #ifdef Xyce_VERBOSE_NONLINEAR
712 if (
normRHS_ < N_UTL_MachineDependentParams::MachineEpsilon())
return 1;
733 int convergedStatus = 0;
742 #ifdef Xyce_DEBUG_NONLINEAR
761 #ifdef Xyce_DEBUG_NONLINEAR
777 #ifdef Xyce_SPICE_NORMS
800 #ifdef Xyce_VERBOSE_NONLINEAR
822 #ifndef Xyce_SPICE_NORMS
837 return convergedStatus;
876 static const char *trace =
"DampedNewton::takeOneSolveStep";
878 #ifdef Xyce_DEBUG_NONLINEAR
902 int convergedStatus = 0;
912 #ifdef Xyce_DEBUG_NONLINEAR
931 #ifdef Xyce_DEBUG_NONLINEAR
947 #ifdef Xyce_SPICE_NORMS
970 #ifdef Xyce_VERBOSE_NONLINEAR
992 #ifdef Xyce_DEBUG_NONLINEAR
993 if (convergedStatus > 0)
1010 return convergedStatus;
1058 #ifdef Xyce_DEBUG_NONLINEAR
1107 static const char *trace =
"DampedNewton::direction_: ";
1109 #ifdef Xyce_DEBUG_NONLINEAR
1118 Xyce::dout() <<
"nonlinear strategy is Newton" << std::endl;
1121 Xyce::dout() <<
"nonlinear strategy is Modified-Newton" << std::endl;
1124 Xyce::dout() <<
"\tnonlinear strategy is Inexact Newton" << std::endl
1125 <<
"\t\tconvergence rate: " <<
resConvRate_ << std::endl;
1128 Xyce::dout() <<
"\tnonlinear strategy is Inexact Modified-Newton\n\t\tconvergence rate: " <<
resConvRate_ << std::endl;
1131 Xyce::dout() <<
"nonlinear strategy is Gradient" << std::endl;
1135 Xyce::Report::DevelFatal0().in(trace) <<
"Invalid nonlinear solver strategy: " <<
static_cast<int> (
nlParams.
getNLStrategy());
1155 const double minRedFac = 0.999;
1165 const double minRedFac = 0.999;
1223 #ifdef Xyce_DEBUG_NONLINEAR
1224 Xyce::Report::DevelFatal0().in(
"DampedNewton::direction_") <<
"Invalid search direction: " <<
static_cast<int>(
nlParams.
getDirection());
1250 static const char *trace =
"DampedNewton::computeStepLength_";
1307 static const char *trace =
"DampedNewton::divide__";
1309 #if defined(Xyce_DEBUG_NONLINEAR)
1315 const double oldNormRHS =
normRHS_;
1333 <<
"\toldNormRHS: " << oldNormRHS <<
", normRHS: " <<
normRHS_ << std::endl;
1337 bool searchDone = (
normRHS_ < oldNormRHS);
1344 if (
stepLength_ < N_UTL_MachineDependentParams::MachineEpsilon())
1346 #ifdef Xyce_DEBUG_NONLINEAR
1349 Xyce::Report::UserWarning0() <<
"\tStep size too small: " <<
stepLength_ <<
"\n\tTaking a full step.\n";
1365 searchDone = ((
normRHS_ < oldNormRHS) || (searchDone) ||
1371 <<
"\toldNormRHS: " << oldNormRHS <<
", normRHS: " <<
normRHS_ << std::endl;
1401 double sdotg = s.dotProduct(g);
1404 const double f = 0.5 * normrhs * normrhs;
1415 if (((sdotg >= 0) || (!issuffdec)) &&
1418 Xyce::lout() <<
"Switching to Cauchy!" << std::endl;
1420 s.scale(-1.0 / normrhs);
1421 sdotg = s.dotProduct(g);
1434 Xyce::lout() <<
"Linesearch failed!" << std::endl;
1458 double f = 0.5 * normrhs * normrhs;
1459 const double alpha = 1.0e-6;
1461 Xyce::dout().setf(std::ios::scientific);
1462 Xyce::dout().precision(10);
1464 Xyce::dout() <<
"\nIteration: " << 0
1466 <<
" F(X): " << finit
1467 <<
" gsinit: " << gsinit
1468 <<
" alpha * gsinit: " << alpha * gsinit
1472 const int nstepmax = 20;
1473 const double minstep = N_UTL_MachineDependentParams::MachineEpsilon();
1477 bool issuffdec =
false;
1481 if (nstep >= nstepmax)
1502 f = 0.5 * normrhs * normrhs;
1505 issuffdec = (f <= (finit + (alpha * step * gsinit)));
1510 Xyce::dout() <<
"Iteration: " << nstep
1511 <<
" Step: " << step
1513 <<
" Test: " << (finit + (alpha * step * gsinit))
1517 Xyce::dout().unsetf(std::ios::scientific);
1532 static const char *trace =
"DampedNewton::computeStepLength_";
1534 #if defined(Xyce_DEBUG_NONLINEAR)
1540 const double oldNormRHS =
normRHS_;
1556 double rho, delta, theta, lambda;
1557 const double t = 1.0e-04, thetaMin = 0.1, thetaMax = 0.5;
1558 const double minStep = pow(N_UTL_MachineDependentParams::MachineEpsilon(), 0.33);
1569 while ((rho > 1.0 - t * lambda) &&
1572 delta = rho * rho - 1.0 + 2.0 * lambda;
1577 theta = lambda / delta;
1579 if (theta > thetaMax)
1581 else if (theta < thetaMin)
1605 <<
"\toldNormRHS: " << oldNormRHS <<
", normRHS: " <<
normRHS_ << std::endl;
1613 return (rho <= 1.0 - t * lambda);
1669 (*nextSolVectorPtrPtr_)->putScalar(0.0);
1698 static const char * trace =
"DampedNewton::evalModNewton_";
1700 const double minConvFactor = 0.01;
1702 const double etaMax = 1.0;
1703 const double etaMin = 1.0e-12;
1704 const double etaInit = 1.0e-01;
1720 #ifdef Xyce_DEBUG_NONLINEAR
1723 N_UTL_Param linRes(
"RESIDUAL", 0.0 );
1725 Xyce::dout() <<
"\tnlResNorm: " << nlResNorm <<
" linRes: " << linRes.getImmutableValue<
double>()
1726 <<
"nlResNormOld: " <<
nlResNormOld <<
"calculated eta: " << eta << std::endl;
1733 #ifdef Xyce_DEBUG_NONLINEAR
1736 Xyce::dout() <<
"\t\teta:\t" << eta <<
"\n" << std::endl;
1745 if (eta < minConvFactor)
1752 #ifdef Xyce_VERBOSE_NONLINEAR
1754 Xyce::lout() <<
" ***** Calculating new Jacobian and preconditioner\n" << std::endl;
1756 Xyce::lout() <<
" ***** Using old Jacobian and preconditioner\n" << std::endl;
1795 static const char *trace =
"DampedNewton::converged_";
1797 const double rhsTol = N_UTL_MachineDependentParams::MachineEpsilon();
1798 const double convRateMax = 0.5 * N_UTL_MachineDependentParams::DoubleMax();
1800 const double minResReduct = 9.0e-1;
1801 const double stagnationTol = 1.0e-3;
1812 bool allDevicesConverged_ =
loaderPtr_->allDevsConverged();
1813 if (!allDevicesConverged_ &&
1821 bool innerDevicesConverged_ =
loaderPtr_->innerDevsConverged();
1822 if (!innerDevicesConverged_ )
1865 #ifdef Xyce_DEBUG_NONLINEAR
1868 Xyce::dout() <<
"\tcount:\t" <<
count << std::endl
1869 <<
"\tresConvRate_:\t" <<
resConvRate_ <<
"\n" << std::endl;
1881 #ifdef Xyce_DEBUG_NONLINEAR
1884 Xyce::dout() <<
"\ttmpConvRate: " <<
tmpConvRate << std::endl
1886 <<
"\tReturning 3\n" << std::endl;
1893 #ifdef Xyce_DEBUG_NONLINEAR
1896 Xyce::dout() <<
"\ttmpConvRate: " <<
tmpConvRate << std::endl
1898 <<
"\tReturning -3\n" << std::endl;
1944 if (Xyce::DEBUG_NONLINEAR)
1945 Xyce::dout() <<
"DampedNewton::constrain_: minValue: " << minValue << std::endl;
1947 #ifdef Xyce_VERBOSE_NONLINEAR
1949 Xyce::lout() <<
" ***** Constraining:\t" << minValue << std::endl;
1967 const double etaExp = 0.5 * (1.0 + sqrt(5.0));
1968 const double etaMax = 0.1;
1969 const double etaMin = 1.0e-12;
1970 const double etaInit = 1.0e-01;
1980 else if (
nlResNormOld > N_UTL_MachineDependentParams::DoubleMin())
1982 N_UTL_Param linRes(
"RESIDUAL", 0.0 );
1984 eta = fabs(nlResNorm - linRes.getImmutableValue<
double>()) /
nlResNormOld;
1988 etaSafe = pow(
etaOld, etaExp);
1998 #ifdef Xyce_DEBUG_NONLINEAR
1999 Xyce::dout() <<
"\tnlResNorm: " << nlResNorm
2000 <<
" linRes: " << linRes.getImmutableValue<
double>()
2002 <<
" calculated eta: " << fabs(nlResNorm - linRes.getImmutableValue<
double>())/
nlResNormOld << std::endl;
2012 #ifdef Xyce_VERBOSE_NONLINEAR
2013 Xyce::lout() <<
"\t\teta:\t" << eta <<
"\n" << std::endl;
2042 Xyce::lout() <<
"THIS IS BROKEN. DO NOT USE THIS METHOD" << std::endl;
2057 Xyce::lout() <<
"THIS IS BROKEN. DO NOT USE THIS METHOD" << std::endl;