void LOCA::Extended::MultiVector::multiply( double alpha, const LOCA::Extended::MultiVector& y, NOX::Abstract::MultiVector::DenseMatrix& b) const { // Verify dimensions are consistent if (y.numMultiVecRows != numMultiVecRows || y.numColumns != b.numRows() || y.numScalarRows != numScalarRows || numColumns != b.numCols()) globalData->locaErrorCheck->throwError( "LOCA::Extended::MultiVector::multiply()", "Size of supplied multivector/matrix is incompatible with this multivector"); // Zero out b b.putScalar(0.0); // Create temporary matrix to hold product for each multivec NOX::Abstract::MultiVector::DenseMatrix tmp(b); // Compute and sum products for each multivec for (int i=0; i<numMultiVecRows; i++) { multiVectorPtrs[i]->multiply(alpha, *(y.multiVectorPtrs[i]), tmp); b += tmp; } // Compute and add in product for scalars if (numScalarRows > 0) b.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, alpha, *y.scalarsPtr, *scalarsPtr, 1.0); }
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::MultiContinuation::CompositeConstraint::multiplyDX( double alpha, const NOX::Abstract::MultiVector& input_x, NOX::Abstract::MultiVector::DenseMatrix& result_p) const { std::string callingFunction = "LOCA::MultiContinuation::CompositeConstraint::multiplyDX()"; NOX::Abstract::Group::ReturnType status; NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok; // If dg/dx is zero for every constraint, result_p is zero if (isDXZero()) { result_p.putScalar(0.0); return finalStatus; } Teuchos::RCP<NOX::Abstract::MultiVector::DenseMatrix> result_p_sub; int num_rows; int num_cols = result_p.numCols(); for (int i=0; i<numConstraintObjects; i++) { num_rows = constraintPtrs[i]->numConstraints(); // if dg/dx is zero for this constraint, set corresponding entries of // result_p to zero if (constraintPtrs[i]->isDXZero()) { for (int j=0; j<num_rows; j++) for (int k=0; k<num_cols; k++) result_p(indices[i][j],k) = 0.0; } else { // Create a sub view of rows indices[i][0] -- indices[i][end] // of result_p result_p_sub = Teuchos::rcp(new NOX::Abstract::MultiVector::DenseMatrix(Teuchos::View, result_p, num_rows, num_cols, indices[i][0], 0)); status = constraintPtrs[i]->multiplyDX(alpha, input_x, *result_p_sub); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes( status, finalStatus, callingFunction); } } return finalStatus; }
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; }
NOX::Abstract::Group::ReturnType LOCA::MultiContinuation::ConstraintInterfaceMVDX::multiplyDX( double alpha, const NOX::Abstract::MultiVector& input_x, NOX::Abstract::MultiVector::DenseMatrix& result_p) const { if (!isDXZero()) { const NOX::Abstract::MultiVector* dgdx = getDX(); input_x.multiply(alpha, *dgdx, result_p); } else result_p.putScalar(0.0); return NOX::Abstract::Group::Ok; }
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; }
void LOCA::BorderedSolver::HouseholderQR::computeQR( const NOX::Abstract::MultiVector::DenseMatrix& C, const NOX::Abstract::MultiVector& B, bool use_c_transpose, NOX::Abstract::MultiVector::DenseMatrix& Y1, NOX::Abstract::MultiVector& Y2, NOX::Abstract::MultiVector::DenseMatrix& T, NOX::Abstract::MultiVector::DenseMatrix& R) { double beta; int m = B.numVectors(); // Initialize Y1.putScalar(0.0); T.putScalar(0.0); Y2 = B; if (use_c_transpose) { for (int i=0; i<m; i++) for (int j=0; j<m; j++) R(i,j) = C(j,i); // Copy transpose of C into R } else R.assign(C); // A temporary vector Teuchos::RCP<NOX::Abstract::MultiVector> v2 = Y2.clone(1); Teuchos::RCP<NOX::Abstract::MultiVector::DenseMatrix> v1; Teuchos::RCP<NOX::Abstract::MultiVector> h2; Teuchos::RCP<NOX::Abstract::MultiVector::DenseMatrix> h1; Teuchos::RCP<NOX::Abstract::MultiVector> y2; Teuchos::RCP<NOX::Abstract::MultiVector::DenseMatrix> y1; Teuchos::RCP<NOX::Abstract::MultiVector::DenseMatrix> z; std::vector<int> h_idx; std::vector<int> y_idx; y_idx.reserve(m); for (int i=0; i<m; i++) { // Create view of column i of Y1 starting at row i v1 = Teuchos::rcp(new NOX::Abstract::MultiVector::DenseMatrix(Teuchos::View, Y1, m-i, 1, i, i)); // Create view of columns i through m-1 of Y2 h_idx.resize(m-i); for (unsigned int j=0; j<h_idx.size(); j++) h_idx[j] = i+j; h2 = Y2.subView(h_idx); // Create view of columns i thru m-1 of R, starting at row i h1 = Teuchos::rcp(new NOX::Abstract::MultiVector::DenseMatrix(Teuchos::View, R, m-i, m-i, i, i)); if (i > 0) { // Create view of columns 0 through i-1 of Y2 y_idx.push_back(i-1); y2 = Y2.subView(y_idx); // Create view of columns 0 through i-1 of Y1, starting at row i y1 = Teuchos::rcp(new NOX::Abstract::MultiVector::DenseMatrix(Teuchos::View, Y1, m-i, i, i, 0)); // Create view of column i, row 0 through i-1 of T z = Teuchos::rcp(new NOX::Abstract::MultiVector::DenseMatrix(Teuchos::View, T, i, 1, 0, i)); } // Compute Householder Vector computeHouseholderVector(i, R, Y2, *v1, *v2, beta); // Apply Householder reflection applyHouseholderVector(*v1, *v2, beta, *h1, *h2); // Copy v2 into Y2 Y2[i] = (*v2)[0]; T(i,i) = -beta; if (i > 0) { // Compute z = y2^T * v2 v2->multiply(1.0, *y2, *z); // Compute z = -beta * (z + y1^T * v1) z->multiply(Teuchos::TRANS, Teuchos::NO_TRANS, -beta, *y1, *v1, -beta); // Compute z = T * z dblas.TRMV(Teuchos::UPPER_TRI, Teuchos::NO_TRANS, Teuchos::NON_UNIT_DIAG, i, T.values(), m, z->values(), 1); } } }