bool NOX::Direction::SteepestDescent::compute(Abstract::Vector& dir, Abstract::Group& soln, const Solver::Generic& solver) { NOX::Abstract::Group::ReturnType status; // Compute F at current solution status = soln.computeF(); if (status != NOX::Abstract::Group::Ok) throwError("compute", "Unable to compute F"); // Compute Jacobian at current solution status = soln.computeJacobian(); if (status != NOX::Abstract::Group::Ok) throwError("compute", "Unable to compute Jacobian"); // Scale switch (scaleType) { case NOX::Direction::SteepestDescent::TwoNorm: meritFuncPtr->computeGradient(soln, dir); dir.scale(-1.0/dir.norm()); break; case NOX::Direction::SteepestDescent::FunctionTwoNorm: meritFuncPtr->computeGradient(soln, dir); dir.scale(-1.0/soln.getNormF()); break; case NOX::Direction::SteepestDescent::QuadMin: meritFuncPtr->computeQuadraticMinimizer(soln, dir); break; case NOX::Direction::SteepestDescent::None: meritFuncPtr->computeGradient(soln, dir); dir.scale( -1.0 ); break; default: throwError("compute", "Invalid scaleType"); } return true; }
bool NonlinearCG::compute(Abstract::Vector& dir, Abstract::Group& soln, const Solver::Generic& solver) { Abstract::Group::ReturnType ok; // Initialize vector memory if haven't already if(Teuchos::is_null(oldDirPtr)) oldDirPtr = soln.getX().clone(NOX::ShapeCopy); if(Teuchos::is_null(oldDescentDirPtr)) oldDescentDirPtr = soln.getX().clone(NOX::ShapeCopy); // These are conditionally created if(Teuchos::is_null(diffVecPtr) && usePRbeta) diffVecPtr = soln.getX().clone(NOX::ShapeCopy); if(Teuchos::is_null(tmpVecPtr) && doPrecondition) tmpVecPtr = soln.getX().clone(NOX::ShapeCopy); // Get a reference to the old solution group (const) oldSolnPtr = &solver.getPreviousSolutionGroup(); const Abstract::Group& oldSoln(*oldSolnPtr); niter = solver.getNumIterations(); // Construct Residual and precondition (if desired) as first step in // getting new search direction ok = soln.computeF(); if (ok != Abstract::Group::Ok) { if (utils->isPrintType(Utils::Warning)) utils->out() << "NOX::Direction::NonlinearCG::compute - Unable to compute F." << std::endl; return false; } dir = soln.getF(); if(doPrecondition) { if(!soln.isJacobian()) ok = soln.computeJacobian(); if (ok != Abstract::Group::Ok) { if (utils->isPrintType(Utils::Warning)) utils->out() << "NOX::Direction::NonlinearCG::compute - Unable to compute Jacobian." << std::endl; return false; } *tmpVecPtr = dir; ok = soln.applyRightPreconditioning(false, paramsPtr->sublist("Nonlinear CG").sublist("Linear Solver"), *tmpVecPtr, dir); if( ok != Abstract::Group::Ok ) { if (utils->isPrintType(Utils::Warning)) utils->out() << "NOX::Direction::NonlinearCG::compute - Unable to apply Right Preconditioner." << std::endl; return false; } } dir.scale(-1.0); // Orthogonalize using previous search direction beta = 0.0; if( niter!=0 ) { // Two choices (for now) for orthogonalizing descent direction with previous: if( usePRbeta ) { // Polak-Ribiere beta *diffVecPtr = dir; diffVecPtr->update(-1.0, *oldDescentDirPtr, 1.0); double denominator = oldDescentDirPtr->innerProduct(oldSoln.getF()); beta = diffVecPtr->innerProduct(soln.getF()) / denominator; // Constrain beta >= 0 if( beta < 0.0 ) { if (utils->isPrintType(Utils::OuterIteration)) utils->out() << "BETA < 0, (" << beta << ") --> Resetting to zero" << std::endl; beta = 0.0; } } else { // Fletcher-Reeves beta double denominator = oldDescentDirPtr->innerProduct(oldSoln.getF()); beta = dir.innerProduct(soln.getF()) / denominator; } // Allow for restart after specified number of nonlinear iterations if( (niter % restartFrequency) == 0 ) { if( utils->isPrintType(Utils::OuterIteration) ) utils->out() << "Resetting beta --> 0" << std::endl; beta = 0 ; // Restart with Steepest Descent direction } } // niter != 0 *oldDescentDirPtr = dir; dir.update(beta, *oldDirPtr, 1.0); *oldDirPtr = dir; return (ok == Abstract::Group::Ok); }