void LOCA::Homotopy::DeflatedGroup:: extractParameterComponent(bool use_transpose, const NOX::Abstract::MultiVector& v, NOX::Abstract::MultiVector::DenseMatrix& v_p) const { // cast v to an extended multi-vec const LOCA::MultiContinuation::ExtendedMultiVector& mc_v = dynamic_cast<const LOCA::MultiContinuation::ExtendedMultiVector&>(v); // get solution and parameter components Teuchos::RCP<const NOX::Abstract::MultiVector> mc_v_x = mc_v.getXMultiVec(); Teuchos::RCP<const NOX::Abstract::MultiVector::DenseMatrix> mc_v_p = mc_v.getScalars(); // If the underlying system isn't bordered, we're done if (!isBordered) { if (!use_transpose) v_p.assign(*mc_v_p); else for (int j=0; j<v_p.numCols(); j++) for (int i=0; i<v_p.numRows(); i++) v_p(i,j) = (*mc_v_p)(j,i); return; } int w = bordered_grp->getBorderedWidth(); if (!use_transpose) { // Split v_p into 2 block rows, the top to store mc_v_x_p and the bottom // to store mc_v_p int num_cols = v_p.numCols(); NOX::Abstract::MultiVector::DenseMatrix v_p_1(Teuchos::View, v_p, w, num_cols, 0, 0); NOX::Abstract::MultiVector::DenseMatrix v_p_2(Teuchos::View, v_p, 1, num_cols, w, 0); // Decompose mc_v_x bordered_grp->extractParameterComponent(use_transpose,*mc_v_x, v_p_1); v_p_2.assign(*mc_v_p); } else { // Split v_p into 2 block columns, the first to store mc_v_x_p^t and the // the second to store mc_v_p^T int num_rows = v_p.numRows(); NOX::Abstract::MultiVector::DenseMatrix v_p_1(Teuchos::View, v_p, num_rows, w, 0, 0); NOX::Abstract::MultiVector::DenseMatrix v_p_2(Teuchos::View, v_p, num_rows, 1, 0, w); // Decompose mc_v_x bordered_grp->extractParameterComponent(use_transpose,*mc_v_x, v_p_1); for (int j=0; j<1; j++) for (int i=0; i<num_rows; i++) v_p_2(i,j) = (*mc_v_p)(j,i); } }
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::Homotopy::DeflatedGroup:: fillC(NOX::Abstract::MultiVector::DenseMatrix& C) const { string callingFunction = "LOCA::Homotopy::DeflatedGroup::fillC"; Teuchos::RCP<const NOX::Abstract::MultiVector::DenseMatrix> my_C = minusOne; // If the underlying system isn't bordered, we're done if (!isBordered) { C.assign(*my_C); return; } Teuchos::RCP<const NOX::Abstract::MultiVector> my_B = totalDistMultiVec; Teuchos::RCP<const NOX::Abstract::MultiVector> my_A = underlyingF; // Create views for underlying group int w = bordered_grp->getBorderedWidth(); NOX::Abstract::MultiVector::DenseMatrix underlyingC(Teuchos::View, C, w, w, 0, 0); // Combine blocks in underlying group bordered_grp->fillC(underlyingC); // Create views for my blocks NOX::Abstract::MultiVector::DenseMatrix my_A_p(Teuchos::View, C, w, 1, 0, w); NOX::Abstract::MultiVector::DenseMatrix my_B_p(Teuchos::View, C, 1, w, w, 0); NOX::Abstract::MultiVector::DenseMatrix my_CC(Teuchos::View, C, 1, 1, w, w); // Extract solution component from my_A and store in my_A_p bordered_grp->extractParameterComponent(false, *my_A, my_A_p); // Extract solution component from my_B and store in my_B_p bordered_grp->extractParameterComponent(true, *my_B, my_B_p); // Copy in my_C my_CC.assign(*my_C); }
void LOCA::Hopf::MinimallyAugmented::ExtendedGroup:: fillC(NOX::Abstract::MultiVector::DenseMatrix& C) const { string callingFunction = "LOCA::Hopf::MinimallyAugmented::ExtendedGroup::fillC"; Teuchos::RCP<const NOX::Abstract::MultiVector::DenseMatrix> my_C = dfdpMultiVec->getScalars(); // If the underlying system isn't bordered, we're done if (!isBordered) { C.assign(*my_C); return; } Teuchos::RCP<const NOX::Abstract::MultiVector> my_B = Teuchos::rcp(constraintsPtr->getDX(),false); Teuchos::RCP<const NOX::Abstract::MultiVector> my_A = dfdpMultiVec->getXMultiVec(); // Create views for underlying group int w = bordered_grp->getBorderedWidth(); NOX::Abstract::MultiVector::DenseMatrix underlyingC(Teuchos::View, C, w, w, 0, 0); // Combine blocks in underlying group bordered_grp->fillC(underlyingC); // Create views for my blocks NOX::Abstract::MultiVector::DenseMatrix my_A_p(Teuchos::View, C, w, 2, 0, w); NOX::Abstract::MultiVector::DenseMatrix my_B_p(Teuchos::View, C, 2, w, w, 0); NOX::Abstract::MultiVector::DenseMatrix my_CC(Teuchos::View, C, 2, 2, w, w); // Extract solution component from my_A and store in my_A_p bordered_grp->extractParameterComponent(false, *my_A, my_A_p); // Extract solution component from my_B and store in my_B_p bordered_grp->extractParameterComponent(true, *my_B, my_B_p); // Copy in my_C my_CC.assign(*my_C); }
NOX::Abstract::Group::ReturnType LOCA::BorderedSolver::Nested::applyTranspose( const NOX::Abstract::MultiVector& X, const NOX::Abstract::MultiVector::DenseMatrix& Y, NOX::Abstract::MultiVector& U, NOX::Abstract::MultiVector::DenseMatrix& V) const { int num_cols = X.numVectors(); Teuchos::RCP<NOX::Abstract::MultiVector> XX = unbordered_grp->getX().createMultiVector(num_cols); Teuchos::RCP<NOX::Abstract::MultiVector> UU = unbordered_grp->getX().createMultiVector(num_cols); NOX::Abstract::MultiVector::DenseMatrix YY(myWidth, num_cols); NOX::Abstract::MultiVector::DenseMatrix VV(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::MultiVector::DenseMatrix VV1(Teuchos::View, VV, underlyingWidth, num_cols, 0, 0); NOX::Abstract::MultiVector::DenseMatrix VV2(Teuchos::View, VV, numConstraints, num_cols, underlyingWidth, 0); grp->extractSolutionComponent(X, *XX); grp->extractParameterComponent(false, X, YY1); YY2.assign(Y); NOX::Abstract::Group::ReturnType status = solver->applyTranspose(*XX, YY, *UU, VV); V.assign(VV2); grp->loadNestedComponents(*UU, VV1, U); return status; }
void LOCA::BorderedSolver::HouseholderQR::applyCompactWY( const NOX::Abstract::MultiVector::DenseMatrix& Y1, const NOX::Abstract::MultiVector& Y2, const NOX::Abstract::MultiVector::DenseMatrix& T, const NOX::Abstract::MultiVector::DenseMatrix* input1, const NOX::Abstract::MultiVector* input2, NOX::Abstract::MultiVector::DenseMatrix& result1, NOX::Abstract::MultiVector& result2, bool useTranspose) const { bool isZeroX1 = (input1 == NULL); bool isZeroX2 = (input2 == NULL); if (!isZeroX1) result1.assign(*input1); if (!isZeroX2) result2 = *input2; applyCompactWY(Y1, Y2, T, result1, result2, isZeroX1, isZeroX2, useTranspose); }
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; }
// Solves Hopf equations via classic Salinger bordering // The first m columns of input_x, input_y, input_z store the RHS, the // next column stores df/dp, (Jy-wBz)_p and (Jz+wBy)_p respectively, the // last column of input_y and input_z store Bz and -By respectively. Note // input_x has m+1 columns, input_y and input_z have m+2, and input_w and // input_p have m columns. result_x, result_y, result_z, result_w and // result_param have the same dimensions as their input counterparts NOX::Abstract::Group::ReturnType LOCA::Hopf::MooreSpence::SalingerBordering::solveContiguous( Teuchos::ParameterList& params, const NOX::Abstract::MultiVector& input_x, const NOX::Abstract::MultiVector& input_y, const NOX::Abstract::MultiVector& input_z, const NOX::Abstract::MultiVector::DenseMatrix& input_w, const NOX::Abstract::MultiVector::DenseMatrix& input_p, NOX::Abstract::MultiVector& result_x, NOX::Abstract::MultiVector& result_y, NOX::Abstract::MultiVector& result_z, NOX::Abstract::MultiVector::DenseMatrix& result_w, NOX::Abstract::MultiVector::DenseMatrix& result_p) const { std::string callingFunction = "LOCA::Hopf::MooreSpence::SalingerBordering::solveContiguous()"; NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok; NOX::Abstract::Group::ReturnType status; int m = input_x.numVectors()-1; std::vector<int> index_input(m); std::vector<int> index_dp(1); std::vector<int> index_B(1); std::vector<int> index_ip(m+1); for (int i=0; i<m; i++) { index_input[i] = i; index_ip[i] = i; } index_ip[m] = m; index_dp[0] = m; index_B[0] = m+1; // verify underlying Jacobian is valid if (!group->isJacobian()) { status = group->computeJacobian(); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); } // compute [A b] = J^-1 [F df/dp] status = group->applyJacobianInverseMultiVector(params, input_x, result_x); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); Teuchos::RCP<NOX::Abstract::MultiVector> A = result_x.subView(index_input); Teuchos::RCP<NOX::Abstract::MultiVector> b = result_x.subView(index_dp); // verify underlying complex matrix is valid if (!group->isComplex()) { status = group->computeComplex(w); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); } // compute (J+iwB)(y+iz)_x [A b] Teuchos::RCP<NOX::Abstract::MultiVector> tmp_real = result_y.clone(NOX::ShapeCopy); Teuchos::RCP<NOX::Abstract::MultiVector> tmp_real_sub = tmp_real->subView(index_ip); Teuchos::RCP<NOX::Abstract::MultiVector> tmp_imag = result_y.clone(NOX::ShapeCopy); Teuchos::RCP<NOX::Abstract::MultiVector> tmp_imag_sub = tmp_imag->subView(index_ip); tmp_real->init(0.0); tmp_imag->init(0.0); status = group->computeDCeDxa(*yVector, *zVector, w, result_x, *CeRealVector, *CeImagVector, *tmp_real_sub, *tmp_imag_sub); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // compute [G+iH d(J+iwB)(y+iz)/dp iB(y+iz)] - [(J+iwB)_x[A b] 0+i0] tmp_real->update(1.0, input_y, -1.0); tmp_imag->update(1.0, input_z, -1.0); // verify underlying complex matrix is valid if (!group->isComplex()) { status = group->computeComplex(w); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); } // compute [C+iD e+if g+ih] = (J+iwB)^-1 (tmp_real + i tmp_imag) status = group->applyComplexInverseMultiVector(params, *tmp_real, *tmp_imag, result_y, result_z); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); Teuchos::RCP<NOX::Abstract::MultiVector> C = result_y.subView(index_input); Teuchos::RCP<NOX::Abstract::MultiVector> D = result_z.subView(index_input); Teuchos::RCP<NOX::Abstract::MultiVector> e = result_y.subView(index_dp); Teuchos::RCP<NOX::Abstract::MultiVector> f = result_z.subView(index_dp); Teuchos::RCP<NOX::Abstract::MultiVector> g = result_y.subView(index_B); Teuchos::RCP<NOX::Abstract::MultiVector> h = result_z.subView(index_B); // compute lambda = ((phi^T h)(phi^T C-u) - (phi^T g)(phi^T D-v)) / // ((phi^T h)(phi^T e)-(phi^T g)(phi^T f)) NOX::Abstract::MultiVector::DenseMatrix ltC(1,m); NOX::Abstract::MultiVector::DenseMatrix ltD(1,m); double lte = hopfGroup->lTransNorm((*e)[0]); double ltf = hopfGroup->lTransNorm((*f)[0]); double ltg = hopfGroup->lTransNorm((*g)[0]); double lth = hopfGroup->lTransNorm((*h)[0]); double denom = lth*lte - ltg*ltf; hopfGroup->lTransNorm(*C, ltC); ltC -= input_w; ltC.scale(lth); hopfGroup->lTransNorm(*D, ltD); ltD -= input_p; result_p.assign(ltD); result_p.scale(-ltg); result_p += ltC; result_p.scale(1.0/denom); // compute omega = (phi^T D-v - (phi^T f)lambda)/(phi^T h) result_w.assign(result_p); result_w.scale(-ltf); result_w += ltD; result_w.scale(1.0/lth); // compute A = A - b*lambda (remember A is a sub-view of result_x) A->update(Teuchos::NO_TRANS, -1.0, *b, result_p, 1.0); // compute C = C - e*lambda - g*omega (remember C is a sub-view of result_y) C->update(Teuchos::NO_TRANS, -1.0, *e, result_p, 1.0); C->update(Teuchos::NO_TRANS, -1.0, *g, result_w, 1.0); // compute D = D - f*lambda - h*omega (remember D is a sub-view of result_z) D->update(Teuchos::NO_TRANS, -1.0, *f, result_p, 1.0); D->update(Teuchos::NO_TRANS, -1.0, *h, result_w, 1.0); 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); } } }
void LOCA::MultiContinuation::ConstrainedGroup::fillC( NOX::Abstract::MultiVector::DenseMatrix& C) const { std::string callingFunction = "LOCA::MultiContinuation::ConstrainedGroup::fillC"; Teuchos::RCP<const NOX::Abstract::MultiVector::DenseMatrix> my_C = dfdpMultiVec->getScalars(); // If the underlying system isn't bordered, we're done if (!isBordered) { C.assign(*my_C); return; } 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); } Teuchos::RCP<const NOX::Abstract::MultiVector> my_A = dfdpMultiVec->getXMultiVec(); // Create views for underlying group int w = bordered_grp->getBorderedWidth(); NOX::Abstract::MultiVector::DenseMatrix underlyingC(Teuchos::View, C, w, w, 0, 0); // Combine blocks in underlying group bordered_grp->fillC(underlyingC); // Create views for my blocks NOX::Abstract::MultiVector::DenseMatrix my_A_p(Teuchos::View, C, w, numParams, 0, w); NOX::Abstract::MultiVector::DenseMatrix my_B_p(Teuchos::View, C, numParams, w, w, 0); NOX::Abstract::MultiVector::DenseMatrix my_CC(Teuchos::View, C, numParams, numParams, w, w); // Extract solution component from my_A and store in my_A_p bordered_grp->extractParameterComponent(false, *my_A, my_A_p); // Extract solution component from my_B and store in my_B_p if (isZeroB) my_B_p.putScalar(0.0); else bordered_grp->extractParameterComponent(true, *my_B, my_B_p); // Copy in my_C my_CC.assign(*my_C); }