Esempio n. 1
0
//======================================================================================================================
// processInput                                                                                                        =
//======================================================================================================================
void Application::processInput()
{
	btVector3 camX;
	camX = camY.cross(camZ);

	if(keys[SDLK_ESCAPE])
	{
		exit(0);
	}

	if(keys[SDLK_w])
	{
		camPos += camZ * -movingDist;
	}

	if(keys[SDLK_a])
	{
		camPos += camX * -movingDist;
	}

	if(keys[SDLK_s])
	{
		camPos += camZ * movingDist;
	}

	if(keys[SDLK_d])
	{
		camPos += camX * movingDist;
	}

	if(keys[SDLK_SPACE])
	{
		camPos += camY * -movingDist;
	}

	if(keys[SDLK_LSHIFT])
	{
		camPos += camY * movingDist;
	}

	if(keys[SDLK_q])
	{
		float s = sin(-movingAng);
		float c = cos(-movingAng);

		camY = camY * c + camX * s;

		camY.normalize();
	}

	if(keys[SDLK_e])
	{
		float s = sin(movingAng);
		float c = cos(movingAng);

		camY = camY * c + camX * s;

		camY.normalize();
	}

	if(keys[SDLK_LEFT])
	{
		float s = sin(movingAng);
		float c = cos(movingAng);

		camZ = camZ * c + camX * s;

		camZ.normalize();
	}

	if(keys[SDLK_RIGHT])
	{
		float s = sin(-movingAng);
		float c = cos(-movingAng);

		camZ = camZ * c + camX * s;

		camZ.normalize();
	}

	if(keys[SDLK_UP])
	{
		float s = sin(-movingAng);
		float c = cos(-movingAng);

		camZ = camZ * c + camY * s;

		camZ.normalize();
	}

	if(keys[SDLK_DOWN])
	{
		float s = sin(movingAng);
		float c = cos(movingAng);

		camZ = camZ * c + camY * s;

		camZ.normalize();

		camY = camZ.cross(camX);
	}

	reorthogonalize();
}
NOX::StatusTest::StatusType NOX::Solver::AndersonAcceleration::step()
{
  prePostOperator.runPreIterate(*this);
  Teuchos::ParameterList lsParams = paramsPtr->sublist("Direction").sublist("Newton").sublist("Linear Solver");

  // On the first step, do some initializations
  if (nIter == 0) {
    // Compute F of initital guess
    NOX::Abstract::Group::ReturnType rtype = solnPtr->computeF();
    if (rtype != NOX::Abstract::Group::Ok) {
      utilsPtr->out() << "NOX::Solver::AndersonAcceleration::init - "
              << "Unable to compute F" << std::endl;
      throw "NOX Error";
    }

    // Test the initial guess
    status = testPtr->checkStatus(*this, checkType);
    if ((status == NOX::StatusTest::Converged) &&
    (utilsPtr->isPrintType(NOX::Utils::Warning))) {
      utilsPtr->out() << "Warning: NOX::Solver::AndersonAcceleration::init() - "
              << "The solution passed into the solver (either "
              << "through constructor or reset method) "
              << "is already converged!  The solver wil not "
              << "attempt to solve this system since status is "
              << "flagged as converged." << std::endl;
    }
    printUpdate();

    // First check status
    if (status != NOX::StatusTest::Unconverged) {
      prePostOperator.runPostIterate(*this);
      printUpdate();
      return status;
    }

    // Apply preconditioner if enabled
    if (precond) {
      if (recomputeJacobian)
        solnPtr->computeJacobian();
      solnPtr->applyRightPreconditioning(false, lsParams, solnPtr->getF(), *oldPrecF);
    }
    else
      *oldPrecF = solnPtr->getF();

    // Copy initial guess to old soln
    *oldSolnPtr = *solnPtr;

    // Compute step then first iterate with a line search.
    workVec->update(mixParam,*oldPrecF);
    bool ok = lineSearchPtr->compute(*solnPtr, stepSize, *workVec, *this);
    if (!ok)
    {
      if (stepSize == 0.0)
      {
        utilsPtr->out() << "NOX::Solver::AndersonAcceleratino::iterate - line search failed" << std::endl;
        status = NOX::StatusTest::Failed;
        prePostOperator.runPostIterate(*this);
        printUpdate();
        return status;
      }
      else if (utilsPtr->isPrintType(NOX::Utils::Warning))
        utilsPtr->out() << "NOX::Solver::AndersonAcceleration::iterate - using recovery step for line search" << std::endl;
    }

    // Compute F for the first iterate in case it isn't in the line search
    rtype = solnPtr->computeF();
    if (rtype != NOX::Abstract::Group::Ok)
    {
      utilsPtr->out() << "NOX::Solver::AndersonAcceleration::iterate - unable to compute F" << std::endl;
      status = NOX::StatusTest::Failed;
      prePostOperator.runPostIterate(*this);
      printUpdate();
      return status;
    }

    // Evaluate the current status.
    status = testPtr->checkStatus(*this, checkType);

    //Update iteration count
    nIter++;

    prePostOperator.runPostIterate(*this);
    printUpdate();
    return status;
  }

  // First check status
  if (status != NOX::StatusTest::Unconverged) {
    prePostOperator.runPostIterate(*this);
    printUpdate();
    return status;
  }

  // Apply preconditioner if enabled
  if (precond) {
    if (recomputeJacobian)
      solnPtr->computeJacobian();
    solnPtr->applyRightPreconditioning(false, lsParams, solnPtr->getF(), *precF);
  }
  else
    *precF = solnPtr->getF();

  // Manage the matrices of past iterates and QR factors
  if (storeParam > 0) {
    if (nIter == accelerationStartIteration) {
      // Initialize
      nStore = 0;
      rMat.shape(0,0);
      oldPrecF->update(1.0, *precF, -1.0);
      qrAdd(*oldPrecF);
      xMat[0]->update(1.0, solnPtr->getX(), -1.0, oldSolnPtr->getX(), 0.0);
    }
    else if (nIter > accelerationStartIteration) {
      if (nStore == storeParam) {
        Teuchos::RCP<NOX::Abstract::Vector> tempPtr = xMat[0];
        for (int ii = 0; ii<nStore-1; ii++)
          xMat[ii] = xMat[ii+1];
        xMat[nStore-1] = tempPtr;
        qrDelete();
      }
      oldPrecF->update(1.0, *precF, -1.0);
      qrAdd(*oldPrecF);
      xMat[nStore-1]->update(1.0, solnPtr->getX(), -1.0, oldSolnPtr->getX(), 0.0);
    }
  }

  // Reorthogonalize 
  if ( (nStore > 1) && (orthoFrequency > 0) )
    if (nIter % orthoFrequency == 0)
      reorthogonalize();

  // Copy current soln to the old soln.
  *oldSolnPtr = *solnPtr;
  *oldPrecF = *precF;

  // Adjust for condition number
  if (nStore > 0) {
    Teuchos::LAPACK<int,double> lapack;
    char normType = '1';
    double invCondNum = 0.0;
    int info = 0;
    if ( WORK.size() < static_cast<std::size_t>(4*nStore) )
      WORK.resize(4*nStore);
    if (IWORK.size() < static_cast<std::size_t>(nStore))
      IWORK.resize(nStore);
    lapack.GECON(normType,nStore,rMat.values(),nStore,rMat.normOne(),&invCondNum,&WORK[0],&IWORK[0],&info);
    if (utilsPtr->isPrintType(Utils::Details))
      utilsPtr->out() << "    R condition number estimate ("<< nStore << ") = " << 1.0/invCondNum << std::endl;

    if (adjustForConditionNumber) {
      while ( (1.0/invCondNum > dropTolerance) && (nStore > 1)  ) {
        Teuchos::RCP<NOX::Abstract::Vector> tempPtr = xMat[0];
        for (int ii = 0; ii<nStore-1; ii++)
          xMat[ii] = xMat[ii+1];
        xMat[nStore-1] = tempPtr;
        qrDelete();
        lapack.GECON(normType,nStore,rMat.values(),nStore,rMat.normOne(),&invCondNum,&WORK[0],&IWORK[0],&info);
        if (utilsPtr->isPrintType(Utils::Details))
          utilsPtr->out() << "    Adjusted R condition number estimate ("<< nStore << ") = " << 1.0/invCondNum << std::endl;
      }
    }
  }

  // Solve the least-squares problem.
  Teuchos::SerialDenseMatrix<int,double> gamma(nStore,1), RHS(nStore,1), Rgamma(nStore,1);
  for (int ii = 0; ii<nStore; ii++)
    RHS(ii,0) = precF->innerProduct( *(qMat[ii]) );

  //Back-solve for gamma
  for (int ii = nStore-1; ii>=0; ii--) {
    gamma(ii,0) = RHS(ii,0);
    for (int jj = ii+1; jj<nStore; jj++) {
      gamma(ii,0) -= rMat(ii,jj)*gamma(jj,0);
    }
    gamma(ii,0) /= rMat(ii,ii);
  }

  if (nStore > 0)
    Rgamma.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,mixParam,rMat,gamma,0.0);

  // Compute the step and new solution using the line search.
  workVec->update(mixParam,*precF);
  for (int ii=0; ii<nStore; ii++)
    workVec->update(-gamma(ii,0), *(xMat[ii]), -Rgamma(ii,0),*(qMat[ii]),1.0);
  bool ok = lineSearchPtr->compute(*solnPtr, stepSize, *workVec, *this);
  if (!ok)
  {
    if (stepSize == 0.0)
    {
      utilsPtr->out() << "NOX::Solver::AndersonAcceleratino::iterate - line search failed" << std::endl;
      status = NOX::StatusTest::Failed;
      prePostOperator.runPostIterate(*this);
      printUpdate();
      return status;
    }
    else if (utilsPtr->isPrintType(NOX::Utils::Warning))
      utilsPtr->out() << "NOX::Solver::AndersonAcceleration::iterate - using recovery step for line search" << std::endl;
  }

  // Compute F for new current solution in case the line search didn't .
  NOX::Abstract::Group::ReturnType rtype = solnPtr->computeF();
  if (rtype != NOX::Abstract::Group::Ok)
  {
    utilsPtr->out() << "NOX::Solver::AndersonAcceleration::iterate - unable to compute F" << std::endl;
    status = NOX::StatusTest::Failed;
    prePostOperator.runPostIterate(*this);
    printUpdate();
    return status;
  }

  // Update iteration count
  nIter++;

  // Evaluate the current status.
  status = testPtr->checkStatus(*this, checkType);

  prePostOperator.runPostIterate(*this);

  printUpdate();
  return status;
}