47 #include <Xyce_config.h>
54 #include <N_ERH_ErrorMgr.h>
55 #include <N_IO_CmdParse.h>
56 #include <N_LAS_Builder.h>
57 #include <N_LAS_Matrix.h>
58 #include <N_LAS_Problem.h>
59 #include <N_LAS_Solver.h>
60 #include <N_LAS_System.h>
61 #include <N_LAS_Vector.h>
68 #include <N_PDS_Comm.h>
69 #include <N_UTL_FeatureTest.h>
70 #include <N_UTL_OptionBlock.h>
71 #include <N_UTL_Param.h>
87 const IO::CmdParse & cp)
91 loadJacobianFlag_(true),
93 searchDirectionPtr_(0),
95 delta_(pow(Util::MachineDependentParams::MachineEpsilon(), 0.67)),
105 constraintFactor_(1.0),
112 initialDeltaXTol(0.0),
270 <<
" Iter Step Wt DX Inf-Norm 2-Norm (rel)\n"
271 <<
" -------------------------------------------------------------------\n";
284 os << Xyce::section_divider << std::endl;
297 os <<
"Niter: " << std::fixed << step
298 <<
" " << std::setprecision(4) << std::scientific <<
stepLength_
299 <<
" " << std::setprecision(4) << std::scientific <<
wtNormDX_
300 <<
" " << std::setprecision(4) << std::scientific <<
maxNormRHS_
301 <<
" " << std::setprecision(4) << std::scientific <<
normRHS_rel_
322 (*nextSolVectorPtrPtr_)->maxValue(&tmp);
323 double solnNorm = fabs(tmp);
325 if ((
iNumCalls_ == 0) && (solnNorm <= Util::MachineDependentParams::DoubleMin()))
331 double newSoln, oldSoln;
333 int length = (*nextSolVectorPtrPtr_)->localLength();
334 for (
int i = 0; i < length; ++i)
336 newSoln = (*(*nextSolVectorPtrPtr_))[i];
337 oldSoln = (*(*currSolVectorPtrPtr_))[i];
371 static const char *trace =
"DampedNewton::solve: ";
396 #ifndef Xyce_SPICE_NORMS
408 if (VERBOSE_NONLINEAR)
413 Xyce::Report::UserWarning0() <<
"Use of the gradient strategy (1) is discouraged";
424 if (VERBOSE_NONLINEAR)
437 std::vector<int> index(1, -1);
468 int convergedStatus = 0;
469 while (convergedStatus == 0)
514 #ifdef Xyce_SPICE_NORMS
537 if (VERBOSE_NONLINEAR)
569 #ifndef Xyce_SPICE_NORMS
580 if (VERBOSE_NONLINEAR)
585 return convergedStatus;
605 static const char *trace =
"DampedNewton::takeFirstSolveStep: ";
622 if (VERBOSE_NONLINEAR)
627 Xyce::Report::UserWarning0() <<
"Use of the gradient strategy (1) is discouraged";
638 if (VERBOSE_NONLINEAR)
658 if (
normRHS_ < Util::MachineDependentParams::MachineEpsilon())
return 1;
679 int convergedStatus = 0;
721 #ifdef Xyce_SPICE_NORMS
744 if (VERBOSE_NONLINEAR)
765 #ifndef Xyce_SPICE_NORMS
780 return convergedStatus;
819 static const char *trace =
"DampedNewton::takeOneSolveStep";
844 int convergedStatus = 0;
887 #ifdef Xyce_SPICE_NORMS
910 if (VERBOSE_NONLINEAR)
931 if (DEBUG_NONLINEAR && convergedStatus > 0)
947 return convergedStatus;
1043 static const char *trace =
"DampedNewton::direction_: ";
1058 const double minRedFac = 0.999;
1068 const double minRedFac = 0.999;
1126 if (DEBUG_NONLINEAR)
1127 Xyce::Report::DevelFatal0().in(
"DampedNewton::direction_") <<
"Invalid search direction: " <<
static_cast<int>(
nlParams.
getDirection());
1152 static const char *trace =
"DampedNewton::computeStepLength_";
1199 static const char *trace =
"DampedNewton::divide__";
1203 const double oldNormRHS =
normRHS_;
1217 if (DEBUG_NONLINEAR &&
debugTimeFlag_ && isActive(Diag::NONLINEAR_PARAMETERS) )
1220 <<
"\toldNormRHS: " << oldNormRHS <<
", normRHS: " <<
normRHS_ << std::endl;
1224 bool searchDone = (
normRHS_ < oldNormRHS);
1231 if (
stepLength_ < Util::MachineDependentParams::MachineEpsilon())
1233 if (DEBUG_NONLINEAR &&
debugTimeFlag_ && isActive(Diag::NONLINEAR_PARAMETERS) )
1235 Xyce::Report::UserWarning0() <<
"\tStep size too small: " <<
stepLength_ <<
"\n\tTaking a full step.\n";
1250 searchDone = ((
normRHS_ < oldNormRHS) || (searchDone) ||
1253 if (DEBUG_NONLINEAR &&
debugTimeFlag_ && isActive(Diag::NONLINEAR_PARAMETERS) )
1256 <<
"\toldNormRHS: " << oldNormRHS <<
", normRHS: " <<
normRHS_ << std::endl;
1286 double sdotg = s.dotProduct(g);
1289 const double f = 0.5 * normrhs * normrhs;
1300 if (((sdotg >= 0) || (!issuffdec)) &&
1303 Xyce::lout() <<
"Switching to Cauchy!" << std::endl;
1305 s.scale(-1.0 / normrhs);
1306 sdotg = s.dotProduct(g);
1319 Xyce::lout() <<
"Linesearch failed!" << std::endl;
1343 double f = 0.5 * normrhs * normrhs;
1344 const double alpha = 1.0e-6;
1346 Xyce::dout().setf(std::ios::scientific);
1347 Xyce::dout().precision(10);
1349 Xyce::dout() <<
"\nIteration: " << 0
1351 <<
" F(X): " << finit
1352 <<
" gsinit: " << gsinit
1353 <<
" alpha * gsinit: " << alpha * gsinit
1357 const int nstepmax = 20;
1358 const double minstep = Util::MachineDependentParams::MachineEpsilon();
1362 bool issuffdec =
false;
1366 if (nstep >= nstepmax)
1387 f = 0.5 * normrhs * normrhs;
1390 issuffdec = (f <= (finit + (alpha * step * gsinit)));
1395 Xyce::dout() <<
"Iteration: " << nstep
1396 <<
" Step: " << step
1398 <<
" Test: " << (finit + (alpha * step * gsinit))
1402 Xyce::dout().unsetf(std::ios::scientific);
1417 static const char *trace =
"DampedNewton::computeStepLength_";
1421 const double oldNormRHS =
normRHS_;
1437 double rho, delta, theta, lambda;
1438 const double t = 1.0e-04, thetaMin = 0.1, thetaMax = 0.5;
1439 const double minStep = pow(Util::MachineDependentParams::MachineEpsilon(), 0.33);
1450 while ((rho > 1.0 - t * lambda) &&
1453 delta = rho * rho - 1.0 + 2.0 * lambda;
1458 theta = lambda / delta;
1460 if (theta > thetaMax)
1462 else if (theta < thetaMin)
1483 if (DEBUG_NONLINEAR &&
debugTimeFlag_ && isActive(Diag::NONLINEAR_PARAMETERS) )
1486 <<
"\toldNormRHS: " << oldNormRHS <<
", normRHS: " <<
normRHS_ << std::endl;
1490 return (rho <= 1.0 - t * lambda);
1532 static const char * trace =
"DampedNewton::evalModNewton_";
1534 const double minConvFactor = 0.01;
1536 const double etaMax = 1.0;
1537 const double etaMin = 1.0e-12;
1538 const double etaInit = 1.0e-01;
1552 if (DEBUG_NONLINEAR &&
debugTimeFlag_ && isActive(Diag::NONLINEAR_PARAMETERS) )
1554 Util::Param linRes(
"RESIDUAL", 0.0 );
1556 Xyce::dout() <<
"\tnlResNorm: " << nlResNorm <<
" linRes: " << linRes.getImmutableValue<
double>()
1557 <<
"nlResNormOld: " <<
nlResNormOld <<
"calculated eta: " << eta << std::endl;
1563 if (DEBUG_NONLINEAR &&
debugTimeFlag_ && isActive(Diag::NONLINEAR_PARAMETERS) )
1564 Xyce::dout() <<
"\t\teta:\t" << eta <<
"\n" << std::endl;
1568 if (eta < minConvFactor)
1573 if (VERBOSE_NONLINEAR) {
1575 Xyce::lout() <<
" ***** Calculating new Jacobian and preconditioner\n" << std::endl;
1577 Xyce::lout() <<
" ***** Using old Jacobian and preconditioner\n" << std::endl;
1615 static const char *trace =
"DampedNewton::converged_";
1617 const double rhsTol = Util::MachineDependentParams::MachineEpsilon();
1618 const double convRateMax = 0.5 * Util::MachineDependentParams::DoubleMax();
1619 const double minResReduct = 9.0e-1;
1620 const double stagnationTol = 1.0e-3;
1646 if (!innerDevicesConverged_ )
1686 if (DEBUG_NONLINEAR &&
debugTimeFlag_ && isActive(Diag::NONLINEAR_PARAMETERS) )
1687 Xyce::dout() <<
"\tcount:\t" <<
count << std::endl
1688 <<
"\tresConvRate_:\t" <<
resConvRate_ <<
"\n" << std::endl;
1698 if (DEBUG_NONLINEAR &&
debugTimeFlag_ && isActive(Diag::NONLINEAR_PARAMETERS) )
1699 Xyce::dout() <<
"\ttmpConvRate: " <<
tmpConvRate << std::endl
1701 <<
"\tReturning 3\n" << std::endl;
1707 if (DEBUG_NONLINEAR &&
debugTimeFlag_ && isActive(Diag::NONLINEAR_PARAMETERS) )
1708 Xyce::dout() <<
"\ttmpConvRate: " <<
tmpConvRate << std::endl
1710 <<
"\tReturning -3\n" << std::endl;
1755 if (DEBUG_NONLINEAR)
1756 Xyce::dout() <<
"DampedNewton::constrain_: minValue: " << minValue << std::endl;
1758 if (VERBOSE_NONLINEAR && minValue < 1.0)
1759 Xyce::lout() <<
" ***** Constraining:\t" << minValue << std::endl;
1776 const double etaExp = 0.5 * (1.0 + sqrt(5.0));
1777 const double etaMax = 0.1;
1778 const double etaMin = 1.0e-12;
1779 const double etaInit = 1.0e-01;
1789 else if (
nlResNormOld > Util::MachineDependentParams::DoubleMin())
1791 Util::Param linRes(
"RESIDUAL", 0.0 );
1793 eta = fabs(nlResNorm - linRes.getImmutableValue<
double>()) /
nlResNormOld;
1797 etaSafe = pow(
etaOld, etaExp);
1799 eta = std::max(eta, etaSafe);
1802 eta = std::min(etaMax, eta);
1805 eta = std::max(etaMin, eta);
1807 if (DEBUG_NONLINEAR)
1808 Xyce::dout() <<
"\tnlResNorm: " << nlResNorm
1809 <<
" linRes: " << linRes.getImmutableValue<
double>()
1811 <<
" calculated eta: " << fabs(nlResNorm - linRes.getImmutableValue<
double>())/
nlResNormOld << std::endl;
1820 if (VERBOSE_NONLINEAR)
1821 Xyce::lout() <<
"\t\teta:\t" << eta <<
"\n" << std::endl;
void debugOutput3(Linear::Vector &dxVector, Linear::Vector &xVector)
double getThetaChange() const
bool simpleBt_(double gsinit, double finit)
Pure virtual class to augment a linear system.
double getSmallUpdateTol() const
void setForcingTerm(double value)
bool getCurrentParams(NLParams &nlp)
unsigned getMaxNewtonStep() const
Linear::Matrix * dFdxTestMatrixPtr_
void printStepInfo_(std::ostream &os, int step)
Linear::Vector ** tmpSolVectorPtrPtr_
Linear::Vector * rhsVectorPtr_
AnalysisMode getAnalysisMode() const
int getDebugLevel() const
bool innerDevicesConverged(Parallel::Machine comm)
double resConvRate_
Convergence Rate.
Linear::Vector * gradVectorPtr_
int getParameterNumber() const
virtual bool initializeAll()
bool setNLPOptions(const Util::OptionBlock &OB)
bool allDevicesConverged(Parallel::Machine comm)
Linear::Matrix * jacobianMatrixPtr_
void setForcing_(const double)
bool addParameterSet(AnalysisMode mode, NLParams &nlp)
N_PDS_Manager * pdsMgrPtr_
bool setHBOptions(const Util::OptionBlock &OB)
Direction getDirection() const
void updateThetaBoundNeg(const Linear::Vector *oldSoln, const Linear::Vector *solnUpdate)
const Analysis::AnalysisManager & getAnalysisManager() const
LineSearchMethod getSearchMethod() const
Linear::System * lasSysPtr_
void setDebugFlags(int output_step_number, double time)
Linear::Vector ** nextSolVectorPtrPtr_
double getForcingTerm() const
void setDeltaXTol(double Tolerance)
void debugOutput1(Linear::Matrix &jacobian, Linear::Vector &rhs)
double getThetaBoundNeg() const
Linear::Solver * lasSolverPtr_
bool getConstraintBT() const
void resetCountersAndTimers_()
const IO::CmdParse & commandLine_
void updateThetaChange(const Linear::Vector *oldSoln, const Linear::Vector *solnUpdate)
Linear::Vector * fdxVLVectorPtr_
Linear::Vector * jdxVLVectorPtr_
void setDirection(Direction value)
void printHeader_(std::ostream &os)
Linear::Vector * searchDirectionPtr_
Pointer to direction vector.
bool getLinearOpt() const
Linear::Matrix * jacTestMatrixPtr_
int takeFirstSolveStep(NonLinearSolver *nlsTmpPtr=NULL)
Loader::NonlinearEquationLoader * nonlinearEquationLoader_
Linear::Vector * solWtVectorPtr_
Linear::Vector * dxVoltlimVectorPtr_
bool setTranOptions(const Util::OptionBlock &OB)
DampedNewton(const IO::CmdParse &cp)
Linear::Vector * NewtonVectorPtr_
Linear::Vector * tmpVectorPtr_
double getDeltaXTol() const
Linear::Vector * qdxVLVectorPtr_
double getThetaBoundPos() const
int solve(NonLinearSolver *nlsTmpPtr=NULL)
NLStrategy getNLStrategy() const
Linear::Matrix * dQdxTestMatrixPtr_
bool isFirstContinuationParam() const
bool setOptions(const Util::OptionBlock &OB)
ConstraintBT * nlConstraintPtr_
Constraint object pointer.
ParamMgr * nonlinearParameterManager_
bool setOptions(const Util::OptionBlock &OB)
bool getEnforceDeviceConvFlag() const
bool getForcingFlag() const
void updateThetaBoundPos(const Linear::Vector *oldSoln, const Linear::Vector *solnUpdate)
bool initializeAll(Linear::System *lasSysPtr, const NLParams &nlParams)
unsigned getMaxSearchStep() const
bool isLinearSystem() const
void printFooter_(std::ostream &os)
bool computeStepLength_()
int getContinuationStep() const