void DiagonalROME<Scalar>::setDiagonalBarVector( const RCP<const Thyra::VectorBase<Scalar> > &diag_bar) { typedef Teuchos::ScalarTraits<Scalar> ST; using Teuchos::rcp_dynamic_cast; using Thyra::createMember; using Thyra::ele_wise_divide; using Thyra::V_S; diag_bar_ = diag_bar.assert_not_null(); // Reset the scalar product for p_space! RCP<Thyra::VectorBase<Scalar> > s_bar = createMember<Scalar>(p_space_); // s_bar[i] = diag[i] / diag_bar[i] V_S( s_bar.ptr(), ST::zero() ); ele_wise_divide( ST::one(), *diag_, *diag_bar_, s_bar.ptr() ); s_bar_ = s_bar; const RCP<Thyra::ScalarProdVectorSpaceBase<Scalar> > sp_p_space = rcp_dynamic_cast<Thyra::ScalarProdVectorSpaceBase<Scalar> >(p_space_, true); //sp_p_space->setScalarProd(diagonalScalarProd<Scalar>(s_bar_)); }
bool sillyCgSolve( const Thyra::LinearOpBase<Scalar> &A, const Thyra::VectorBase<Scalar> &b, const int maxNumIters, const typename Teuchos::ScalarTraits<Scalar>::magnitudeType tolerance, const Teuchos::Ptr<Thyra::VectorBase<Scalar> > &x, std::ostream &out ) { // Create some typedefs and some other stuff to make the code cleaner typedef Teuchos::ScalarTraits<Scalar> ST; typedef typename ST::magnitudeType ScalarMag; const Scalar one = ST::one(), zero = ST::zero(); using Teuchos::as; using Teuchos::RCP; using Thyra::VectorSpaceBase; using Thyra::VectorBase; using Thyra::NOTRANS; using Thyra::V_V; using Thyra::apply; // Validate input THYRA_ASSERT_LINEAR_OP_VEC_APPLY_SPACES("sillyCgSolve()", A, Thyra::NOTRANS, *x, &b); Teuchos::EVerbosityLevel vl = Teuchos::VERB_MEDIUM; out << "\nStarting CG solver ...\n" << std::scientific << "\ndescribe A:\n"<<describe(A, vl) << "\ndescribe b:\n"<<describe(b, vl)<<"\ndescribe x:\n"<<describe(*x, vl)<<"\n"; // Initialization const RCP<const VectorSpaceBase<Scalar> > space = A.domain(); const RCP<VectorBase<Scalar> > r = createMember(space); // r = -A*x + b V_V(r.ptr(), b); apply<Scalar>(A, NOTRANS, *x, r.ptr(), -one, one); const ScalarMag r0_nrm = norm(*r); if (r0_nrm==zero) return true; const RCP<VectorBase<Scalar> > p = createMember(space), q = createMember(space); Scalar rho_old = -one; // Perform the iterations for( int iter = 0; iter <= maxNumIters; ++iter ) { // Check convergence and output iteration const ScalarMag r_nrm = norm(*r); const bool isConverged = r_nrm/r0_nrm <= tolerance; if( iter%(maxNumIters/10+1) == 0 || iter == maxNumIters || isConverged ) { out << "Iter = " << iter << ", ||b-A*x||/||b-A*x0|| = " << (r_nrm/r0_nrm) << std::endl; if( r_nrm/r0_nrm < tolerance ) return true; // Success! } // Compute iteration const Scalar rho = inner(*r, *r); // <r,r> -> rho if (iter==0) V_V(p.ptr(), *r); // r -> p (iter == 0) else Vp_V( p.ptr(), *r, rho/rho_old ); // r+(rho/rho_old)*p -> p (iter > 0) apply<Scalar>(A, NOTRANS, *p, q.ptr()); // A*p -> q const Scalar alpha = rho/inner(*p, *q); // rho/<p,q> -> alpha Vp_StV( x, +alpha, *p ); // +alpha*p + x -> x Vp_StV( r.ptr(), -alpha, *q ); // -alpha*q + r -> r rho_old = rho; // rho -> rho_old (for next iter) } return false; // Failure } // end sillyCgSolve
void ImplicitBDFStepperRampingStepControl<Scalar>::initialize( const StepperBase<Scalar>& stepper) { // Initialize can be called from the stepper when setInitialCondition // is called. using Teuchos::as; typedef Teuchos::ScalarTraits<Scalar> ST; using Thyra::createMember; // Set initial time: TimeRange<Scalar> stepperRange = stepper.getTimeRange(); TEUCHOS_TEST_FOR_EXCEPTION( !stepperRange.isValid(), std::logic_error, "Error, Stepper does not have valid time range for initialization " "of ImplicitBDFStepperRampingStepControl!\n"); if (is_null(parameterList_)) { RCP<Teuchos::ParameterList> emptyParameterList = Teuchos::rcp(new Teuchos::ParameterList); this->setParameterList(emptyParameterList); } if (is_null(errWtVecCalc_)) { RCP<ImplicitBDFStepperErrWtVecCalc<Scalar> > IBDFErrWtVecCalc = rcp(new ImplicitBDFStepperErrWtVecCalc<Scalar>()); errWtVecCalc_ = IBDFErrWtVecCalc; } stepControlState_ = UNINITIALIZED; requestedStepSize_ = Scalar(-1.0); currentStepSize_ = initialStepSize_; currentOrder_ = 1; nextStepSize_ = initialStepSize_; nextOrder_ = 1; numberOfSteps_ = 0; totalNumberOfFailedSteps_ = 0; countOfConstantStepsAfterFailure_ = 0; if (is_null(delta_)) { delta_ = createMember(stepper.get_x_space()); } if (is_null(errWtVec_)) { errWtVec_ = createMember(stepper.get_x_space()); } V_S(delta_.ptr(),ST::zero()); if ( doOutput_(Teuchos::VERB_HIGH) ) { RCP<Teuchos::FancyOStream> out = this->getOStream(); Teuchos::OSTab ostab(out,1,"initialize"); *out << "currentOrder_ = " << currentOrder_ << std::endl; *out << "numberOfSteps_ = " << numberOfSteps_ << std::endl; } setStepControlState_(BEFORE_FIRST_STEP); }
void tLSCIntegrationTest::loadStableSystem() { Epetra_CrsMatrix *F=0, *B=0, *Bt=0,*Qu=0; F=0; B=0; Bt=0; Qu=0; // read in stable discretization TEST_FOR_EXCEPT(EpetraExt::MatrixMarketFileToCrsMatrix("./data/lsc_F_2.mm",*velMap_,*velMap_,*velMap_,F)); TEST_FOR_EXCEPT(EpetraExt::MatrixMarketFileToCrsMatrix("./data/lsc_B_2.mm",*prsMap_,*prsMap_,*velMap_,B)); TEST_FOR_EXCEPT(EpetraExt::MatrixMarketFileToCrsMatrix("./data/lsc_Bt_2.mm",*velMap_,*velMap_,*prsMap_,Bt)); TEST_FOR_EXCEPT(EpetraExt::MatrixMarketFileToCrsMatrix("./data/lsc_Qu_2.mm",*velMap_,*velMap_,*velMap_,Qu)); // set stable matrix pointers sF_ = rcp(F); sB_ = rcp(B); sBt_ = rcp(Bt); sQu_ = rcp(Qu); Teko::LinearOp C; Teko::LinearOp tA_ = Teko::block2x2<double>(epetraLinearOp(sF_),epetraLinearOp(sBt_),epetraLinearOp(sB_),C,"A"); sA_ = rcp(new Teko::Epetra::EpetraOperatorWrapper(tA_)); // build an exporter to work around issue with MMFileToVector Epetra_Export exporter(*fullMap_,sA_->OperatorRangeMap()); // read in RHS vector { Epetra_Vector *vfull=0, *temp=0; // read in rhs file TEST_FOR_EXCEPT(EpetraExt::MatrixMarketFileToVector("./data/lsc_rhs.mm",*fullMap_,vfull)); // MMFileToVector is immplemented incompletely...thats why an exporter is used temp = new Epetra_Vector(sA_->OperatorRangeMap()); temp->Export(*vfull,exporter,Insert); rhs_ = rcp(temp); delete vfull; } // read in solution vector { Epetra_Vector *vfull=0, *temp=0; // read in exact solution file TEST_FOR_EXCEPT(EpetraExt::MatrixMarketFileToVector("./data/lsc_exact_2.mm",*fullMap_,vfull)); // MMFileToVector is immplemented incompletely...thats why an exporter is used temp = new Epetra_Vector(sA_->OperatorRangeMap()); temp->Export(*vfull,exporter,Insert); sExact_ = rcp(temp); delete vfull; } }
const Teuchos::RCP<TriKota::DiagonalROME<Scalar> > createModel( const int globalDim, const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &g_offset ) { using Teuchos::RCP; const RCP<const Teuchos::Comm<Thyra::Ordinal> > comm = Teuchos::DefaultComm<Thyra::Ordinal>::getComm(); const int numProcs = comm->getSize(); TEUCHOS_TEST_FOR_EXCEPT_MSG( numProcs > globalDim, "Error, the number of processors can not be greater than the global" " dimension of the vectors!." ); const int localDim = globalDim / numProcs; const int localDimRemainder = globalDim % numProcs; TEUCHOS_TEST_FOR_EXCEPT_MSG( localDimRemainder != 0, "Error, the number of processors must divide into the global number" " of elements exactly for now!." ); const RCP<TriKota::DiagonalROME<Scalar> > model = Teuchos::rcp(new TriKota::DiagonalROME<Scalar>(localDim)); const RCP<const Thyra::VectorSpaceBase<Scalar> > p_space = model->get_p_space(0); const RCP<Thyra::VectorBase<Scalar> > ps = createMember(p_space); const Scalar ps_val = 2.0; Thyra::V_S(ps.ptr(), ps_val); model->setSolutionVector(ps); model->setScalarOffset(g_offset); return model; }
void DefaultPolyLineSearchPointEvaluator<Scalar>::computePoint( const ScalarMag &alpha, const Ptr<Thyra::VectorBase<Scalar> > &p ) const { typedef ScalarTraits<Scalar> ST; using Teuchos::as; using Thyra::V_V; using Thyra::Vp_StV; V_V( p, *vecs_[0] ); if (alpha != ST::zero()) { ScalarMag alpha_i = alpha; const int n = vecs_.size(); for (int i = 1; i < n; ++i, alpha_i *= alpha) { Vp_StV(p, alpha_i, *vecs_[i]); } } }
void ExplicitModelEvaluator<Scalar>:: buildInverseMassMatrix() const { typedef Thyra::ModelEvaluatorBase MEB; using Teuchos::RCP; using Thyra::createMember; RCP<const Thyra::ModelEvaluator<Scalar> > me = this->getUnderlyingModel(); // first allocate space for the mass matrix RCP<Thyra::LinearOpBase<Scalar> > mass = me->create_W_op(); // intialize a zero to get rid of the x-dot if(zero_==Teuchos::null) { zero_ = Thyra::createMember(*me->get_x_space()); Thyra::assign(zero_.ptr(),0.0); } // request only the mass matrix from the physics // Model evaluator builds: alpha*u_dot + beta*F(u) = 0 MEB::InArgs<Scalar> inArgs = me->createInArgs(); inArgs.set_x(createMember(me->get_x_space())); inArgs.set_x_dot(zero_); inArgs.set_alpha(-1.0); inArgs.set_beta(0.0); // set the one time beta to ensure dirichlet conditions // are correctly included in the mass matrix: do it for // both epetra and Tpetra. If a panzer model evaluator has // not been passed in...oh well you get what you asked for! if(panzerModel_!=Teuchos::null) panzerModel_->setOneTimeDirichletBeta(-1.0); else if(panzerEpetraModel_!=Teuchos::null) panzerEpetraModel_->setOneTimeDirichletBeta(-1.0); // set only the mass matrix MEB::OutArgs<Scalar> outArgs = me->createOutArgs(); outArgs.set_W_op(mass); // this will fill the mass matrix operator me->evalModel(inArgs,outArgs); if(!massLumping_) { invMassMatrix_ = Thyra::inverse<Scalar>(*me->get_W_factory(),mass); } else { // build lumped mass matrix (assumes all positive mass entries, does a simple sum) Teuchos::RCP<Thyra::VectorBase<Scalar> > ones = Thyra::createMember(*mass->domain()); Thyra::assign(ones.ptr(),1.0); RCP<Thyra::VectorBase<Scalar> > invLumpMass = Thyra::createMember(*mass->range()); Thyra::apply(*mass,Thyra::NOTRANS,*ones,invLumpMass.ptr()); Thyra::reciprocal(*invLumpMass,invLumpMass.ptr()); invMassMatrix_ = Thyra::diagonal(invLumpMass); } }
DiagonalROME<Scalar>::DiagonalROME( const int localDim, const RCP<const Teuchos::Comm<Thyra::Ordinal> > &comm ) :Np_(1), Ng_(1), comm_(comm), localDim_(localDim), nonlinearTermFactor_(0.0), g_offset_(0.0) { typedef Teuchos::ScalarTraits<Scalar> ST; using Thyra::createMember; TEUCHOS_ASSERT( localDim > 0 ); // Get the comm if (is_null(comm_)) { comm_ = Teuchos::DefaultComm<Thyra::Ordinal>::getComm(); } // Locally replicated space for g g_space_ = Thyra::locallyReplicatedDefaultSpmdVectorSpace<Scalar>(comm_, 1); // Distributed space for p p_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(comm_, localDim, -1); // Default solution const RCP<Thyra::VectorBase<Scalar> > ps = createMember<Scalar>(p_space_); V_S(ps.ptr(), ST::zero()); ps_ = ps; // Default diagonal const RCP<Thyra::VectorBase<Scalar> > diag = createMember<Scalar>(p_space_); V_S(diag.ptr(), ST::one()); diag_ = diag; diag_bar_ = diag; // Default inner product const RCP<Thyra::VectorBase<Scalar> > s_bar = createMember<Scalar>(p_space_); V_S(s_bar.ptr(), ST::one()); s_bar_ = s_bar; // Default response offset g_offset_ = ST::zero(); }
bool DefaultBlockedTriangularLinearOpWithSolve<Scalar>::opSupportedImpl( EOpTransp M_trans ) const { using Thyra::opSupported; assertBlockFillIsActive(false); for ( int k = 0; k < numDiagBlocks_; ++k ) { if ( !opSupported(*diagonalBlocks_[k].getConstObj(),M_trans) ) return false; } return true; // ToDo: To be safe we really should do a collective reduction of all // clusters of processes. However, for the typical use case, every block // will return the same info and we should be safe! }
bool DefaultBlockedTriangularLinearOpWithSolve<Scalar>::solveSupportsSolveMeasureTypeImpl( EOpTransp M_trans, const SolveMeasureType& solveMeasureType ) const { using Thyra::solveSupportsSolveMeasureType; assertBlockFillIsActive(false); for ( int k = 0; k < numDiagBlocks_; ++k ) { if ( !solveSupportsSolveMeasureType( *diagonalBlocks_[k].getConstObj(), M_trans, solveMeasureType ) ) { return false; } } return true; }
Simple2DModelEvaluator<Scalar>::Simple2DModelEvaluator() : x_space_(Thyra::defaultSpmdVectorSpace<Scalar>(2)), f_space_(x_space_), W_factory_(Thyra::defaultSerialDenseLinearOpWithSolveFactory<Scalar>()), d_(0.0), p_(x_space_->dim(), Teuchos::ScalarTraits<Scalar>::zero()), showGetInvalidArg_(false) { using Teuchos::RCP; using Thyra::VectorBase; using Thyra::createMember; typedef Thyra::ModelEvaluatorBase MEB; typedef Teuchos::ScalarTraits<Scalar> ST; MEB::InArgsSetup<Scalar> inArgs; inArgs.setModelEvalDescription(this->description()); inArgs.setSupports(MEB::IN_ARG_x); prototypeInArgs_ = inArgs; MEB::OutArgsSetup<Scalar> outArgs; outArgs.setModelEvalDescription(this->description()); outArgs.setSupports(MEB::OUT_ARG_f); outArgs.setSupports(MEB::OUT_ARG_W_op); outArgs.setSupports(MEB::OUT_ARG_W_prec); prototypeOutArgs_ = outArgs; nominalValues_ = inArgs; x0_ = createMember(x_space_); V_S(x0_.ptr(), ST::zero()); nominalValues_.set_x(x0_); set_d(10.0); set_p(Teuchos::tuple<Scalar>(2.0, 0.0)()); set_x0(Teuchos::tuple<Scalar>(1.0, 1.0)()); }
NonlinearCGUtils::ESolveReturn NonlinearCG<Scalar>::doSolve( const Ptr<Thyra::VectorBase<Scalar> > &p_inout, const Ptr<ScalarMag> &g_opt_out, const Ptr<const ScalarMag> &g_reduct_tol_in, const Ptr<const ScalarMag> &g_grad_tol_in, const Ptr<const ScalarMag> &alpha_init_in, const Ptr<int> &numIters_out ) { typedef ScalarTraits<Scalar> ST; typedef ScalarTraits<ScalarMag> SMT; using Teuchos::null; using Teuchos::as; using Teuchos::tuple; using Teuchos::rcpFromPtr; using Teuchos::optInArg; using Teuchos::inOutArg; using GlobiPack::computeValue; using GlobiPack::PointEval1D; using Thyra::VectorSpaceBase; using Thyra::VectorBase; using Thyra::MultiVectorBase; using Thyra::scalarProd; using Thyra::createMember; using Thyra::createMembers; using Thyra::get_ele; using Thyra::norm; using Thyra::V_StV; using Thyra::Vt_S; using Thyra::eval_g_DgDp; typedef Thyra::Ordinal Ordinal; typedef Thyra::ModelEvaluatorBase MEB; namespace NCGU = NonlinearCGUtils; using std::max; // Validate input g_opt_out.assert_not_null(); // Set streams const RCP<Teuchos::FancyOStream> out = this->getOStream(); linesearch_->setOStream(out); // Determine what step constants will be computed const bool compute_beta_PR = ( solverType_ == NCGU::NONLINEAR_CG_PR_PLUS || solverType_ == NCGU::NONLINEAR_CG_FR_PR ); const bool compute_beta_HS = (solverType_ == NCGU::NONLINEAR_CG_HS); // // A) Set up the storage for the algorithm // const RCP<DefaultPolyLineSearchPointEvaluator<Scalar> > pointEvaluator = defaultPolyLineSearchPointEvaluator<Scalar>(); const RCP<UnconstrainedOptMeritFunc1D<Scalar> > meritFunc = unconstrainedOptMeritFunc1D<Scalar>( model_, paramIndex_, responseIndex_ ); const RCP<const VectorSpaceBase<Scalar> > p_space = model_->get_p_space(paramIndex_), g_space = model_->get_g_space(responseIndex_); // Stoarge for current iteration RCP<VectorBase<Scalar> > p_k = rcpFromPtr(p_inout), // Current solution for p p_kp1 = createMember(p_space), // Trial point for p (in line search) g_vec = createMember(g_space), // Vector (size 1) form of objective g(p) g_grad_k = createMember(p_space), // Gradient of g DgDp^T d_k = createMember(p_space), // Search direction g_grad_k_diff_km1 = null; // g_grad_k - g_grad_km1 (if needed) // Storage for previous iteration RCP<VectorBase<Scalar> > g_grad_km1 = null, // Will allocate if we need it! d_km1 = null; // Will allocate if we need it! ScalarMag alpha_km1 = SMT::zero(), g_km1 = SMT::zero(), g_grad_km1_inner_g_grad_km1 = SMT::zero(), g_grad_km1_inner_d_km1 = SMT::zero(); if (compute_beta_PR || compute_beta_HS) { g_grad_km1 = createMember(p_space); g_grad_k_diff_km1 = createMember(p_space); } if (compute_beta_HS) { d_km1 = createMember(p_space); } // // B) Do the nonlinear CG iterations // *out << "\nStarting nonlinear CG iterations ...\n"; if (and_conv_tests_) { *out << "\nNOTE: Using AND of convergence tests!\n"; } else { *out << "\nNOTE: Using OR of convergence tests!\n"; } const Scalar alpha_init = ( !is_null(alpha_init_in) ? *alpha_init_in : alpha_init_ ); const Scalar g_reduct_tol = ( !is_null(g_reduct_tol_in) ? *g_reduct_tol_in : g_reduct_tol_ ); const Scalar g_grad_tol = ( !is_null(g_grad_tol_in) ? *g_grad_tol_in : g_grad_tol_ ); const Ordinal globalDim = p_space->dim(); bool foundSolution = false; bool fatalLinesearchFailure = false; bool restart = true; int numConsecutiveLineSearchFailures = 0; int numConsecutiveIters = 0; for (numIters_ = 0; numIters_ < maxIters_; ++numIters_, ++numConsecutiveIters) { Teuchos::OSTab tab(out); *out << "\nNonlinear CG Iteration k = " << numIters_ << "\n"; Teuchos::OSTab tab2(out); // // B.1) Evaluate the point (on first iteration) // eval_g_DgDp( *model_, paramIndex_, *p_k, responseIndex_, numIters_ == 0 ? g_vec.ptr() : null, // Only on first iteration MEB::Derivative<Scalar>(g_grad_k, MEB::DERIV_MV_GRADIENT_FORM) ); const ScalarMag g_k = get_ele(*g_vec, 0); // Above: If numIters_ > 0, then g_vec was updated in meritFunc->eval(...). // // B.2) Check for convergence // // B.2.a) ||g_k - g_km1|| |g_k + g_mag| <= g_reduct_tol bool g_reduct_converged = false; if (numIters_ > 0) { const ScalarMag g_reduct = g_k - g_km1; *out << "\ng_k - g_km1 = "<<g_reduct<<"\n"; const ScalarMag g_reduct_err = SMT::magnitude(g_reduct / SMT::magnitude(g_k + g_mag_)); g_reduct_converged = (g_reduct_err <= g_reduct_tol); *out << "\nCheck convergence: |g_k - g_km1| / |g_k + g_mag| = "<<g_reduct_err << (g_reduct_converged ? " <= " : " > ") << "g_reduct_tol = "<<g_reduct_tol<<"\n"; } // B.2.b) ||g_grad_k|| g_mag <= g_grad_tol const Scalar g_grad_k_inner_g_grad_k = scalarProd<Scalar>(*g_grad_k, *g_grad_k); const ScalarMag norm_g_grad_k = ST::magnitude(ST::squareroot(g_grad_k_inner_g_grad_k)); *out << "\n||g_grad_k|| = "<<norm_g_grad_k << "\n"; const ScalarMag g_grad_err = norm_g_grad_k / g_mag_; const bool g_grad_converged = (g_grad_err <= g_grad_tol); *out << "\nCheck convergence: ||g_grad_k|| / g_mag = "<<g_grad_err << (g_grad_converged ? " <= " : " > ") << "g_grad_tol = "<<g_grad_tol<<"\n"; // B.2.c) Convergence status bool isConverged = false; if (and_conv_tests_) { isConverged = g_reduct_converged && g_grad_converged; } else { isConverged = g_reduct_converged || g_grad_converged; } if (isConverged) { if (numIters_ < minIters_) { *out << "\nnumIters="<<numIters_<<" < minIters="<<minIters_ << ", continuing on!\n"; } else { *out << "\nFound solution, existing algorithm!\n"; foundSolution = true; } } else { *out << "\nNot converged!\n"; } if (foundSolution) { break; } // // B.3) Compute the search direction d_k // if (numConsecutiveIters == globalDim) { *out << "\nThe number of consecutive iterations exceeds the" << " global dimension so restarting!\n"; restart = true; } if (restart) { *out << "\nResetting search direction back to steppest descent!\n"; // d_k = -g_grad_k V_StV( d_k.ptr(), as<Scalar>(-1.0), *g_grad_k ); restart = false; } else { // g_grad_k - g_grad_km1 if (!is_null(g_grad_k_diff_km1)) { V_VmV( g_grad_k_diff_km1.ptr(), *g_grad_k, *g_grad_km1 ); } // beta_FR = inner(g_grad_k, g_grad_k) / inner(g_grad_km1, g_grad_km1) const Scalar beta_FR = g_grad_k_inner_g_grad_k / g_grad_km1_inner_g_grad_km1; *out << "\nbeta_FR = " << beta_FR << "\n"; // NOTE: Computing beta_FR is free so we might as well just do it! // beta_PR = inner(g_grad_k, g_grad_k - g_grad_km1) / // inner(g_grad_km1, g_grad_km1) Scalar beta_PR = ST::zero(); if (compute_beta_PR) { beta_PR = inner(*g_grad_k, *g_grad_k_diff_km1) / g_grad_km1_inner_g_grad_km1; *out << "\nbeta_PR = " << beta_PR << "\n"; } // beta_HS = inner(g_grad_k, g_grad_k - g_grad_km1) / // inner(g_grad_k - g_grad_km1, d_km1) Scalar beta_HS = ST::zero(); if (compute_beta_HS) { beta_HS = inner(*g_grad_k, *g_grad_k_diff_km1) / inner(*g_grad_k_diff_km1, *d_km1); *out << "\nbeta_HS = " << beta_HS << "\n"; } Scalar beta_k = ST::zero(); switch(solverType_) { case NCGU::NONLINEAR_CG_FR: { beta_k = beta_FR; break; } case NCGU::NONLINEAR_CG_PR_PLUS: { beta_k = max(beta_PR, ST::zero()); break; } case NCGU::NONLINEAR_CG_FR_PR: { // NOTE: This does not seem to be working :-( if (numConsecutiveIters < 2) { beta_k = beta_PR; } else if (beta_PR < -beta_FR) beta_k = -beta_FR; else if (ST::magnitude(beta_PR) <= beta_FR) beta_k = beta_PR; else // beta_PR > beta_FR beta_k = beta_FR; } case NCGU::NONLINEAR_CG_HS: { beta_k = beta_HS; break; } default: TEUCHOS_TEST_FOR_EXCEPT(true); } *out << "\nbeta_k = " << beta_k << "\n"; // d_k = beta_k * d_last + -g_grad_k if (!is_null(d_km1)) V_StV( d_k.ptr(), beta_k, *d_km1 ); else Vt_S( d_k.ptr(), beta_k ); Vp_StV( d_k.ptr(), as<Scalar>(-1.0), *g_grad_k ); } // // B.4) Perform the line search // // B.4.a) Compute the initial step length Scalar alpha_k = as<Scalar>(-1.0); if (numIters_ == 0) { alpha_k = alpha_init; } else { if (alpha_reinit_) { alpha_k = alpha_init; } else { alpha_k = alpha_km1; // ToDo: Implement better logic from Nocedal and Wright for selecting // this step length after first iteration! } } // B.4.b) Perform the linesearch (computing updated quantities in process) pointEvaluator->initialize(tuple<RCP<const VectorBase<Scalar> > >(p_k, d_k)()); ScalarMag g_grad_k_inner_d_k = ST::zero(); // Set up the merit function to only compute the value meritFunc->setEvaluationQuantities(pointEvaluator, p_kp1, g_vec, null); PointEval1D<ScalarMag> point_k(ST::zero(), g_k); if (linesearch_->requiresBaseDeriv()) { g_grad_k_inner_d_k = scalarProd(*g_grad_k, *d_k); point_k.Dphi = g_grad_k_inner_d_k; } ScalarMag g_kp1 = computeValue(*meritFunc, alpha_k); // NOTE: The above call updates p_kp1 and g_vec as well! PointEval1D<ScalarMag> point_kp1(alpha_k, g_kp1); const bool linesearchResult = linesearch_->doLineSearch( *meritFunc, point_k, inOutArg(point_kp1), null ); alpha_k = point_kp1.alpha; g_kp1 = point_kp1.phi; if (linesearchResult) { numConsecutiveLineSearchFailures = 0; } else { if (numConsecutiveLineSearchFailures==0) { *out << "\nLine search failure, resetting the search direction!\n"; restart = true; } if (numConsecutiveLineSearchFailures==1) { *out << "\nLine search failure on last iteration also, terminating algorithm!\n"; fatalLinesearchFailure = true; } ++numConsecutiveLineSearchFailures; } if (fatalLinesearchFailure) { break; } // // B.5) Transition to the next iteration // alpha_km1 = alpha_k; g_km1 = g_k; g_grad_km1_inner_g_grad_km1 = g_grad_k_inner_g_grad_k; g_grad_km1_inner_d_km1 = g_grad_k_inner_d_k; std::swap(p_k, p_kp1); if (!is_null(g_grad_km1)) std::swap(g_grad_km1, g_grad_k); if (!is_null(d_km1)) std::swap(d_k, d_km1); #ifdef TEUCHOS_DEBUG // Make sure we compute these correctly before they are used! V_S(g_grad_k.ptr(), ST::nan()); V_S(p_kp1.ptr(), ST::nan()); #endif } // // C) Final clean up // // Get the most current value of g(p) *g_opt_out = get_ele(*g_vec, 0); // Make sure that the final value for p has been copied in! V_V( p_inout, *p_k ); if (!is_null(numIters_out)) { *numIters_out = numIters_; } if (numIters_ == maxIters_) { *out << "\nMax nonlinear CG iterations exceeded!\n"; } if (foundSolution) { return NonlinearCGUtils::SOLVE_SOLUTION_FOUND; } else if(fatalLinesearchFailure) { return NonlinearCGUtils::SOLVE_LINSEARCH_FAILURE; } // Else, the max number of iterations was exceeded return NonlinearCGUtils::SOLVE_MAX_ITERS_EXCEEDED; }
bool runCgSolveExample( const int dim, const Scalar diagScale, const bool symOp, const bool showAllTests, const typename Teuchos::ScalarTraits<Scalar>::magnitudeType tolerance, const int maxNumIters ) { using Teuchos::as; using Teuchos::null; using Teuchos::RCP; using Teuchos::rcp; using Teuchos::OSTab; typedef Teuchos::ScalarTraits<Scalar> ST; using Thyra::multiply; using Thyra::scale; typedef typename ST::magnitudeType ScalarMag; bool success = true; bool result; Teuchos::RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream(); *out << "\n***\n*** Running silly CG solver using scalar type = \'" << ST::name() << "\' ...\n***\n"; Teuchos::Time timer(""); timer.start(true); // // (A) Setup a simple linear system with tridiagonal operator: // // [ a*2 -1 ] // [ -r(1) a*2 -1 ] // A = [ . . . ] // [ -r(n-2) a*2 -1 ] // [ -r(n-1) a*2 ] // // (A.1) Create the tridiagonal matrix operator *out << "\nConstructing tridiagonal matrix A of dimension = " << dim << " and diagonal multiplier = " << diagScale << " ...\n"; Teuchos::Array<Scalar> lower(dim-1), diag(dim), upper(dim-1); const Scalar up = -ST::one(), diagTerm = as<Scalar>(2.0) * diagScale * ST::one(), low = -(symOp ? ST::one() : ST::random()); int k = 0; // First row diag[k] = diagTerm; upper[k] = up; // Middle rows for( k = 1; k < dim - 1; ++k ) { lower[k-1] = low; diag[k] = diagTerm; upper[k] = up; } // Last row lower[k-1] = low; diag[k] = diagTerm; RCP<const Thyra::LinearOpBase<Scalar> > A = rcp(new ExampleTridiagSerialLinearOp<Scalar>(dim, lower, diag, upper)); // (A.2) Testing the linear operator constructed linear operator *out << "\nTesting the constructed linear operator A ...\n"; Thyra::LinearOpTester<Scalar> linearOpTester; linearOpTester.enable_all_tests(false); linearOpTester.check_linear_properties(true); linearOpTester.set_all_error_tol(tolerance); linearOpTester.set_all_warning_tol(1e-2*tolerance); linearOpTester.show_all_tests(showAllTests); result = linearOpTester.check(*A, out.ptr()); if(!result) success = false; // (A.3) Create RHS vector b and set to a random value RCP<Thyra::VectorBase<Scalar> > b = createMember(A->range()); Thyra::seed_randomize<Scalar>(0); Thyra::randomize( -ST::one(), +ST::one(), b.ptr() ); // (A.4) Create LHS vector x and set to zero RCP<Thyra::VectorBase<Scalar> > x = createMember(A->domain()); Thyra::V_S( x.ptr(), ST::zero() ); // (A.5) Create the final linear system if(!symOp) { *out << "\nSetting up normal equations for unsymmetric system A^H*(A*x-b) => new A*x = b ...\n"; // A^H*A RCP<const Thyra::LinearOpBase<Scalar> > AtA = multiply(adjoint(A), A); // A^H*b RCP<Thyra::VectorBase<Scalar> > nb = createMember(AtA->range()); Thyra::apply<Scalar>(*A, Thyra::CONJTRANS, *b, nb.ptr()); A = AtA; b = nb; } // (A.6) Testing the linear operator used with the solve *out << "\nTesting the linear operator used with the solve ...\n"; linearOpTester.check_for_symmetry(true); result = linearOpTester.check(*A, out.ptr()); if(!result) success = false; // // (B) Solve the linear system with the silly CG solver // *out << "\nSolving the linear system with sillyCgSolve(...) ...\n"; { OSTab tab2(out); result = sillyCgSolve(*A, *b, maxNumIters, tolerance, x.ptr(), *out); } if(!result) success = false; // // (C) Check that the linear system was solved to the specified tolerance // RCP<Thyra::VectorBase<Scalar> > r = createMember(A->range()); // r = b Thyra::V_V(r.ptr(), *b); // r = -A*x + r Thyra::apply<Scalar>(*A, Thyra::NOTRANS, *x, r.ptr(), -ST::one(), ST::one()); const ScalarMag r_nrm = Thyra::norm(*r), b_nrm = Thyra::norm(*b); const ScalarMag rel_err = r_nrm/b_nrm, relaxTol = 10.0*tolerance; result = rel_err <= relaxTol; if(!result) success = false; *out << "\nChecking the residual ourselves ...\n"; { OSTab tab(out); *out << "\n||b-A*x||/||b|| = "<<r_nrm<<"/"<<b_nrm<<" = "<<rel_err<<(result?" <= ":" > ") <<"10.0*tolerance = "<<relaxTol<<": "<<(result?"passed":"failed")<<std::endl; } timer.stop(); *out << "\nTotal time = " << timer.totalElapsedTime() << " sec\n"; return success; } // end runCgSolveExample()
int main(int argc, char *argv[]) { using std::endl; typedef double Scalar; typedef double ScalarMag; using Teuchos::describe; using Teuchos::RCP; using Teuchos::rcp; using Teuchos::rcp_implicit_cast; using Teuchos::rcp_dynamic_cast; using Teuchos::as; using Teuchos::ParameterList; using Teuchos::CommandLineProcessor; typedef Teuchos::ParameterList::PrintOptions PLPrintOptions; typedef Thyra::ModelEvaluatorBase MEB; using Thyra::createMember; using Thyra::createMembers; bool success = true; Teuchos::GlobalMPISession mpiSession(&argc,&argv); RCP<Epetra_Comm> epetra_comm; #ifdef HAVE_MPI epetra_comm = rcp( new Epetra_MpiComm(MPI_COMM_WORLD) ); #else epetra_comm = rcp( new Epetra_SerialComm ); #endif // HAVE_MPI RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream(); try { // // A) Read commandline options // CommandLineProcessor clp; clp.throwExceptions(false); clp.addOutputSetupOptions(true); std::string paramsFileName = ""; clp.setOption( "params-file", ¶msFileName, "File name for XML parameters" ); std::string extraParamsString = ""; clp.setOption( "extra-params", &extraParamsString, "Extra XML parameter string" ); Teuchos::EVerbosityLevel verbLevel = Teuchos::VERB_DEFAULT; setVerbosityLevelOption( "verb-level", &verbLevel, "Top-level verbosity level. By default, this gets deincremented as you go deeper into numerical objects.", &clp ); double finalTime = 1.0; clp.setOption( "final-time", &finalTime, "Final time (the inital time)" ); int numTimeSteps = 2; clp.setOption( "num-time-steps", &numTimeSteps, "Number of time steps" ); bool dumpFinalSolutions = false; clp.setOption( "dump-final-solutions", "no-dump-final-solutions", &dumpFinalSolutions, "Determine if the final solutions are dumpped or not." ); double maxStateError = 1e-6; clp.setOption( "max-state-error", &maxStateError, "The maximum allowed error in the integrated state in relation to the exact state solution" ); // ToDo: Read in more parameters CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv); if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return; if ( Teuchos::VERB_DEFAULT == verbLevel ) verbLevel = Teuchos::VERB_LOW; const Teuchos::EVerbosityLevel solnVerbLevel = ( dumpFinalSolutions ? Teuchos::VERB_EXTREME : verbLevel ); // // B) Get the base parameter list that all other parameter lists will be // read from. // RCP<ParameterList> paramList = Teuchos::parameterList(); if (paramsFileName.length()) updateParametersFromXmlFile( paramsFileName, &*paramList ); if (extraParamsString.length()) updateParametersFromXmlString( extraParamsString, &*paramList ); paramList->validateParameters(*getValidParameters()); // // C) Create the Stratimikos linear solver factories. // // Get the linear solve strategy that will be used to solve for the linear // system with the dae's W matrix. Stratimikos::DefaultLinearSolverBuilder daeLinearSolverBuilder; daeLinearSolverBuilder.setParameterList(sublist(paramList,DAELinearSolver_name)); RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > daeLOWSF = createLinearSolveStrategy(daeLinearSolverBuilder); // Get the linear solve strategy that can be used to override the overall // linear system solve Stratimikos::DefaultLinearSolverBuilder overallLinearSolverBuilder; overallLinearSolverBuilder.setParameterList(sublist(paramList,OverallLinearSolver_name)); RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > overallLOWSF = createLinearSolveStrategy(overallLinearSolverBuilder); // // D) Create the underlying EpetraExt::ModelEvaluator // RCP<EpetraExt::DiagonalTransientModel> epetraDaeModel = EpetraExt::diagonalTransientModel( epetra_comm, sublist(paramList,DiagonalTransientModel_name) ); *out <<"\nepetraDaeModel valid options:\n"; epetraDaeModel->getValidParameters()->print( *out, PLPrintOptions().indent(2).showTypes(true).showDoc(true) ); // // E) Create the Thyra-wrapped ModelEvaluator // RCP<Thyra::ModelEvaluator<double> > daeModel = epetraModelEvaluator(epetraDaeModel,daeLOWSF); // // F) Create the TimeDiscretizedBackwardEulerModelEvaluator // MEB::InArgs<Scalar> initCond = daeModel->createInArgs(); initCond.setArgs(daeModel->getNominalValues()); RCP<Thyra::ModelEvaluator<Scalar> > discretizedModel = Rythmos::timeDiscretizedBackwardEulerModelEvaluator<Scalar>( daeModel, initCond, finalTime, numTimeSteps, overallLOWSF ); *out << "\ndiscretizedModel = " << describe(*discretizedModel,verbLevel); // // F) Setup a nonlinear solver and solve the system // // F.1) Setup a nonlinear solver Thyra::DampenedNewtonNonlinearSolver<Scalar> nonlinearSolver; nonlinearSolver.setOStream(out); nonlinearSolver.setVerbLevel(verbLevel); //nonlinearSolver.setParameterList(sublist(paramList,NonlinearSolver_name)); //2007/11/27: rabartl: ToDo: Implement parameter list handling for //DampenedNonlinearSolve so that I can uncomment the above line. nonlinearSolver.setModel(discretizedModel); // F.2) Solve the system RCP<Thyra::VectorBase<Scalar> > x_bar = createMember(discretizedModel->get_x_space()); V_S( x_bar.ptr(), 0.0 ); Thyra::SolveStatus<Scalar> solveStatus = Thyra::solve( nonlinearSolver, &*x_bar ); *out << "\nsolveStatus:\n" << solveStatus; *out << "\nx_bar = " << describe(*x_bar,solnVerbLevel); // // G) Verify that the solution is correct??? // // Check against the end time exact solution. RCP<const Thyra::VectorBase<Scalar> > exact_x_final = Thyra::create_Vector( epetraDaeModel->getExactSolution(finalTime), daeModel->get_x_space() ); RCP<const Thyra::VectorBase<Scalar> > solved_x_final = rcp_dynamic_cast<Thyra::ProductVectorBase<Scalar> >(x_bar,true)->getVectorBlock(numTimeSteps-1); const bool result = Thyra::testRelNormDiffErr( "exact_x_final", *exact_x_final, "solved_x_final", *solved_x_final, "maxStateError", maxStateError, "warningTol", 1.0, // Don't warn &*out, solnVerbLevel ); if (!result) success = false; } TEUCHOS_STANDARD_CATCH_STATEMENTS(true,*out,success); if(success) *out << "\nEnd Result: TEST PASSED" << endl; else *out << "\nEnd Result: TEST FAILED" << endl; return ( success ? 0 : 1 ); } // end main() [Doxygen looks for this!]
bool run_composite_linear_ops_tests( const Teuchos::RCP<const Teuchos::Comm<Thyra::Ordinal> > comm, const int n, const bool useSpmd, const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &tol, const bool dumpAll, Teuchos::FancyOStream *out_arg ) { using Teuchos::as; typedef Teuchos::ScalarTraits<Scalar> ST; typedef typename ST::magnitudeType ScalarMag; typedef Teuchos::ScalarTraits<ScalarMag> STM; using Teuchos::RCP; using Teuchos::rcp; using Teuchos::null; using Teuchos::rcp_const_cast; using Teuchos::rcp_dynamic_cast; using Teuchos::dyn_cast; using Teuchos::OSTab; using Thyra::relErr; using Thyra::passfail; RCP<Teuchos::FancyOStream> out = rcp(new Teuchos::FancyOStream(rcp(out_arg,false))); const Teuchos::EVerbosityLevel verbLevel = dumpAll?Teuchos::VERB_EXTREME:Teuchos::VERB_HIGH; if (nonnull(out)) *out << "\n*** Entering run_composite_linear_ops_tests<"<<ST::name()<<">(...) ...\n"; bool success = true, result; const ScalarMag warning_tol = ScalarMag(1e-2)*tol, error_tol = tol; Thyra::LinearOpTester<Scalar> linearOpTester; linearOpTester.linear_properties_warning_tol(warning_tol); linearOpTester.linear_properties_error_tol(error_tol); linearOpTester.adjoint_warning_tol(warning_tol); linearOpTester.adjoint_error_tol(error_tol); linearOpTester.dump_all(dumpAll); Thyra::LinearOpTester<Scalar> symLinearOpTester(linearOpTester); symLinearOpTester.check_for_symmetry(true); symLinearOpTester.symmetry_warning_tol(STM::squareroot(warning_tol)); symLinearOpTester.symmetry_error_tol(STM::squareroot(error_tol)); RCP<const Thyra::VectorSpaceBase<Scalar> > space; if(useSpmd) space = Thyra::defaultSpmdVectorSpace<Scalar>(comm,n,-1); else space = Thyra::defaultSpmdVectorSpace<Scalar>(n); if (nonnull(out)) *out << "\nUsing a basic vector space described as " << describe(*space,verbLevel) << " ...\n"; if (nonnull(out)) *out << "\nCreating random n x (n/2) multi-vector origA ...\n"; RCP<Thyra::MultiVectorBase<Scalar> > mvOrigA = createMembers(space,n/2,"origA"); Thyra::seed_randomize<Scalar>(0); //RTOpPack::show_spmd_apply_op_dump = true; Thyra::randomize( as<Scalar>(as<Scalar>(-1)*ST::one()), as<Scalar>(as<Scalar>(+1)*ST::one()), mvOrigA.ptr() ); RCP<const Thyra::LinearOpBase<Scalar> > origA = mvOrigA; if (nonnull(out)) *out << "\norigA =\n" << describe(*origA,verbLevel); //RTOpPack::show_spmd_apply_op_dump = false; if (nonnull(out)) *out << "\nTesting origA ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.check(*origA, out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nCreating implicit scaled linear operator A1 = scale(0.5,origA) ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A1 = scale(as<Scalar>(0.5),origA); if (nonnull(out)) *out << "\nA1 =\n" << describe(*A1,verbLevel); if (nonnull(out)) *out << "\nTesting A1 ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.check(*A1,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nTesting that A1.getOp() == origA ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.compare( *dyn_cast<const Thyra::DefaultScaledAdjointLinearOp<Scalar> >(*A1).getOp(), *origA,out.ptr()); if(!result) success = false; { if (nonnull(out)) *out << "\nUnwrapping origA to get non-persisting pointer to origA_1, scalar and transp ...\n"; Scalar scalar; Thyra::EOpTransp transp; const Thyra::LinearOpBase<Scalar> *origA_1 = NULL; unwrap( *origA, &scalar, &transp, &origA_1 ); TEUCHOS_TEST_FOR_EXCEPT( origA_1 == NULL ); if (nonnull(out)) *out << "\nscalar = " << scalar << " == 1 ? "; result = (scalar == ST::one()); if(!result) success = false; if (nonnull(out)) *out << passfail(result) << std::endl; if (nonnull(out)) *out << "\ntransp = " << toString(transp) << " == NOTRANS ? "; result = (transp == Thyra::NOTRANS); if(!result) success = false; if (nonnull(out)) *out << passfail(result) << std::endl; if (nonnull(out)) *out << "\nTesting that origA_1 == origA ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.compare(*origA_1,*origA,out.ptr()); if(!result) success = false; } { if (nonnull(out)) *out << "\nUnwrapping A1 to get non-persisting pointer to origA_2 ...\n"; Scalar scalar; Thyra::EOpTransp transp; const Thyra::LinearOpBase<Scalar> *origA_2 = NULL; unwrap( *A1, &scalar, &transp, &origA_2 ); TEUCHOS_TEST_FOR_EXCEPT( origA_2 == NULL ); if (nonnull(out)) *out << "\nscalar = " << scalar << " == 0.5 ? "; result = (scalar == as<Scalar>(0.5)); if(!result) success = false; if (nonnull(out)) *out << passfail(result) << std::endl; if (nonnull(out)) *out << "\ntransp = " << toString(transp) << " == NOTRANS ? "; result = (transp == Thyra::NOTRANS); if(!result) success = false; if (nonnull(out)) *out << passfail(result) << std::endl; if (nonnull(out)) *out << "\nTesting that origA_2 == origA ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.compare(*origA_2,*origA,out.ptr()); if(!result) success = false; } if (nonnull(out)) *out << "\nCreating implicit scaled linear operator A2 = adjoint(A1) ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A2 = adjoint(A1); if (nonnull(out)) *out << "\nA2 =\n" << describe(*A2,verbLevel); if (nonnull(out)) *out << "\nTesting A2 ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.check(*A2,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nTesting that A2.getOp() == A1 ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.compare(*dyn_cast<const Thyra::DefaultScaledAdjointLinearOp<Scalar> >(*A2).getOp(),*A1,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nCreating implicit scaled, adjoined linear operator A3 = adjoint(scale(2.0,(A2)) ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A3 = adjoint(scale(as<Scalar>(2.0),A2)); if (nonnull(out)) *out << "\nA3 =\n" << describe(*A3,verbLevel); if (nonnull(out)) *out << "\nTesting A3 ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.check(*A3,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nTesting that A3 == origA ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.compare(*A3,*origA,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nCalling all of the rest of the functions for non-const just to test them ...\n"; RCP<Thyra::LinearOpBase<Scalar> > A4 = nonconstScale( as<Scalar>(0.25) ,nonconstAdjoint( nonconstTranspose( nonconstAdjoint( nonconstScaleAndAdjoint( as<Scalar>(4.0) ,Thyra::TRANS ,Teuchos::rcp_const_cast<Thyra::LinearOpBase<Scalar> >(origA) ) ) ) ) ); if(!ST::isComplex) A4 = nonconstTranspose(nonconstAdjoint(A4)); // Should result in CONJ if (nonnull(out)) *out << "\nA4 =\n" << describe(*A4,verbLevel); if (nonnull(out)) *out << "\nTesting A4 ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.check(*A4,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nCalling all of the rest of the functions for const just to test them ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A5 = scale( as<Scalar>(0.25) ,adjoint( transpose( adjoint( scaleAndAdjoint( as<Scalar>(4.0) ,Thyra::TRANS ,origA ) ) ) ) ); if(!ST::isComplex) A5 = transpose(adjoint(A5)); // Should result in CONJ if (nonnull(out)) *out << "\nA5 =\n" << describe(*A5,verbLevel); if (nonnull(out)) *out << "\nTesting A5 ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.check(*A5,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nCreating a multiplied operator A6 = origA^H*A1 ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A6 = multiply(adjoint(origA),A1); if (nonnull(out)) *out << "\nA6 =\n" << describe(*A6,verbLevel); if (nonnull(out)) *out << "\nTesting A6 ...\n"; Thyra::seed_randomize<Scalar>(0); result = symLinearOpTester.check(*A6,out.ptr()); if(!result) success = false; // Note that testing the symmetry above helps to check the transpose mode // against the non-transpose mode! #ifdef TEUCHOS_DEBUG if (nonnull(out)) *out << "\nCreating an invalid multiplied operator A6b = origA*origA (should throw an exception) ...\n\n"; try { RCP<const Thyra::LinearOpBase<Scalar> > A6b = multiply(origA,origA); result = true; } TEUCHOS_STANDARD_CATCH_STATEMENTS(true,out.get()?*out:std::cerr,result) if (nonnull(out)) *out << "\nCaught expected exception : " << (result?"failed\n":"passed\n"); if(result) success = false; #endif // TEUCHOS_DEBUG if (nonnull(out)) *out << "\nCreating a non-const multiplied operator A7 = origA^H*A1 ...\n"; RCP<Thyra::LinearOpBase<Scalar> > A7 = nonconstMultiply( rcp_const_cast<Thyra::LinearOpBase<Scalar> >(adjoint(origA)) ,rcp_const_cast<Thyra::LinearOpBase<Scalar> >(A1) ); if (nonnull(out)) *out << "\nA7 =\n" << describe(*A7,verbLevel); if (nonnull(out)) *out << "\nTesting A7 ...\n"; Thyra::seed_randomize<Scalar>(0); result = symLinearOpTester.check(*A7,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nCreating an added operator A8 = origA + A1 ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A8 = add(origA,A1); if (nonnull(out)) *out << "\nA8 =\n" << describe(*A8,verbLevel); if (nonnull(out)) *out << "\nTesting A8 ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.check(*A8,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nCreating a symmetric subtracted operator A8b = A6 + adjoint(origA)*origA ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A8b = subtract(A6,multiply(adjoint(origA),origA)); if (nonnull(out)) *out << "\nA8b =\n" << describe(*A8b,verbLevel); if (nonnull(out)) *out << "\nTesting A8b ...\n"; Thyra::seed_randomize<Scalar>(0); result = symLinearOpTester.check(*A8b,out.ptr()); if(!result) success = false; #ifdef TEUCHOS_DEBUG if (nonnull(out)) *out << "\nCreating an invalid added operator A8c = origA + adjoint(origA) (should throw an exception) ...\n\n"; try { RCP<const Thyra::LinearOpBase<Scalar> > A8c = add(origA,adjoint(origA)); result = true; } TEUCHOS_STANDARD_CATCH_STATEMENTS(true,out.get()?*out:std::cerr,result) if (nonnull(out)) *out << "\nCaught expected exception : " << (result?"failed\n":"passed\n"); if(result) success = false; #endif // TEUCHOS_DEBUG RCP<const Thyra::LinearOpBase<Scalar> > nullOp = null; if (nonnull(out)) *out << "\nCreating a blocked 2x2 linear operator A9 = [ A6, A1^H; A1, null ] ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A9 = Thyra::block2x2<Scalar>( A6, adjoint(A1) ,A1, nullOp ); if (nonnull(out)) *out << "\nA9 =\n" << describe(*A9,verbLevel); if (nonnull(out)) *out << "\nTesting A9 ...\n"; Thyra::seed_randomize<Scalar>(0); result = symLinearOpTester.check(*A9,out.ptr()); if(!result) success = false; // Note that testing the symmetry above helps to check the transpose mode // against the non-transpose mode! if (nonnull(out)) *out << "\nCreating a blocked 2x2 linear operator A9_a = [ A6, A1^H; A1, null ] using pre-formed range and domain product spaces ...\n"; RCP<Thyra::PhysicallyBlockedLinearOpBase<Scalar> > A9_a = rcp(new Thyra::DefaultBlockedLinearOp<Scalar>()); A9_a->beginBlockFill( rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(A9,true)->productRange() ,rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(A9,true)->productDomain() ); A9_a->setBlock(0,0,A6); A9_a->setBlock(0,1,adjoint(A1)); A9_a->setBlock(1,0,A1); A9_a->endBlockFill(); if (nonnull(out)) *out << "\nA9_a =\n" << describe(*A9_a,verbLevel); if (nonnull(out)) *out << "\nTesting A9_a ...\n"; Thyra::seed_randomize<Scalar>(0); result = symLinearOpTester.check(*A9_a,out.ptr()); if(!result) success = false; // Note that testing the symmetry above helps to check the transpose mode // against the non-transpose mode! if (nonnull(out)) *out << "\nComparing A9 == A9_a ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.compare(*A9,*A9_a,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nCreating a blocked 2x2 linear operator A9_b = [ A6, A1^H; A1, null ] using flexible fill ...\n"; RCP<Thyra::PhysicallyBlockedLinearOpBase<Scalar> > A9_b = rcp(new Thyra::DefaultBlockedLinearOp<Scalar>()); A9_b->beginBlockFill(); A9_b->setBlock(0,0,A6); A9_b->setBlock(0,1,adjoint(A1)); A9_b->setBlock(1,0,A1); A9_b->endBlockFill(); if (nonnull(out)) *out << "\nA9_b =\n" << describe(*A9_b,verbLevel); if (nonnull(out)) *out << "\nTesting A9_b ...\n"; Thyra::seed_randomize<Scalar>(0); result = symLinearOpTester.check(*A9_b,out.ptr()); if(!result) success = false; // Note that testing the symmetry above helps to check the transpose mode // against the non-transpose mode! if (nonnull(out)) *out << "\nComparing A9 == A9_b ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.compare(*A9,*A9_b,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nCreating a blocked 2x2 linear operator A9a = [ null, A1^H; A1, null ] ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A9a = Thyra::block2x2<Scalar>( nullOp, adjoint(A1), A1, nullOp ); if (nonnull(out)) *out << "\nA9a =\n" << describe(*A9a,verbLevel); if (nonnull(out)) *out << "\nTesting A9a ...\n"; Thyra::seed_randomize<Scalar>(0); result = symLinearOpTester.check(*A9a,out.ptr()); if(!result) success = false; // Note that testing the symmetry above helps to check the transpose mode // against the non-transpose mode! #ifdef TEUCHOS_DEBUG if (nonnull(out)) *out << "\nCreating an invalid blocked 2x2 operator A9b = [ A6, A1^H; A1, A1 ] (should throw an exception) ...\n\n"; try { RCP<const Thyra::LinearOpBase<Scalar> > A9b = Thyra::block2x2<Scalar>( A6, adjoint(A1), A1, A1 ); result = true; } TEUCHOS_STANDARD_CATCH_STATEMENTS(true,out.get()?*out:std::cerr,result) if (nonnull(out)) *out << "\nCaught expected exception : " << (result?"failed\n":"passed\n"); if(result) success = false; #endif // TEUCHOS_DEBUG #ifdef TEUCHOS_DEBUG if (nonnull(out)) *out << "\nCreating an invalid blocked 2x2 operator A9c = [ A1, A1 ; null, null ] (should throw an exception) ...\n\n"; try { RCP<const Thyra::LinearOpBase<Scalar> > A9c = Thyra::block2x2<Scalar>( A1, A1, nullOp, nullOp ); result = true; } TEUCHOS_STANDARD_CATCH_STATEMENTS(true,out.get()?*out:std::cerr,result) if (nonnull(out)) *out << "\nCaught expected exception : " << (result?"failed\n":"passed\n"); if(result) success = false; #endif // TEUCHOS_DEBUG #ifdef TEUCHOS_DEBUG if (nonnull(out)) *out << "\nCreating an invalid blocked 2x2 operator A9d = [ A1, null; A1, null ] (should throw an exception) ...\n\n"; try { RCP<const Thyra::LinearOpBase<Scalar> > A9d = Thyra::block2x2<Scalar>( A1, nullOp, A1, nullOp ); result = true; } TEUCHOS_STANDARD_CATCH_STATEMENTS(true,out.get()?*out:std::cerr,result) if (nonnull(out)) *out << "\nCaught expected exception : " << (result?"failed\n":"passed\n"); if(result) success = false; #endif // TEUCHOS_DEBUG if (nonnull(out)) *out << "\nCreating a blocked 2x1 linear operator A10 = [ A6; A1 ] ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A10 = Thyra::block2x1<Scalar>( A6, A1 ); if (nonnull(out)) *out << "\nA10 =\n" << describe(*A10,verbLevel); if (nonnull(out)) *out << "\nTesting A10 ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.check(*A10,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nCreating a blocked 1x2 linear operator A11 = [ A9, A10 ] ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A11 = Thyra::block1x2<Scalar>( A9, A10 ); if (nonnull(out)) *out << "\nA11 =\n" << describe(*A11,verbLevel); if (nonnull(out)) *out << "\nTesting A11 ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.check(*A11,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nCreating a zero linear operator A12 = 0 (range and domain spaces of origA) ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A12 = Thyra::zero(origA->range(),origA->domain()); if (nonnull(out)) *out << "\nA12 =\n" << describe(*A12,verbLevel); if (nonnull(out)) *out << "\nTesting A12 ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.check(*A12,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nCreating a blocked 2x2 linear operator A13 = [ zero, A1^H; A1, zero ] ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A13 = Thyra::block2x2<Scalar>( Thyra::zero(A1->domain(),A1->domain()), adjoint(A1), A1, Thyra::zero(A1->range(),A1->range()) ); if (nonnull(out)) *out << "\nA13 =\n" << describe(*A13,verbLevel); if (nonnull(out)) *out << "\nComparing A9a == A13 ...\n"; Thyra::seed_randomize<Scalar>(0); result = linearOpTester.compare(*A9a,*A13,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\nCreating a zero linear operator A14 = I (range space of origA) ...\n"; RCP<const Thyra::LinearOpBase<Scalar> > A14 = Thyra::identity(origA->range()); if (nonnull(out)) *out << "\nA14 =\n" << describe(*A14,verbLevel); if (nonnull(out)) *out << "\nTesting A14 ...\n"; Thyra::seed_randomize<Scalar>(0); result = symLinearOpTester.check(*A14,out.ptr()); if(!result) success = false; if (nonnull(out)) *out << "\n*** Leaving run_composite_linear_ops_tests<"<<ST::name()<<">(...) ...\n"; return success; } // end run_composite_linear_ops_tests() [Doxygen looks for this!]
void CubicSplineInterpolator<Scalar>::interpolate( const Array<Scalar> &t_values, typename DataStore<Scalar>::DataStoreVector_t *data_out ) const { using Teuchos::as; using Teuchos::outArg; typedef Teuchos::ScalarTraits<Scalar> ST; TEUCHOS_TEST_FOR_EXCEPTION( nodesSet_ == false, std::logic_error, "Error!, setNodes must be called before interpolate" ); #ifdef HAVE_RYTHMOS_DEBUG // Check that our nodes_ have not changed between the call to setNodes and interpolate assertNodesUnChanged<Scalar>(*nodes_,*nodes_copy_); // Assert that the base interpolator preconditions are satisfied assertBaseInterpolatePreconditions(*nodes_,t_values,data_out); #endif // HAVE_RYTHMOS_DEBUG // Output info const RCP<FancyOStream> out = this->getOStream(); const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel(); Teuchos::OSTab ostab(out,1,"CSI::interpolator"); if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) { *out << "nodes_:" << std::endl; for (Teuchos::Ordinal i=0 ; i<(*nodes_).size() ; ++i) { *out << "nodes_[" << i << "] = " << std::endl; (*nodes_)[i].describe(*out,Teuchos::VERB_EXTREME); } *out << "t_values = " << std::endl; for (Teuchos::Ordinal i=0 ; i<t_values.size() ; ++i) { *out << "t_values[" << i << "] = " << t_values[i] << std::endl; } } data_out->clear(); // Return immediately if no time points are requested ... if (t_values.size() == 0) { return; } if ((*nodes_).size() == 1) { // trivial case of one node. Preconditions assert that t_values[0] == // (*nodes_)[0].time so we can just pass it out DataStore<Scalar> DS((*nodes_)[0]); data_out->push_back(DS); } else { // (*nodes_).size() >= 2 int n = 0; // index into t_values // Loop through all of the time interpolation points in the buffer and // satisfiy all of the requested time points that you find. NOTE: The // loop will be existed once all of the time points are satisified (see // return below). for (Teuchos::Ordinal i=0 ; i < (*nodes_).size()-1; ++i) { const Scalar& ti = (*nodes_)[i].time; const Scalar& tip1 = (*nodes_)[i+1].time; const TimeRange<Scalar> range_i(ti,tip1); // For the interpolation range of [ti,tip1], satisify all of the // requested points in this range. while ( range_i.isInRange(t_values[n]) ) { // First we check for exact node matches: if (compareTimeValues(t_values[n],ti)==0) { DataStore<Scalar> DS((*nodes_)[i]); data_out->push_back(DS); } else if (compareTimeValues(t_values[n],tip1)==0) { DataStore<Scalar> DS((*nodes_)[i+1]); data_out->push_back(DS); } else { if (!splineCoeffComputed_) { computeCubicSplineCoeff<Scalar>(*nodes_,outArg(splineCoeff_)); splineCoeffComputed_ = true; } DataStore<Scalar> DS; RCP<Thyra::VectorBase<Scalar> > x = createMember((*nodes_)[i].x->space()); evaluateCubicSpline<Scalar>( splineCoeff_, i, t_values[n], outArg(*x) ); DS.time = t_values[n]; DS.x = x; DS.accuracy = ST::zero(); data_out->push_back(DS); } // Move to the next user time point to consider! n++; if (n == as<int>(t_values.size())) { // WE ARE ALL DONE! MOVE OUT! return; } } // Move on the the next interpolation time range } } // (*nodes_).size() == 1 }
bool tLSCIntegrationTest::test_withmassStable(int verbosity,std::ostream & os) { Teuchos::ParameterList paramList; solveList(paramList,8); RCP<Teko::InverseFactory> invFact = Teko::invFactoryFromParamList(paramList,"ML"); TEUCHOS_ASSERT(invFact!=Teuchos::null); bool status = false; bool allPassed = true; // load everything loadStableSystem(); // if you get here you automatically pass the first test if(verbosity>=10 ) { os << std::endl << " tLSCIntegrationTest::test_withmassStable: loading system ... " << toString(true) << std::endl; } LinearOp Qu = epetraLinearOp(sQu_); const RCP<Teko::NS::LSCStrategy> strategy = rcp(new Teko::NS::InvLSCStrategy(invFact,Qu)); const RCP<Teko::BlockPreconditionerFactory> precFact = rcp(new Teko::NS::LSCPreconditionerFactory(strategy)); const RCP<Teko::Epetra::EpetraBlockPreconditioner> prec = rcp(new Teko::Epetra::EpetraBlockPreconditioner(precFact)); prec->buildPreconditioner(sA_); // B. Build solver and solve system Epetra_Vector x(sA_->OperatorDomainMap()); x.Scale(0.0); // build Epetra problem Epetra_LinearProblem problem(&*sA_,&x,&*rhs_); // this doesn't take const arguments! AztecOO solver(problem); solver.SetAztecOption(AZ_solver,AZ_gmres); solver.SetAztecOption(AZ_precond,AZ_none); solver.SetAztecOption(AZ_kspace,50); solver.SetAztecOption(AZ_output,AZ_none); solver.SetPrecOperator(&*prec); solver.Iterate(1000,1e-8); // check iteration count status = (solver.NumIters()<=16); if(not status || verbosity>=10 ) { os << std::endl << " tLSCIntegrationTest::test_withmassStable " << toString(status) << ": # of iterations = " << solver.NumIters() << " (should be 16)" << std::endl; } allPassed &= status; // check exact answer (versus IFISS solution) x.Update(-1.0,*sExact_,1.0); // x = x - x* double errnorm,exactnorm,relerr; x.Norm2(&errnorm); sExact_->Norm2(&exactnorm); status = ((relerr = errnorm/exactnorm) <= tolerance_); if(not status || verbosity>=10 ) { os << std::endl << " tLSCIntegrationTest::test_withmassStable " << toString(status) << ": error in solution = " << std::scientific << relerr << " <= " << tolerance_ << std::endl; } allPassed &= status; return allPassed; }
bool tBlockJacobiPreconditionerFactory::test_initializePrec(int verbosity,std::ostream & os) { using Thyra::zero; bool status = false; bool allPassed = true; std::string constrType[3] = { std::string("Static"), std::string("2x2 Static Strategy"), std::string("3x3 Static Strategy") }; // three by three bloock diagonal std::vector<RCP<const Thyra::LinearOpBase<double> > > invD; invD.push_back(invF_); invD.push_back(invC_); invD.push_back(invF_); // allocate new linear operator const RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blkOp = Thyra::defaultBlockedLinearOp<double>(); blkOp->beginBlockFill(3,3); blkOp->setBlock(0,0,F_); blkOp->setBlock(0,1,Bt_); blkOp->setBlock(1,0,B_); blkOp->setBlock(1,1,C_); blkOp->setBlock(1,2,B_); blkOp->setBlock(2,1,Bt_); blkOp->setBlock(2,2,F_); blkOp->endBlockFill(); const RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > invBlkOp = Thyra::defaultBlockedLinearOp<double>(); invBlkOp->beginBlockFill(3,3); invBlkOp->setBlock(0,0,invF_); invBlkOp->setBlock(1,1,invC_); invBlkOp->setBlock(2,2,invF_); invBlkOp->endBlockFill(); // build factory array RCP<JacobiPreconditionerFactory> fact_array[3] = { rcp(new JacobiPreconditionerFactory(invF_,invC_)), rcp(new JacobiPreconditionerFactory(rcp(new StaticInvDiagStrategy(invF_,invC_)))), rcp(new JacobiPreconditionerFactory(rcp(new StaticInvDiagStrategy(invD)))) }; RCP<const Thyra::LinearOpBase<double> > A[3] = { block2x2(F_,Bt_,B_,C_), block2x2(F_,Bt_,B_,C_), blkOp }; // this is what the factory should build RCP<const Thyra::LinearOpBase<double> > invA[3] = { block2x2(invF_,zero(Bt_->range(),Bt_->domain()),zero(B_->range(),B_->domain()),invC_), block2x2(invF_,zero(Bt_->range(),Bt_->domain()),zero(B_->range(),B_->domain()),invC_), invBlkOp }; // test both constructors for(int i=0;i<3;i++) { RCP<const Thyra::LinearOpBase<double> > op; RCP<Thyra::PreconditionerFactoryBase<double> > fact = fact_array[i]; RCP<Thyra::PreconditionerBase<double> > prec = fact->createPrec(); // initialize the preconditioner fact->initializePrec(Thyra::defaultLinearOpSource(A[i]), &*prec); op = prec->getRightPrecOp(); TEST_EQUALITY(op,Teuchos::null, std::endl << " tBlockJacobiPreconditionerFactory::test_initializePrec " << "using \"" << constrType[i] << "\" constructor " << toString(status) << ": Preconditioner \"getRightPrecOp\" is not null (it should be!)"); op = prec->getLeftPrecOp(); TEST_EQUALITY(op,Teuchos::null, std::endl << " tBlockJacobiPreconditionerFactory::test_initializePrec " << "using \"" << constrType[i] << "\" constructor " << toString(status) << ": Preconditioner \"getLeftPrecOp\" is not null (it should be!)"); op = prec->getUnspecifiedPrecOp(); TEST_NOT_EQUAL(op,Teuchos::null, std::endl << " tBlockJacobiPreconditionerFactory::test_initializePrec " << "using \"" << constrType[i] << "\" constructor " << toString(status) << ": Preconditioner \"getUnspecifiedPrecOp\" is null (it should not be!)"); LinearOpTester<double> tester; tester.show_all_tests(true); std::stringstream ss; Teuchos::FancyOStream fos(rcpFromRef(ss)," |||"); const bool result = tester.compare( *invA[i], *op, &fos ); TEST_ASSERT(result, std::endl << " tBlockJacobiPreconditionerFactory::test_initializePrec " << ": Comparing factory generated operator to correct operator"); if(not result || verbosity>=10) os << ss.str(); } return allPassed; }
int exampleImplicitlyComposedLinearOperators( const int n0, const int n1, const int n2, Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel, typename Teuchos::ScalarTraits<Scalar>::magnitudeType errorTol, const bool testAdjoint ) { // Using and other declarations typedef Teuchos::ScalarTraits<Scalar> ST; using Teuchos::as; using Teuchos::RCP; using Teuchos::OSTab; using Thyra::VectorSpaceBase; using Thyra::VectorBase; using Thyra::MultiVectorBase; using Thyra::LinearOpBase; using Thyra::defaultSpmdVectorSpace; using Thyra::randomize; using Thyra::identity; using Thyra::diagonal; using Thyra::multiply; using Thyra::add; using Thyra::subtract; using Thyra::scale; using Thyra::adjoint; using Thyra::block1x2; using Thyra::block2x2; using Thyra::block2x2; out << "\n***" << "\n*** Demonstrating building linear operators for scalar type " << ST::name() << "\n***\n"; OSTab tab(out); // // A) Set up the basic objects and other inputs to build the implicitly // composed linear operators. // // Create serial vector spaces in this case const RCP<const VectorSpaceBase<Scalar> > space0 = defaultSpmdVectorSpace<Scalar>(n0), space1 = defaultSpmdVectorSpace<Scalar>(n1), space2 = defaultSpmdVectorSpace<Scalar>(n2); // Create the component linear operators first as multi-vectors const RCP<MultiVectorBase<Scalar> > mvA = createMembers(space2, n0, "A"), mvB = createMembers(space0, n2, "B"), mvC = createMembers(space0, n0, "C"), mvE = createMembers(space0, n1, "E"), mvF = createMembers(space0, n1, "F"), mvJ = createMembers(space2, n1, "J"), mvK = createMembers(space1, n2, "K"), mvL = createMembers(space2, n1, "L"), mvN = createMembers(space0, n1, "N"), mvP = createMembers(space2, n1, "P"), mvQ = createMembers(space0, n2, "Q"); // Create the vector diagonal for D const RCP<VectorBase<Scalar> > d = createMember(space2); // Get the constants const Scalar one = 1.0, beta = 2.0, gamma = 3.0, eta = 4.0; // Randomize the values in the Multi-Vector randomize( -one, +one, mvA.ptr() ); randomize( -one, +one, mvB.ptr() ); randomize( -one, +one, mvC.ptr() ); randomize( -one, +one, d.ptr() ); randomize( -one, +one, mvE.ptr() ); randomize( -one, +one, mvF.ptr() ); randomize( -one, +one, mvJ.ptr() ); randomize( -one, +one, mvK.ptr() ); randomize( -one, +one, mvL.ptr() ); randomize( -one, +one, mvN.ptr() ); randomize( -one, +one, mvP.ptr() ); randomize( -one, +one, mvQ.ptr() ); // Get the linear operator forms of the basic component linear operators const RCP<const LinearOpBase<Scalar> > A = mvA, B = mvB, C = mvC, E = mvE, F = mvF, J = mvJ, K = mvK, L = mvL, N = mvN, P = mvP, Q = mvQ; out << describe(*A, verbLevel); out << describe(*B, verbLevel); out << describe(*C, verbLevel); out << describe(*E, verbLevel); out << describe(*F, verbLevel); out << describe(*J, verbLevel); out << describe(*K, verbLevel); out << describe(*L, verbLevel); out << describe(*N, verbLevel); out << describe(*P, verbLevel); out << describe(*Q, verbLevel); // // B) Create the composed linear operators // // I const RCP<const LinearOpBase<Scalar> > I = identity(space1, "I"); // D = diag(d) const RCP<const LinearOpBase<Scalar> > D = diagonal(d, "D"); // M00 = [ gama*B*A + C, E + F ] ^H // [ J^H * A, I ] const RCP<const LinearOpBase<Scalar> > M00 = adjoint( block2x2( add( scale(gamma,multiply(B,A)), C ), add( E, F ), multiply(adjoint(J),A), I ), "M00" ); out << "\nM00 = " << describe(*M00, verbLevel); // M01 = beta * [ Q ] // [ K ] const RCP<const LinearOpBase<Scalar> > M01 = scale( beta, block2x1( Q, K ), "M01" ); out << "\nM01 = " << describe(*M01, verbLevel); // M10 = [ L * N^H, eta*P ] const RCP<const LinearOpBase<Scalar> > M10 = block1x2( multiply(L,adjoint(N)), scale(eta,P), "M10" ); out << "\nM10 = " << describe(*M10, verbLevel); // M11 = D - Q^H*Q const RCP<const LinearOpBase<Scalar> > M11 = subtract( D, multiply(adjoint(Q),Q), "M11" ); out << "\nM11 = " << describe(*M11, verbLevel); // M = [ M00, M01 ] // [ M10, M11 ] const RCP<const LinearOpBase<Scalar> > M = block2x2( M00, M01, M10, M11, "M" ); out << "\nM = " << describe(*M, verbLevel); // // C) Test the final composed operator // Thyra::LinearOpTester<Scalar> linearOpTester; linearOpTester.set_all_error_tol(errorTol); linearOpTester.check_adjoint(testAdjoint); if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH)) linearOpTester.show_all_tests(true); if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_EXTREME)) linearOpTester.dump_all(true); const bool result = linearOpTester.check(*M,&out); return result; }
void computeCubicSplineCoeff( const typename DataStore<Scalar>::DataStoreVector_t & data, const Ptr<CubicSplineCoeff<Scalar> > & coeffPtr ) { using Teuchos::outArg; typedef Teuchos::ScalarTraits<Scalar> ST; using Thyra::createMember; TEUCHOS_TEST_FOR_EXCEPTION( (data.size() < 2), std::logic_error, "Error! A minimum of two data points is required for this cubic spline." ); // time data in the DataStoreVector should be unique and sorted Array<Scalar> t; Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > > x_vec, xdot_vec; dataStoreVectorToVector<Scalar>( data, &t, &x_vec, &xdot_vec, NULL ); #ifdef HAVE_RYTHMOS_DEBUG assertTimePointsAreSorted<Scalar>( t ); #endif // HAVE_RYTHMOS_DEBUG // 11/18/08 tscoffe: Question: Should I erase everything in coeffPtr or // re-use what I can? For now, I'll erase and create new each time. CubicSplineCoeff<Scalar>& coeff = *coeffPtr; // If there are only two points, then we do something special and just create // a linear polynomial between the points and return. if (t.size() == 2) { coeff.t.clear(); coeff.a.clear(); coeff.b.clear(); coeff.c.clear(); coeff.d.clear(); coeff.t.reserve(2); coeff.a.reserve(1); coeff.b.reserve(1); coeff.c.reserve(1); coeff.d.reserve(1); coeff.t.push_back(t[0]); coeff.t.push_back(t[1]); coeff.a.push_back(x_vec[0]->clone_v()); coeff.b.push_back(createMember(x_vec[0]->space())); coeff.c.push_back(createMember(x_vec[0]->space())); coeff.d.push_back(createMember(x_vec[0]->space())); Scalar h = coeff.t[1] - coeff.t[0]; V_StVpStV(outArg(*coeff.b[0]),ST::one()/h,*x_vec[1],-ST::one()/h,*x_vec[0]); V_S(outArg(*coeff.c[0]),ST::zero()); V_S(outArg(*coeff.d[0]),ST::zero()); return; } // Data objects we'll need: int n = t.length()-1; // Number of intervals coeff.t.clear(); coeff.t.reserve(n+1); coeff.a.clear(); coeff.a.reserve(n+1); coeff.b.clear(); coeff.b.reserve(n); coeff.c.clear(); coeff.c.reserve(n+1); coeff.d.clear(); coeff.d.reserve(n); Array<Scalar> h(n); Array<RCP<Thyra::VectorBase<Scalar> > > alpha(n), z(n+1); Array<Scalar> l(n+1), mu(n); for (int i=0 ; i<n ; ++i) { coeff.t.push_back(t[i]); coeff.a.push_back(x_vec[i]->clone_v()); coeff.b.push_back(Thyra::createMember(x_vec[0]->space())); coeff.c.push_back(Thyra::createMember(x_vec[0]->space())); coeff.d.push_back(Thyra::createMember(x_vec[0]->space())); alpha[i] = Thyra::createMember(x_vec[0]->space()); z[i] = Thyra::createMember(x_vec[0]->space()); } coeff.a.push_back(x_vec[n]->clone_v()); coeff.t.push_back(t[n]); coeff.c.push_back(Thyra::createMember(x_vec[0]->space())); z[n] = Thyra::createMember(x_vec[0]->space()); Scalar zero = ST::zero(); Scalar one = ST::one(); Scalar two = Scalar(2*ST::one()); Scalar three = Scalar(3*ST::one()); // Algorithm starts here: for (int i=0 ; i<n ; ++i) { h[i] = coeff.t[i+1]-coeff.t[i]; } for (int i=1 ; i<n ; ++i) { V_StVpStV(outArg(*(alpha[i])),three/h[i],*coeff.a[i+1],-3/h[i],*coeff.a[i]); Vp_StV(outArg(*(alpha[i])),-three/h[i-1],*coeff.a[i]); Vp_StV(outArg(*(alpha[i])),+three/h[i-1],*coeff.a[i-1]); } l[0] = one; mu[0] = zero; V_S(outArg(*(z[0])),zero); for (int i=1 ; i<n ; ++i) { l[i] = 2*(coeff.t[i+1]-coeff.t[i-1])-h[i-1]*mu[i-1]; mu[i] = h[i]/l[i]; V_StVpStV(outArg(*(z[i])),one/l[i],*alpha[i],-h[i-1]/l[i],*z[i-1]); } l[n] = one; V_S(outArg(*(z[n])),zero); V_S(outArg(*(coeff.c[n])),zero); for (int j=n-1 ; j >= 0 ; --j) { V_StVpStV(outArg(*(coeff.c[j])),one,*z[j],-mu[j],*coeff.c[j+1]); V_StVpStV(outArg(*(coeff.b[j])),one/h[j],*coeff.a[j+1],-one/h[j],*coeff.a[j]); Vp_StV(outArg(*(coeff.b[j])),-h[j]/three,*coeff.c[j+1]); Vp_StV(outArg(*(coeff.b[j])),-h[j]*two/three,*coeff.c[j]); V_StVpStV(outArg(*(coeff.d[j])),one/(three*h[j]),*coeff.c[j+1],-one/(three*h[j]),*coeff.c[j]); } // Pop the last entry off of a and c to make them the right size. coeff.a.erase(coeff.a.end()-1); coeff.c.erase(coeff.c.end()-1); }
//! Scale a multivector by a constant inline void scale(const double alpha,BlockedMultiVector & x) { MultiVector x_mv = toMultiVector(x); scale(alpha,x_mv); }
int main(int argc, char* argv[]) { using Teuchos::describe; using Teuchos::rcp; using Teuchos::rcp_dynamic_cast; using Teuchos::rcp_const_cast; using Teuchos::RCP; using Teuchos::CommandLineProcessor; using Teuchos::ParameterList; using Teuchos::sublist; using Teuchos::getParametersFromXmlFile; typedef ParameterList::PrintOptions PLPrintOptions; using Thyra::inverse; using Thyra::initializePreconditionedOp; using Thyra::initializeOp; using Thyra::unspecifiedPrec; using Thyra::solve; typedef RCP<const Thyra::LinearOpBase<double> > LinearOpPtr; typedef RCP<Thyra::VectorBase<double> > VectorPtr; bool success = true; bool verbose = true; Teuchos::GlobalMPISession mpiSession(&argc,&argv); Teuchos::RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream(); try { // // Read in options from the command line // CommandLineProcessor clp(false); // Don't throw exceptions const int numVerbLevels = 6; Teuchos::EVerbosityLevel verbLevelValues[] = { Teuchos::VERB_DEFAULT, Teuchos::VERB_NONE, Teuchos::VERB_LOW, Teuchos::VERB_MEDIUM, Teuchos::VERB_HIGH, Teuchos::VERB_EXTREME }; const char* verbLevelNames[] = { "default", "none", "low", "medium", "high", "extreme" }; Teuchos::EVerbosityLevel verbLevel = Teuchos::VERB_MEDIUM; clp.setOption( "verb-level", &verbLevel, numVerbLevels, verbLevelValues, verbLevelNames, "Verbosity level used for all objects." ); std::string matrixFile = "."; clp.setOption( "matrix-file", &matrixFile, "Matrix file." ); std::string paramListFile = ""; clp.setOption( "param-list-file", ¶mListFile, "Parameter list for preconditioner and solver blocks." ); bool showParams = false; clp.setOption( "show-params", "no-show-params", &showParams, "Show the parameter list or not." ); bool testPrecIsLinearOp = true; clp.setOption( "test-prec-is-linear-op", "test-prec-is-linear-op", &testPrecIsLinearOp, "Test if the preconditioner is a linear operator or not." ); double solveTol = 1e-8; clp.setOption( "solve-tol", &solveTol, "Tolerance for the solution to determine success or failure!" ); clp.setDocString( "This example program shows how to use one linear solver (e.g. AztecOO)\n" "as a preconditioner for another iterative solver (e.g. Belos).\n" ); // Note: Use --help on the command line to see the above documentation CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv); if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return; // *out << "\nA) Reading in the matrix ...\n"; // #ifdef HAVE_MPI Epetra_MpiComm comm(MPI_COMM_WORLD); #else Epetra_SerialComm comm; #endif const LinearOpPtr A = readEpetraCrsMatrixFromMatrixMarketAsLinearOp( matrixFile, comm, "A"); *out << "\nA = " << describe(*A,verbLevel) << "\n"; const RCP<ParameterList> paramList = getParametersFromXmlFile(paramListFile); if (showParams) { *out << "\nRead in parameter list:\n\n"; paramList->print(*out, PLPrintOptions().indent(2).showTypes(true)); } // *out << "\nB) Get the preconditioner as a forward solver\n"; // const RCP<ParameterList> precParamList = sublist(paramList, "Preconditioner Solver"); Stratimikos::DefaultLinearSolverBuilder precSolverBuilder; precSolverBuilder.setParameterList(precParamList); const RCP<const Thyra::LinearOpWithSolveFactoryBase<double> > precSolverStrategy = createLinearSolveStrategy(precSolverBuilder); //precSolverStrategy->setVerbLevel(verbLevel); const LinearOpPtr A_inv_prec = inverse<double>(*precSolverStrategy, A, Thyra::SUPPORT_SOLVE_FORWARD_ONLY, Teuchos::null, // Use internal solve criteria Thyra::IGNORE_SOLVE_FAILURE // Ignore solve failures since this is just a prec ); *out << "\nA_inv_prec = " << describe(*A_inv_prec, verbLevel) << "\n"; if (testPrecIsLinearOp) { *out << "\nTest that the preconditioner A_inv_prec is indeed a linear operator.\n"; Thyra::LinearOpTester<double> linearOpTester; linearOpTester.check_adjoint(false); const bool linearOpCheck = linearOpTester.check(*A_inv_prec, out.ptr()); if (!linearOpCheck) { success = false; } } // *out << "\nC) Create the forward solver using the created preconditioner ...\n"; // const RCP<ParameterList> fwdSolverParamList = sublist(paramList, "Forward Solver"); Stratimikos::DefaultLinearSolverBuilder fwdSolverSolverBuilder; fwdSolverSolverBuilder.setParameterList(fwdSolverParamList); const RCP<const Thyra::LinearOpWithSolveFactoryBase<double> > fwdSolverSolverStrategy = createLinearSolveStrategy(fwdSolverSolverBuilder); const RCP<Thyra::LinearOpWithSolveBase<double> > A_lows = fwdSolverSolverStrategy->createOp(); initializePreconditionedOp<double>( *fwdSolverSolverStrategy, A, unspecifiedPrec(A_inv_prec), A_lows.ptr()); //A_lows->setVerbLevel(verbLevel); *out << "\nA_lows = " << describe(*A_lows, verbLevel) << "\n"; // *out << "\nD) Solve the linear system for a random RHS ...\n"; // VectorPtr x = createMember(A->domain()); VectorPtr b = createMember(A->range()); Thyra::randomize(-1.0, +1.0, b.ptr()); Thyra::assign(x.ptr(), 0.0); // Must give an initial guess! Thyra::SolveStatus<double> solveStatus = solve<double>( *A_lows, Thyra::NOTRANS, *b, x.ptr() ); *out << "\nSolve status:\n" << solveStatus; *out << "\nSolution ||x|| = " << Thyra::norm(*x) << "\n"; if(showParams) { *out << "\nParameter list after use:\n\n"; paramList->print(*out, PLPrintOptions().indent(2).showTypes(true)); } // *out << "\nF) Checking the error in the solution of r=b-A*x ...\n"; // VectorPtr Ax = Thyra::createMember(b->space()); Thyra::apply( *A, Thyra::NOTRANS, *x, Ax.ptr() ); VectorPtr r = Thyra::createMember(b->space()); Thyra::V_VmV<double>(r.ptr(), *b, *Ax); double Ax_nrm = Thyra::norm(*Ax), r_nrm = Thyra::norm(*r), b_nrm = Thyra::norm(*b), r_nrm_over_b_nrm = r_nrm / b_nrm; bool resid_tol_check = ( r_nrm_over_b_nrm <= solveTol ); if(!resid_tol_check) success = false; *out << "\n||A*x|| = " << Ax_nrm << "\n"; *out << "\n||A*x-b||/||b|| = " << r_nrm << "/" << b_nrm << " = " << r_nrm_over_b_nrm << " <= " << solveTol << " : " << Thyra::passfail(resid_tol_check) << "\n"; Teuchos::TimeMonitor::summarize(*out<<"\n"); } TEUCHOS_STANDARD_CATCH_STATEMENTS(verbose, std::cerr, success) if (verbose) { if(success) *out << "\nCongratulations! All of the tests checked out!\n"; else *out << "\nOh no! At least one of the tests failed!\n"; } return ( success ? EXIT_SUCCESS : EXIT_FAILURE ); }