bool
NOX::Solver::TensorBased::computeCurvilinearStep(NOX::Abstract::Vector& dir,
                     const NOX::Abstract::Group& soln,
                     const NOX::Solver::Generic& s,
                     double& lambda)
{
  double qval = 0;
  double lambdaBar = 1;
  double beta1 = calculateBeta(sTinvJa, 1, sTinvJF, qval, lambdaBar, lambda);
  double betaFactor = ( (beta == 0.0) ? 0.0 : beta1*beta1 / (beta*beta));

  dir.update(lambda - betaFactor, *newtonVecPtr, betaFactor, *tensorVecPtr, 0.0);

#if DEBUG_LEVEL > 0
  double sDotD = dir.innerProduct(sVec);
  if (utilsPtr->isPrintType(NOX::Utils::Details))
  {
    utilsPtr->out() << "  Beta = " << utilsPtr->sciformat(beta, 6)
     << "  std = " << utilsPtr->sciformat(sDotD, 6)
     << "  qval = " << qval
     << "  lambdaBar = " << lambdaBar
     << std::endl;
    utilsPtr->out() << "  betaFactor = " << utilsPtr->sciformat(betaFactor,6)
     << "  beta1 = " << utilsPtr->sciformat(beta1, 6)
     << std::endl;
  }
#endif

  return true;
}
示例#2
0
文件: LMM.cpp 项目: gpcr/rvtests
  int FitNullModel(Matrix& Xnull, Matrix& Y) {
    G_to_Eigen(Xnull, &this->x);
    G_to_Eigen(Y, &this->y);

    // append identity matrix
    AppendIdentity();
    
    // initialize beta and sigma2
    sigma2.resize(kinship.size());
    for (size_t i = 0; i < sigma2.size(); ++i) {
      sigma2[i] = 1.0;
    }
    calculateSigmaMat();
    calculateBeta();
    
    // fit null model
    calculateLLK();
    double oldLLK = llk;
    int time = 1;
    double diff;
    while (true) {
      calculateSigma2();
      diff = llk - oldLLK;
      if (diff < 1e-6) {
#ifdef DEBUG        
        fprintf(stderr, "Model converges or llk cannot be improved\n");
#endif
        break;
      }
      oldLLK = llk;
      time ++;
      if (time > 100) {
#ifdef DEBUG                
        fprintf(stderr, "Model probably do not converge at 100 times, llk = %g", llk);
#endif
        break;
      }      
    }  
    return 0;
  }
