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); }
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; }