void
LOCA::BorderedSolver::HouseholderQR::applyCompactWY(
                const NOX::Abstract::MultiVector::DenseMatrix& Y1,
                const NOX::Abstract::MultiVector& Y2,
                const NOX::Abstract::MultiVector::DenseMatrix& T,
                NOX::Abstract::MultiVector::DenseMatrix& X1,
                NOX::Abstract::MultiVector& X2,
                bool isZeroX1, bool isZeroX2,
                bool useTranspose) const
{
  if (isZeroX1 && isZeroX2) {
    X1.putScalar(0.0);
    X2.init(0.0);
    return;
  }

  int m = Y2.numVectors();

  Teuchos::ETransp T_flag;
  if (useTranspose)
    T_flag = Teuchos::TRANS;
  else
    T_flag = Teuchos::NO_TRANS;

  NOX::Abstract::MultiVector::DenseMatrix tmp(m, X2.numVectors());

  // Compute Y1^T*X1 + Y2^T*X2
  if (!isZeroX2)
    X2.multiply(1.0, Y2, tmp);

  // Opportunity for optimization here since Y1 is a lower-triangular
  // matrix with unit diagonal
  if (!isZeroX2 && !isZeroX1)
    tmp.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, 1.0, Y1, X1, 1.0);
  else if (!isZeroX1)
    tmp.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, 1.0, Y1, X1, 0.0);

  // Compute op(T)*(Y1^T*X1 + Y2^T*X2)
  dblas.TRMM(Teuchos::LEFT_SIDE, Teuchos::UPPER_TRI, T_flag,
         Teuchos::NON_UNIT_DIAG, tmp.numRows(), tmp.numCols(), 1.0,
         T.values(), T.numRows(), tmp.values(), tmp.numRows());

  // Compute X1 = X1 + Y1*op(T)*(Y1^T*X1 + Y2^T*X2)
  // Opportunity for optimization here since Y1 is a lower-triangular
  // matrix with unit diagonal
  if (isZeroX1)
    X1.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1.0, Y1, tmp, 0.0);
  else
    X1.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1.0, Y1, tmp, 1.0);

  // Compute X2 = X2 + Y1*op(T)*(Y1^T*X1 + Y2^T*X2)
  if (isZeroX2)
    X2.update(Teuchos::NO_TRANS, 1.0, Y2, tmp, 0.0);
  else
    X2.update(Teuchos::NO_TRANS, 1.0, Y2, tmp, 1.0);
}
Example #2
0
NOX::Abstract::Group::ReturnType 
LOCA::BorderedSolver::Nested::applyInverseTranspose(
			      Teuchos::ParameterList& params,
			      const NOX::Abstract::MultiVector* F,
			      const NOX::Abstract::MultiVector::DenseMatrix* G,
			      NOX::Abstract::MultiVector& X,
			      NOX::Abstract::MultiVector::DenseMatrix& Y) const
{
  bool isZeroF = (F == NULL);
  bool isZeroG = (G == NULL);

  if (isZeroF && isZeroG) {
    X.init(0.0);
    Y.putScalar(0.0);
  }

  int num_cols = X.numVectors();  
  Teuchos::RCP<NOX::Abstract::MultiVector> FF;
  if (!isZeroF) 
    FF = unbordered_grp->getX().createMultiVector(num_cols);
  NOX::Abstract::MultiVector::DenseMatrix GG(myWidth, num_cols);  
  GG.putScalar(0.0);
  
  if (!isZeroF) {
    NOX::Abstract::MultiVector::DenseMatrix GG1(Teuchos::View, GG,
						underlyingWidth, num_cols, 
						0, 0);
    grp->extractSolutionComponent(*F, *FF);
    grp->extractParameterComponent(false, *F, GG1);
  }
  if (!isZeroG) {
    NOX::Abstract::MultiVector::DenseMatrix GG2(Teuchos::View, GG,
						numConstraints, num_cols, 
						underlyingWidth, 0);
    GG2.assign(*G);
  }

  Teuchos::RCP<NOX::Abstract::MultiVector> XX = 
    unbordered_grp->getX().createMultiVector(num_cols);
  NOX::Abstract::MultiVector::DenseMatrix YY(myWidth, num_cols);
  NOX::Abstract::MultiVector::DenseMatrix YY1(Teuchos::View, YY,
					      underlyingWidth, num_cols, 
					      0, 0);
  NOX::Abstract::MultiVector::DenseMatrix YY2(Teuchos::View, YY,
					      numConstraints, num_cols, 
					      underlyingWidth, 0);

  NOX::Abstract::Group::ReturnType status = 
    solver->applyInverseTranspose(params, FF.get(), &GG, *XX, YY);

  Y.assign(YY2);
  grp->loadNestedComponents(*XX, YY1, X);

  return status;
}
void
LOCA::MultiContinuation::ConstrainedGroup::fillB(
	                                  NOX::Abstract::MultiVector& B) const
{
  std::string callingFunction = 
    "LOCA::MultiContinuation::ConstrainedGroup::fillB";

  bool isZeroB = constraintsPtr->isDXZero();
  Teuchos::RCP<const NOX::Abstract::MultiVector> my_B;

  if (!isZeroB) {
    Teuchos::RCP<const LOCA::MultiContinuation::ConstraintInterfaceMVDX> constraints_mvdx = Teuchos::rcp_dynamic_cast<const LOCA::MultiContinuation::ConstraintInterfaceMVDX>(constraintsPtr);
    if (constraints_mvdx == Teuchos::null)
      globalData->locaErrorCheck->throwError(
				callingFunction,
				std::string("Constraints object must be of type") +
				std::string("ConstraintInterfaceMVDX"));

    my_B = Teuchos::rcp(constraints_mvdx->getDX(),false);
  }

  // If the underlying system isn't bordered, we're done
  if (!isBordered) {
    if (isZeroB)
      B.init(0.0);
    else
      B = *my_B;
    return;
  }

  // Create views for underlying group
  int w = bordered_grp->getBorderedWidth();
  std::vector<int> idx1(w);
  for (int i=0; i<w; i++)
    idx1[i] = i;
  Teuchos::RCP<NOX::Abstract::MultiVector> underlyingB = 
    B.subView(idx1);

  // Combine blocks in underlying group
  bordered_grp->fillB(*underlyingB);

  // Create views for my blocks
  std::vector<int> idx2(numParams);
  for (int i=0; i<numParams; i++)
    idx2[i] = w+i;
  Teuchos::RCP<NOX::Abstract::MultiVector> my_B_x = 
    B.subView(idx2);

  // Extract solution component from my_B and store in B
  if (isZeroB)
    my_B_x->init(0.0);
  else
    bordered_grp->extractSolutionComponent(*my_B, *my_B_x);
}
NOX::Abstract::Group::ReturnType 
LOCA::BorderedSolver::LowerTriangularBlockElimination::
solve(Teuchos::ParameterList& params,
      const LOCA::BorderedSolver::AbstractOperator& op,
      const LOCA::MultiContinuation::ConstraintInterface& B,
      const NOX::Abstract::MultiVector::DenseMatrix& C,
      const NOX::Abstract::MultiVector* F,
      const NOX::Abstract::MultiVector::DenseMatrix* G,
      NOX::Abstract::MultiVector& X,
      NOX::Abstract::MultiVector::DenseMatrix& Y) const
{
  string callingFunction = 
    "LOCA::BorderedSolver::LowerTriangularBlockElimination::solve()";
  NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok;
  NOX::Abstract::Group::ReturnType status;

  // Determine if X or Y is zero
  bool isZeroF = (F == NULL);
  bool isZeroG = (G == NULL);
  bool isZeroB = B.isDXZero();
  bool isZeroX = isZeroF;
  bool isZeroY = isZeroG && (isZeroB  || isZeroX);

  // First compute X
  if (isZeroX)
    X.init(0.0);
  else {
    // Solve X = J^-1 F, note F must be nonzero
    status = op.applyInverse(params, *F, X);
    finalStatus = 
      globalData->locaErrorCheck->combineAndCheckReturnTypes(status, 
							     finalStatus,
							     callingFunction);
  }

  // Now compute Y
  if (isZeroY)
    Y.putScalar(0.0);
  else {
    // Compute G - B^T*X and store in Y
    if (isZeroG) 
      B.multiplyDX(-1.0, X, Y);
    else {
      Y.assign(*G);
      if (!isZeroB && !isZeroX) {
	NOX::Abstract::MultiVector::DenseMatrix T(Y.numRows(),Y.numCols());
	B.multiplyDX(1.0, X, T);
	Y -= T;
      }
    }

    // Overwrite Y with Y = C^-1 * (G - B^T*X)
    NOX::Abstract::MultiVector::DenseMatrix M(C);
    int *ipiv = new int[M.numRows()];
    Teuchos::LAPACK<int,double> L;
    int info;
    L.GETRF(M.numRows(), M.numCols(), M.values(), M.stride(), ipiv, &info);
    if (info != 0) {
      status = NOX::Abstract::Group::Failed;
      finalStatus = 
	globalData->locaErrorCheck->combineAndCheckReturnTypes(
							      status, 
							      finalStatus,
							      callingFunction);
    }
    L.GETRS('N', M.numRows(), Y.numCols(), M.values(), M.stride(), ipiv, 
	    Y.values(), Y.stride(), &info);
    delete [] ipiv;
    if (info != 0) {
      status = NOX::Abstract::Group::Failed;
      finalStatus = 
	globalData->locaErrorCheck->combineAndCheckReturnTypes(
							     status, 
							     finalStatus,
							     callingFunction);
    }
  }

  return finalStatus;
}