Made the double dogleg capability operational. It can now be used by users reliably.

This commit is contained in:
Harry Moffat 2011-09-29 23:11:12 +00:00
parent d153aa8c0a
commit 9af9a3e702
2 changed files with 742 additions and 479 deletions

File diff suppressed because it is too large Load diff

View file

@ -37,6 +37,32 @@ namespace Cantera {
#define NSOLN_TYPE_STEADY_STATE 0
//@}
//@{
/// @name Constant which determines the Return int from the nonlinear solver
/*!
* This int is returned from the nonlinear solver
*/
//! The nonlinear solve is successful.
#define NSOLN_RETN_SUCCESS 1
//! Problem isn't solved yet
#define NSOLN_RETN_CONTINUE 0
//! The nonlinear problem started to take too small an update step. This indicates that either the
//! Jacobian is bad, or a constraint is being bumped up against.
#define NSOLN_RETN_FAIL_STEPTOOSMALL -1
//! The nonlinear problem didn't solve the problem
#define NSOLN_RETN_FAIL_DAMPSTEP -2
//! The nonlinear problem's jacobian is singular
#define NSOLN_RETN_MATRIXINVERSIONERROR -3
//! The nonlinear problem's jacobian formation produced an error
#define NSOLN_RETN_JACOBIANFORMATIONERROR -4
//! The nonlinear problem's base residual produced an error
#define NSOLN_RETN_RESIDUALFORMATIONERROR -5
//! The nonlinear problem's max number of iterations has been exceeded
#define NSOLN_RETN_MAXIMUMITERATIONSEXCEEDED -7
//@}
//@}
//@{
/// @name Constant which determines the type of the Jacobian
//! The jacobian will be calculated from a numerical method
@ -162,7 +188,7 @@ namespace Cantera {
* @return Returns the L2 norm of the delta
*/
doublereal solnErrorNorm(const doublereal * const delta_y, const char * title = 0, int printLargest = 0,
const doublereal dampFactor = 1.0) const;
const doublereal dampFactor = 1.0) const;
//! L2 norm of the residual of the equation system
/*!
@ -270,7 +296,7 @@ namespace Cantera {
* We carry out a norm of deltaX_trust_ first. Then, we multiply that value
* by trustDelta_
*/
double trustRegionLength() const;
doublereal trustRegionLength() const;
//! Set default deulta bounds amounts
/*!
@ -281,6 +307,8 @@ namespace Cantera {
*/
void setDefaultDeltaBoundsMagnitudes();
void adjustUpStepMinimums();
//! Set the delta Bounds magnitudes by hand
/*!
* @param deltaBoundsMagnitudes set the deltaBoundsMagnitude vector
@ -311,7 +339,7 @@ namespace Cantera {
* @param alpha Relative length along the dog length that you are on.
* @param deltaX Vector to be filled up
*/
void fillDogLegStep(int leg, double alpha, std::vector<doublereal> & deltaX) const;
void fillDogLegStep(int leg, doublereal alpha, std::vector<doublereal> & deltaX) const;
//! Calculate the trust distance of a step in the solution variables
/*!
@ -370,10 +398,10 @@ namespace Cantera {
const doublereal * const y_high_bounds);
//! Return an editable vector of the low bounds constraints
std::vector<double> & lowBoundsConstraintVector();
std::vector<doublereal> & lowBoundsConstraintVector();
//! Return an editable vector of the high bounds constraints
std::vector<double> & highBoundsConstraintVector();
std::vector<doublereal> & highBoundsConstraintVector();
//! Internal function to calculate the time derivative of the solution at the new step
/*!
@ -450,34 +478,34 @@ namespace Cantera {
//! Find a damping coefficient through a look-ahead mechanism
/*!
* On entry, step0 must contain an undamped Newton step for the
* solution x0. This method attempts to find a damping coefficient
* On entry, step_1 must contain an undamped Newton step for the
* solution y_n_curr. This method attempts to find a damping coefficient
* such that all components stay in bounds, and the next
* undamped step would have a norm smaller than
* that of step0. If successful, the new solution after taking the
* damped step is returned in y1, and the undamped step at y1 is
* returned in step1.
* that of step_1. If successful, the new solution after taking the
* damped step is returned in y_n_1, and the undamped step at y_n_1 is
* returned in step_2.
*
* @param time_curr Current physical time
* @param y0 Base value of the solution before any steps
* are taken
* @param ydot0 Base value of the time derivative of teh
* solution
* @param step0 Initial step suggested.
* @param y1 Value of y1, the suggested solution after damping
* @param ydot1 Value of the time derivative of the solution at y1
* @param step1 Value of the step change from y0 to y1
* @param s1 norm of the step change in going from y0 to y1
* @param jac Jacobian
* @param writetitle Write a title line
* @param y_n_curr Base value of the solution before any steps
* are taken
* @param ydot_n_curr Base value of the time derivative of teh
* solution
* @param step_1 Initial step suggested.
* @param y_n_1 Value of y1, the suggested solution after damping
* @param ydot_n_1 Value of the time derivative of the solution at y_n_1
* @param step_2 Value of the step change from y_n_1 to y_n_2
* @param stepNorm_2 norm of the step change in going from y_n_1 to y_n_2
* @param jac Jacobian
* @param writetitle Write a title line
* @param num_backtracks Number of backtracks taken
*
* @return returns an integer indicating what happened.
*/
int dampStep(const doublereal time_curr, const double* y0,
const doublereal *ydot0, const double* step0,
double* const y1, double* const ydot1, double* step1,
double& s1, SquareMatrix& jac, bool writetitle,
int dampStep(const doublereal time_curr, const double* y_n_curr,
const doublereal *ydot_n_curr, double * const step_1,
double* const y_n_1, double* const ydot_n_1, double* step_2,
double& stepNorm_2, SquareMatrix& jac, bool writetitle,
int& num_backtracks);
//! Find the solution to F(X) = 0 by damped Newton iteration.
@ -521,27 +549,27 @@ namespace Cantera {
* @param ydot_comm Current value of the time derivative of the solution vector
* @param time_curr current value of the time
*/
void scaleMatrix(SquareMatrix& jac, double* y_comm, double* ydot_comm, doublereal time_curr);
void scaleMatrix(SquareMatrix& jac, double* y_comm, double* ydot_comm, doublereal time_curr, int num_newt_its);
//! Print solution norm contribution
/*!
* Prints out the most important entries to the update to the solution vector for the current step
*
* @param solnDelta0 Raw update vector for the current nonlinear step
* @param s0 Norm of the vector solnDelta0
* @param solnDelta1 Raw update vector for the next solution value based on the old matrix
* @param s1 Norm of the vector solnDelta1
* @param step_1 Raw update vector for the current nonlinear step
* @param stepNorm_1 Norm of the vector step_1
* @param step_2 Raw update vector for the next solution value based on the old matrix
* @param stepNorm_2 Norm of the vector step_2
* @param title title of the printout
* @param y0 Old value of the solution
* @param y1 New value of the solution after damping corrections
* @param y_n_curr Old value of the solution
* @param y_n_1 New value of the solution after damping corrections
* @param damp Value of the damping factor
* @param num_entries Number of entries to print out
*/
void
print_solnDelta_norm_contrib(const doublereal * const solnDelta0, const char * const s0,
const doublereal * const solnDelta1, const char * const s1,
const char * const title, const doublereal * const y0, const doublereal * const y1,
doublereal damp, int num_entries);
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, int num_entries);
//! Compute the Residual Weights
/*!
@ -640,8 +668,9 @@ namespace Cantera {
* @param time_curr Current time
* @param ydot0 INPUT Current value of the derivative of the solution vector
* @param ydot1 INPUT Time derivates of solution at the conditions which are evalulated for success
* @param numTrials OUTPUT Counter for the number of residual evaluations
*/
void descentComparison(double time_curr ,double *ydot0, double *ydot1);
void descentComparison(doublereal time_curr ,doublereal * ydot0, doublereal * ydot1, int &numTrials);
//! Setup the parameters for the double dog leg
@ -659,7 +688,7 @@ namespace Cantera {
*
* @return Returns the leg number ( 0, 1, or 2).
*/
int lambdaToLeg(const double lambda, double &alpha) const;
int lambdaToLeg(const doublereal lambda, doublereal &alpha) const;
//! Given a trust distance, this routine calculates the intersection of the this distance with the
//! double dogleg curve
@ -669,7 +698,7 @@ namespace Cantera {
* @param alpha (OUTPUT) Returns the relative distance along the appropriate leg
* @return leg (OUTPUT) Returns the leg ID (0, 1, or 2)
*/
int calcTrustIntersection(double trustVal, double &lambda, double &alpha) const;
int calcTrustIntersection(doublereal trustVal, doublereal &lambda, doublereal &alpha) const;
//! Initialize the size of the trust vector.
/*!
@ -687,7 +716,8 @@ namespace Cantera {
* @param step_1 INPUT First trial step for the first iteration
* @param y_n_1 INPUT First trial value of the solution vector
* @param ydot_n_1 INPUT First trial value of the derivative of the solution vector
* @param s1 OUTPUT Norm of the vector step_1
* @param stepNorm_1 OUTPUT Norm of the vector step_1
* @param stepNorm_2 OUTPUT Estimated norm of the vector step_2
* @param jac INPUT jacobian
* @param num_backtracks OUTPUT number of backtracks taken in the current damping step
*
@ -704,7 +734,7 @@ namespace Cantera {
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& s1, SquareMatrix& jac, int& num_backtracks);
doublereal& stepNorm_1, doublereal& stepNorm_2, SquareMatrix& jac, int& num_backtracks);
//! Decide whether the current step is acceptable and adjust the trust region size
/*!
@ -733,9 +763,10 @@ namespace Cantera {
* -2 Current value of the solution vector caused a residual error in its evaluation.
* Step is a failure, and the step size must be reduced in order to proceed further.
*/
int decideStep(const doublereal time_curr, int leg, double alpha, const double* const y0, const doublereal * const ydot0,
int decideStep(const doublereal time_curr, int leg, doublereal alpha, const doublereal * const y0,
const doublereal * const ydot0,
const std::vector<doublereal> & step0,
const double* const y1, const double* const ydot1, double trustDeltaOld);
const doublereal * const y1, const doublereal * const ydot1, doublereal trustDeltaOld);
//! Calculated the expected residual along the double dogleg curve.
/*!
@ -830,9 +861,14 @@ namespace Cantera {
//! Vector containing the solution at the previous time step
std::vector<doublereal> m_y_nm1;
//! Vector containing the solution at the previous time step
std::vector<doublereal> m_y_n_1;
//! Value of the solution time derivative at the new point that is to be considered
std::vector<doublereal> m_ydot_n_1;
std::vector<doublereal> m_step_1;
//! Vector of column scaling factors
std::vector<doublereal> m_colScales;
@ -870,10 +906,16 @@ namespace Cantera {
std::vector<doublereal> m_residWts;
//! Norm of the residual at the start of each nonlinear iteration
doublereal m_normResid0;
doublereal m_normResid_0;
//! Norm of the residual before damping
doublereal m_normResidFRaw;
//! Norm of the residual after it has been bounded
doublereal m_normResid_Bound;
//! Norm of the residual at the end of the first leg of the current iteration
doublereal m_normResid_1;
//! Norm of the residual at the end of the first leg of the current iteration
doublereal m_normResid_full;
//! Norm of the solution update created by the iteration in its raw, undamped form, using the solution norm
doublereal m_normDeltaSoln_Newton;
@ -927,9 +969,12 @@ namespace Cantera {
//! int indicating whether row scaling is turned on (1) or not (0)
int m_rowScaling;
//! Total number of linear solves
//! Total number of linear solves taken by the solver object
int m_numTotalLinearSolves;
//! Number of local linear solves done during the current iteration
int m_numLocalLinearSolves;
//! Total number of newton iterations
int m_numTotalNewtIts;
@ -992,7 +1037,7 @@ namespace Cantera {
int m_print_flag;
//! Scale factor for turning residual norms into solution norms
double m_ScaleSolnNormToResNorm;
doublereal m_ScaleSolnNormToResNorm;
//! Copy of the jacobian that doesn't get overwritten when the inverse is determined
/*!
@ -1020,6 +1065,12 @@ namespace Cantera {
//! were valid
doublereal residNorm2Cauchy_;
//! Current leg
int dogLegID_;
//! Current Alpha param along the leg
doublereal dogLegAlpha_;
//! Residual dot Jd norm
/*!
* This is equal to R_hat dot J_hat d_y_descent
@ -1075,13 +1126,34 @@ namespace Cantera {
//! General toggle for turning on Affine solve with Hessian
int doAffineSolve_;
//! Condition number of the matrix
doublereal m_conditionNumber;
//! Factor indicating how much trust region has been changed this iteration - output variable
doublereal CurrentTrustFactor_;
//! Factor indicating how much trust region has been changed next iteration - output variable
doublereal NextTrustFactor_;
//! Boolean indicating that the residual weights have been reevalulated this iteration - output variable
bool ResidWtsReevaluated_;
//! Expected DResid_dS for the steepest descent path - output variable
doublereal ResidDecreaseSDExp_;
//! Actual DResid_dS for the steepest descent path - output variable
doublereal ResidDecreaseSD_;
//! Expected DResid_dS for the Newton path - output variable
doublereal ResidDecreaseNewtExp_;
//! Actual DResid_dS for the newton path - output variable
doublereal ResidDecreaseNewt_;
/*******************************************************************************************
* OTHER COUNTERS
* STATIC VARIABLES
*****************************************************************************************/
public:
//! Turn off printing of time
/*!
@ -1092,7 +1164,7 @@ namespace Cantera {
//! Turn on or off printing of the Jacobian
static bool s_print_NumJac;
//! Turn on all printing of dogleg information
//! Turn on extra printing of dogleg information
static bool s_print_DogLeg;
//! Turn on solving both the Newton and Hessian systems and comparing the results