bool
NOX::Solver::TensorBased::computeTensorDirection(NOX::Abstract::Group& soln,
                     const NOX::Solver::Generic& solver)
{
  NOX::Abstract::Group::ReturnType dir_status;

  Teuchos::ParameterList& linearParams = paramsPtr->sublist("Direction").
    sublist(paramsPtr->sublist("Direction").
        get("Method","Tensor")).
    sublist("Linear Solver");

  // Compute F at current solution.
  dir_status = soln.computeF();
  if (dir_status != NOX::Abstract::Group::Ok)
    throwError("computeTensorDirection", "Unable to compute F");

  // Compute Jacobian at current solution.
  dir_status = soln.computeJacobian();
  if (dir_status != NOX::Abstract::Group::Ok)
    throwError("computeTensorDirection", "Unable to compute Jacobian");

  // Begin processing for the tensor step, if necessary.
  double sDotS = 0.0;
  int tempVal1 = 0;
  if ((nIter > 0)  &&  (requestedBaseStep == TensorStep))
  {
    // Compute the tensor term s = x_{k-1} - x_k
    *sVecPtr = soln.getX();
    sVecPtr->update(1.0, solver.getPreviousSolutionGroup().getX(), -1.0);
    double normS = sVecPtr->norm();
    sDotS = normS * normS;

    // Form the tensor term a = (F_{k-1} - F_k - J*s) / (s^T s)^2
    soln.applyJacobian(*sVecPtr, *aVecPtr);
    numJvMults++;
    aVecPtr->update(1.0, solver.getPreviousSolutionGroup().getF(), -1.0);
    aVecPtr->update(-1.0, soln.getF(), 1.0);
    if (sDotS != 0)
      aVecPtr->scale(1.0 / (sDotS * sDotS));

    // Save old Newton step as initial guess to second system
    *tmpVecPtr = *newtonVecPtr;
    tmpVecPtr->scale(-1.0);   // Rewrite to avoid this?

    // Compute residual of linear system using initial guess...
    soln.applyJacobian(*tmpVecPtr, *residualVecPtr);
    numJvMults++;
    residualVecPtr->update(1.0, solver.getPreviousSolutionGroup().getF(),-1.0);
    double residualNorm = residualVecPtr->norm();

#if DEBUG_LEVEL > 0
    double tmpVecNorm = tmpVecPtr->norm();
    double residualNormRel = residualNorm /
      solver.getPreviousSolutionGroup().getNormF();
    if (utilsPtr->isPrintType(NOX::Utils::Details))
    {
      utilsPtr->out() << "  Norm of initial guess: " << utilsPtr->sciformat(tmpVecNorm, 6)
       << std::endl;
      utilsPtr->out() << "  initg norm of model residual =   "
       << utilsPtr->sciformat(residualNorm, 6) << " (abs)     "
       << utilsPtr->sciformat(residualNormRel, 6) << " (rel)" << std::endl;
    }
#endif

    // Save some parameters and use them later...
    double tol = linearParams.get("Tolerance", 1e-4);
    double relativeResidual = residualNorm /
      solver.getPreviousSolutionGroup().getNormF();

    // Decide whether to use initial guess...
    bool isInitialGuessGood = false;
#ifdef USE_INITIAL_GUESS_LOGIC
    if (relativeResidual < 1.0)
    {
      if (utilsPtr->isPrintType(NOX::Utils::Details))
    utilsPtr->out() << "  Initial guess is good..." << std::endl;
      isInitialGuessGood = true;
      // RPP - Brett please make sure the line below is correct.
      *tensorVecPtr = *tmpVecPtr;
      double newTol = tol / relativeResidual;
      if (newTol > 0.99)
    newTol = 0.99;  // force at least one iteration
      linearParams.set("Tolerance",  newTol);
      if (utilsPtr->isPrintType(NOX::Utils::Details))
    utilsPtr->out() << "  Setting tolerance to " << utilsPtr->sciformat(newTol,6) << std::endl;
    }
    else
#endif // USE_INITIAL_GUESS_LOGIC
    {
      //utilsPtr->out() << "  Initial guess is BAD... do not use!\n";
      isInitialGuessGood = false;
      *residualVecPtr = solver.getPreviousSolutionGroup().getF();
    }

    // Compute the term inv(J)*Fp....
    tmpVecPtr->init(0.0);
    dir_status = soln.applyJacobianInverse(linearParams, *residualVecPtr,
                       *tmpVecPtr);

    // If it didn't converge, maybe we can recover.
    if (dir_status != NOX::Abstract::Group::Ok)
    {
      if (doRescue == false)
    throwError("computeTensorDirection", "Unable to apply Jacobian inverse");
      else if ((doRescue == true) &&
           (utilsPtr->isPrintType(NOX::Utils::Warning)))
    utilsPtr->out() << "WARNING: NOX::Solver::TensorBased::computeTensorDirection() - "
         << "Linear solve failed to achieve convergence - "
         << "using the step anyway "
         << "since \"Rescue Bad Newton Solve\" is true." << std::endl;
    }

    // Continue processing
#ifdef USE_INITIAL_GUESS_LOGIC
    if (isInitialGuessGood)
    {
      tmpVecPtr->update(1.0, *tensorVecPtr, 1.0);
      linearParams.set("Tolerance",  tol);
    }
#endif

    // Save iteration count for comparison later
    if (linearParams.sublist("Output").
    isParameter("Number of Linear Iterations"))
      tempVal1 = linearParams.sublist("Output").
    get("Number of Linear Iterations",0);

#if DEBUG_LEVEL > 0
    // Compute residual of linear system with initial guess...
    soln.applyJacobian(*tmpVecPtr, *residualVecPtr);
    numJvMults++;
    residualVec.update(-1.0, solver.getPreviousSolutionGroup().getF(),1.0);
    double residualNorm2 = residualVec.norm();
    double residualNorm2Rel = residualNorm2 /
      solver.getPreviousSolutionGroup().getNormF();
    if (utilsPtr->isPrintType(NOX::Utils::Details))
      utilsPtr->out() << " jifp norm of model residual =   "
       << utilsPtr->sciformat(residualNorm2, 6) << " (abs)     "
       << utilsPtr->sciformat(residualNorm2Rel, 6) << " (rel)" << std::endl;
#endif
  }

  // Compute the Newton direction
  dir_status = soln.computeNewton(linearParams);

  // If it didn't converge, maybe we can recover.
  if (dir_status != NOX::Abstract::Group::Ok)
  {
    if (doRescue == false)
      throwError("computeTensorDirection", "Unable to apply Jacobian inverse");
    else if ((doRescue == true) &&
         (utilsPtr->isPrintType(NOX::Utils::Warning)))
      utilsPtr->out() << "WARNING: NOX::Solver::TensorBased::computeTensorDirection() - "
       << "Linear solve failed to achieve convergence - "
       << "using the step anyway "
       << "since \"Rescue Bad Newton Solve\" is true." << std::endl;
  }

  // Set Newton direction
  *newtonVecPtr = soln.getNewton();

  // Update counter
  int tempVal2 = 0;
  if (linearParams.sublist("Output").
      isParameter("Number of Linear Iterations"))
    tempVal2 = linearParams.sublist("Output").
      get("Number of Linear Iterations",0);
  numJ2vMults += (tempVal1 > tempVal2) ? tempVal1 : tempVal2;

#ifdef CHECK_RESIDUALS
  printDirectionInfo("newtonVec", *newtonVecPtr, soln, false);
#endif // CHECK_RESIDUALS

  // Continue processing the tensor step, if necessary
  if ((nIter > 0)  &&  (requestedBaseStep == TensorStep))
  {
    // Form the term inv(J)*a...  (note that a is not multiplied by 2)
    // The next line does not work in some implementations for some reason
    //tmpVec.update(1.0, newtonVec, -1.0, sVec, 1.0);
    tmpVecPtr->update(1.0, *newtonVecPtr, 1.0);
    tmpVecPtr->update(-1.0, *sVecPtr, 1.0);
    if (sDotS != 0.0)
      tmpVecPtr->scale( 1.0 / (sDotS * sDotS));

    // Calculate value of beta
    sTinvJF = -sVecPtr->innerProduct(*newtonVecPtr);
    sTinvJa = sVecPtr->innerProduct(*tmpVecPtr);
    double qval = 0;
    double lambdaBar = 1;
    beta = calculateBeta(sTinvJa, 1.0, sTinvJF, qval, lambdaBar);

    double sVecNorm = sVecPtr->norm();
    double aVecNorm = aVecPtr->norm();
    if (utilsPtr->isPrintType(NOX::Utils::Details))
    {
      utilsPtr->out() << " sTinvJF = " << utilsPtr->sciformat(sTinvJF, 6)
       << "  sTinvJa = " << utilsPtr->sciformat(sTinvJa, 6) << std::endl;
      utilsPtr->out() << " norm(s) = " << utilsPtr->sciformat(sVecNorm, 6)
       << "  norm(a) = " << utilsPtr->sciformat(aVecNorm, 6) << std::endl;
    }

    if (useModifiedMethod)
    {
      double alpha2 = lambdaBar;
      if (utilsPtr->isPrintType(NOX::Utils::Details))
    utilsPtr->out() << " Beta = " << utilsPtr->sciformat(beta, 6)
         << "  Alpha2 = " << utilsPtr->sciformat(alpha2, 6) << std::endl;
      if (alpha2 != 1.0)
      {
    if (utilsPtr->isPrintType(NOX::Utils::Details))
      utilsPtr->out() << "   *** Scaling tensor term a ***" << std::endl;
    aVecPtr->scale(alpha2);
    tmpVecPtr->scale(alpha2);
    sTinvJa *= alpha2;
    beta /= alpha2;
    lambdaBar = 1.0;
    qval = 0;
      }
    }

    // Form the tensor step
    tensorVecPtr->update(1.0, *newtonVecPtr, -beta*beta, *tmpVecPtr, 0.0);

#ifdef CHECK_RESIDUALS
    printDirectionInfo("tensorVec", *tensorVecPtr, soln, true);
#endif // CHECK_RESIDUALS
#if DEBUG_LEVEL > 0
    double sDotT = tensorVecPtr->innerProduct(sVec);
    if (utilsPtr->isPrintType(NOX::Utils::Details))
      utilsPtr->out() << "  Beta = " << utilsPtr->sciformat(beta, 6)
       << "  std = " << utilsPtr->sciformat(sDotT, 6)
       << "  qval = " << utilsPtr->sciformat(qval, 2)
       << "  lambdaBar = " << lambdaBar << std::endl;
#endif
  }
  else
    *tensorVecPtr = *newtonVecPtr;

  return true;
}