LOCA::TurningPoint::MooreSpence::ExtendedMultiVector::ExtendedMultiVector( const Teuchos::RCP<LOCA::GlobalData>& global_data, const NOX::Abstract::MultiVector& xVec, const NOX::Abstract::MultiVector& nullVec, const NOX::Abstract::MultiVector::DenseMatrix& bifParams) : LOCA::Extended::MultiVector(global_data, xVec.numVectors(), 2, 1) { LOCA::Extended::MultiVector::setMultiVectorPtr(0, xVec.clone(NOX::DeepCopy)); LOCA::Extended::MultiVector::setMultiVectorPtr(1, nullVec.clone(NOX::DeepCopy)); LOCA::Extended::MultiVector::getScalars()->assign(bifParams); }
LOCA::Hopf::MooreSpence::ExtendedMultiVector::ExtendedMultiVector( const Teuchos::RCP<LOCA::GlobalData>& global_data, const NOX::Abstract::MultiVector& xVec, const NOX::Abstract::MultiVector& realEigenVec, const NOX::Abstract::MultiVector& imagEigenVec, const NOX::Abstract::MultiVector::DenseMatrix& freqs, const NOX::Abstract::MultiVector::DenseMatrix& bifParams) : LOCA::Extended::MultiVector(global_data, xVec.numVectors(), 3, 2) { LOCA::Extended::MultiVector::setMultiVectorPtr(0, xVec.clone(NOX::DeepCopy)); LOCA::Extended::MultiVector::setMultiVectorPtr(1, realEigenVec.clone(NOX::DeepCopy)); LOCA::Extended::MultiVector::setMultiVectorPtr(2, imagEigenVec.clone(NOX::DeepCopy)); LOCA::Extended::MultiVector::getScalarRows(1,0)->assign(freqs); LOCA::Extended::MultiVector::getScalarRows(1,1)->assign(bifParams); }
LOCA::Pitchfork::MooreSpence::ExtendedMultiVector::ExtendedMultiVector( const Teuchos::RCP<LOCA::GlobalData>& global_data, const NOX::Abstract::MultiVector& xVec, const NOX::Abstract::MultiVector& nullVec, const NOX::Abstract::MultiVector::DenseMatrix& slacks, const NOX::Abstract::MultiVector::DenseMatrix& bifParams) : LOCA::Extended::MultiVector(global_data, xVec.numVectors(), 2, 2) { LOCA::Extended::MultiVector::setMultiVectorPtr(0, xVec.clone(NOX::DeepCopy)); LOCA::Extended::MultiVector::setMultiVectorPtr(1, nullVec.clone(NOX::DeepCopy)); LOCA::Extended::MultiVector::getScalarRows(1,0)->assign(slacks); LOCA::Extended::MultiVector::getScalarRows(1,1)->assign(bifParams); }
void LOCA::AnasaziOperator::Cayley2Matrix::apply(const NOX::Abstract::MultiVector& input, NOX::Abstract::MultiVector& output) const { std::string callingFunction = "LOCA::AnasaziOperator::Cayley2Matrix::apply()"; NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok; NOX::Abstract::Group::ReturnType status; // Allocate temporary vector if (tmp_r == Teuchos::null || tmp_r->numVectors() != input.numVectors()) tmp_r = input.clone(NOX::ShapeCopy); // Compute J-mu*M -- moved to preProcessSeedVector // Compute (J-mu*M)*input status = grp->applySecondShiftedMatrixMultiVector(input, *tmp_r); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Compute J-sigma*M -- moved to preProcessSeedVector // Solve (J-sigma*M)*output = (J-mu*M)*input status = grp->applyShiftedMatrixInverseMultiVector(*solverParams, *tmp_r, output); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); }
LOCA::MultiContinuation::ExtendedMultiVector::ExtendedMultiVector( const Teuchos::RCP<LOCA::GlobalData>& global_data, const NOX::Abstract::MultiVector& xVec, int nScalarRows) : LOCA::Extended::MultiVector(global_data, xVec.numVectors(), 1, nScalarRows) { LOCA::Extended::MultiVector::setMultiVectorPtr(0, xVec.clone(NOX::DeepCopy)); }
void LOCA::Epetra::AnasaziOperator::Floquet::apply(const NOX::Abstract::MultiVector& input, NOX::Abstract::MultiVector& output) const { // Apply first part of monodromy operator on input vector Teuchos::RCP<NOX::Abstract::MultiVector> tmpVec = input.clone(); for (int i=0; i < input.numVectors(); i++) { NOX::Abstract::Vector& nAV = tmpVec->operator[](i); NOX::Epetra::Vector& nEV = dynamic_cast<NOX::Epetra::Vector&>(nAV); Epetra_Vector& eV = nEV.getEpetraVector(); xyztInterface->beginFloquetOperatorApplication(eV); } // Now apply the main part of the monodromy matrix NOX::Abstract::Group::ReturnType status = grp->applyJacobianInverseMultiVector(*solverParams, *(tmpVec.get()), output); globalData->locaErrorCheck->checkReturnType(status, "LOCA::Epetra::AnasaziOperator::Floquet::apply()"); for (int i=0; i < input.numVectors(); i++) { NOX::Abstract::Vector& nAV = output.operator[](i); NOX::Epetra::Vector& nEV = dynamic_cast<NOX::Epetra::Vector&>(nAV); Epetra_Vector& eV = nEV.getEpetraVector(); xyztInterface->finishFloquetOperatorApplication(eV); } // Was this needed? // TESTING: Doubling the call to this routine resulted in the // squaring of the Floquet multipliers, as they should. // Replacing the apply function so the operator is diagonal // with entries 1/(i+2) led to the Floquet multipliers. /* std::cout << " Fixing apply so Floquets at 1/2 1/3 1/4 ... " << std::endl; Teuchos::RCP<NOX::Abstract::MultiVector> tmpVec = input.clone(); for (int i=0; i < input.numVectors(); i++) { NOX::Abstract::Vector& nAV = output.operator[](i); NOX::Epetra::Vector& nEV = dynamic_cast<NOX::Epetra::Vector&>(nAV); Epetra_Vector& oV = nEV.getEpetraVector(); NOX::Abstract::Vector& nAV2 = tmpVec->operator[](i); NOX::Epetra::Vector& nEV2 = dynamic_cast<NOX::Epetra::Vector&>(nAV2); Epetra_Vector& iV = nEV2.getEpetraVector(); for (int j=0; j < iV.MyLength(); j++) { oV[j] = iV[j] / (j + 2.0); } } */ }
LOCA::MultiContinuation::ExtendedMultiVector::ExtendedMultiVector( const Teuchos::RCP<LOCA::GlobalData>& global_data, const NOX::Abstract::MultiVector& xVec, const NOX::Abstract::MultiVector::DenseMatrix& params) : LOCA::Extended::MultiVector(global_data, xVec.numVectors(), 1, params.numRows()) { LOCA::Extended::MultiVector::setMultiVectorPtr(0, xVec.clone(NOX::DeepCopy)); LOCA::Extended::MultiVector::getScalars()->assign(params); }
NOX::Abstract::Group::ReturnType LOCA::DerivUtils::computeDwtJnDx(LOCA::MultiContinuation::AbstractGroup& grp, const NOX::Abstract::MultiVector& w, const NOX::Abstract::Vector& nullVector, NOX::Abstract::MultiVector& result) const { string callingFunction = "LOCA::DerivUtils::computeDwtJnDx()"; NOX::Abstract::Group::ReturnType status, finalStatus; // Vector to store w^T*J Teuchos::RCP<NOX::Abstract::MultiVector> wtJ = w.clone(NOX::ShapeCopy); // Compute base w^T*J finalStatus = grp.computeJacobian(); globalData->locaErrorCheck->checkReturnType(finalStatus, callingFunction); status = grp.applyJacobianTransposeMultiVector(w, *wtJ); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Copy original solution vector Teuchos::RCP<NOX::Abstract::Vector> Xvec = grp.getX().clone(NOX::DeepCopy); // Perturb solution vector in direction of nullVector, return perturbation double eps = perturbXVec(grp, *Xvec, nullVector); // Fill perturbed w^T*J vector finalStatus = grp.computeJacobian(); globalData->locaErrorCheck->checkReturnType(finalStatus, callingFunction); status = grp.applyJacobianTransposeMultiVector(w, result); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Difference perturbed and base vector result.update(-1.0, *wtJ, 1.0); result.scale(1.0/eps); // Restore original solution vector grp.setX(*Xvec); return finalStatus; }
void LOCA::AnasaziOperator::Cayley2Matrix::preProcessSeedVector(NOX::Abstract::MultiVector& ivec) { // Changes random seed vector ivec: ivec = (J - sigma*M)^{-1}*M*ivec std::string callingFunction = "LOCA::AnasaziOperator::Cayley2Matrix::preProcessSeedVector()"; NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok; NOX::Abstract::Group::ReturnType status; // Allocate temporary vector if (tmp_r == Teuchos::null || tmp_r->numVectors() != ivec.numVectors()) tmp_r = ivec.clone(NOX::ShapeCopy); // Compute M status = grp->computeShiftedMatrix(0.0, 1.0); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Compute M*ivec status = grp->applyShiftedMatrixMultiVector(ivec, *tmp_r); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Compute J-sigma*M status = grp->computeShiftedMatrix(1.0, -sigma); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Solve (J-sigma*M)*output = (M)*ivec status = grp->applyShiftedMatrixInverseMultiVector(*solverParams, *tmp_r, ivec); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Compute J-mu*M status = grp->computeSecondShiftedMatrix(1.0, -mu); }
void LOCA::AnasaziOperator::ShiftInvert::apply( const NOX::Abstract::MultiVector& input, NOX::Abstract::MultiVector& output) const { std::string callingFunction = "LOCA::AnasaziOperator::ShiftInvert::apply()"; NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok; NOX::Abstract::Group::ReturnType status; // Allocate temporary vector if (tmp_r == Teuchos::null || tmp_r->numVectors() != input.numVectors()) tmp_r = input.clone(NOX::ShapeCopy); // Compute M status = grp->computeShiftedMatrix(0.0, 1.0); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Compute M*input status = grp->applyShiftedMatrixMultiVector(input, *tmp_r); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Compute J-omega*M status = grp->computeShiftedMatrix(1.0, -shift); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // Solve (J-omega*M)*output = M*input status = grp->applyShiftedMatrixInverseMultiVector(*solverParams, *tmp_r, output); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); }
// Solves turning point equations via classic Salinger bordering // The first m columns of input_x and input_null store the RHS while // the last column stores df/dp, d(Jn)/dp respectively. Note however // input_param has only m columns (not m+1). result_x, result_null, // are result_param have the same dimensions as their input counterparts NOX::Abstract::Group::ReturnType LOCA::TurningPoint::MooreSpence::PhippsBordering::solveTransposeContiguous( Teuchos::ParameterList& params, const NOX::Abstract::MultiVector& input_x, const NOX::Abstract::MultiVector& input_null, const NOX::Abstract::MultiVector::DenseMatrix& input_param, NOX::Abstract::MultiVector& result_x, NOX::Abstract::MultiVector& result_null, NOX::Abstract::MultiVector::DenseMatrix& result_param) const { std::string callingFunction = "LOCA::TurningPoint::MooreSpence::PhippsBordering::solveTransposeContiguous()"; NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok; NOX::Abstract::Group::ReturnType status; int m = input_x.numVectors()-2; std::vector<int> index_input(m); std::vector<int> index_input_dp(m+1); std::vector<int> index_null(1); std::vector<int> index_dp(1); for (int i=0; i<m; i++) { index_input[i] = i; index_input_dp[i] = i; } index_input_dp[m] = m; index_dp[0] = m; index_null[0] = m+1; NOX::Abstract::MultiVector::DenseMatrix tmp_mat_1(1, m+1); NOX::Abstract::MultiVector::DenseMatrix tmp_mat_2(1, m+2); // Create view of first m+1 columns of input_null, result_null Teuchos::RCP<NOX::Abstract::MultiVector> input_null_view = input_null.subView(index_input_dp); Teuchos::RCP<NOX::Abstract::MultiVector> result_null_view = result_null.subView(index_input_dp); // verify underlying Jacobian is valid if (!group->isJacobian()) { status = group->computeJacobian(); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); } // Solve |J^T v||A B| = |G -phi| // |u^T 0||a b| |0 0 | status = transposeBorderedSolver->applyInverseTranspose(params, input_null_view.get(), NULL, *result_null_view, tmp_mat_1); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); Teuchos::RCP<NOX::Abstract::MultiVector> A = result_null.subView(index_input); Teuchos::RCP<NOX::Abstract::MultiVector> B = result_null.subView(index_dp); double b = tmp_mat_1(0,m); // compute (Jv)_x^T[A B u] result_null[m+1] = *uVector; Teuchos::RCP<NOX::Abstract::MultiVector> tmp = result_null.clone(NOX::ShapeCopy); status = group->computeDwtJnDxMulti(result_null, *nullVector, *tmp); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // compute [F 0 0] - (Jv)_x^T[A B u] tmp->update(1.0, input_x, -1.0); // verify underlying Jacobian is valid if (!group->isJacobian()) { status = group->computeJacobian(); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); } // Solve |J^T v||C D E| = |F - (Jv)_x^T A -(Jv)_x^T B -(Jv)_x^T u| // |u^T 0||c d e| | 0 0 0 | status = transposeBorderedSolver->applyInverseTranspose(params, tmp.get(), NULL, result_x, tmp_mat_2); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); Teuchos::RCP<NOX::Abstract::MultiVector> C = result_x.subView(index_input); Teuchos::RCP<NOX::Abstract::MultiVector> D = result_x.subView(index_dp); Teuchos::RCP<NOX::Abstract::MultiVector> E = result_x.subView(index_null); double d = tmp_mat_2(0, m); double e = tmp_mat_2(0, m+1); // compute (Jv)_p^T*[A B u] NOX::Abstract::MultiVector::DenseMatrix t1(1,m+2); result_null.multiply(1.0, *dJndp, t1); // compute f_p^T*[C D E] NOX::Abstract::MultiVector::DenseMatrix t2(1,m+2); result_x.multiply(1.0, *dfdp, t2); // compute f_p^T*u double fptu = uVector->innerProduct((*dfdp)[0]); // Fill coefficient arrays double M[9]; M[0] = st; M[1] = -e; M[2] = t1(0,m+1) + t2(0,m+1); M[3] = 0.0; M[4] = st; M[5] = fptu; M[6] = -b; M[7] = -d; M[8] = t1(0,m) + t2(0,m); // Compute RHS double *R = new double[3*m]; for (int i=0; i<m; i++) { R[3*i] = tmp_mat_1(0,i); R[3*i+1] = tmp_mat_2(0,i); R[3*i+2] = result_param(0,i) - t1(0,i) - t2(0,i); } // Solve M*P = R int three = 3; int piv[3]; int info; Teuchos::LAPACK<int,double> L; L.GESV(three, m, M, three, piv, R, three, &info); if (info != 0) { globalData->locaErrorCheck->throwError( callingFunction, "Solve of 3x3 coefficient matrix failed!"); return NOX::Abstract::Group::Failed; } NOX::Abstract::MultiVector::DenseMatrix alpha(1,m); NOX::Abstract::MultiVector::DenseMatrix beta(1,m); for (int i=0; i<m; i++) { alpha(0,i) = R[3*i]; beta(0,i) = R[3*i+1]; result_param(0,i) = R[3*i+2]; } // compute A = A + B*z + alpha*u (remember A is a sub-view of result_null) A->update(Teuchos::NO_TRANS, 1.0, *B, result_param, 1.0); A->update(Teuchos::NO_TRANS, 1.0, *uMultiVector, alpha, 1.0); // compute C = C + D*z + alpha*E + beta*u // (remember C is a sub-view of result_x) C->update(Teuchos::NO_TRANS, 1.0, *D, result_param, 1.0); C->update(Teuchos::NO_TRANS, 1.0, *E, alpha, 1.0); C->update(Teuchos::NO_TRANS, 1.0, *uMultiVector, beta, 1.0); delete [] R; return finalStatus; }
// Solves turning point equations via Phipps modified bordering // The first m columns of input_x and input_null store the RHS while // the last column stores df/dp, d(Jn)/dp respectively. Note however // input_param has only m columns (not m+1). result_x, result_null, // are result_param have the same dimensions as their input counterparts NOX::Abstract::Group::ReturnType LOCA::TurningPoint::MooreSpence::PhippsBordering::solveContiguous( Teuchos::ParameterList& params, const NOX::Abstract::MultiVector& input_x, const NOX::Abstract::MultiVector& input_null, const NOX::Abstract::MultiVector::DenseMatrix& input_param, NOX::Abstract::MultiVector& result_x, NOX::Abstract::MultiVector& result_null, NOX::Abstract::MultiVector::DenseMatrix& result_param) const { std::string callingFunction = "LOCA::TurningPoint::MooreSpence::PhippsBordering::solveContiguous()"; NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok; NOX::Abstract::Group::ReturnType status; int m = input_x.numVectors()-2; std::vector<int> index_input(m); std::vector<int> index_input_dp(m+1); std::vector<int> index_null(1); std::vector<int> index_dp(1); for (int i=0; i<m; i++) { index_input[i] = i; index_input_dp[i] = i; } index_input_dp[m] = m; index_dp[0] = m; index_null[0] = m+1; NOX::Abstract::MultiVector::DenseMatrix tmp_mat_1(1, m+1); NOX::Abstract::MultiVector::DenseMatrix tmp_mat_2(1, m+2); // Create view of first m+1 columns of input_x, result_x Teuchos::RCP<NOX::Abstract::MultiVector> input_x_view = input_x.subView(index_input_dp); Teuchos::RCP<NOX::Abstract::MultiVector> result_x_view = result_x.subView(index_input_dp); // verify underlying Jacobian is valid if (!group->isJacobian()) { status = group->computeJacobian(); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); } // Solve |J u||A B| = |F df/dp| // |v^T 0||a b| |0 0 | status = borderedSolver->applyInverse(params, input_x_view.get(), NULL, *result_x_view, tmp_mat_1); 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); double b = tmp_mat_1(0,m); // compute (Jv)_x[A B v] result_x[m+1] = *nullVector; Teuchos::RCP<NOX::Abstract::MultiVector> tmp = result_x.clone(NOX::ShapeCopy); status = group->computeDJnDxaMulti(*nullVector, *JnVector, result_x, *tmp); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // compute (Jv)_x[A B v] - [G d(Jn)/dp 0] tmp->update(-1.0, input_null, 1.0); // verify underlying Jacobian is valid if (!group->isJacobian()) { status = group->computeJacobian(); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); } // Solve |J u||C D E| = |(Jv)_x A - G (Jv)_x B - d(Jv)/dp (Jv)_x v| // |v^T 0||c d e| | 0 0 0 | status = borderedSolver->applyInverse(params, tmp.get(), NULL, result_null, tmp_mat_2); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); Teuchos::RCP<NOX::Abstract::MultiVector> C = result_null.subView(index_input); Teuchos::RCP<NOX::Abstract::MultiVector> D = result_null.subView(index_dp); Teuchos::RCP<NOX::Abstract::MultiVector> E = result_null.subView(index_null); double d = tmp_mat_2(0, m); double e = tmp_mat_2(0, m+1); // Fill coefficient arrays double M[9]; M[0] = s; M[1] = e; M[2] = -tpGroup->lTransNorm((*E)[0]); M[3] = 0.0; M[4] = s; M[5] = tpGroup->lTransNorm(*nullVector); M[6] = b; M[7] = -d; M[8] = tpGroup->lTransNorm((*D)[0]); // compute h + phi^T C tpGroup->lTransNorm(*C, result_param); result_param += input_param; double *R = new double[3*m]; for (int i=0; i<m; i++) { R[3*i] = tmp_mat_1(0,i); R[3*i+1] = -tmp_mat_2(0,i); R[3*i+2] = result_param(0,i); } // Solve M*P = R int three = 3; int piv[3]; int info; Teuchos::LAPACK<int,double> L; L.GESV(three, m, M, three, piv, R, three, &info); if (info != 0) { globalData->locaErrorCheck->throwError( callingFunction, "Solve of 3x3 coefficient matrix failed!"); return NOX::Abstract::Group::Failed; } NOX::Abstract::MultiVector::DenseMatrix alpha(1,m); NOX::Abstract::MultiVector::DenseMatrix beta(1,m); for (int i=0; i<m; i++) { alpha(0,i) = R[3*i]; beta(0,i) = R[3*i+1]; result_param(0,i) = R[3*i+2]; } // compute A = A - B*z + v*alpha (remember A is a sub-view of result_x) A->update(Teuchos::NO_TRANS, -1.0, *B, result_param, 1.0); A->update(Teuchos::NO_TRANS, 1.0, *nullMultiVector, alpha, 1.0); // compute C = -C + d*z - E*alpha + v*beta // (remember C is a sub-view of result_null) C->update(Teuchos::NO_TRANS, 1.0, *D, result_param, -1.0); C->update(Teuchos::NO_TRANS, -1.0, *E, alpha, 1.0); C->update(Teuchos::NO_TRANS, 1.0, *nullMultiVector, beta, 1.0); delete [] R; 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); } } }
// Solves pitchfork equations via Phipps modified bordering // The first m columns of input_x and input_null store the RHS, // column m+1 stores df/dp, d(Jn)/dp, column m+2 stores psi and 0, // and the last column provides space for solving (Jv_x) v. Note however // input_param has only m columns. result_x, result_null, // are result_param have the same dimensions as their input counterparts NOX::Abstract::Group::ReturnType LOCA::Pitchfork::MooreSpence::PhippsBordering::solveContiguous( Teuchos::ParameterList& params, const NOX::Abstract::MultiVector& input_x, const NOX::Abstract::MultiVector& input_null, const NOX::Abstract::MultiVector::DenseMatrix& input_slack, const NOX::Abstract::MultiVector::DenseMatrix& input_param, NOX::Abstract::MultiVector& result_x, NOX::Abstract::MultiVector& result_null, NOX::Abstract::MultiVector::DenseMatrix& result_slack, NOX::Abstract::MultiVector::DenseMatrix& result_param) const { string callingFunction = "LOCA::Pitchfork::MooreSpence::PhippsBordering::solveContiguous()"; NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok; NOX::Abstract::Group::ReturnType status; int m = input_x.numVectors()-3; vector<int> index_input(m); vector<int> index_input_dp(m+2); vector<int> index_null(1); vector<int> index_dp(1); vector<int> index_s(1); for (int i=0; i<m; i++) { index_input[i] = i; index_input_dp[i] = i; } index_input_dp[m] = m; index_input_dp[m+1] = m+1; index_dp[0] = m; index_s[0] = m+1; index_null[0] = m+2; NOX::Abstract::MultiVector::DenseMatrix tmp_mat_1(1, m+2); NOX::Abstract::MultiVector::DenseMatrix tmp_mat_2(1, m+3); // Create view of first m+2 columns of input_x, result_x Teuchos::RCP<NOX::Abstract::MultiVector> input_x_view = input_x.subView(index_input_dp); Teuchos::RCP<NOX::Abstract::MultiVector> result_x_view = result_x.subView(index_input_dp); // verify underlying Jacobian is valid if (!group->isJacobian()) { status = group->computeJacobian(); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); } // Solve |J u||A B C| = |F df/dp psi| // |v^T 0||a b c| |0 0 0 | status = borderedSolver->applyInverse(params, input_x_view.get(), NULL, *result_x_view, tmp_mat_1); 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); Teuchos::RCP<NOX::Abstract::MultiVector> C = result_x.subView(index_s); double b = tmp_mat_1(0,m); double c = tmp_mat_1(0,m+1); // compute (Jv)_x[A B C v] result_x[m+2] = *nullVector; Teuchos::RCP<NOX::Abstract::MultiVector> tmp = result_x.clone(NOX::ShapeCopy); status = group->computeDJnDxaMulti(*nullVector, *JnVector, result_x, *tmp); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); // compute [G d(Jn)/dp 0 0] - (Jv)_x[A B C v] tmp->update(1.0, input_null, -1.0); // verify underlying Jacobian is valid if (!group->isJacobian()) { status = group->computeJacobian(); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); } // Solve |J u||D E K L| = |G-(Jv)_xA d(Jv)/dp-(Jv)_xB -(Jv)_xC -(Jv)_xv| // |v^T 0||d e k l| | 0 0 0 0 | status = borderedSolver->applyInverse(params, tmp.get(), NULL, result_null, tmp_mat_2); finalStatus = globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus, callingFunction); Teuchos::RCP<NOX::Abstract::MultiVector> D = result_null.subView(index_input); Teuchos::RCP<NOX::Abstract::MultiVector> E = result_null.subView(index_dp); Teuchos::RCP<NOX::Abstract::MultiVector> K = result_null.subView(index_s); Teuchos::RCP<NOX::Abstract::MultiVector> L = result_null.subView(index_null); double e = tmp_mat_2(0, m); double k = tmp_mat_2(0, m+1); double l = tmp_mat_2(0, m+2); double ltE = pfGroup->lTransNorm((*E)[0]); double ltK = pfGroup->lTransNorm((*K)[0]); double ltL = pfGroup->lTransNorm((*L)[0]); double ltv = pfGroup->lTransNorm(*nullVector); double ipv = group->innerProduct(*nullVector, *asymVector); double ipB = group->innerProduct((*B)[0], *asymVector); double ipC = group->innerProduct((*C)[0], *asymVector); // Fill coefficient arrays double M[16]; M[0] = sigma; M[1] = -l; M[2] = ipv; M[3] = ltL; M[4] = 0.0; M[5] = sigma; M[6] = 0.0; M[7] = ltv; M[8] = b; M[9] = e; M[10] = -ipB; M[11] = -ltE; M[12] = c; M[13] = k; M[14] = -ipC; M[15] = -ltK; // compute s - <A,psi> NOX::Abstract::MultiVector::DenseMatrix tmp_mat_3(1, m); group->innerProduct(*asymMultiVector, *A, tmp_mat_3); tmp_mat_3 -= input_slack; tmp_mat_3.scale(-1.0); // compute h - phi^T D NOX::Abstract::MultiVector::DenseMatrix tmp_mat_4(1, m); pfGroup->lTransNorm(*D, tmp_mat_4); tmp_mat_4 -= input_param; tmp_mat_4.scale(-1.0); double *R = new double[4*m]; for (int i=0; i<m; i++) { R[4*i] = tmp_mat_1(0,i); R[4*i+1] = tmp_mat_2(0,i); R[4*i+2] = tmp_mat_3(0,i); R[4*i+3] = tmp_mat_4(0,i); } // Solve M*P = R int piv[4]; int info; Teuchos::LAPACK<int,double> dlapack; dlapack.GESV(4, m, M, 4, piv, R, 4, &info); if (info != 0) { globalData->locaErrorCheck->throwError( callingFunction, "Solve of 4x4 coefficient matrix failed!"); return NOX::Abstract::Group::Failed; } NOX::Abstract::MultiVector::DenseMatrix alpha(1,m); NOX::Abstract::MultiVector::DenseMatrix beta(1,m); for (int i=0; i<m; i++) { alpha(0,i) = R[4*i]; beta(0,i) = R[4*i+1]; result_param(0,i) = R[4*i+2]; result_slack(0,i) = R[4*i+3]; } // compute A = A - B*z -C*w + v*alpha (remember A is a sub-view of result_x) A->update(Teuchos::NO_TRANS, -1.0, *B, result_param, 1.0); A->update(Teuchos::NO_TRANS, -1.0, *C, result_slack, 1.0); A->update(Teuchos::NO_TRANS, 1.0, *nullMultiVector, alpha, 1.0); // compute D = D - E*z - K*w + L*alpha + v*beta // (remember D is a sub-view of result_null) D->update(Teuchos::NO_TRANS, -1.0, *E, result_param, 1.0); D->update(Teuchos::NO_TRANS, -1.0, *K, result_slack, 1.0); D->update(Teuchos::NO_TRANS, 1.0, *L, alpha, 1.0); D->update(Teuchos::NO_TRANS, 1.0, *nullMultiVector, beta, 1.0); delete [] R; return finalStatus; }