void Piro::LOCASolver<Scalar>::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs, const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs) const { const int l = 0; // TODO: Allow user to select parameter index const Teuchos::RCP<const Thyra::VectorBase<Scalar> > p_inargs = inArgs.get_p(l); // Forward parameter values to the LOCA stepper { const Teuchos::RCP<const Thyra::VectorBase<Scalar> > p_inargs_or_nominal = Teuchos::nonnull(p_inargs) ? p_inargs : this->getNominalValues().get_p(l); const Thyra::ConstDetachedVectorView<Scalar> p_init_values(p_inargs_or_nominal); const Teuchos_Ordinal p_entry_count = p_init_values.subDim(); TEUCHOS_ASSERT(p_entry_count == Teuchos::as<Teuchos_Ordinal>(paramVector_.length())); for (Teuchos_Ordinal k = 0; k < p_entry_count; ++k) { paramVector_[k] = p_init_values[k]; } group_->setParams(paramVector_); } stepper_->reset(globalData_, group_, locaStatusTests_, noxStatusTests_, piroParams_); const LOCA::Abstract::Iterator::IteratorStatus status = stepper_->run(); if (status == LOCA::Abstract::Iterator::Finished) { std::cerr << "Continuation Stepper Finished.\n"; } else if (status == LOCA::Abstract::Iterator::NotFinished) { std::cerr << "Continuation Stepper did not reach final value.\n"; } else { std::cerr << "Nonlinear solver failed to converge.\n"; outArgs.setFailed(); } const Teuchos::RCP<Thyra::VectorBase<Scalar> > x_outargs = outArgs.get_g(this->num_g()); const Teuchos::RCP<Thyra::VectorBase<Scalar> > x_final = Teuchos::nonnull(x_outargs) ? x_outargs : Thyra::createMember(this->get_g_space(this->num_g())); { // Deep copy final solution from LOCA group NOX::Thyra::Vector finalSolution(x_final); finalSolution = group_->getX(); } // Compute responses for the final solution { Thyra::ModelEvaluatorBase::InArgs<Scalar> modelInArgs = this->getModel().createInArgs(); { modelInArgs.set_x(x_final); modelInArgs.set_p(l, p_inargs); } this->evalConvergedModel(modelInArgs, outArgs); } }
Thyra::ModelEvaluatorBase::InArgs<Scalar> Piro::VelocityVerletSolver<Scalar>::getNominalValues() const { Thyra::ModelEvaluatorBase::InArgs<Scalar> result = this->createInArgs(); const Thyra::ModelEvaluatorBase::InArgs<Scalar> modelNominalValues = model->getNominalValues(); for (int l = 0; l < num_p; ++l) { result.set_p(l, modelNominalValues.get_p(l)); } return result; }
Thyra::ModelEvaluatorBase::InArgs<Scalar> Piro::SteadyStateSolver<Scalar>::getNominalValues() const { Thyra::ModelEvaluatorBase::InArgs<Scalar> result = this->createInArgsImpl(); result.setArgs( model_->getNominalValues(), /* ignoreUnsupported = */ true, /* cloneObjects = */ false); return result; }
Thyra::ModelEvaluatorBase::InArgs<Scalar> DiagonalROME<Scalar>::getNominalValues() const { Thyra::ModelEvaluatorBase::InArgs<Scalar> initialGuess = this->createInArgs(); RCP<Thyra::VectorBase<Scalar> > p_init = Thyra::createMember<Scalar>(p_space_); Thyra::V_S( p_init.ptr(), 1.5 ); initialGuess.set_p(0, p_init); return initialGuess; }
void ImplicitRKStepper<Scalar>::setInitialCondition( const Thyra::ModelEvaluatorBase::InArgs<Scalar> &initialCondition ) { typedef ScalarTraits<Scalar> ST; typedef Thyra::ModelEvaluatorBase MEB; basePoint_ = initialCondition; // x RCP<const Thyra::VectorBase<Scalar> > x_init = initialCondition.get_x(); #ifdef HAVE_RYTHMOS_DEBUG TEUCHOS_TEST_FOR_EXCEPTION( is_null(x_init), std::logic_error, "Error, if the client passes in an intial condition to setInitialCondition(...),\n" "then x can not be null!" ); #endif x_ = x_init->clone_v(); // x_dot x_dot_ = createMember(x_->space()); RCP<const Thyra::VectorBase<Scalar> > x_dot_init = initialCondition.get_x_dot(); if (!is_null(x_dot_init)) assign(x_dot_.ptr(),*x_dot_init); else assign(x_dot_.ptr(),ST::zero()); // t const Scalar t = ( initialCondition.supports(MEB::IN_ARG_t) ? initialCondition.get_t() : ST::zero() ); timeRange_ = timeRange(t,t); // x_old x_old_ = x_->clone_v(); haveInitialCondition_ = true; }
TEUCHOS_UNIT_TEST( Rythmos_ExplicitRKStepper, basePoint ) { RCP<SinCosModel> model = sinCosModel(false); { RCP<ParameterList> pl = Teuchos::parameterList(); pl->set("Accept model parameters",true); model->setParameterList(pl); } Thyra::ModelEvaluatorBase::InArgs<double> ic = model->getNominalValues(); // t_ic double t_ic = 1.0; // not used // x_ic RCP<VectorBase<double> > x_ic = Thyra::createMember(*model->get_x_space()); { Thyra::DetachedVectorView<double> x_ic_view( *x_ic ); x_ic_view[0] = 5.0; x_ic_view[1] = 6.0; } // parameter 0 ic RCP<VectorBase<double> > p_ic = Thyra::createMember(*model->get_p_space(0)); { Thyra::DetachedVectorView<double> p_ic_view( *p_ic ); p_ic_view[0] = 2.0; // a p_ic_view[1] = 3.0; // f p_ic_view[2] = 4.0; // L } ic.set_p(0,p_ic); ic.set_x(x_ic); ic.set_t(t_ic); RCP<ExplicitRKStepper<double> > stepper = explicitRKStepper<double>(); stepper->setModel(model); stepper->setInitialCondition(ic); stepper->setRKButcherTableau(createRKBT<double>("Forward Euler")); double dt = 0.2; double dt_taken; dt_taken = stepper->takeStep(dt,STEP_TYPE_FIXED); TEST_EQUALITY_CONST( dt_taken, 0.2 ); const StepStatus<double> status = stepper->getStepStatus(); TEST_ASSERT( !is_null(status.solution) ); double tol = 1.0e-10; { Thyra::ConstDetachedVectorView<double> x_new_view( *(status.solution) ); TEST_FLOATING_EQUALITY( x_new_view[0], 5.0 + 0.2*(6.0), tol ); TEST_FLOATING_EQUALITY( x_new_view[1], 6.0 + 0.2*( (3.0/4.0)*(3.0/4.0)*(2.0-5.0) ), tol ); } }
void DiagonalROME<Scalar>::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs, const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs ) const { using Teuchos::as; using Teuchos::outArg; typedef Teuchos::ScalarTraits<Scalar> ST; using Thyra::get_mv; using Thyra::ConstDetachedSpmdVectorView; using Thyra::DetachedSpmdVectorView; typedef Thyra::Ordinal Ordinal; typedef Thyra::ModelEvaluatorBase MEB; typedef MEB::DerivativeMultiVector<Scalar> DMV; const ConstDetachedSpmdVectorView<Scalar> p(inArgs.get_p(0)); const ConstDetachedSpmdVectorView<Scalar> ps(ps_); const ConstDetachedSpmdVectorView<Scalar> diag(diag_); const ConstDetachedSpmdVectorView<Scalar> s_bar(s_bar_); // g(p) if (!is_null(outArgs.get_g(0))) { Scalar g_val = ST::zero(); for (Ordinal i = 0; i < p.subDim(); ++i) { const Scalar p_ps = p[i] - ps[i]; g_val += diag[i] * p_ps*p_ps; if (nonlinearTermFactor_ != ST::zero()) { g_val += nonlinearTermFactor_ * p_ps * p_ps * p_ps; } } Scalar global_g_val; Teuchos::reduceAll<Ordinal, Scalar>(*comm_, Teuchos::REDUCE_SUM, g_val, outArg(global_g_val) ); DetachedSpmdVectorView<Scalar>(outArgs.get_g(0))[0] = as<Scalar>(0.5) * global_g_val + g_offset_; } // DgDp[i] if (!outArgs.get_DgDp(0,0).isEmpty()) { const RCP<Thyra::MultiVectorBase<Scalar> > DgDp_trans_mv = get_mv<Scalar>(outArgs.get_DgDp(0,0), "DgDp^T", MEB::DERIV_TRANS_MV_BY_ROW); const DetachedSpmdVectorView<Scalar> DgDp_grad(DgDp_trans_mv->col(0)); for (Thyra::Ordinal i = 0; i < p.subDim(); ++i) { const Scalar p_ps = p[i] - ps[i]; Scalar DgDp_grad_i = diag[i] * p_ps; if (nonlinearTermFactor_ != ST::zero()) { DgDp_grad_i += as<Scalar>(1.5) * nonlinearTermFactor_ * p_ps * p_ps; } DgDp_grad[i] = DgDp_grad_i / s_bar[i]; } } }
void TimeDiscretizedBackwardEulerModelEvaluator<Scalar>::initialize( const RCP<const Thyra::ModelEvaluator<Scalar> > &daeModel, const Thyra::ModelEvaluatorBase::InArgs<Scalar> &initCond, const Scalar finalTime, const int numTimeSteps, const RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > &W_bar_factory ) { TEST_FOR_EXCEPT(is_null(daeModel)); TEST_FOR_EXCEPT(is_null(initCond.get_x())); TEST_FOR_EXCEPT(is_null(initCond.get_x_dot())); TEST_FOR_EXCEPT(finalTime <= initCond.get_t()); TEST_FOR_EXCEPT(numTimeSteps <= 0); // ToDo: Validate that daeModel is of the right form! daeModel_ = daeModel; initCond_ = initCond; finalTime_ = finalTime; numTimeSteps_ = numTimeSteps; initTime_ = initCond.get_t(); delta_t_ = (finalTime_ - initTime_) / numTimeSteps_; x_bar_space_ = productVectorSpace(daeModel_->get_x_space(),numTimeSteps_); f_bar_space_ = productVectorSpace(daeModel_->get_f_space(),numTimeSteps_); if (!is_null(W_bar_factory)) { W_bar_factory_ = W_bar_factory; } else { W_bar_factory_ = Thyra::defaultBlockedTriangularLinearOpWithSolveFactory<Scalar>( daeModel_->get_W_factory() ); } }
void Simple2DModelEvaluator<Scalar>::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs, const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs ) const { using Teuchos::rcp_dynamic_cast; const Scalar one = 1.0, two = 2.0, zero = 0.0; const ConstDetachedVectorView<Scalar> x(inArgs.get_x()); const RCP<Thyra::VectorBase<Scalar> > f_out = outArgs.get_f(); const RCP<Thyra::LinearOpBase< Scalar > > W_op_out = outArgs.get_W_op(); const RCP<Thyra::PreconditionerBase< Scalar > > W_prec_out = outArgs.get_W_prec(); if (nonnull(f_out)) { const DetachedVectorView<Scalar> f(f_out); f[0] = x[0] + x[1] * x[1] - p_[0]; f[1] = d_ * (x[0] * x[0] - x[1] - p_[1]); } if (nonnull(W_op_out)) { const RCP<SimpleDenseLinearOp<Scalar> > W = rcp_dynamic_cast<SimpleDenseLinearOp<Scalar> >(W_op_out, true); const RCP<MultiVectorBase<Scalar> > W_mv = W->getNonconstMultiVector(); Thyra::DetachedMultiVectorView<Scalar> W_dmvv(W_mv); W_dmvv(0, 0) = one; W_dmvv(0, 1) = two * x[1]; W_dmvv(1, 0) = d_ * two * x[0]; W_dmvv(1, 1) = -d_; } if (nonnull(W_prec_out)) { const RCP<SimpleDenseLinearOp<Scalar> > W_prec_op = rcp_dynamic_cast<SimpleDenseLinearOp<Scalar> >( W_prec_out->getNonconstUnspecifiedPrecOp(), true); const RCP<MultiVectorBase<Scalar> > W_prec_mv = W_prec_op->getNonconstMultiVector(); Thyra::DetachedMultiVectorView<Scalar> W_prec_dmvv(W_prec_mv); // Diagonal inverse of W (see W above) W_prec_dmvv(0, 0) = one; W_prec_dmvv(0, 1) = zero; W_prec_dmvv(1, 0) = zero; W_prec_dmvv(1, 1) = -one/d_; } }
void Albany::ModelEvaluatorT::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<ST>& inArgsT, const Thyra::ModelEvaluatorBase::OutArgs<ST>& outArgsT) const { Teuchos::TimeMonitor Timer(*timer); //start timer // // Get the input arguments // const Teuchos::RCP<const Tpetra_Vector> xT = ConverterT::getConstTpetraVector(inArgsT.get_x()); const Teuchos::RCP<const Tpetra_Vector> x_dotT = Teuchos::nonnull(inArgsT.get_x_dot()) ? ConverterT::getConstTpetraVector(inArgsT.get_x_dot()) : Teuchos::null; // AGS: x_dotdot time integrators not imlemented in Thyra ME yet //const Teuchos::RCP<const Tpetra_Vector> x_dotdotT = // Teuchos::nonnull(inArgsT.get_x_dotdot()) ? // ConverterT::getConstTpetraVector(inArgsT.get_x_dotdot()) : // Teuchos::null; const Teuchos::RCP<const Tpetra_Vector> x_dotdotT = Teuchos::null; const double alpha = (Teuchos::nonnull(x_dotT) || Teuchos::nonnull(x_dotdotT)) ? inArgsT.get_alpha() : 0.0; // AGS: x_dotdot time integrators not imlemented in Thyra ME yet // const double omega = (Teuchos::nonnull(x_dotT) || Teuchos::nonnull(x_dotdotT)) ? inArgsT.get_omega() : 0.0; const double omega = 0.0; const double beta = (Teuchos::nonnull(x_dotT) || Teuchos::nonnull(x_dotdotT)) ? inArgsT.get_beta() : 1.0; const double curr_time = (Teuchos::nonnull(x_dotT) || Teuchos::nonnull(x_dotdotT)) ? inArgsT.get_t() : 0.0; for (int l = 0; l < inArgsT.Np(); ++l) { const Teuchos::RCP<const Thyra::VectorBase<ST> > p = inArgsT.get_p(l); if (Teuchos::nonnull(p)) { const Teuchos::RCP<const Tpetra_Vector> pT = ConverterT::getConstTpetraVector(p); const Teuchos::ArrayRCP<const ST> pT_constView = pT->get1dView(); ParamVec &sacado_param_vector = sacado_param_vec[l]; for (unsigned int k = 0; k < sacado_param_vector.size(); ++k) { sacado_param_vector[k].baseValue = pT_constView[k]; } } } // // Get the output arguments // const Teuchos::RCP<Tpetra_Vector> fT_out = Teuchos::nonnull(outArgsT.get_f()) ? ConverterT::getTpetraVector(outArgsT.get_f()) : Teuchos::null; const Teuchos::RCP<Tpetra_Operator> W_op_outT = Teuchos::nonnull(outArgsT.get_W_op()) ? ConverterT::getTpetraOperator(outArgsT.get_W_op()) : Teuchos::null; // Cast W to a CrsMatrix, throw an exception if this fails const Teuchos::RCP<Tpetra_CrsMatrix> W_op_out_crsT = Teuchos::nonnull(W_op_outT) ? Teuchos::rcp_dynamic_cast<Tpetra_CrsMatrix>(W_op_outT, true) : Teuchos::null; // // Compute the functions // bool f_already_computed = false; // W matrix if (Teuchos::nonnull(W_op_out_crsT)) { app->computeGlobalJacobianT( alpha, beta, omega, curr_time, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, fT_out.get(), *W_op_out_crsT); f_already_computed = true; } // df/dp for (int l = 0; l < outArgsT.Np(); ++l) { const Teuchos::RCP<Thyra::MultiVectorBase<ST> > dfdp_out = outArgsT.get_DfDp(l).getMultiVector(); const Teuchos::RCP<Tpetra_MultiVector> dfdp_outT = Teuchos::nonnull(dfdp_out) ? ConverterT::getTpetraMultiVector(dfdp_out) : Teuchos::null; if (Teuchos::nonnull(dfdp_outT)) { const Teuchos::RCP<ParamVec> p_vec = Teuchos::rcpFromRef(sacado_param_vec[l]); app->computeGlobalTangentT( 0.0, 0.0, 0.0, curr_time, false, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, p_vec.get(), NULL, NULL, NULL, NULL, fT_out.get(), NULL, dfdp_outT.get()); f_already_computed = true; } } // f if (app->is_adjoint) { const Thyra::ModelEvaluatorBase::Derivative<ST> f_derivT( outArgsT.get_f(), Thyra::ModelEvaluatorBase::DERIV_TRANS_MV_BY_ROW); const Thyra::ModelEvaluatorBase::Derivative<ST> dummy_derivT; const int response_index = 0; // need to add capability for sending this in app->evaluateResponseDerivativeT( response_index, curr_time, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, NULL, NULL, f_derivT, dummy_derivT, dummy_derivT, dummy_derivT); } else { if (Teuchos::nonnull(fT_out) && !f_already_computed) { app->computeGlobalResidualT( curr_time, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, *fT_out); } } // Response functions for (int j = 0; j < outArgsT.Ng(); ++j) { const Teuchos::RCP<Thyra::VectorBase<ST> > g_out = outArgsT.get_g(j); Teuchos::RCP<Tpetra_Vector> gT_out = Teuchos::nonnull(g_out) ? ConverterT::getTpetraVector(g_out) : Teuchos::null; const Thyra::ModelEvaluatorBase::Derivative<ST> dgdxT_out = outArgsT.get_DgDx(j); const Thyra::ModelEvaluatorBase::Derivative<ST> dgdxdotT_out = outArgsT.get_DgDx_dot(j); // AGS: x_dotdot time integrators not imlemented in Thyra ME yet const Thyra::ModelEvaluatorBase::Derivative<ST> dgdxdotdotT_out; // dg/dx, dg/dxdot if (!dgdxT_out.isEmpty() || !dgdxdotT_out.isEmpty()) { const Thyra::ModelEvaluatorBase::Derivative<ST> dummy_derivT; app->evaluateResponseDerivativeT( j, curr_time, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, NULL, gT_out.get(), dgdxT_out, dgdxdotT_out, dgdxdotdotT_out, dummy_derivT); // Set gT_out to null to indicate that g_out was evaluated. gT_out = Teuchos::null; } // dg/dp for (int l = 0; l < outArgsT.Np(); ++l) { const Teuchos::RCP<Thyra::MultiVectorBase<ST> > dgdp_out = outArgsT.get_DgDp(j, l).getMultiVector(); const Teuchos::RCP<Tpetra_MultiVector> dgdpT_out = Teuchos::nonnull(dgdp_out) ? ConverterT::getTpetraMultiVector(dgdp_out) : Teuchos::null; if (Teuchos::nonnull(dgdpT_out)) { const Teuchos::RCP<ParamVec> p_vec = Teuchos::rcpFromRef(sacado_param_vec[l]); app->evaluateResponseTangentT( j, alpha, beta, omega, curr_time, false, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, p_vec.get(), NULL, NULL, NULL, NULL, gT_out.get(), NULL, dgdpT_out.get()); gT_out = Teuchos::null; } } if (Teuchos::nonnull(gT_out)) { app->evaluateResponseT( j, curr_time, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, *gT_out); } } }
void Albany::ModelEvaluatorT::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<ST>& inArgsT, const Thyra::ModelEvaluatorBase::OutArgs<ST>& outArgsT) const { #ifdef OUTPUT_TO_SCREEN std::cout << "DEBUG: " << __PRETTY_FUNCTION__ << "\n"; #endif Teuchos::TimeMonitor Timer(*timer); //start timer // // Get the input arguments // const Teuchos::RCP<const Tpetra_Vector> xT = ConverterT::getConstTpetraVector(inArgsT.get_x()); const Teuchos::RCP<const Tpetra_Vector> x_dotT = (supports_xdot && Teuchos::nonnull(inArgsT.get_x_dot())) ? ConverterT::getConstTpetraVector(inArgsT.get_x_dot()) : Teuchos::null; const Teuchos::RCP<const Tpetra_Vector> x_dotdotT = (supports_xdotdot && Teuchos::nonnull(this->get_x_dotdot())) ? ConverterT::getConstTpetraVector(this->get_x_dotdot()) : Teuchos::null; const double alpha = (Teuchos::nonnull(x_dotT) || Teuchos::nonnull(x_dotdotT)) ? inArgsT.get_alpha() : 0.0; const double omega = Teuchos::nonnull(x_dotdotT) ? this->get_omega() : 0.0; const double beta = (Teuchos::nonnull(x_dotT) || Teuchos::nonnull(x_dotdotT)) ? inArgsT.get_beta() : 1.0; const double curr_time = (Teuchos::nonnull(x_dotT) || Teuchos::nonnull(x_dotdotT)) ? inArgsT.get_t() : 0.0; for (int l = 0; l < inArgsT.Np(); ++l) { const Teuchos::RCP<const Thyra::VectorBase<ST> > p = inArgsT.get_p(l); if (Teuchos::nonnull(p)) { const Teuchos::RCP<const Tpetra_Vector> pT = ConverterT::getConstTpetraVector(p); const Teuchos::ArrayRCP<const ST> pT_constView = pT->get1dView(); ParamVec &sacado_param_vector = sacado_param_vec[l]; for (unsigned int k = 0; k < sacado_param_vector.size(); ++k) { sacado_param_vector[k].baseValue = pT_constView[k]; } } } // // Get the output arguments // const Teuchos::RCP<Tpetra_Vector> fT_out = Teuchos::nonnull(outArgsT.get_f()) ? ConverterT::getTpetraVector(outArgsT.get_f()) : Teuchos::null; const Teuchos::RCP<Tpetra_Operator> W_op_outT = Teuchos::nonnull(outArgsT.get_W_op()) ? ConverterT::getTpetraOperator(outArgsT.get_W_op()) : Teuchos::null; #ifdef WRITE_MASS_MATRIX_TO_MM_FILE //IK, 4/24/15: adding object to hold mass matrix to be written to matrix market file const Teuchos::RCP<Tpetra_Operator> Mass = Teuchos::nonnull(outArgsT.get_W_op()) ? ConverterT::getTpetraOperator(outArgsT.get_W_op()) : Teuchos::null; //IK, 4/24/15: needed for writing mass matrix out to matrix market file const Teuchos::RCP<Tpetra_Vector> ftmp = Teuchos::nonnull(outArgsT.get_f()) ? ConverterT::getTpetraVector(outArgsT.get_f()) : Teuchos::null; #endif // Cast W to a CrsMatrix, throw an exception if this fails const Teuchos::RCP<Tpetra_CrsMatrix> W_op_out_crsT = Teuchos::nonnull(W_op_outT) ? Teuchos::rcp_dynamic_cast<Tpetra_CrsMatrix>(W_op_outT, true) : Teuchos::null; #ifdef WRITE_MASS_MATRIX_TO_MM_FILE //IK, 4/24/15: adding object to hold mass matrix to be written to matrix market file const Teuchos::RCP<Tpetra_CrsMatrix> Mass_crs = Teuchos::nonnull(Mass) ? Teuchos::rcp_dynamic_cast<Tpetra_CrsMatrix>(Mass, true) : Teuchos::null; #endif // // Compute the functions // bool f_already_computed = false; // W matrix if (Teuchos::nonnull(W_op_out_crsT)) { app->computeGlobalJacobianT( alpha, beta, omega, curr_time, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, fT_out.get(), *W_op_out_crsT); f_already_computed = true; #ifdef WRITE_MASS_MATRIX_TO_MM_FILE //IK, 4/24/15: write mass matrix to matrix market file //Warning: to read this in to MATLAB correctly, code must be run in serial. //Otherwise Mass will have a distributed Map which would also need to be read in to MATLAB for proper //reading in of Mass. app->computeGlobalJacobianT(1.0, 0.0, 0.0, curr_time, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, ftmp.get(), *Mass_crs); Tpetra_MatrixMarket_Writer::writeSparseFile("mass.mm", Mass_crs); Tpetra_MatrixMarket_Writer::writeMapFile("rowmap.mm", *Mass_crs->getRowMap()); Tpetra_MatrixMarket_Writer::writeMapFile("colmap.mm", *Mass_crs->getColMap()); #endif } // df/dp for (int l = 0; l < outArgsT.Np(); ++l) { const Teuchos::RCP<Thyra::MultiVectorBase<ST> > dfdp_out = outArgsT.get_DfDp(l).getMultiVector(); const Teuchos::RCP<Tpetra_MultiVector> dfdp_outT = Teuchos::nonnull(dfdp_out) ? ConverterT::getTpetraMultiVector(dfdp_out) : Teuchos::null; if (Teuchos::nonnull(dfdp_outT)) { const Teuchos::RCP<ParamVec> p_vec = Teuchos::rcpFromRef(sacado_param_vec[l]); app->computeGlobalTangentT( 0.0, 0.0, 0.0, curr_time, false, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, p_vec.get(), NULL, NULL, NULL, NULL, fT_out.get(), NULL, dfdp_outT.get()); f_already_computed = true; } } // f if (app->is_adjoint) { const Thyra::ModelEvaluatorBase::Derivative<ST> f_derivT( outArgsT.get_f(), Thyra::ModelEvaluatorBase::DERIV_TRANS_MV_BY_ROW); const Thyra::ModelEvaluatorBase::Derivative<ST> dummy_derivT; const int response_index = 0; // need to add capability for sending this in app->evaluateResponseDerivativeT( response_index, curr_time, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, NULL, NULL, f_derivT, dummy_derivT, dummy_derivT, dummy_derivT); } else { if (Teuchos::nonnull(fT_out) && !f_already_computed) { app->computeGlobalResidualT( curr_time, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, *fT_out); } } // Response functions for (int j = 0; j < outArgsT.Ng(); ++j) { const Teuchos::RCP<Thyra::VectorBase<ST> > g_out = outArgsT.get_g(j); Teuchos::RCP<Tpetra_Vector> gT_out = Teuchos::nonnull(g_out) ? ConverterT::getTpetraVector(g_out) : Teuchos::null; const Thyra::ModelEvaluatorBase::Derivative<ST> dgdxT_out = outArgsT.get_DgDx(j); Thyra::ModelEvaluatorBase::Derivative<ST> dgdxdotT_out; if(supports_xdot) dgdxdotT_out = outArgsT.get_DgDx_dot(j); // const Thyra::ModelEvaluatorBase::Derivative<ST> dgdxdotdotT_out = this->get_DgDx_dotdot(j); const Thyra::ModelEvaluatorBase::Derivative<ST> dgdxdotdotT_out; sanitize_nans(dgdxT_out); sanitize_nans(dgdxdotT_out); sanitize_nans(dgdxdotdotT_out); // dg/dx, dg/dxdot if (!dgdxT_out.isEmpty() || !dgdxdotT_out.isEmpty()) { const Thyra::ModelEvaluatorBase::Derivative<ST> dummy_derivT; app->evaluateResponseDerivativeT( j, curr_time, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, NULL, gT_out.get(), dgdxT_out, dgdxdotT_out, dgdxdotdotT_out, dummy_derivT); // Set gT_out to null to indicate that g_out was evaluated. gT_out = Teuchos::null; } // dg/dp for (int l = 0; l < outArgsT.Np(); ++l) { const Teuchos::RCP<Thyra::MultiVectorBase<ST> > dgdp_out = outArgsT.get_DgDp(j, l).getMultiVector(); const Teuchos::RCP<Tpetra_MultiVector> dgdpT_out = Teuchos::nonnull(dgdp_out) ? ConverterT::getTpetraMultiVector(dgdp_out) : Teuchos::null; if (Teuchos::nonnull(dgdpT_out)) { const Teuchos::RCP<ParamVec> p_vec = Teuchos::rcpFromRef(sacado_param_vec[l]); app->evaluateResponseTangentT( j, alpha, beta, omega, curr_time, false, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, p_vec.get(), NULL, NULL, NULL, NULL, gT_out.get(), NULL, dgdpT_out.get()); gT_out = Teuchos::null; } } if (Teuchos::nonnull(gT_out)) { app->evaluateResponseT( j, curr_time, x_dotT.get(), x_dotdotT.get(), *xT, sacado_param_vec, *gT_out); } } }
// The solve is done in the felix_driver_run function, and the solution is passed back to Glimmer-CISM // IK, 12/3/13: time_inc_yr and cur_time_yr are not used here... void felix_driver_run(FelixToGlimmer * ftg_ptr, double& cur_time_yr, double time_inc_yr) { //IK, 12/9/13: how come FancyOStream prints an all processors?? Teuchos::RCP<Teuchos::FancyOStream> out(Teuchos::VerboseObjectBase::getDefaultOStream()); if (debug_output_verbosity != 0 & mpiCommT->getRank() == 0) { std::cout << "In felix_driver_run, cur_time, time_inc = " << cur_time_yr << " " << time_inc_yr << std::endl; } // --------------------------------------------- // get u and v velocity solution from Glimmer-CISM // IK, 11/26/13: need to concatenate these into a single solve for initial condition for Albany/FELIX solve // IK, 3/14/14: moved this step to felix_driver_run from felix_driver init, since we still want to grab and u and v velocities for CISM if the mesh hasn't changed, // in which case only felix_driver_run will be called, not felix_driver_init. // --------------------------------------------- if (debug_output_verbosity != 0 & mpiCommT->getRank() == 0) std::cout << "In felix_driver_run: grabbing pointers to u and v velocities in CISM..." << std::endl; uVel_ptr = ftg_ptr ->getDoubleVar("uvel", "velocity"); vVel_ptr = ftg_ptr ->getDoubleVar("vvel", "velocity"); // --------------------------------------------- // Set restart solution to the one passed from CISM // IK, 3/14/14: moved this from felix_driver_init to felix_driver_run. // --------------------------------------------- if (debug_output_verbosity != 0 & mpiCommT->getRank() == 0) std::cout << "In felix_driver_run: setting initial condition from CISM..." << std::endl; //Check what kind of ordering you have in the solution & create solutionField object. interleavedOrdering = meshStruct->getInterleavedOrdering(); Albany::AbstractSTKFieldContainer::VectorFieldType* solutionField; if(interleavedOrdering) solutionField = Teuchos::rcp_dynamic_cast<Albany::OrdinarySTKFieldContainer<true> >(meshStruct->getFieldContainer())->getSolutionField(); else solutionField = Teuchos::rcp_dynamic_cast<Albany::OrdinarySTKFieldContainer<false> >(meshStruct->getFieldContainer())->getSolutionField(); //Create vector used to renumber nodes on each processor from the Albany convention (horizontal levels first) to the CISM convention (vertical layers first) nNodes2D = (global_ewn + 1)*(global_nsn+1); //number global nodes in the domain in 2D nNodesProc2D = (nsn-2*nhalo+1)*(ewn-2*nhalo+1); //number of nodes on each processor in 2D cismToAlbanyNodeNumberMap.resize(upn*nNodesProc2D); for (int j=0; j<nsn-2*nhalo+1;j++) { for (int i=0; i<ewn-2*nhalo+1; i++) { for (int k=0; k<upn; k++) { int index = k+upn*i + j*(ewn-2*nhalo+1)*upn; cismToAlbanyNodeNumberMap[index] = k*nNodes2D + global_node_id_owned_map_Ptr[i+j*(ewn-2*nhalo+1)]; //if (mpiComm->MyPID() == 0) // std::cout << "index: " << index << ", cismToAlbanyNodeNumberMap: " << cismToAlbanyNodeNumberMap[index] << std::endl; } } } //The way it worked out, uVel_ptr and vVel_ptr have more nodes than the nodes in the mesh passed to Albany/CISM for the solve. In particular, //there is 1 row of halo elements in uVel_ptr and vVel_ptr. To account for this, we copy uVel_ptr and vVel_ptr into std::vectors, which do not have the halo elements. std::vector<double> uvel_vec(upn*nNodesProc2D); std::vector<double> vvel_vec(upn*nNodesProc2D); int counter1 = 0; int counter2 = 0; int local_nodeID; for (int j=0; j<nsn-1; j++) { for (int i=0; i<ewn-1; i++) { for (int k=0; k<upn; k++) { if (j >= nhalo-1 & j < nsn-nhalo) { if (i >= nhalo-1 & i < ewn-nhalo) { #ifdef CISM_USE_EPETRA local_nodeID = node_map->LID(cismToAlbanyNodeNumberMap[counter1]); #else local_nodeID = node_map->getLocalElement(cismToAlbanyNodeNumberMap[counter1]); #endif uvel_vec[counter1] = uVel_ptr[counter2]; vvel_vec[counter1] = vVel_ptr[counter2]; counter1++; } } counter2++; } } } //Loop over all the elements to find which nodes are active. For the active nodes, copy uvel and vvel from CISM into Albany solution array to //use as initial condition. //NOTE: there is some inefficiency here by looping over all the elements. TO DO? pass only active nodes from Albany-CISM to improve this? double velScale = seconds_per_year*vel_scaling_param; for (int i=0; i<nElementsActive; i++) { for (int j=0; j<8; j++) { int node_GID = global_element_conn_active_Ptr[i + nElementsActive*j]; //node_GID is 1-based #ifdef CISM_USE_EPETRA int node_LID = node_map->LID(node_GID); //node_LID is 0-based #else int node_LID = node_map->getLocalElement(node_GID); //node_LID is 0-based #endif stk::mesh::Entity node = meshStruct->bulkData->get_entity(stk::topology::NODE_RANK, node_GID); double* sol = stk::mesh::field_data(*solutionField, node); //IK, 3/18/14: added division by velScale to convert uvel and vvel from dimensionless to having units of m/year (the Albany units) sol[0] = uvel_vec[node_LID]/velScale; sol[1] = vvel_vec[node_LID]/velScale; } } // --------------------------------------------------------------------------------------------------- // Solve // --------------------------------------------------------------------------------------------------- if (debug_output_verbosity != 0 & mpiCommT->getRank() == 0) std::cout << "In felix_driver_run: starting the solve... " << std::endl; //Need to set HasRestart solution such that uvel_Ptr and vvel_Ptr (u and v from Glimmer/CISM) are always set as initial condition? meshStruct->setHasRestartSolution(!first_time_step); //Turn off homotopy if we're not in the first time-step. //NOTE - IMPORTANT: Glen's Law Homotopy parameter should be set to 1.0 in the parameter list for this logic to work!!! if (!first_time_step) { meshStruct->setRestartDataTime(parameterList->sublist("Problem").get("Homotopy Restart Step", 1.)); double homotopy = parameterList->sublist("Problem").sublist("FELIX Viscosity").get("Glen's Law Homotopy Parameter", 1.0); if(meshStruct->restartDataTime()== homotopy) { parameterList->sublist("Problem").set("Solution Method", "Steady"); parameterList->sublist("Piro").set("Solver Type", "NOX"); } } albanyApp->createDiscretization(); //IK, 10/30/14: Check that # of elements from previous time step hasn't changed. //If it has not, use previous solution as initial guess for current time step. //Otherwise do not set initial solution. It's possible this can be improved so some part of the previous solution is used //defined on the current mesh (if it receded, which likely it will in dynamic ice sheet simulations...). if (nElementsActivePrevious != nElementsActive) previousSolution = Teuchos::null; albanyApp->finalSetUp(parameterList, previousSolution); //if (!first_time_step) // std::cout << "previousSolution: " << *previousSolution << std::endl; #ifdef CISM_USE_EPETRA solver = slvrfctry->createThyraSolverAndGetAlbanyApp(albanyApp, mpiComm, mpiComm, Teuchos::null, false); #else solver = slvrfctry->createAndGetAlbanyAppT(albanyApp, mpiCommT, mpiCommT, Teuchos::null, false); #endif Teuchos::ParameterList solveParams; solveParams.set("Compute Sensitivities", true); Teuchos::Array<Teuchos::RCP<const Thyra::VectorBase<double> > > thyraResponses; Teuchos::Array<Teuchos::Array<Teuchos::RCP<const Thyra::MultiVectorBase<double> > > > thyraSensitivities; Piro::PerformSolveBase(*solver, solveParams, thyraResponses, thyraSensitivities); #ifdef CISM_USE_EPETRA const Epetra_Map& ownedMap(*albanyApp->getDiscretization()->getMap()); //owned map const Epetra_Map& overlapMap(*albanyApp->getDiscretization()->getOverlapMap()); //overlap map Epetra_Import import(overlapMap, ownedMap); //importer from ownedMap to overlapMap Epetra_Vector solutionOverlap(overlapMap); //overlapped solution solutionOverlap.Import(*albanyApp->getDiscretization()->getSolutionField(), import, Insert); #else Teuchos::RCP<const Tpetra_Map> ownedMap = albanyApp->getDiscretization()->getMapT(); //owned map Teuchos::RCP<const Tpetra_Map> overlapMap = albanyApp->getDiscretization()->getOverlapMapT(); //overlap map Teuchos::RCP<Tpetra_Import> import = Teuchos::rcp(new Tpetra_Import(ownedMap, overlapMap)); Teuchos::RCP<Tpetra_Vector> solutionOverlap = Teuchos::rcp(new Tpetra_Vector(overlapMap)); solutionOverlap->doImport(*albanyApp->getDiscretization()->getSolutionFieldT(), *import, Tpetra::INSERT); Teuchos::ArrayRCP<const ST> solutionOverlap_constView = solutionOverlap->get1dView(); #endif #ifdef WRITE_TO_MATRIX_MARKET #ifdef CISM_USE_EPETRA //For debug: write solution and maps to matrix market file EpetraExt::BlockMapToMatrixMarketFile("node_map.mm", *node_map); EpetraExt::BlockMapToMatrixMarketFile("map.mm", ownedMap); EpetraExt::BlockMapToMatrixMarketFile("overlap_map.mm", overlapMap); EpetraExt::MultiVectorToMatrixMarketFile("solution.mm", *albanyApp->getDiscretization()->getSolutionField()); #else Tpetra_MatrixMarket_Writer::writeMapFile("node_map.mm", *node_map); Tpetra_MatrixMarket_Writer::writeMapFile("map.mm", *ownedMap); Tpetra_MatrixMarket_Writer::writeMapFile("overlap_map.mm", *overlapMap); Tpetra_MatrixMarket_Writer::writeDenseFile("solution.mm", app->getDiscretization()->getSolutionFieldT()); #endif #endif //set previousSolution (used as initial guess for next time step) to final Albany solution. previousSolution = Teuchos::rcp(new Tpetra_Vector(*albanyApp->getDiscretization()->getSolutionFieldT())); nElementsActivePrevious = nElementsActive; //std::cout << "Final solution: " << *albanyApp->getDiscretization()->getSolutionField() << std::endl; // --------------------------------------------------------------------------------------------------- // Compute sensitivies / responses and perform regression tests // IK, 12/9/13: how come this is turned off in mpas branch? // --------------------------------------------------------------------------------------------------- if (debug_output_verbosity != 0 & mpiCommT->getRank() == 0) std::cout << "Computing responses and sensitivities..." << std::endl; int status=0; // 0 = pass, failures are incremented #ifdef CISM_USE_EPETRA Teuchos::Array<Teuchos::RCP<const Epetra_Vector> > responses; Teuchos::Array<Teuchos::Array<Teuchos::RCP<const Epetra_MultiVector> > > sensitivities; epetraFromThyra(mpiComm, thyraResponses, thyraSensitivities, responses, sensitivities); #else Teuchos::Array<Teuchos::RCP<const Tpetra_Vector> > responses; Teuchos::Array<Teuchos::Array<Teuchos::RCP<const Tpetra_MultiVector> > > sensitivities; tpetraFromThyra(thyraResponses, thyraSensitivities, responses, sensitivities); #endif const int num_p = solver->Np(); // Number of *vectors* of parameters const int num_g = solver->Ng(); // Number of *vectors* of responses if (debug_output_verbosity != 0) { *out << "Finished eval of first model: Params, Responses " << std::setprecision(12) << std::endl; } const Thyra::ModelEvaluatorBase::InArgs<double> nominal = solver->getNominalValues(); if (debug_output_verbosity != 0) { for (int i=0; i<num_p; i++) { #ifdef CISM_USE_EPETRA const Teuchos::RCP<const Epetra_Vector> p_init = epetraVectorFromThyra(mpiComm, nominal.get_p(i)); p_init->Print(*out << "\nParameter vector " << i << ":\n"); #else Albany::printTpetraVector(*out << "\nParameter vector " << i << ":\n", ConverterT::getConstTpetraVector(nominal.get_p(i))); #endif } } for (int i=0; i<num_g-1; i++) { #ifdef CISM_USE_EPETRA const Teuchos::RCP<const Epetra_Vector> g = responses[i]; #else const Teuchos::RCP<const Tpetra_Vector> g = responses[i]; #endif bool is_scalar = true; if (albanyApp != Teuchos::null) is_scalar = albanyApp->getResponse(i)->isScalarResponse(); if (is_scalar) { if (debug_output_verbosity != 0) { #ifdef CISM_USE_EPETRA g->Print(*out << "\nResponse vector " << i << ":\n"); #else Albany::printTpetraVector(*out << "\nResponse vector " << i << ":\n", g); #endif } if (num_p == 0 && cur_time_yr == final_time) { // Just calculate regression data -- only if in final time step #ifdef CISM_USE_EPETRA status += slvrfctry->checkSolveTestResults(i, 0, g.get(), NULL); #else status += slvrfctry->checkSolveTestResultsT(i, 0, g.get(), NULL); #endif } else { for (int j=0; j<num_p; j++) { #ifdef CISM_USE_EPETRA const Teuchos::RCP<const Epetra_MultiVector> dgdp = sensitivities[i][j]; #else const Teuchos::RCP<const Tpetra_MultiVector> dgdp = sensitivities[i][j]; #endif if (debug_output_verbosity != 0) { if (Teuchos::nonnull(dgdp)) { #ifdef CISM_USE_EPETRA dgdp->Print(*out << "\nSensitivities (" << i << "," << j << "):!\n"); #else Albany::printTpetraVector(*out << "\nSensitivities (" << i << "," << j << "):!\n", dgdp); #endif } } if (cur_time_yr == final_time) { #ifdef CISM_USE_EPETRA status += slvrfctry->checkSolveTestResults(i, j, g.get(), dgdp.get()); #else status += slvrfctry->checkSolveTestResultsT(i, j, g.get(), dgdp.get()); #endif } } } } } if (debug_output_verbosity != 0 && cur_time_yr == final_time) //only print regression test result if you're in the final time step *out << "\nNumber of Failed Comparisons: " << status << std::endl; //IK, 10/30/14: added the following line so that when you run ctest from CISM the test fails if there are some failed comparisons. if (status > 0) TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "All regression comparisons did not pass!" << std::endl); // --------------------------------------------------------------------------------------------------- // Copy solution back to glimmer uvel and vvel arrays to be passed back // --------------------------------------------------------------------------------------------------- //std::cout << "overlapMap # global elements: " << overlapMap.NumGlobalElements() << std::endl; //std::cout << "overlapMap # my elements: " << overlapMap.NumMyElements() << std::endl; //std::cout << "overlapMap: " << overlapMap << std::endl; //std::cout << "map # global elements: " << ownedMap.NumGlobalElements() << std::endl; //std::cout << "map # my elements: " << ownedMap.NumMyElements() << std::endl; //std::cout << "node_map # global elements: " << node_map->NumGlobalElements() << std::endl; //std::cout << "node_map # my elements: " << node_map->NumMyElements() << std::endl; //std::cout << "node_map: " << *node_map << std::endl; if (debug_output_verbosity != 0 & mpiCommT->getRank() == 0) std::cout << "In felix_driver_run: copying Albany solution to uvel and vvel to send back to CISM... " << std::endl; #ifdef CISM_USE_EPETRA //Epetra_Vectors to hold uvel and vvel to be passed to Glimmer/CISM Epetra_Vector uvel(*node_map, true); Epetra_Vector vvel(*node_map, true); #else //Tpetra_Vectors to hold uvel and vvel to be passed to Glimmer/CISM Teuchos::RCP<Tpetra_Vector> uvel = Teuchos::rcp(new Tpetra_Vector(node_map, true)); Teuchos::RCP<Tpetra_Vector> vvel = Teuchos::rcp(new Tpetra_Vector(node_map, true)); #endif #ifdef CISM_USE_EPETRA if (interleavedOrdering == true) { for (int i=0; i<overlapMap.NumMyElements(); i++) { int global_dof = overlapMap.GID(i); double sol_value = solutionOverlap[i]; int modulo = (global_dof % 2); //check if dof is for u or for v int vel_global_dof, vel_local_dof; if (modulo == 0) { //u dof vel_global_dof = global_dof/2+1; //add 1 because node_map is 1-based vel_local_dof = node_map->LID(vel_global_dof); //look up local id corresponding to global id in node_map //std::cout << "uvel: global_dof = " << global_dof << ", uvel_global_dof = " << vel_global_dof << ", uvel_local_dof = " << vel_local_dof << std::endl; uvel.ReplaceMyValues(1, &sol_value, &vel_local_dof); } else { // v dof vel_global_dof = (global_dof-1)/2+1; //add 1 because node_map is 1-based vel_local_dof = node_map->LID(vel_global_dof); //look up local id corresponding to global id in node_map vvel.ReplaceMyValues(1, &sol_value, & vel_local_dof); } } } else { //note: the case with non-interleaved ordering has not been tested... int numDofs = overlapMap.NumGlobalElements(); for (int i=0; i<overlapMap.NumMyElements(); i++) { int global_dof = overlapMap.GID(i); double sol_value = solutionOverlap[i]; int vel_global_dof, vel_local_dof; if (global_dof < numDofs/2) { //u dof vel_global_dof = global_dof+1; //add 1 because node_map is 1-based vel_local_dof = node_map->LID(vel_global_dof); //look up local id corresponding to global id in node_map uvel.ReplaceMyValues(1, &sol_value, &vel_local_dof); } else { //v dofs vel_global_dof = global_dof-numDofs/2+1; //add 1 because node_map is 1-based vel_local_dof = node_map->LID(vel_global_dof); //look up local id corresponding to global id in node_map vvel.ReplaceMyValues(1, &sol_value, & vel_local_dof); } } } #else if (interleavedOrdering == true) { for (int i=0; i<overlapMap->getNodeNumElements(); i++) { int global_dof = overlapMap->getGlobalElement(i); double sol_value = solutionOverlap_constView[i]; int modulo = (global_dof % 2); //check if dof is for u or for v int vel_global_dof, vel_local_dof; if (modulo == 0) { //u dof vel_global_dof = global_dof/2+1; //add 1 because node_map is 1-based vel_local_dof = node_map->getLocalElement(vel_global_dof); //look up local id corresponding to global id in node_map //std::cout << "uvel: global_dof = " << global_dof << ", uvel_global_dof = " << vel_global_dof << ", uvel_local_dof = " << vel_local_dof << std::endl; uvel->replaceLocalValue(vel_local_dof, sol_value); } else { // v dof vel_global_dof = (global_dof-1)/2+1; //add 1 because node_map is 1-based vel_local_dof = node_map->getLocalElement(vel_global_dof); //look up local id corresponding to global id in node_map vvel->replaceLocalValue(vel_local_dof, sol_value); } } } else { //note: the case with non-interleaved ordering has not been tested... int numDofs = overlapMap->getGlobalNumElements(); for (int i=0; i<overlapMap->getNodeNumElements(); i++) { int global_dof = overlapMap->getGlobalElement(i); double sol_value = solutionOverlap_constView[i]; int vel_global_dof, vel_local_dof; if (global_dof < numDofs/2) { //u dof vel_global_dof = global_dof+1; //add 1 because node_map is 1-based vel_local_dof = node_map->getLocalElement(vel_global_dof); //look up local id corresponding to global id in node_map uvel->replaceLocalValue(vel_local_dof, sol_value); } else { //v dofs vel_global_dof = global_dof-numDofs/2+1; //add 1 because node_map is 1-based vel_local_dof = node_map->getLocalElement(vel_global_dof); //look up local id corresponding to global id in node_map vvel->replaceLocalValue(vel_local_dof, sol_value); } } } #endif #ifdef WRITE_TO_MATRIX_MARKET //For debug: write solution to matrix market file #ifdef CISM_USE_EPETRA EpetraExt::MultiVectorToMatrixMarketFile("uvel.mm", uvel); EpetraExt::MultiVectorToMatrixMarketFile("vvel.mm", vvel); #else Tpetra_MatrixMarket_Writer::writeDenseFile("uvel.mm", uvel); Tpetra_MatrixMarket_Writer::writeDenseFile("vvel.mm", vvel); #endif #endif //Copy uvel and vvel into uVel_ptr and vVel_ptr respectively (the arrays passed back to CISM) according to the numbering consistent w/ CISM. counter1 = 0; counter2 = 0; #ifdef CISM_USE_EPETRA #else Teuchos::ArrayRCP<const ST> uvel_constView = uvel->get1dView(); Teuchos::ArrayRCP<const ST> vvel_constView = vvel->get1dView(); #endif local_nodeID = 0; for (int j=0; j<nsn-1; j++) { for (int i=0; i<ewn-1; i++) { for (int k=0; k<upn; k++) { if (j >= nhalo-1 & j < nsn-nhalo) { if (i >= nhalo-1 & i < ewn-nhalo) { #ifdef CISM_USE_EPETRA local_nodeID = node_map->LID(cismToAlbanyNodeNumberMap[counter1]); //if (mpiComm->MyPID() == 0) //std::cout << "counter1:" << counter1 << ", cismToAlbanyNodeNumberMap[counter1]: " << cismToAlbanyNodeNumberMap[counter1] << ", local_nodeID: " //<< local_nodeID << ", uvel: " << uvel[local_nodeID] << std::endl; //uvel[local_nodeID] << std::endl; uVel_ptr[counter2] = uvel[local_nodeID]; vVel_ptr[counter2] = vvel[local_nodeID]; #else local_nodeID = node_map->getLocalElement(cismToAlbanyNodeNumberMap[counter1]); uVel_ptr[counter2] = uvel_constView[local_nodeID]; vVel_ptr[counter2] = vvel_constView[local_nodeID]; #endif counter1++; } } else { uVel_ptr[counter2] = 0.0; vVel_ptr[counter2] = 0.0; } counter2++; } } } first_time_step = false; }
// hide the original parental method AMET->evalModelImpl(): void Aeras::HVDecorator::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<ST>& inArgsT, const Thyra::ModelEvaluatorBase::OutArgs<ST>& outArgsT) const { #ifdef OUTPUT_TO_SCREEN std::cout << "DEBUG WHICH HVDecorator: " << __PRETTY_FUNCTION__ << "\n"; #endif Teuchos::TimeMonitor Timer(*timer); //start timer // // Get the input arguments // // Thyra vectors const Teuchos::RCP<const Thyra_Vector> x = inArgsT.get_x(); const Teuchos::RCP<const Thyra_Vector> x_dot = (supports_xdot ? inArgsT.get_x_dot() : Teuchos::null); const Teuchos::RCP<const Thyra_Vector> x_dotdot = (supports_xdotdot ? inArgsT.get_x_dot_dot() : Teuchos::null); const double alpha = (Teuchos::nonnull(x_dot) || Teuchos::nonnull(x_dotdot)) ? inArgsT.get_alpha() : 0.0; // AGS: x_dotdot time integrators not imlemented in Thyra ME yet // const double omega = (Teuchos::nonnull(x_dot) || Teuchos::nonnull(x_dotdot)) ? inArgsT.get_omega() : 0.0; const double omega = 0.0; const double beta = (Teuchos::nonnull(x_dot) || Teuchos::nonnull(x_dotdot)) ? inArgsT.get_beta() : 1.0; const double curr_time = (Teuchos::nonnull(x_dot) || Teuchos::nonnull(x_dotdot)) ? inArgsT.get_t() : 0.0; for (int l = 0; l < inArgsT.Np(); ++l) { const Teuchos::RCP<const Thyra_Vector> p = inArgsT.get_p(l); if (Teuchos::nonnull(p)) { const Teuchos::RCP<const Tpetra_Vector> pT = Albany::getConstTpetraVector(p); const Teuchos::ArrayRCP<const ST> pT_constView = pT->get1dView(); ParamVec &sacado_param_vector = sacado_param_vec[l]; for (unsigned int k = 0; k < sacado_param_vector.size(); ++k) { sacado_param_vector[k].baseValue = pT_constView[k]; } } } // // Get the output arguments // auto f = outArgsT.get_f(); auto W_op = outArgsT.get_W_op(); // // Compute the functions // bool f_already_computed = false; // W matrix if (Teuchos::nonnull(W_op)) { app->computeGlobalJacobian( alpha, beta, omega, curr_time, x, x_dot, x_dotdot, sacado_param_vec, f, W_op); f_already_computed = true; } // df/dp for (int l = 0; l < outArgsT.Np(); ++l) { const Teuchos::RCP<Thyra_MultiVector> df_dp = outArgsT.get_DfDp(l).getMultiVector(); if (Teuchos::nonnull(df_dp)) { const Teuchos::RCP<ParamVec> p_vec = Teuchos::rcpFromRef(sacado_param_vec[l]); app->computeGlobalTangent( 0.0, 0.0, 0.0, curr_time, false, x, x_dot, x_dotdot, sacado_param_vec, p_vec.get(), Teuchos::null, Teuchos::null, Teuchos::null, Teuchos::null, f, Teuchos::null, df_dp); f_already_computed = true; } } // f if (app->is_adjoint) { const Thyra_Derivative f_deriv(f, Thyra::ModelEvaluatorBase::DERIV_TRANS_MV_BY_ROW); const Thyra_Derivative dummy_deriv; const int response_index = 0; // need to add capability for sending this in app->evaluateResponseDerivative( response_index, curr_time, x, x_dot, x_dotdot, sacado_param_vec, NULL, Teuchos::null, f_deriv, dummy_deriv, dummy_deriv, dummy_deriv); } else { if (Teuchos::nonnull(f) && !f_already_computed) { app->computeGlobalResidual( curr_time, x, x_dot, x_dotdot, sacado_param_vec, f); } } //compute xtilde applyLinvML(x, xtilde); #ifdef WRITE_TO_MATRIX_MARKET_TO_MM_FILE //writing to MatrixMarket for debug char name[100]; //create string for file name sprintf(name, "xT_%i.mm", mm_counter); const Teuchos::RCP<const Tpetra_Vector> xT = Albany::getConstTpetraVector(x); Tpetra::MatrixMarket::Writer<Tpetra_CrsMatrix>::writeDenseFile(name, xT); sprintf(name, "xtildeT_%i.mm", mm_counter); const Teuchos::RCP<const Tpetra_Vector> xtildeT = Albany::getConstTpetraVector(xtilde); Tpetra::MatrixMarket::Writer<Tpetra_CrsMatrix>::writeDenseFile(name, xtildeT); mm_counter++; #endif if (supports_xdot && Teuchos::nonnull(inArgsT.get_x_dot()) && Teuchos::nonnull(f)){ #ifdef OUTPUT_TO_SCREEN std::cout <<"in the if-statement for the update" <<std::endl; #endif f->update(1.0,*xtilde); } // Response functions for (int j = 0; j < outArgsT.Ng(); ++j) { Teuchos::RCP<Thyra_Vector> g = outArgsT.get_g(j); const Thyra_Derivative dg_dx = outArgsT.get_DgDx(j); const Thyra_Derivative dg_dxdot = outArgsT.get_DgDx_dot(j); // AGS: x_dotdot time integrators not imlemented in Thyra ME yet const Thyra_Derivative dg_dxdotdot; sanitize_nans(dg_dx); sanitize_nans(dg_dxdot); sanitize_nans(dg_dxdotdot); // dg/dx, dg/dxdot if (!dg_dx.isEmpty() || !dg_dxdot.isEmpty()) { const Thyra_Derivative dummy_deriv; app->evaluateResponseDerivative( j, curr_time, x, x_dot, x_dotdot, sacado_param_vec, NULL, g, dg_dx, dg_dxdot, dg_dxdotdot, dummy_deriv); // Set g to null to indicate the response was evaluated. g= Teuchos::null; } // dg/dp for (int l = 0; l < outArgsT.Np(); ++l) { const Teuchos::RCP<Thyra_MultiVector> dg_dp = outArgsT.get_DgDp(j, l).getMultiVector(); if (Teuchos::nonnull(dg_dp)) { const Teuchos::RCP<ParamVec> p_vec = Teuchos::rcpFromRef(sacado_param_vec[l]); app->evaluateResponseTangent( j, alpha, beta, omega, curr_time, false, x, x_dot, x_dotdot, sacado_param_vec, p_vec.get(), Teuchos::null, Teuchos::null, Teuchos::null, Teuchos::null, g, Teuchos::null, dg_dp); g = Teuchos::null; } } // If response was not yet evaluated, do it now. if (Teuchos::nonnull(g)) { app->evaluateResponse( j, curr_time, x, x_dot, x_dotdot, sacado_param_vec, g); } } }
int main(int argc, char *argv[]) { int status=0; // 0 = pass, failures are incremented bool success = true; #ifdef ALBANY_DEBUG Teuchos::GlobalMPISession mpiSession(&argc, &argv); #else // bypass printing process startup info Teuchos::GlobalMPISession mpiSession(&argc, &argv, NULL); #endif Kokkos::initialize(argc, argv); #ifdef ALBANY_FLUSH_DENORMALS _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); #endif #ifdef ALBANY_CHECK_FPE // Catch FPEs. Follow Main_SolveT.cpp's approach to checking for floating // point exceptions. //_mm_setcsr(_MM_MASK_MASK &~ (_MM_MASK_OVERFLOW | _MM_MASK_INVALID | _MM_MASK_DIV_ZERO) ); _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID); #endif using Teuchos::RCP; using Teuchos::rcp; RCP<Teuchos::FancyOStream> out(Teuchos::VerboseObjectBase::getDefaultOStream()); // Command-line argument for input file Albany::CmdLineArgs cmd; cmd.parse_cmdline(argc, argv, *out); try { RCP<Teuchos::Time> totalTime = Teuchos::TimeMonitor::getNewTimer("Albany: ***Total Time***"); RCP<Teuchos::Time> setupTime = Teuchos::TimeMonitor::getNewTimer("Albany: Setup Time"); Teuchos::TimeMonitor totalTimer(*totalTime); //start timer Teuchos::TimeMonitor setupTimer(*setupTime); //start timer RCP<const Teuchos_Comm> comm = Tpetra::DefaultPlatform::getDefaultPlatform().getComm(); // Connect vtune for performance profiling if (cmd.vtune) { Albany::connect_vtune(comm->getRank()); } Albany::SolverFactory slvrfctry(cmd.xml_filename, comm); RCP<Epetra_Comm> appComm = Albany::createEpetraCommFromTeuchosComm(comm); RCP<Albany::Application> app; const RCP<Thyra::ModelEvaluator<double> > solver = slvrfctry.createThyraSolverAndGetAlbanyApp(app, appComm, appComm); setupTimer.~TimeMonitor(); // PHX::InitializeKokkosDevice(); Teuchos::ParameterList &solveParams = slvrfctry.getAnalysisParameters().sublist("Solve", /*mustAlreadyExist =*/ false); // By default, request the sensitivities if not explicitly disabled solveParams.get("Compute Sensitivities", true); Teuchos::Array<Teuchos::RCP<const Thyra::VectorBase<double> > > thyraResponses; Teuchos::Array<Teuchos::Array<Teuchos::RCP<const Thyra::MultiVectorBase<double> > > > thyraSensitivities; // The PoissonSchrodinger_SchroPo and PoissonSchroMosCap1D tests seg fault as albanyApp is null - // For now, do not resize the response vectors. FIXME sort out this issue. if(Teuchos::nonnull(app)) Piro::PerformSolveBase(*solver, solveParams, thyraResponses, thyraSensitivities, app->getAdaptSolMgr()->getSolObserver()); else Piro::PerformSolveBase(*solver, solveParams, thyraResponses, thyraSensitivities); Teuchos::Array<Teuchos::RCP<const Epetra_Vector> > responses; Teuchos::Array<Teuchos::Array<Teuchos::RCP<const Epetra_MultiVector> > > sensitivities; epetraFromThyra(appComm, thyraResponses, thyraSensitivities, responses, sensitivities); const int num_p = solver->Np(); // Number of *vectors* of parameters const int num_g = solver->Ng(); // Number of *vectors* of responses *out << "Finished eval of first model: Params, Responses " << std::setprecision(12) << std::endl; Teuchos::ParameterList& parameterParams = slvrfctry.getParameters().sublist("Problem").sublist("Parameters"); int num_param_vecs = (parameterParams.isType<int>("Number")) ? int(parameterParams.get("Number", 0) > 0) : parameterParams.get("Number of Parameter Vectors", 0); const Thyra::ModelEvaluatorBase::InArgs<double> nominal = solver->getNominalValues(); double norm2; for (int i=0; i<num_p; i++) { const Teuchos::RCP<const Epetra_Vector> p_init = epetraVectorFromThyra(appComm, nominal.get_p(i)); if(i < num_param_vecs) p_init->Print(*out << "\nParameter vector " << i << ":\n"); else { //distributed parameters, we print only 2-norm p_init->Norm2(&norm2); *out << "\nDistributed Parameter " << i << ": " << norm2 << " (two-norm)\n" << std::endl; } } for (int i=0; i<num_g-1; i++) { const RCP<const Epetra_Vector> g = responses[i]; bool is_scalar = true; if (app != Teuchos::null) is_scalar = app->getResponse(i)->isScalarResponse(); if (is_scalar) { g->Print(*out << "\nResponse vector " << i << ":\n"); if (num_p == 0) { // Just calculate regression data status += slvrfctry.checkSolveTestResults(i, 0, g.get(), NULL); } else { for (int j=0; j<num_p; j++) { const RCP<const Epetra_MultiVector> dgdp = sensitivities[i][j]; if (Teuchos::nonnull(dgdp)) { if(j < num_param_vecs) { dgdp->Print(*out << "\nSensitivities (" << i << "," << j << "): \n"); status += slvrfctry.checkSolveTestResults(i, j, g.get(), dgdp.get()); } else { const Epetra_Map serial_map(-1, 1, 0, dgdp.get()->Comm()); Epetra_MultiVector norms(serial_map,dgdp->NumVectors()); // RCP<Albany::ScalarResponseFunction> response = rcp_dynamic_cast<Albany::ScalarResponseFunction>(app->getResponse(i)); // int numResponses = response->numResponses(); *out << "\nSensitivities (" << i << "," << j << ") for Distributed Parameters: (two-norm)\n"; *out << " "; for(int ir=0; ir<dgdp->NumVectors(); ++ir) { (*dgdp)(ir)->Norm2(&norm2); (*norms(ir))[0] = norm2; *out << " " << norm2; } *out << "\n" << std::endl; status += slvrfctry.checkSolveTestResults(i, j, g.get(), &norms); } } } } } } // Create debug output object Teuchos::ParameterList &debugParams = slvrfctry.getParameters().sublist("Debug Output", true); bool writeToMatrixMarketSoln = debugParams.get("Write Solution to MatrixMarket", false); bool writeToMatrixMarketDistrSolnMap = debugParams.get("Write Distributed Solution and Map to MatrixMarket", false); bool writeToCoutSoln = debugParams.get("Write Solution to Standard Output", false); const RCP<const Epetra_Vector> xfinal = responses.back(); double mnv; xfinal->MeanValue(&mnv); *out << "Main_Solve: MeanValue of final solution " << mnv << std::endl; *out << "\nNumber of Failed Comparisons: " << status << std::endl; if (writeToCoutSoln == true) std::cout << "xfinal: " << *xfinal << std::endl; #ifdef ALBANY_PERIDIGM #if defined(ALBANY_EPETRA) if (Teuchos::nonnull(LCM::PeridigmManager::self())) { *out << setprecision(12) << "\nPERIDIGM-ALBANY OPTIMIZATION-BASED COUPLING FINAL FUNCTIONAL VALUE = " << LCM::PeridigmManager::self()->obcEvaluateFunctional() << "\n" << std::endl; } #endif #endif if (debugParams.get<bool>("Analyze Memory", false)) Albany::printMemoryAnalysis(std::cout, comm); if (writeToMatrixMarketSoln == true) { //create serial map that puts the whole solution on processor 0 int numMyElements = (xfinal->Comm().MyPID() == 0) ? app->getDiscretization()->getMap()->NumGlobalElements() : 0; const Epetra_Map serial_map(-1, numMyElements, 0, xfinal->Comm()); //create importer from parallel map to serial map and populate serial solution xfinal_serial Epetra_Import importOperator(serial_map, *app->getDiscretization()->getMap()); Epetra_Vector xfinal_serial(serial_map); xfinal_serial.Import(*app->getDiscretization()->getSolutionField(), importOperator, Insert); //writing to MatrixMarket file EpetraExt::MultiVectorToMatrixMarketFile("xfinal.mm", xfinal_serial); } if (writeToMatrixMarketDistrSolnMap == true) { //writing to MatrixMarket file EpetraExt::MultiVectorToMatrixMarketFile("xfinal_distributed.mm", *xfinal); EpetraExt::BlockMapToMatrixMarketFile("xfinal_distributed_map.mm", *app->getDiscretization()->getMap()); } } TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success); if (!success) status+=10000; Teuchos::TimeMonitor::summarize(*out,false,true,false/*zero timers*/); Kokkos::finalize_all(); return status; }
TEUCHOS_UNIT_TEST( Rythmos_GlobalErrorEstimator, SinCos ) { typedef Teuchos::ScalarTraits<double> ST; // Forward Solve, storing data in linear interpolation buffer int storageLimit = 100; double finalTime = 0.1; double dt = 0.1; RCP<IntegratorBuilder<double> > ib = integratorBuilder<double>(); { RCP<ParameterList> ibPL = Teuchos::parameterList(); ibPL->sublist("Integrator Settings").sublist("Integrator Selection").set("Integrator Type","Default Integrator"); ibPL->sublist("Integrator Settings").set("Final Time",finalTime); ibPL->sublist("Integration Control Strategy Selection").set("Integration Control Strategy Type","Simple Integration Control Strategy"); ibPL->sublist("Integration Control Strategy Selection").sublist("Simple Integration Control Strategy").set("Take Variable Steps",false); ibPL->sublist("Integration Control Strategy Selection").sublist("Simple Integration Control Strategy").set("Fixed dt",dt); ibPL->sublist("Stepper Settings").sublist("Stepper Selection").set("Stepper Type","Backward Euler"); //ibPL->sublist("Stepper Settings").sublist("Stepper Selection").set("Stepper Type","Implicit RK"); //ibPL->sublist("Stepper Settings").sublist("Runge Kutta Butcher Tableau Selection").set("Runge Kutta Butcher Tableau Type","Backward Euler"); ibPL->sublist("Interpolation Buffer Settings").sublist("Trailing Interpolation Buffer Selection").set("Interpolation Buffer Type","Interpolation Buffer"); ibPL->sublist("Interpolation Buffer Settings").sublist("Trailing Interpolation Buffer Selection").sublist("Interpolation Buffer").set("StorageLimit",storageLimit); ibPL->sublist("Interpolation Buffer Settings").sublist("Interpolator Selection").set("Interpolator Type","Linear Interpolator"); ib->setParameterList(ibPL); } RCP<SinCosModel> fwdModel = sinCosModel(true); // implicit formulation Thyra::ModelEvaluatorBase::InArgs<double> fwdIC = fwdModel->getNominalValues(); RCP<Thyra::NonlinearSolverBase<double> > fwdNLSolver = timeStepNonlinearSolver<double>(); RCP<IntegratorBase<double> > fwdIntegrator = ib->create(fwdModel,fwdIC,fwdNLSolver); RCP<const VectorBase<double> > x_final; { Array<double> time_vec; time_vec.push_back(finalTime); Array<RCP<const Thyra::VectorBase<double> > > x_final_array; fwdIntegrator->getFwdPoints(time_vec,&x_final_array,NULL,NULL); x_final = x_final_array[0]; } // Verify x_final is correct { // Defaults from SinCos Model: double f = 1.0; double L = 1.0; double a = 0.0; double x_ic_0 = 0.0; double x_ic_1 = 1.0; double x_0 = dt/(1.0+std::pow(dt*f/L,2))*(x_ic_0/dt+x_ic_1+dt*std::pow(f/L,2)*a); double x_1 = dt/(1.0+std::pow(dt*f/L,2))*(-std::pow(f/L,2)*x_ic_0+x_ic_1/dt+std::pow(f/L,2)*a); double tol = 1.0e-10; Thyra::ConstDetachedVectorView<double> x_final_view( *x_final ); TEST_FLOATING_EQUALITY( x_final_view[0], x_0, tol ); TEST_FLOATING_EQUALITY( x_final_view[1], x_1, tol ); } // Copy InterpolationBuffer data into Cubic Spline interpolation buffer for use in Adjoint Solve TimeRange<double> fwdTimeRange; RCP<InterpolationBufferBase<double> > fwdCubicSplineInterpBuffer; { RCP<PointwiseInterpolationBufferAppender<double> > piba = pointwiseInterpolationBufferAppender<double>(); RCP<InterpolationBuffer<double> > sinkInterpBuffer = interpolationBuffer<double>(); sinkInterpBuffer->setStorage(storageLimit); RCP<CubicSplineInterpolator<double> > csi = cubicSplineInterpolator<double>(); sinkInterpBuffer->setInterpolator(csi); RCP<const InterpolationBufferBase<double> > sourceInterpBuffer; { RCP<TrailingInterpolationBufferAcceptingIntegratorBase<double> > tibaib = Teuchos::rcp_dynamic_cast<TrailingInterpolationBufferAcceptingIntegratorBase<double> >(fwdIntegrator,true); sourceInterpBuffer = tibaib->getTrailingInterpolationBuffer(); } fwdTimeRange = sourceInterpBuffer->getTimeRange(); piba->append(*sourceInterpBuffer, fwdTimeRange, Teuchos::outArg(*sinkInterpBuffer)); fwdCubicSplineInterpBuffer = sinkInterpBuffer; TimeRange<double> sourceRange = sourceInterpBuffer->getTimeRange(); TimeRange<double> sinkRange = sinkInterpBuffer->getTimeRange(); TEST_EQUALITY( sourceRange.lower(), sinkRange.lower() ); TEST_EQUALITY( sourceRange.upper(), sinkRange.upper() ); } // Adjoint Solve, reading forward solve data from Cubic Spline interpolation buffer { RCP<ParameterList> ibPL = Teuchos::parameterList(); ibPL->sublist("Integrator Settings").sublist("Integrator Selection").set("Integrator Type","Default Integrator"); ibPL->sublist("Integrator Settings").set("Final Time",finalTime); ibPL->sublist("Integration Control Strategy Selection").set("Integration Control Strategy Type","Simple Integration Control Strategy"); ibPL->sublist("Integration Control Strategy Selection").sublist("Simple Integration Control Strategy").set("Take Variable Steps",false); ibPL->sublist("Integration Control Strategy Selection").sublist("Simple Integration Control Strategy").set("Fixed dt",dt); ibPL->sublist("Stepper Settings").sublist("Stepper Selection").set("Stepper Type","Backward Euler"); //ibPL->sublist("Stepper Settings").sublist("Stepper Selection").set("Stepper Type","Implicit RK"); //ibPL->sublist("Stepper Settings").sublist("Runge Kutta Butcher Tableau Selection").set("Runge Kutta Butcher Tableau Type","Implicit 1 Stage 2nd order Gauss"); ibPL->sublist("Interpolation Buffer Settings").sublist("Trailing Interpolation Buffer Selection").set("Interpolation Buffer Type","Interpolation Buffer"); ibPL->sublist("Interpolation Buffer Settings").sublist("Trailing Interpolation Buffer Selection").sublist("Interpolation Buffer").set("StorageLimit",storageLimit); ibPL->sublist("Interpolation Buffer Settings").sublist("Interpolator Selection").set("Interpolator Type","Linear Interpolator"); ib->setParameterList(ibPL); } RCP<Thyra::ModelEvaluator<double> > adjModel; { RCP<Rythmos::AdjointModelEvaluator<double> > model = Rythmos::adjointModelEvaluator<double>( fwdModel, fwdTimeRange ); //model->setFwdStateSolutionBuffer(fwdCubicSplineInterpBuffer); adjModel = model; } Thyra::ModelEvaluatorBase::InArgs<double> adjIC = adjModel->getNominalValues(); double phi_ic_0 = 2.0; double phi_ic_1 = 3.0; { // Initial conditions for adjoint: const RCP<const Thyra::VectorSpaceBase<double> > f_space = fwdModel->get_f_space(); const RCP<Thyra::VectorBase<double> > x_ic = createMember(f_space); { Thyra::DetachedVectorView<double> x_ic_view( *x_ic ); x_ic_view[0] = phi_ic_0; x_ic_view[1] = phi_ic_1; } const RCP<Thyra::VectorBase<double> > xdot_ic = createMember(f_space); V_S( Teuchos::outArg(*xdot_ic), ST::zero() ); adjIC.set_x(x_ic); adjIC.set_x_dot(xdot_ic); } RCP<Thyra::LinearNonlinearSolver<double> > adjNLSolver = Thyra::linearNonlinearSolver<double>(); RCP<IntegratorBase<double> > adjIntegrator = ib->create(adjModel,adjIC,adjNLSolver); RCP<const VectorBase<double> > phi_final; { Array<double> time_vec; time_vec.push_back(finalTime); Array<RCP<const Thyra::VectorBase<double> > > phi_final_array; adjIntegrator->getFwdPoints(time_vec,&phi_final_array,NULL,NULL); phi_final = phi_final_array[0]; } // Verify phi_final is correct { // Defaults from SinCos Model: double f = 1.0; double L = 1.0; double h = -dt; double phi_0 = 1.0/(1.0+std::pow(f*h/L,2.0))*(phi_ic_0+std::pow(f/L,2.0)*h*phi_ic_1); double phi_1 = 1.0/(1.0+std::pow(f*h/L,2.0))*(-h*phi_ic_0+phi_ic_1); double tol = 1.0e-10; Thyra::ConstDetachedVectorView<double> phi_final_view( *phi_final ); TEST_FLOATING_EQUALITY( phi_final_view[0], phi_0, tol ); TEST_FLOATING_EQUALITY( phi_final_view[1], phi_1, tol ); } // Compute error estimate //TEST_ASSERT( false ); }
int main(int argc, char *argv[]) { // Create output stream. (Handy for multicore output.) auto out = Teuchos::VerboseObjectBase::getDefaultOStream(); Teuchos::GlobalMPISession session(&argc, &argv, NULL); auto comm = Teuchos::DefaultComm<int>::getComm(); // Wrap the whole code in a big try-catch-statement. bool success = true; try { // ========================================================================= // Handle command line arguments. // Boost::program_options is somewhat more complete here (e.g. you can // specify options without the "--" syntax), but it isn't less complicated // to use. Stick with Teuchos for now. Teuchos::CommandLineProcessor myClp; myClp.setDocString( "Numerical parameter continuation for nonlinear Schr\"odinger equations.\n" ); std::string xmlInputPath = ""; myClp.setOption("xml-input-file", &xmlInputPath, "XML file containing the parameter list", true ); // Print warning for unrecognized arguments and make sure to throw an // exception if something went wrong. //myClp.throwExceptions(false); //myClp.recogniseAllOptions ( true ); // Finally, parse the command line. myClp.parse(argc, argv); // Retrieve Piro parameter list from given file. std::shared_ptr<Teuchos::ParameterList> piroParams( new Teuchos::ParameterList() ); Teuchos::updateParametersFromXmlFile( xmlInputPath, Teuchos::rcp(piroParams).ptr() ); // ======================================================================= // Extract the location of input and output files. const Teuchos::ParameterList outputList = piroParams->sublist("Output", true); // Set default directory to be the directory of the XML file itself const std::string xmlDirectory = xmlInputPath.substr(0, xmlInputPath.find_last_of( "/" ) + 1); // By default, take the current directory. std::string prefix = "./"; if (!xmlDirectory.empty()) prefix = xmlDirectory + "/"; const std::string outputDirectory = prefix; const std::string contFilePath = prefix + outputList.get<std::string>("Continuation data file name"); Teuchos::ParameterList & inputDataList = piroParams->sublist("Input", true); const std::string inputExodusFile = prefix + inputDataList.get<std::string>("File"); const int step = inputDataList.get<int>("Initial Psi Step"); //const bool useBordering = piroParams->get<bool>("Bordering"); // ======================================================================= // Read the data from the file. auto mesh = std::make_shared<Nosh::StkMesh>( Teuchos::get_shared_ptr(comm), inputExodusFile, step ); // Cast the data into something more accessible. auto psi = mesh->getComplexVector("psi"); //psi->Random(); // Set the output directory for later plotting with this. std::stringstream outputFile; outputFile << outputDirectory << "/solution.e"; mesh->openOutputChannel(outputFile.str()); // Create a parameter map from the initial parameter values. Teuchos::ParameterList initialParameterValues = piroParams->sublist("Initial parameter values", true); // Check if we need to interpret the time value stored in the file // as a parameter. const std::string & timeName = piroParams->get<std::string>("Interpret time as", ""); if (!timeName.empty()) { initialParameterValues.set(timeName, mesh->getTime()); } // Explicitly set the initial parameter value for this list. const std::string & paramName = piroParams->sublist( "LOCA" ) .sublist( "Stepper" ) .get<std::string>("Continuation Parameter"); *out << "Setting the initial parameter value of \"" << paramName << "\" to " << initialParameterValues.get<double>(paramName) << "." << std::endl; piroParams->sublist( "LOCA" ) .sublist( "Stepper" ) .set("Initial Value", initialParameterValues.get<double>(paramName)); // Set the thickness field. auto thickness = std::make_shared<Nosh::ScalarField::Constant>(*mesh, 1.0); // Some alternatives for the positive-definite operator. // (a) -\Delta (Laplace operator with Neumann boundary) //const std::shared_ptr<Nosh::ParameterMatrix::Virtual> matrixBuilder = // rcp(new Nosh::ParameterMatrix::Laplace(mesh, thickness)); // (b) (-i\nabla-A)^2 (Kinetic energy of a particle in magnetic field) // (b1) 'A' explicitly given in file. const double mu = initialParameterValues.get<double>("mu"); auto mvp = std::make_shared<Nosh::VectorField::ExplicitValues>(*mesh, "A", mu); //const std::shared_ptr<Nosh::ParameterMatrix::Virtual> keoBuilder( // new Nosh::ParameterMatrix::Keo(mesh, thickness, mvp) // ); //const std::shared_ptr<Nosh::ParameterMatrix::Virtual> DKeoDPBuilder( // new Nosh::ParameterMatrix::DKeoDP(mesh, thickness, mvp, "mu") // ); // (b2) 'A' analytically given (here with constant curl). // Optionally add a rotation axis u. This is important // if continuation happens as a rotation of the vector // field around an axis. //const std::shared_ptr<DoubleVector> b = rcp(new DoubleVector(3)); //std::shared_ptr<Teuchos::SerialDenseVector<int,double> > u = Teuchos::null; //if ( piroParams->isSublist("Rotation vector") ) //{ // u = rcp(new Teuchos::SerialDenseVector<int,double>(3)); // Teuchos::ParameterList & rotationVectorList = // piroParams->sublist( "Rotation vector", false ); // (*u)[0] = rotationVectorList.get<double>("x"); // (*u)[1] = rotationVectorList.get<double>("y"); // (*u)[2] = rotationVectorList.get<double>("z"); //} //std::shared_ptr<Nosh::VectorField::Virtual> mvp = // rcp(new Nosh::VectorField::ConstantCurl(mesh, b, u)); //const std::shared_ptr<Nosh::ParameterMatrix::Virtual> matrixBuilder = // rcp(new Nosh::ParameterMatrix::Keo(mesh, thickness, mvp)); // (b3) 'A' analytically given in a class you write yourself, derived // from Nosh::ParameterMatrix::Virtual. // [...] // // Setup the scalar potential V. // (a) A constant potential. //std::shared_ptr<Nosh::ScalarField::Virtual> sp = //rcp(new Nosh::ScalarField::Constant(*mesh, -1.0)); //const double T = initialParameterValues.get<double>("T"); // (b) With explicit values. //std::shared_ptr<Nosh::ScalarField::Virtual> sp = //rcp(new Nosh::ScalarField::ExplicitValues(*mesh, "V")); // (c) One you built yourself by deriving from Nosh::ScalarField::Virtual. auto sp = std::make_shared<MyScalarField>(mesh); const double g = initialParameterValues.get<double>("g"); // Finally, create the model evaluator. // This is the most important object in the whole stack. auto modelEvaluator = std::make_shared<Nosh::ModelEvaluator::Nls>( mesh, mvp, sp, g, thickness, psi, "mu" ); // Build the Piro model evaluator. It's used to hook up with // several different backends (NOX, LOCA, Rhythmos,...). std::shared_ptr<Thyra::ModelEvaluator<double>> piro; // Declare the eigensaver; it will be used only for LOCA solvers, though. std::shared_ptr<Nosh::SaveEigenData> glEigenSaver; // Switch by solver type. std::string & solver = piroParams->get<std::string>("Piro Solver"); if (solver == "NOX") { auto observer = std::make_shared<Nosh::Observer>(modelEvaluator); piro = std::make_shared<Piro::NOXSolver<double>>( Teuchos::rcp(piroParams), Teuchos::rcp(modelEvaluator), Teuchos::rcp(observer) ); } else if (solver == "LOCA") { auto observer = std::make_shared<Nosh::Observer>( modelEvaluator, contFilePath, piroParams->sublist("LOCA") .sublist("Stepper") .get<std::string>("Continuation Parameter") ); // Setup eigen saver. #ifdef HAVE_LOCA_ANASAZI bool computeEigenvalues = piroParams->sublist( "LOCA" ) .sublist( "Stepper" ) .get<bool>("Compute Eigenvalues"); if (computeEigenvalues) { Teuchos::ParameterList & eigenList = piroParams->sublist("LOCA") .sublist("Stepper") .sublist("Eigensolver"); std::string eigenvaluesFilePath = xmlDirectory + "/" + outputList.get<std::string> ( "Eigenvalues file name" ); glEigenSaver = std::make_shared<Nosh::SaveEigenData>( eigenList, modelEvaluator, eigenvaluesFilePath ); std::shared_ptr<LOCA::SaveEigenData::AbstractStrategy> glSaveEigenDataStrategy = glEigenSaver; eigenList.set("Save Eigen Data Method", "User-Defined"); eigenList.set("User-Defined Save Eigen Data Name", "glSaveEigenDataStrategy"); eigenList.set("glSaveEigenDataStrategy", glSaveEigenDataStrategy); } #endif // Get the solver. std::shared_ptr<Piro::LOCASolver<double>> piroLOCASolver( new Piro::LOCASolver<double>( Teuchos::rcp(piroParams), Teuchos::rcp(modelEvaluator), Teuchos::null //Teuchos::rcp(observer) ) ); // // Get stepper and inject it into the eigensaver. // std::shared_ptr<LOCA::Stepper> stepper = Teuchos::get_shared_ptr( // piroLOCASolver->getLOCAStepperNonConst() // ); //#ifdef HAVE_LOCA_ANASAZI // if (computeEigenvalues) // glEigenSaver->setLocaStepper(stepper); //#endif piro = piroLOCASolver; } #if 0 else if ( solver == "Turning Point" ) { std::shared_ptr<Nosh::Observer> observer; Teuchos::ParameterList & bifList = piroParams->sublist("LOCA").sublist("Bifurcation"); // Fetch the (approximate) null state. auto nullstateZ = mesh->getVector("null"); // Set the length normalization vector to be the initial null vector. TEUCHOS_ASSERT(nullstateZ); auto lengthNormVec = Teuchos::rcp(new NOX::Thyra::Vector(*nullstateZ)); //lengthNormVec->init(1.0); bifList.set("Length Normalization Vector", lengthNormVec); // Set the initial null vector. auto initialNullAbstractVec = Teuchos::rcp(new NOX::Thyra::Vector(*nullstateZ)); // initialNullAbstractVec->init(1.0); bifList.set("Initial Null Vector", initialNullAbstractVec); piro = std::make_shared<Piro::LOCASolver<double>>( Teuchos::rcp(piroParams), Teuchos::rcp(modelEvaluator), Teuchos::null //Teuchos::rcp(observer) ); } #endif else { TEUCHOS_TEST_FOR_EXCEPT_MSG( true, "Unknown solver type \"" << solver << "\"." ); } // ---------------------------------------------------------------------- // Now the setting of inputs and outputs. Thyra::ModelEvaluatorBase::InArgs<double> inArgs = piro->createInArgs(); inArgs.set_p( 0, piro->getNominalValues().get_p(0) ); // Set output arguments to evalModel call. Thyra::ModelEvaluatorBase::OutArgs<double> outArgs = piro->createOutArgs(); // Now solve the problem and return the responses. const Teuchos::RCP<Teuchos::Time> piroSolveTime = Teuchos::TimeMonitor::getNewTimer("Piro total solve time");; { Teuchos::TimeMonitor tm(*piroSolveTime); piro->evalModel(inArgs, outArgs); } // Manually release LOCA stepper. #ifdef HAVE_LOCA_ANASAZI if (glEigenSaver) glEigenSaver->releaseLocaStepper(); #endif // Print timing data. Teuchos::TimeMonitor::summarize(); } catch (Teuchos::CommandLineProcessor::HelpPrinted) { } catch (Teuchos::CommandLineProcessor::ParseError) { } TEUCHOS_STANDARD_CATCH_STATEMENTS(true, *out, success); return success ? EXIT_SUCCESS : EXIT_FAILURE; }
int main(int argc, char *argv[]) { int status=0; // 0 = pass, failures are incremented bool success = true; Teuchos::GlobalMPISession mpiSession(&argc,&argv); #ifdef ENABLE_CHECK_FPE // Catch FPEs _mm_setcsr(_MM_MASK_MASK &~ (_MM_MASK_OVERFLOW | _MM_MASK_INVALID | _MM_MASK_DIV_ZERO) ); #endif using Teuchos::RCP; using Teuchos::rcp; RCP<Teuchos::FancyOStream> out(Teuchos::VerboseObjectBase::getDefaultOStream()); // Command-line argument for input file std::string xmlfilename; if(argc > 1){ if(!strcmp(argv[1],"--help")){ printf("albany [inputfile.xml]\n"); exit(1); } else xmlfilename = argv[1]; } else xmlfilename = "input.xml"; try { RCP<Teuchos::Time> totalTime = Teuchos::TimeMonitor::getNewTimer("Albany: ***Total Time***"); RCP<Teuchos::Time> setupTime = Teuchos::TimeMonitor::getNewTimer("Albany: Setup Time"); Teuchos::TimeMonitor totalTimer(*totalTime); //start timer Teuchos::TimeMonitor setupTimer(*setupTime); //start timer Albany::SolverFactory slvrfctry(xmlfilename, Albany_MPI_COMM_WORLD); RCP<Epetra_Comm> appComm = Albany::createEpetraCommFromMpiComm(Albany_MPI_COMM_WORLD); RCP<Albany::Application> app; const RCP<Thyra::ModelEvaluator<double> > solver = slvrfctry.createThyraSolverAndGetAlbanyApp(app, appComm, appComm); setupTimer.~TimeMonitor(); Teuchos::ParameterList &solveParams = slvrfctry.getAnalysisParameters().sublist("Solve", /*mustAlreadyExist =*/ false); // By default, request the sensitivities if not explicitly disabled solveParams.get("Compute Sensitivities", true); Teuchos::Array<Teuchos::RCP<const Thyra::VectorBase<double> > > thyraResponses; Teuchos::Array<Teuchos::Array<Teuchos::RCP<const Thyra::MultiVectorBase<double> > > > thyraSensitivities; // The PoissonSchrodinger_SchroPo and PoissonSchroMosCap1D tests seg fault as albanyApp is null - // For now, do not resize the response vectors. FIXME sort out this issue. if(Teuchos::nonnull(app)) Piro::PerformSolveBase(*solver, solveParams, thyraResponses, thyraSensitivities, app->getAdaptSolMgr()->getSolObserver()); else Piro::PerformSolveBase(*solver, solveParams, thyraResponses, thyraSensitivities); *out << "After main solve" << std::endl; Teuchos::Array<Teuchos::RCP<const Epetra_Vector> > responses; Teuchos::Array<Teuchos::Array<Teuchos::RCP<const Epetra_MultiVector> > > sensitivities; epetraFromThyra(appComm, thyraResponses, thyraSensitivities, responses, sensitivities); const int num_p = solver->Np(); // Number of *vectors* of parameters const int num_g = solver->Ng(); // Number of *vectors* of responses *out << "Finished eval of first model: Params, Responses " << std::setprecision(12) << std::endl; const Thyra::ModelEvaluatorBase::InArgs<double> nominal = solver->getNominalValues(); for (int i=0; i<num_p; i++) { const Teuchos::RCP<const Epetra_Vector> p_init = epetraVectorFromThyra(appComm, nominal.get_p(i)); p_init->Print(*out << "\nParameter vector " << i << ":\n"); } for (int i=0; i<num_g-1; i++) { const RCP<const Epetra_Vector> g = responses[i]; bool is_scalar = true; if (app != Teuchos::null) is_scalar = app->getResponse(i)->isScalarResponse(); if (is_scalar) { g->Print(*out << "\nResponse vector " << i << ":\n"); if (num_p == 0) { // Just calculate regression data status += slvrfctry.checkSolveTestResults(i, 0, g.get(), NULL); } else { for (int j=0; j<num_p; j++) { const RCP<const Epetra_MultiVector> dgdp = sensitivities[i][j]; if (Teuchos::nonnull(dgdp)) { dgdp->Print(*out << "\nSensitivities (" << i << "," << j << "):!\n"); } status += slvrfctry.checkSolveTestResults(i, j, g.get(), dgdp.get()); } } } } const RCP<const Epetra_Vector> xfinal = responses.back(); double mnv; xfinal->MeanValue(&mnv); *out << "Main_Solve: MeanValue of final solution " << mnv << std::endl; *out << "\nNumber of Failed Comparisons: " << status << std::endl; } TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success); if (!success) status+=10000; Teuchos::TimeMonitor::summarize(*out,false,true,false/*zero timers*/); return status; }
void Piro::LOCAAdaptiveSolver<Scalar>::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs, const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs) const { const int l = 0; // TODO: Allow user to select parameter index const Teuchos::RCP<const Thyra::VectorBase<Scalar> > p_inargs = inArgs.get_p(l); // Forward parameter values to the LOCAAdaptive stepper { const Teuchos::RCP<const Thyra::VectorBase<Scalar> > p_inargs_or_nominal = Teuchos::nonnull(p_inargs) ? p_inargs : this->getNominalValues().get_p(l); const Thyra::ConstDetachedVectorView<Scalar> p_init_values(p_inargs_or_nominal); const Teuchos_Ordinal p_entry_count = p_init_values.subDim(); TEUCHOS_ASSERT(p_entry_count == Teuchos::as<Teuchos_Ordinal>(paramVector_.length())); for (Teuchos_Ordinal k = 0; k < p_entry_count; ++k) { paramVector_[k] = p_init_values[k]; } // solMgr_->getSolutionGroup()->setParams(paramVector_); Teuchos::rcp_dynamic_cast< ::Thyra::LOCAAdaptiveState >(solMgr_->getState()) ->getSolutionGroup()->setParams(paramVector_); } LOCA::Abstract::Iterator::IteratorStatus status; status = stepper_->run(); if (status == LOCA::Abstract::Iterator::Finished) { utils_.out() << "Continuation Stepper Finished.\n"; } else if (status == LOCA::Abstract::Iterator::NotFinished) { utils_.out() << "Continuation Stepper did not reach final value.\n"; } else { utils_.out() << "Nonlinear solver failed to converge.\n"; outArgs.setFailed(); } // The time spent globalData_->locaUtils->out() << std::endl << "#### Statistics ########" << std::endl; // Check number of steps int numSteps = stepper_->getStepNumber(); globalData_->locaUtils->out() << std::endl << " Number of continuation Steps = " << numSteps << std::endl; // Check number of failed steps int numFailedSteps = stepper_->getNumFailedSteps(); globalData_->locaUtils->out() << std::endl << " Number of failed continuation Steps = " << numFailedSteps << std::endl; globalData_->locaUtils->out() << std::endl; // Note: the last g is used to store the final solution. It can be null - if it is just // skip the store. If adaptation has occurred, g is not the correct size. const Teuchos::RCP<Thyra::VectorBase<Scalar> > x_outargs = outArgs.get_g(this->num_g()); Teuchos::RCP<Thyra::VectorBase<Scalar> > x_final; int x_args_dim = 0; int f_sol_dim = 0; // Pardon the nasty cast to resize the last g in outArgs - need to fit the solution Thyra::ModelEvaluatorBase::OutArgs<Scalar>* mutable_outArgsPtr = const_cast<Thyra::ModelEvaluatorBase::OutArgs<Scalar>* >(&outArgs); if(Teuchos::nonnull(x_outargs)){ // g has been allocated, calculate the sizes of g and the solution x_args_dim = x_outargs->space()->dim(); // f_sol_dim = solMgr_->getSolutionGroup()->getX().length(); f_sol_dim = Teuchos::rcp_dynamic_cast< ::Thyra::LOCAAdaptiveState >(solMgr_->getState()) ->getSolutionGroup()->getX().length(); } if(Teuchos::is_null(x_outargs) || (x_args_dim != f_sol_dim)){ // g is not the right size x_final = Thyra::createMember(this->get_g_space(this->num_g())); mutable_outArgsPtr->set_g(this->num_g(), x_final); } else { // g is OK, use it x_final = x_outargs; } { // Deep copy final solution from LOCA group NOX::Thyra::Vector finalSolution(x_final); // finalSolution = solMgr_->getSolutionGroup()->getX(); finalSolution = Teuchos::rcp_dynamic_cast< ::Thyra::LOCAAdaptiveState >(solMgr_->getState()) ->getSolutionGroup()->getX(); } // If the arrays need resizing if(x_args_dim != f_sol_dim){ const int parameterCount = this->Np(); for (int pc = 0; pc < parameterCount; ++pc) { const Thyra::ModelEvaluatorBase::DerivativeSupport dgdp_support = outArgs.supports(Thyra::ModelEvaluatorBase::OUT_ARG_DgDp, this->num_g(), pc); const Thyra::ModelEvaluatorBase::EDerivativeMultiVectorOrientation dgdp_orient = Thyra::ModelEvaluatorBase::DERIV_MV_JACOBIAN_FORM; if (dgdp_support.supports(dgdp_orient)) { const Thyra::ModelEvaluatorBase::DerivativeMultiVector<Scalar> dgdp = Thyra::create_DgDp_mv(*this, this->num_g(), pc, dgdp_orient); mutable_outArgsPtr->set_DgDp(this->num_g(), pc, dgdp); } } } // Compute responses for the final solution { Thyra::ModelEvaluatorBase::InArgs<Scalar> modelInArgs = this->getModel().createInArgs(); { modelInArgs.set_x(x_final); modelInArgs.set_p(l, p_inargs); } this->evalConvergedModel(modelInArgs, outArgs); // Save the final solution TODO: this needs to be redone Teuchos::RCP<Thyra::ModelEvaluatorBase::InArgs<Scalar> > fp = Teuchos::rcp_const_cast<Thyra::ModelEvaluatorBase::InArgs<Scalar> >(finalPoint_); Thyra::ModelEvaluatorBase::InArgsSetup<Scalar> ia; ia.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_x, true); *fp = ia; fp->set_x(x_final); } }
void Piro::RythmosSolver<Scalar>::evalModelImpl( #endif const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs, const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs) const { using Teuchos::RCP; using Teuchos::rcp; // TODO: Support more than 1 parameter and 1 response const int j = 0; const int l = 0; // Parse InArgs RCP<const Thyra::VectorBase<Scalar> > p_in; if (num_p > 0) { p_in = inArgs.get_p(l); } RCP<const Thyra::VectorBase<Scalar> > p_in2; //JF add for multipoint if (num_p > 1) { p_in2 = inArgs.get_p(l+1); } // Parse OutArgs RCP<Thyra::VectorBase<Scalar> > g_out; if (num_g > 0) { g_out = outArgs.get_g(j); } const RCP<Thyra::VectorBase<Scalar> > gx_out = outArgs.get_g(num_g); Thyra::ModelEvaluatorBase::InArgs<Scalar> state_ic = model->getNominalValues(); // Set initial time in ME if needed if(t_initial > 0.0 && state_ic.supports(Thyra::ModelEvaluatorBase::IN_ARG_t)) state_ic.set_t(t_initial); if (Teuchos::nonnull(initialConditionModel)) { // The initial condition depends on the parameter // It is found by querying the auxiliary model evaluator as the last response const RCP<Thyra::VectorBase<Scalar> > initialState = Thyra::createMember(model->get_x_space()); { Thyra::ModelEvaluatorBase::InArgs<Scalar> initCondInArgs = initialConditionModel->createInArgs(); if (num_p > 0) { initCondInArgs.set_p(l, inArgs.get_p(l)); } Thyra::ModelEvaluatorBase::OutArgs<Scalar> initCondOutArgs = initialConditionModel->createOutArgs(); initCondOutArgs.set_g(initCondOutArgs.Ng() - 1, initialState); initialConditionModel->evalModel(initCondInArgs, initCondOutArgs); } state_ic.set_x(initialState); } // Set paramters p_in as part of initial conditions if (num_p > 0) { if (Teuchos::nonnull(p_in)) { state_ic.set_p(l, p_in); } } if (num_p > 1) { //JF added for multipoint if (Teuchos::nonnull(p_in2)) { state_ic.set_p(l+1, p_in2); } } *out << "\nstate_ic:\n" << Teuchos::describe(state_ic, solnVerbLevel); //JF may need a version of the following for multipoint, i.e. num_p>1, l+1, if we want sensitivities RCP<Thyra::MultiVectorBase<Scalar> > dgxdp_out; Thyra::ModelEvaluatorBase::Derivative<Scalar> dgdp_deriv_out; if (num_p > 0) { const Thyra::ModelEvaluatorBase::DerivativeSupport dgxdp_support = outArgs.supports(Thyra::ModelEvaluatorBase::OUT_ARG_DgDp, num_g, l); if (dgxdp_support.supports(Thyra::ModelEvaluatorBase::DERIV_MV_JACOBIAN_FORM)) { const Thyra::ModelEvaluatorBase::Derivative<Scalar> dgxdp_deriv = outArgs.get_DgDp(num_g, l); dgxdp_out = dgxdp_deriv.getMultiVector(); } if (num_g > 0) { const Thyra::ModelEvaluatorBase::DerivativeSupport dgdp_support = outArgs.supports(Thyra::ModelEvaluatorBase::OUT_ARG_DgDp, j, l); if (!dgdp_support.none()) { dgdp_deriv_out = outArgs.get_DgDp(j, l); } } } const bool requestedSensitivities = Teuchos::nonnull(dgxdp_out) || !dgdp_deriv_out.isEmpty(); RCP<const Thyra::VectorBase<Scalar> > finalSolution; if (!requestedSensitivities) { // *out << "\nE) Solve the forward problem ...\n"; // fwdStateStepper->setInitialCondition(state_ic); fwdStateIntegrator->setStepper(fwdStateStepper, t_final, true); *out << "T final : " << t_final << " \n"; Teuchos::Array<RCP<const Thyra::VectorBase<Scalar> > > x_final_array; fwdStateIntegrator->getFwdPoints( Teuchos::tuple<Scalar>(t_final), &x_final_array, NULL, NULL); finalSolution = x_final_array[0]; if (Teuchos::VERB_MEDIUM <= solnVerbLevel) { std::cout << "Final Solution\n" << *finalSolution << std::endl; } } else { // Computing sensitivities // *out << "\nE) Solve the forward problem with Sensitivities...\n"; // RCP<Rythmos::ForwardSensitivityStepper<Scalar> > stateAndSensStepper = Rythmos::forwardSensitivityStepper<Scalar>(); stateAndSensStepper->initializeSyncedSteppers( model, l, model->getNominalValues(), fwdStateStepper, fwdTimeStepSolver); // // Set the initial condition for the state and forward sensitivities // const RCP<Thyra::VectorBase<Scalar> > s_bar_init = Thyra::createMember(stateAndSensStepper->getFwdSensModel()->get_x_space()); const RCP<Thyra::VectorBase<Scalar> > s_bar_dot_init = Thyra::createMember(stateAndSensStepper->getFwdSensModel()->get_x_space()); if (Teuchos::is_null(initialConditionModel)) { // The initial condition is assumed to be independent from the parameters // Therefore, the initial condition for the sensitivity is zero Thyra::assign(s_bar_init.ptr(), Teuchos::ScalarTraits<Scalar>::zero()); } else { // Use initialConditionModel to compute initial condition for sensitivity Thyra::ModelEvaluatorBase::InArgs<Scalar> initCondInArgs = initialConditionModel->createInArgs(); initCondInArgs.set_p(l, inArgs.get_p(l)); Thyra::ModelEvaluatorBase::OutArgs<Scalar> initCondOutArgs = initialConditionModel->createOutArgs(); typedef Thyra::DefaultMultiVectorProductVector<Scalar> DMVPV; const RCP<DMVPV> s_bar_init_downcasted = Teuchos::rcp_dynamic_cast<DMVPV>(s_bar_init); const Thyra::ModelEvaluatorBase::Derivative<Scalar> initCond_deriv( s_bar_init_downcasted->getNonconstMultiVector(), Thyra::ModelEvaluatorBase::DERIV_MV_JACOBIAN_FORM); initCondOutArgs.set_DgDp(initCondOutArgs.Ng() - 1, l, initCond_deriv); initialConditionModel->evalModel(initCondInArgs, initCondOutArgs); } Thyra::assign(s_bar_dot_init.ptr(), Teuchos::ScalarTraits<Scalar>::zero()); RCP<const Rythmos::StateAndForwardSensitivityModelEvaluator<Scalar> > stateAndSensModel = stateAndSensStepper->getStateAndFwdSensModel(); Thyra::ModelEvaluatorBase::InArgs<Scalar> state_and_sens_ic = stateAndSensStepper->getModel()->createInArgs(); // Copy time, parameters etc. state_and_sens_ic.setArgs(state_ic); // Set initial condition for x_bar = [ x; s_bar ] state_and_sens_ic.set_x(stateAndSensModel->create_x_bar_vec(state_ic.get_x(), s_bar_init)); // Set initial condition for x_bar_dot = [ x_dot; s_bar_dot ] state_and_sens_ic.set_x_dot(stateAndSensModel->create_x_bar_vec(state_ic.get_x_dot(), s_bar_dot_init)); stateAndSensStepper->setInitialCondition(state_and_sens_ic); // // Use a StepperAsModelEvaluator to integrate the state+sens // const RCP<Rythmos::StepperAsModelEvaluator<Scalar> > stateAndSensIntegratorAsModel = Rythmos::stepperAsModelEvaluator( Teuchos::rcp_implicit_cast<Rythmos::StepperBase<Scalar> >(stateAndSensStepper), Teuchos::rcp_implicit_cast<Rythmos::IntegratorBase<Scalar> >(fwdStateIntegrator), state_and_sens_ic); // StepperAsModelEvaluator outputs the solution as its last response const int stateAndSensModelStateResponseIndex = stateAndSensIntegratorAsModel->Ng() - 1; *out << "\nUse the StepperAsModelEvaluator to integrate state + sens x_bar(p,t_final) ... \n"; Teuchos::OSTab tab(out); // Solution sensitivity in column-oriented (Jacobian) MultiVector form RCP<const Thyra::MultiVectorBase<Scalar> > dxdp; const RCP<Thyra::VectorBase<Scalar> > x_bar_final = Thyra::createMember(stateAndSensIntegratorAsModel->get_g_space(stateAndSensModelStateResponseIndex)); // Extract pieces of x_bar_final to prepare output { const RCP<const Thyra::ProductVectorBase<Scalar> > x_bar_final_downcasted = Thyra::productVectorBase<Scalar>(x_bar_final); // Solution const int solutionBlockIndex = 0; finalSolution = x_bar_final_downcasted->getVectorBlock(solutionBlockIndex); // Sensitivity const int sensitivityBlockIndex = 1; const RCP<const Thyra::VectorBase<Scalar> > s_bar_final = x_bar_final_downcasted->getVectorBlock(sensitivityBlockIndex); { typedef Thyra::DefaultMultiVectorProductVector<Scalar> DMVPV; const RCP<const DMVPV> s_bar_final_downcasted = Teuchos::rcp_dynamic_cast<const DMVPV>(s_bar_final); dxdp = s_bar_final_downcasted->getMultiVector(); } } Thyra::eval_g( *stateAndSensIntegratorAsModel, l, *state_ic.get_p(l), t_final, stateAndSensModelStateResponseIndex, x_bar_final.get() ); *out << "\nx_bar_final = x_bar(p,t_final) evaluated using " << "stateAndSensIntegratorAsModel:\n" << Teuchos::describe(*x_bar_final,solnVerbLevel); if (Teuchos::nonnull(dgxdp_out)) { Thyra::assign(dgxdp_out.ptr(), *dxdp); } if (!dgdp_deriv_out.isEmpty()) { RCP<Thyra::DefaultAddedLinearOp<Scalar> > dgdp_op_out; { const RCP<Thyra::LinearOpBase<Scalar> > dgdp_op = dgdp_deriv_out.getLinearOp(); if (Teuchos::nonnull(dgdp_op)) { dgdp_op_out = Teuchos::rcp_dynamic_cast<Thyra::DefaultAddedLinearOp<Scalar> >(dgdp_op); dgdp_op_out.assert_not_null(); } } Thyra::ModelEvaluatorBase::InArgs<Scalar> modelInArgs = model->createInArgs(); { modelInArgs.set_x(finalSolution); if (num_p > 0) { modelInArgs.set_p(l, p_in); } } // require dgdx, dgdp from model Thyra::ModelEvaluatorBase::OutArgs<Scalar> modelOutArgs = model->createOutArgs(); { const Thyra::ModelEvaluatorBase::Derivative<Scalar> dgdx_deriv(model->create_DgDx_op(j)); modelOutArgs.set_DgDx(j, dgdx_deriv); Thyra::ModelEvaluatorBase::Derivative<Scalar> dgdp_deriv; if (Teuchos::nonnull(dgdp_op_out)) { dgdp_deriv = model->create_DgDp_op(j, l); } else { dgdp_deriv = dgdp_deriv_out; } modelOutArgs.set_DgDp(j, l, dgdp_deriv); } model->evalModel(modelInArgs, modelOutArgs); const RCP<const Thyra::LinearOpBase<Scalar> > dgdx = modelOutArgs.get_DgDx(j).getLinearOp(); // dgdp_out = dgdp + <dgdx, dxdp> if (Teuchos::nonnull(dgdp_op_out)) { Teuchos::Array<RCP<const Thyra::LinearOpBase<Scalar> > > op_args(2); { op_args[0] = modelOutArgs.get_DgDp(j, l).getLinearOp(); op_args[1] = Thyra::multiply<Scalar>(dgdx, dxdp); } dgdp_op_out->initialize(op_args); } else { const RCP<Thyra::MultiVectorBase<Scalar> > dgdp_mv_out = dgdp_deriv_out.getMultiVector(); Thyra::apply( *dgdx, Thyra::NOTRANS, *dxdp, dgdp_mv_out.ptr(), Teuchos::ScalarTraits<Scalar>::one(), Teuchos::ScalarTraits<Scalar>::one()); } } } *out << "\nF) Check the solution to the forward problem ...\n"; // As post-processing step, calculate responses at final solution { Thyra::ModelEvaluatorBase::InArgs<Scalar> modelInArgs = model->createInArgs(); { modelInArgs.set_x(finalSolution); if (num_p > 0) { modelInArgs.set_p(l, p_in); } if (num_p > 1) { //JF added for multipoint modelInArgs.set_p(l+1, p_in2); } //Set time to be final time at which the solve occurs (< t_final in the case we don't make it to t_final). modelInArgs.set_t(fwdStateStepper->getTimeRange().lower()); } Thyra::ModelEvaluatorBase::OutArgs<Scalar> modelOutArgs = model->createOutArgs(); if (Teuchos::nonnull(g_out)) { Thyra::put_scalar(Teuchos::ScalarTraits<Scalar>::zero(), g_out.ptr()); modelOutArgs.set_g(j, g_out); } model->evalModel(modelInArgs, modelOutArgs); } // Return the final solution as an additional g-vector, if requested if (Teuchos::nonnull(gx_out)) { Thyra::copy(*finalSolution, gx_out.ptr()); } }
void Piro::VelocityVerletSolver<Scalar, LocalOrdinal, GlobalOrdinal, Node>::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs, const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs) const { using Teuchos::RCP; using Teuchos::rcp; // TODO: Support more than 1 parameter and 1 response const int j = 0; const int l = 0; // Parse InArgs RCP<const Thyra::VectorBase<Scalar> > p_in; if (num_p > 0) { p_in = inArgs.get_p(l); } // Parse OutArgs RCP<Thyra::VectorBase<Scalar> > g_out; if (num_g > 0) { g_out = outArgs.get_g(j); } const RCP<Thyra::VectorBase<Scalar> > gx_out = outArgs.get_g(num_g); // create a new vector and fill it with the contents of model->get_x() // Build a multivector holding x (0th vector), v (1st vector), and a (2nd vector) // Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > soln = createMembers(model->get_x_space(), 3); // create a new vector and fill it with the contents of model->get_x() /* Teuchos::RCP<Thyra::VectorBase<Scalar> > x = soln->col(0); assign(x.ptr(), *model->getNominalValues().get_x()); Teuchos::RCP<Thyra::VectorBase<Scalar> > v = soln->col(1); assign(v.ptr(), *model->getNominalValues().get_x_dot()); Teuchos::RCP<Thyra::VectorBase<Scalar> > a = soln->col(2); assign(a.ptr(), *model->get_x_dotdot()); */ Teuchos::RCP<Thyra::VectorBase<Scalar> > x = model->getNominalValues().get_x()->clone_v(); Teuchos::RCP<Thyra::VectorBase<Scalar> > v = model->getNominalValues().get_x_dot()->clone_v(); // Note that Thyra doesn't have x_dotdot - go get it from the transient decorator around the Albany model // Teuchos::RCP<Thyra::VectorBase<Scalar> > a = model->get_x_dotdot()->clone_v(); Teuchos::RCP<Thyra::DefaultModelEvaluatorWithSolveFactory<Scalar> > DMEWSF(Teuchos::rcp_dynamic_cast<Thyra::DefaultModelEvaluatorWithSolveFactory<Scalar> >(model)); Teuchos::RCP<const Piro::TransientDecorator<Scalar, LocalOrdinal, GlobalOrdinal, Node> > dec = Teuchos::rcp_dynamic_cast<const Piro::TransientDecorator<Scalar, LocalOrdinal, GlobalOrdinal, Node> > (DMEWSF->getUnderlyingModel()); TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::is_null(dec), std::logic_error, "Underlying model in VelovityVerletSolver does not cast to a Piro::TransientDecorator<Scalar, LocalOrdinal, GlobalOrdinal, Node>" << std::endl); Teuchos::RCP<Thyra::VectorBase<Scalar> > a = dec->get_x_dotdot()->clone_v(); RCP<Thyra::VectorBase<Scalar> > finalSolution; // Zero out the acceleration vector put_scalar(0.0, a.ptr()); TEUCHOS_TEST_FOR_EXCEPTION(v == Teuchos::null || x == Teuchos::null, Teuchos::Exceptions::InvalidParameter, std::endl << "Error in Piro::VelocityVerletSolver " << "Requires initial x and x_dot: " << std::endl); Scalar t = t_init; // Observe initial condition // if (observer != Teuchos::null) observer->observeSolution(*soln, t); Scalar vo = norm_2(*v); *out << "Initial Velocity = " << vo << std::endl; if (Teuchos::VERB_MEDIUM <= solnVerbLevel) *out << std::endl; Thyra::ModelEvaluatorBase::InArgs<Scalar> model_inargs = model->createInArgs(); Thyra::ModelEvaluatorBase::OutArgs<Scalar> model_outargs = model->createOutArgs(); model_inargs.set_x(x); if (num_p > 0) model_inargs.set_p(0, p_in); model_outargs.set_f(a); if (g_out != Teuchos::null) model_outargs.set_g(0, g_out); Scalar ddt = 0.5 * delta_t * delta_t; // Calculate acceleration at time 0 model->evalModel(model_inargs, model_outargs); for (int timeStep = 1; timeStep <= numTimeSteps; timeStep++) { // x->Update(delta_t, *v, ddt, *a, 1.0); Vp_StV(x.ptr(), delta_t, *v); Vp_StV(x.ptr(), ddt, *a); t += delta_t; model_inargs.set_t(t); // v->Update(0.5*delta_t, *a, 1.0); Vp_StV(v.ptr(), 0.5 * delta_t, *a); //calc a(x,t,p); model->evalModel(model_inargs, model_outargs); // v->Update(0.5*delta_t, *a, 1.0); Vp_StV(v.ptr(), 0.5 * delta_t, *a); // Observe completed time step if (observer != Teuchos::null) observer->observeSolution(*x, t); } // return the final solution as an additional g-vector, if requested if (finalSolution != Teuchos::null) finalSolution = x->clone_v(); // Return the final solution as an additional g-vector, if requested if (Teuchos::nonnull(gx_out)) { Thyra::copy(*finalSolution, gx_out.ptr()); } }
TEUCHOS_UNIT_TEST( Rythmos_ImplicitBDFStepper, exactNumericalAnswer_BE_nonlinear ) { double epsilon = 0.5; RCP<ParameterList> modelPL = Teuchos::parameterList(); { modelPL->set("Implicit model formulation",true); modelPL->set("Coeff epsilon",epsilon); } RCP<VanderPolModel> model = vanderPolModel(); model->setParameterList(modelPL); Thyra::ModelEvaluatorBase::InArgs<double> model_ic = model->getNominalValues(); RCP<TimeStepNonlinearSolver<double> > nlSolver = timeStepNonlinearSolver<double>(); { RCP<ParameterList> nlPL = Teuchos::parameterList(); nlPL->set("Default Tol",1.0e-10); nlPL->set("Default Max Iters",20); nlSolver->setParameterList(nlPL); } RCP<ParameterList> stepperPL = Teuchos::parameterList(); { ParameterList& pl = stepperPL->sublist("Step Control Settings"); pl.set("minOrder",1); pl.set("maxOrder",1); ParameterList& vopl = pl.sublist("VerboseObject"); vopl.set("Verbosity Level","none"); } RCP<ImplicitBDFStepper<double> > stepper = implicitBDFStepper<double>(model,nlSolver,stepperPL); stepper->setInitialCondition(model_ic); double h = 0.1; std::vector<double> x_0_exact; std::vector<double> x_1_exact; std::vector<double> x_0_dot_exact; std::vector<double> x_1_dot_exact; { x_0_exact.push_back(2.0); // IC x_1_exact.push_back(0.0); x_0_exact.push_back(1.982896621392518e+00); // matlab x_1_exact.push_back(-1.710337860748234e-01); x_0_exact.push_back(1.951487185706842e+00); // matlab x_1_exact.push_back(-3.140943568567556e-01); x_0_exact.push_back(1.908249109758246e+00); // matlab x_1_exact.push_back(-4.323807594859574e-01); x_0_dot_exact.push_back(0.0); x_1_dot_exact.push_back(0.0); for ( int i=1 ; i< Teuchos::as<int>(x_0_exact.size()) ; ++i ) { x_0_dot_exact.push_back( (x_0_exact[i]-x_0_exact[i-1])/h ); x_1_dot_exact.push_back( (x_1_exact[i]-x_1_exact[i-1])/h ); //std::cout << "x_0_dot_exact["<<i<<"] = "<<x_0_dot_exact[i] << std::endl; //std::cout << "x_1_dot_exact["<<i<<"] = "<<x_1_dot_exact[i] << std::endl; } } double tol_discrete = 1.0e-12; double tol_continuous = 1.0e-2; { // Get IC out double t = 0.0; RCP<const VectorBase<double> > x; RCP<const VectorBase<double> > xdot; { // Get x out of stepper. Array<double> t_vec; Array<RCP<const VectorBase<double> > > x_vec; Array<RCP<const VectorBase<double> > > xdot_vec; t_vec.resize(1); t_vec[0] = t; stepper->getPoints(t_vec,&x_vec,&xdot_vec,NULL); x = x_vec[0]; xdot = xdot_vec[0]; } { Thyra::ConstDetachedVectorView<double> x_view( *x ); TEST_FLOATING_EQUALITY( x_view[0], x_0_exact[0], tol_discrete ); TEST_FLOATING_EQUALITY( x_view[1], x_1_exact[0], tol_discrete ); Thyra::ConstDetachedVectorView<double> xdot_view( *xdot ); TEST_FLOATING_EQUALITY( xdot_view[0], x_0_dot_exact[0], tol_discrete ); TEST_FLOATING_EQUALITY( xdot_view[1], x_1_dot_exact[0], tol_discrete ); } } for (int i=1 ; i < Teuchos::as<int>(x_0_exact.size()); ++i) { // Each time step double t = 0.0+i*h; double h_taken = stepper->takeStep(h,STEP_TYPE_FIXED); TEST_ASSERT( h_taken == h ); RCP<const VectorBase<double> > x; RCP<const VectorBase<double> > xdot; { // Get x out of stepper. Array<double> t_vec; Array<RCP<const VectorBase<double> > > x_vec; Array<RCP<const VectorBase<double> > > xdot_vec; t_vec.resize(1); t_vec[0] = t; stepper->getPoints(t_vec,&x_vec,&xdot_vec,NULL); x = x_vec[0]; xdot = xdot_vec[0]; } { Thyra::ConstDetachedVectorView<double> x_view( *x ); TEST_FLOATING_EQUALITY( x_view[0], x_0_exact[i], tol_discrete ); TEST_FLOATING_EQUALITY( x_view[1], x_1_exact[i], tol_discrete ); Thyra::ConstDetachedVectorView<double> xdot_view( *xdot ); TEST_FLOATING_EQUALITY( xdot_view[0], x_0_dot_exact[i], tol_discrete ); TEST_FLOATING_EQUALITY( xdot_view[1], x_1_dot_exact[i], tol_discrete ); } // Now compare this to the continuous exact solution: { Thyra::ModelEvaluatorBase::InArgs<double> inArgs = model->getExactSolution(t); RCP<const VectorBase<double> > x_continuous_exact = inArgs.get_x(); RCP<const VectorBase<double> > xdot_continuous_exact = inArgs.get_x_dot(); { Thyra::ConstDetachedVectorView<double> x_view( *x ); Thyra::ConstDetachedVectorView<double> xce_view( *x_continuous_exact ); TEST_FLOATING_EQUALITY( x_view[0], xce_view[0], tol_continuous ); TEST_FLOATING_EQUALITY( x_view[1], xce_view[1], tol_continuous*10 ); Thyra::ConstDetachedVectorView<double> xdot_view( *xdot ); Thyra::ConstDetachedVectorView<double> xdotce_view( *xdot_continuous_exact ); TEST_FLOATING_EQUALITY( xdot_view[0], xdotce_view[0], tol_continuous*10 ); TEST_FLOATING_EQUALITY( xdot_view[1], xdotce_view[1], tol_continuous*10 ); } } } }
void DiagonalImplicitRKModelEvaluator<Scalar>::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs_stage, const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs_stage ) const { typedef ScalarTraits<Scalar> ST; typedef Thyra::ModelEvaluatorBase MEB; TEUCHOS_TEST_FOR_EXCEPTION( !isInitialized_, std::logic_error, "Error! initializeDIRKModel must be called before evalModel\n" ); TEUCHOS_TEST_FOR_EXCEPTION( !setTimeStepPointCalled_, std::logic_error, "Error! setTimeStepPoint must be called before evalModel" ); TEUCHOS_TEST_FOR_EXCEPTION( currentStage_ == -1, std::logic_error, "Error! setCurrentStage must be called before evalModel" ); THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_GEN_BEGIN( "Rythmos::DiagonalImplicitRKModelEvaluator",inArgs_stage,outArgs_stage,daeModel_ ); // // A) Unwrap the inArgs and outArgs // const RCP<const Thyra::VectorBase<Scalar> > x_in = inArgs_stage.get_x(); const RCP<Thyra::VectorBase<Scalar> > f_out = outArgs_stage.get_f(); const RCP<Thyra::LinearOpBase<Scalar> > W_op_out = outArgs_stage.get_W_op(); // // B) Assemble f_out and W_op_out for given stage // MEB::InArgs<Scalar> daeInArgs = daeModel_->createInArgs(); MEB::OutArgs<Scalar> daeOutArgs = daeModel_->createOutArgs(); const RCP<Thyra::VectorBase<Scalar> > x_i = createMember(daeModel_->get_x_space()); daeInArgs.setArgs(basePoint_); // B.1) Setup the DAE's inArgs for stage f(currentStage_) ... V_V(stage_derivatives_->getNonconstVectorBlock(currentStage_).ptr(),*x_in); assembleIRKState( currentStage_, dirkButcherTableau_->A(), delta_t_, *x_old_, *stage_derivatives_, outArg(*x_i) ); daeInArgs.set_x( x_i ); daeInArgs.set_x_dot( x_in ); daeInArgs.set_t( t_old_ + dirkButcherTableau_->c()(currentStage_) * delta_t_ ); daeInArgs.set_alpha(ST::one()); daeInArgs.set_beta( delta_t_ * dirkButcherTableau_->A()(currentStage_,currentStage_) ); // B.2) Setup the DAE's outArgs for stage f(i) ... if (!is_null(f_out)) daeOutArgs.set_f( f_out ); if (!is_null(W_op_out)) daeOutArgs.set_W_op(W_op_out); // B.3) Compute f_out(i) and/or W_op_out ... daeModel_->evalModel( daeInArgs, daeOutArgs ); daeOutArgs.set_f(Teuchos::null); daeOutArgs.set_W_op(Teuchos::null); THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_END(); }
void TimeDiscretizedBackwardEulerModelEvaluator<Scalar>::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs_bar, const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs_bar ) const { using Teuchos::rcp_dynamic_cast; typedef ScalarTraits<Scalar> ST; typedef Thyra::ModelEvaluatorBase MEB; typedef Thyra::VectorBase<Scalar> VB; typedef Thyra::ProductVectorBase<Scalar> PVB; typedef Thyra::BlockedLinearOpBase<Scalar> BLWB; /* THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_GEN_BEGIN( "Rythmos::ImplicitRKModelEvaluator",inArgs_bar,outArgs_bar,daeModel_ ); */ TEST_FOR_EXCEPTION( delta_t_ <= 0.0, std::logic_error, "Error, you have not initialized this object correctly!" ); // // A) Unwrap the inArgs and outArgs to get at product vectors and block op // const RCP<const PVB> x_bar = rcp_dynamic_cast<const PVB>(inArgs_bar.get_x(), true); const RCP<PVB> f_bar = rcp_dynamic_cast<PVB>(outArgs_bar.get_f(), true); RCP<BLWB> W_op_bar = rcp_dynamic_cast<BLWB>(outArgs_bar.get_W_op(), true); // // B) Assemble f_bar and W_op_bar by looping over stages // MEB::InArgs<Scalar> daeInArgs = daeModel_->createInArgs(); MEB::OutArgs<Scalar> daeOutArgs = daeModel_->createOutArgs(); const RCP<VB> x_dot_i = createMember(daeModel_->get_x_space()); daeInArgs.setArgs(initCond_); Scalar t_i = initTime_; // ToDo: Define t_init! const Scalar oneOverDeltaT = 1.0/delta_t_; for ( int i = 0; i < numTimeSteps_; ++i ) { // B.1) Setup the DAE's inArgs for time step eqn f(i) ... const RCP<const Thyra::VectorBase<Scalar> > x_i = x_bar->getVectorBlock(i), x_im1 = ( i==0 ? initCond_.get_x() : x_bar->getVectorBlock(i-1) ); V_VmV( x_dot_i.ptr(), *x_i, *x_im1 ); // x_dot_i = 1/dt * ( x[i] - x[i-1] ) Vt_S( x_dot_i.ptr(), oneOverDeltaT ); // ... daeInArgs.set_x_dot( x_dot_i ); daeInArgs.set_x( x_i ); daeInArgs.set_t( t_i ); daeInArgs.set_alpha( oneOverDeltaT ); daeInArgs.set_beta( 1.0 ); // B.2) Setup the DAE's outArgs for f(i) and/or W(i,i) ... if (!is_null(f_bar)) daeOutArgs.set_f( f_bar->getNonconstVectorBlock(i) ); if (!is_null(W_op_bar)) daeOutArgs.set_W_op(W_op_bar->getNonconstBlock(i,i).assert_not_null()); // B.3) Compute f_bar(i) and/or W_op_bar(i,i) ... daeModel_->evalModel( daeInArgs, daeOutArgs ); daeOutArgs.set_f(Teuchos::null); daeOutArgs.set_W_op(Teuchos::null); // B.4) Evaluate W_op_bar(i,i-1) if ( !is_null(W_op_bar) && i > 0 ) { daeInArgs.set_alpha( -oneOverDeltaT ); daeInArgs.set_beta( 0.0 ); daeOutArgs.set_W_op(W_op_bar->getNonconstBlock(i,i-1).assert_not_null()); daeModel_->evalModel( daeInArgs, daeOutArgs ); daeOutArgs.set_W_op(Teuchos::null); } // t_i += delta_t_; } /* THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_END(); */ }
void Piro::NOXSolver<Scalar>::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs, const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs ) const { using Teuchos::RCP; using Teuchos::rcp; //*out << "In eval Modle " << endl; // Parse InArgs RCP<const Thyra::VectorBase<Scalar> > p_in; if (num_p > 0) p_in = inArgs.get_p(0); // Parse OutArgs: always 1 extra RCP< Thyra::VectorBase<Scalar> > g_out; if (num_g > 0) g_out = outArgs.get_g(0); RCP< Thyra::VectorBase<Scalar> > gx_out = outArgs.get_g(num_g); // Parse out-args for sensitivity calculation ::Thyra::SolveCriteria<double> solve_criteria; ::Thyra::SolveStatus<double> solve_status; RCP< ::Thyra::VectorBase<double> > initial_guess = model->getNominalValues().get_x()->clone_v(); solve_status = solver->solve(initial_guess.get(), &solve_criteria, NULL); // if (solve_status.solveStatus == ::Thyra::SOLVE_STATUS_CONVERGED) // std::cout << "Test passed!" << std::endl; // return the final solution as an additional g-vector, if requested RCP<const Thyra::VectorBase<Scalar> > finalSolution = solver->get_current_x(); if (gx_out != Teuchos::null) Thyra::copy(*finalSolution, gx_out.ptr()); if (g_out != Teuchos::null) { // As post-processing step, calc responses at final solution Thyra::ModelEvaluatorBase::InArgs<Scalar> model_inargs = model->createInArgs(); Thyra::ModelEvaluatorBase::OutArgs<Scalar> model_outargs = model->createOutArgs(); model_inargs.set_x(finalSolution); if (num_p > 0) model_inargs.set_p(0, p_in); if (g_out != Teuchos::null) { Thyra::put_scalar(0.0,g_out.ptr()); model_outargs.set_g(0, g_out); } model->evalModel(model_inargs, model_outargs); } /********************* NEED TO CONVERT TO THYRA ******************* RCP< Thyra::MultiVectorBase<Scalar> > dgdp_out; if (num_p>0 && num_g>0) dgdp_out = outArgs.get_DgDp(0,0).getMultiVector(); if (dgdp_out == Teuchos::null) { Teuchos::RCP<Epetra_MultiVector> dgdx = Teuchos::rcp(new Epetra_MultiVector(finalSolution->Map(), dgdp_out->GlobalLength())); Teuchos::Array<int> p_indexes = outArgs.get_DgDp(0,0).getDerivativeMultiVector().getParamIndexes(); EpetraExt::ModelEvaluator::DerivativeMultiVector dmv_dgdp(dgdp_out, DERIV_MV_BY_COL, p_indexes); EpetraExt::ModelEvaluator::InArgs model_inargs = model->createInArgs(); EpetraExt::ModelEvaluator::OutArgs model_outargs = model->createOutArgs(); model_inargs.set_x(finalSolution); model_inargs.set_p(0, p_in); if (g_out != Teuchos::null) { g_out->PutScalar(0.0); model_outargs.set_g(0, g_out); } model_outargs.set_DgDp(0,0,dmv_dgdp); model_outargs.set_DgDx(0,dgdx); model->evalModel(model_inargs, model_outargs); // (3) Calculate dg/dp = dg/dx*dx/dp + dg/dp // This may be the transpose of what we want since we specified // we want dg/dp by column in createOutArgs(). // In this case just interchange the order of dgdx and dxdp // We should really probably check what the underlying ME does if (Teuchos::VERB_MEDIUM <= solnVerbLevel) cout << " dgdx \n" << *dgdx << endl; if (Teuchos::VERB_MEDIUM <= solnVerbLevel) cout << " dxdp \n" << *dxdp << endl; dgdp_out->Multiply('T', 'N', 1.0, *dgdx, *dxdp, 1.0); } *********************/ }
void DiagonalImplicitRKModelEvaluator<Scalar>::initializeDIRKModel( const RCP<const Thyra::ModelEvaluator<Scalar> >& daeModel, const Thyra::ModelEvaluatorBase::InArgs<Scalar>& basePoint, const RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> >& dirk_W_factory, const RCP<const RKButcherTableauBase<Scalar> >& irkButcherTableau ) { typedef ScalarTraits<Scalar> ST; // ToDo: Assert input arguments! // How do I verify the basePoint is an authentic InArgs from daeModel? TEUCHOS_TEST_FOR_EXCEPTION( is_null(basePoint.get_x()), std::logic_error, "Error! The basepoint x vector is null!" ); TEUCHOS_TEST_FOR_EXCEPTION( is_null(daeModel), std::logic_error, "Error! The model evaluator pointer is null!" ); TEUCHOS_TEST_FOR_EXCEPTION( !daeModel->get_x_space()->isCompatible(*(basePoint.get_x()->space())), std::logic_error, "Error! The basepoint input arguments are incompatible with the model evaluator vector space!" ); //TEUCHOS_TEST_FOR_EXCEPT(is_null(dirk_W_factory)); daeModel_ = daeModel; basePoint_ = basePoint; dirk_W_factory_ = dirk_W_factory; dirkButcherTableau_ = irkButcherTableau; const int numStages = dirkButcherTableau_->numStages(); using Teuchos::rcp_dynamic_cast; stage_space_ = productVectorSpace(daeModel_->get_x_space(),numStages); RCP<const Thyra::VectorSpaceBase<Scalar> > vs = rcp_dynamic_cast<const Thyra::VectorSpaceBase<Scalar> >(stage_space_,true); stage_derivatives_ = rcp_dynamic_cast<Thyra::ProductVectorBase<Scalar> >(createMember(vs),true); Thyra::V_S( rcp_dynamic_cast<Thyra::VectorBase<Scalar> >(stage_derivatives_).ptr(),ST::zero()); // Set up prototypical InArgs { typedef Thyra::ModelEvaluatorBase MEB; MEB::InArgsSetup<Scalar> inArgs; inArgs.setModelEvalDescription(this->description()); inArgs.setSupports(MEB::IN_ARG_x); inArgs_ = inArgs; } // Set up prototypical OutArgs { typedef Thyra::ModelEvaluatorBase MEB; MEB::OutArgsSetup<Scalar> outArgs; outArgs.setModelEvalDescription(this->description()); outArgs.setSupports(MEB::OUT_ARG_f); outArgs.setSupports(MEB::OUT_ARG_W_op); outArgs_ = outArgs; } // Set up nominal values nominalValues_ = inArgs_; isInitialized_ = true; }
virtual void evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<double> &in_args, const Thyra::ModelEvaluatorBase::OutArgs<double> &out_args ) const { const auto & x_in = in_args.get_x(); #ifndef NDEBUG TEUCHOS_ASSERT(!x_in.is_null()); #endif // create corresponding tpetra vector auto x_in_tpetra = Thyra::TpetraOperatorVectorExtraction<double,int,int>::getConstTpetraVector( x_in ); // compute F const auto & f_out = out_args.get_f(); if (!f_out.is_null()) { // Dissect in_args.get_p(0) into parameter sublists. const auto & p_in = in_args.get_p(0); #ifndef NDEBUG TEUCHOS_ASSERT(!p_in.is_null()); // Make sure the parameters aren't NaNs. for (int k = 0; k < p_in->space()->dim(); k++) { TEUCHOS_ASSERT(!std::isnan(Thyra::get_ele(*p_in, k))); } #endif // Fill the parameters into a std::map. const auto param_names = this->get_p_names(0); const double alph = Thyra::get_ele(*p_in, 0); auto f_out_tpetra = Thyra::TpetraOperatorVectorExtraction<double,int,int>::getTpetraVector( f_out ); const auto x_data = x_in_tpetra->getData(); auto f_data = f_out_tpetra->getDataNonConst(); for (size_t i = 0; i < f_data.size(); i++) { f_data[i] = x_data[i] * x_data[i] - alph; } } // Compute df/dp. const auto & derivMv = out_args.get_DfDp(0).getDerivativeMultiVector(); const auto & dfdp_out = derivMv.getMultiVector(); if (!dfdp_out.is_null()) { auto dfdp_out_tpetra = Thyra::TpetraOperatorVectorExtraction<double,int,int>::getTpetraMultiVector( dfdp_out ); TEUCHOS_ASSERT_EQUALITY(dfdp_out_tpetra->getNumVectors(), 1); auto out = dfdp_out_tpetra->getVectorNonConst(0); auto out_data = out->getDataNonConst(); for (size_t k = 0; k < out_data.size(); k++) { out_data[k] = -1.0; } } // Fill Jacobian. const auto & W_out = out_args.get_W_op(); if(!W_out.is_null()) { auto W_outT = Thyra::TpetraOperatorVectorExtraction<double,int,int>::getTpetraOperator( W_out ); const auto & jac = Teuchos::rcp_dynamic_cast<jac_sqrt_alpha>(W_outT, true); jac->set_x0(*x_in_tpetra); } return; }
void Piro::RythmosSolver<Scalar>::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs, const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs ) const { using Teuchos::RCP; using Teuchos::rcp; // Parse InArgs RCP<const Thyra::VectorBase<Scalar> > p_in; if (num_p > 0) p_in = inArgs.get_p(0); // Parse OutArgs: always 1 extra RCP< Thyra::VectorBase<Scalar> > g_out; if (num_g > 0) g_out = outArgs.get_g(0); RCP< Thyra::VectorBase<Scalar> > gx_out = outArgs.get_g(num_g); // Parse out-args for sensitivity calculation RCP< Thyra::MultiVectorBase<Scalar> > dgdp_out; if (num_p>0 && num_g>0) dgdp_out = outArgs.get_DgDp(0,0).getMultiVector(); RCP<const Thyra::VectorBase<Scalar> > finalSolution; Thyra::ModelEvaluatorBase::InArgs<Scalar> state_ic = model->getNominalValues(); // Set paramters p_in as part of initial conditions if (num_p > 0) state_ic.set_p(0,p_in); //*out << "\nstate_ic:\n" << Teuchos::describe(state_ic,Teuchos::VERB_NONE); *out << "\nstate_ic:\n" << Teuchos::describe(state_ic,solnVerbLevel); if (dgdp_out == Teuchos::null) { // *out << "\nE) Solve the forward problem ...\n"; // fwdStateStepper->setInitialCondition(state_ic); fwdStateIntegrator->setStepper(fwdStateStepper, t_final, true); Teuchos::Array<RCP<const Thyra::VectorBase<Scalar> > > x_final_array; fwdStateIntegrator->getFwdPoints( Teuchos::tuple<Scalar>(t_final), &x_final_array, NULL, NULL ); finalSolution = x_final_array[0]; if (Teuchos::VERB_MEDIUM <= solnVerbLevel) std::cout << "Final Solution\n" << *finalSolution << std::endl; // As post-processing step, calc responses at final solution Thyra::ModelEvaluatorBase::InArgs<Scalar> model_inargs = model->createInArgs(); Thyra::ModelEvaluatorBase::OutArgs<Scalar> model_outargs = model->createOutArgs(); model_inargs.set_x(finalSolution); if (num_p > 0) model_inargs.set_p(0, p_in); if (g_out != Teuchos::null) { Thyra::put_scalar(0.0,g_out.ptr()); model_outargs.set_g(0, g_out); } model->evalModel(model_inargs, model_outargs); } else {//Doing sensitivities // *out << "\nE) Solve the forward problem with Sensitivities...\n"; // RCP<Rythmos::ForwardSensitivityStepper<Scalar> > stateAndSensStepper = Rythmos::forwardSensitivityStepper<Scalar>(); stateAndSensStepper->initializeSyncedSteppers( model, 0, model->getNominalValues(), fwdStateStepper, fwdTimeStepSolver); // // Set the initial condition for the state and forward sensitivities // RCP< Thyra::VectorBase<Scalar> > s_bar_init = createMember(stateAndSensStepper->getFwdSensModel()->get_x_space()); assign( s_bar_init.ptr(), 0.0 ); RCP< Thyra::VectorBase<Scalar> > s_bar_dot_init = createMember(stateAndSensStepper->getFwdSensModel()->get_x_space()); assign( s_bar_dot_init.ptr(), 0.0 ); // Above, I believe that these are the correct initial conditions for // s_bar and s_bar_dot given how the EpetraExt::DiagonalTransientModel // is currently implemented! RCP<const Rythmos::StateAndForwardSensitivityModelEvaluator<Scalar> > stateAndSensModel = stateAndSensStepper->getStateAndFwdSensModel(); Thyra::ModelEvaluatorBase::InArgs<Scalar> state_and_sens_ic = stateAndSensStepper->getModel()->createInArgs(); // Copy time, parameters etc. state_and_sens_ic.setArgs(state_ic); // Set initial condition for x_bar = [ x; s_bar ] state_and_sens_ic.set_x( stateAndSensModel->create_x_bar_vec(state_ic.get_x(),s_bar_init) ); // Set initial condition for x_bar_dot = [ x_dot; s_bar_dot ] state_and_sens_ic.set_x_dot( stateAndSensModel->create_x_bar_vec(state_ic.get_x_dot(),s_bar_dot_init) ); // *out << "\nstate_and_sens_ic:\n" << Teuchos::describe(state_and_sens_ic,Teuchos::VERB_DEFAULT); stateAndSensStepper->setInitialCondition(state_and_sens_ic); // // Use a StepperAsModelEvaluator to integrate the state+sens // RCP<Rythmos::StepperAsModelEvaluator<Scalar> > stateAndSensIntegratorAsModel = Rythmos::stepperAsModelEvaluator( Teuchos::rcp_implicit_cast<Rythmos::StepperBase<Scalar> >(stateAndSensStepper), Teuchos::rcp_implicit_cast<Rythmos::IntegratorBase<Scalar> >(fwdStateIntegrator), state_and_sens_ic ); *out << "\nUse the StepperAsModelEvaluator to integrate state + sens x_bar(p,t_final) ... \n"; RCP< Thyra::VectorBase<Scalar> > x_bar_final; Teuchos::OSTab tab(out); x_bar_final = createMember(stateAndSensIntegratorAsModel->get_g_space(0)); eval_g( *stateAndSensIntegratorAsModel, 0, *state_ic.get_p(0), t_final, 0, &*x_bar_final ); *out << "\nx_bar_final = x_bar(p,t_final) evaluated using " << "stateAndSensIntegratorAsModel:\n" << Teuchos::describe(*x_bar_final,solnVerbLevel); // As post-processing step, calc responses and gradient at final solution finalSolution = Thyra::productVectorBase<Scalar>(x_bar_final)->getVectorBlock(0); *out << "\nF) Check the solution to the forward problem ...\n"; // Extract sensitivity vectors into Epetra_MultiVector Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> > dxdp = Teuchos::rcp_dynamic_cast<const Thyra::DefaultMultiVectorProductVector<Scalar> > (Thyra::productVectorBase<Scalar>(x_bar_final)->getVectorBlock(1)) ->getMultiVector();; Thyra::assign(dgdp_out.ptr(), 0.0); /********************* NEED TO CONVERT TO THYRA ******************* Teuchos::RCP<Epetra_MultiVector> dgdx = Teuchos::rcp(new Epetra_MultiVector(finalSolution->Map(), dgdp_out->GlobalLength())); Teuchos::Array<int> p_indexes = outArgs.get_DgDp(0,0).getDerivativeMultiVector().getParamIndexes(); EpetraExt::ModelEvaluator::DerivativeMultiVector dmv_dgdp(dgdp_out, DERIV_MV_BY_COL, p_indexes); EpetraExt::ModelEvaluator::InArgs model_inargs = model->createInArgs(); EpetraExt::ModelEvaluator::OutArgs model_outargs = model->createOutArgs(); model_inargs.set_x(finalSolution); model_inargs.set_p(0, p_in); if (g_out != Teuchos::null) { g_out->PutScalar(0.0); model_outargs.set_g(0, g_out); } model_outargs.set_DgDp(0,0,dmv_dgdp); model_outargs.set_DgDx(0,dgdx); model->evalModel(model_inargs, model_outargs); // (3) Calculate dg/dp = dg/dx*dx/dp + dg/dp // This may be the transpose of what we want since we specified // we want dg/dp by column in createOutArgs(). // In this case just interchange the order of dgdx and dxdp // We should really probably check what the underlying ME does if (Teuchos::VERB_MEDIUM <= solnVerbLevel) cout << " dgdx \n" << *dgdx << endl; if (Teuchos::VERB_MEDIUM <= solnVerbLevel) cout << " dxdp \n" << *dxdp << endl; dgdp_out->Multiply('T', 'N', 1.0, *dgdx, *dxdp, 1.0); *********************/ } // return the final solution as an additional g-vector, if requested if (gx_out != Teuchos::null) Thyra::copy(*finalSolution, gx_out.ptr()); }
void Piro::VelocityVerletSolver<Scalar>::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs, const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs) const { using Teuchos::RCP; using Teuchos::rcp; // TODO: Support more than 1 parameter and 1 response const int j = 0; const int l = 0; // Parse InArgs RCP<const Thyra::VectorBase<Scalar> > p_in; if (num_p > 0) { p_in = inArgs.get_p(l); } // Parse OutArgs RCP<Thyra::VectorBase<Scalar> > g_out; if (num_g > 0) { g_out = outArgs.get_g(j); } const RCP<Thyra::VectorBase<Scalar> > gx_out = outArgs.get_g(num_g); Teuchos::RCP<Thyra::VectorBase<Scalar> > x = inArgs.get_x()->clone_v(); Teuchos::RCP<Thyra::VectorBase<Scalar> > v = inArgs.get_x_dot()->clone_v(); Teuchos::RCP<Thyra::VectorBase<Scalar> > a = Thyra::createMember<Scalar>(model->get_f_space()); RCP<Thyra::VectorBase<Scalar> > finalSolution; // Zero out the acceleration vector put_scalar(0.0, a.ptr()); TEUCHOS_TEST_FOR_EXCEPTION(v == Teuchos::null || x == Teuchos::null, Teuchos::Exceptions::InvalidParameter, std::endl << "Error in Piro::VelocityVerletSolver " << "Requires initial x and x_dot: " << std::endl); Scalar t = t_init; // Observe initial condition if (observer != Teuchos::null) observer->observeSolution(*x, t); Scalar vo = norm_2(*v); *out << "Initial Velocity = " << vo << std::endl; if (Teuchos::VERB_MEDIUM <= solnVerbLevel) *out << std::endl; Thyra::ModelEvaluatorBase::InArgs<Scalar> model_inargs = model->createInArgs(); Thyra::ModelEvaluatorBase::OutArgs<Scalar> model_outargs = model->createOutArgs(); model_inargs.set_x(x); if (num_p > 0) model_inargs.set_p(0, p_in); model_outargs.set_f(a); if (g_out != Teuchos::null) model_outargs.set_g(0, g_out); Scalar ddt = 0.5 * delta_t * delta_t; // Calculate acceleration at time 0 model->evalModel(model_inargs, model_outargs); for (int timeStep = 1; timeStep <= numTimeSteps; timeStep++) { // x->Update(delta_t, *v, ddt, *a, 1.0); V_StVpStV(x.ptr(), delta_t, *v, ddt, *a); t += delta_t; model_inargs.set_t(t); // v->Update(0.5*delta_t, *a, 1.0); V_StV(v.ptr(), 0.5 * delta_t, *a); //calc a(x,t,p); model->evalModel(model_inargs, model_outargs); // v->Update(0.5*delta_t, *a, 1.0); V_StV(v.ptr(), 0.5 * delta_t, *a); // Observe completed time step if (observer != Teuchos::null) observer->observeSolution(*x, t); } // return the final solution as an additional g-vector, if requested if (finalSolution != Teuchos::null) finalSolution = x->clone_v(); // Return the final solution as an additional g-vector, if requested if (Teuchos::nonnull(gx_out)) { Thyra::copy(*finalSolution, gx_out.ptr()); } }
void Piro::SteadyStateSolver<Scalar>::evalConvergedModel( const Thyra::ModelEvaluatorBase::InArgs<Scalar>& modelInArgs, const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs) const { using Teuchos::RCP; using Teuchos::rcp; // Solution at convergence is the response at index num_g_ { const RCP<Thyra::VectorBase<Scalar> > gx_out = outArgs.get_g(num_g_); if (Teuchos::nonnull(gx_out)) { Thyra::copy(*modelInArgs.get_x(), gx_out.ptr()); } } // Setup output for final evalution of underlying model Thyra::ModelEvaluatorBase::OutArgs<Scalar> modelOutArgs = model_->createOutArgs(); { // Responses for (int j = 0; j < num_g_; ++j) { const RCP<Thyra::VectorBase<Scalar> > g_out = outArgs.get_g(j); // Forward to underlying model modelOutArgs.set_g(j, g_out); } // Jacobian { bool jacobianRequired = false; for (int j = 0; j <= num_g_; ++j) { for (int l = 0; l < num_p_; ++l) { const Thyra::ModelEvaluatorBase::DerivativeSupport dgdp_support = outArgs.supports(Thyra::ModelEvaluatorBase::OUT_ARG_DgDp, j, l); if (!dgdp_support.none()) { const Thyra::ModelEvaluatorBase::Derivative<Scalar> dgdp_deriv = outArgs.get_DgDp(j, l); if (!dgdp_deriv.isEmpty()) { jacobianRequired = true; } } } } if (jacobianRequired) { const RCP<Thyra::LinearOpWithSolveBase<Scalar> > jacobian = model_->create_W(); modelOutArgs.set_W(jacobian); } } // DfDp derivatives for (int l = 0; l < num_p_; ++l) { Thyra::ModelEvaluatorBase::DerivativeSupport dfdp_request; for (int j = 0; j <= num_g_; ++j) { const Thyra::ModelEvaluatorBase::DerivativeSupport dgdp_support = outArgs.supports(Thyra::ModelEvaluatorBase::OUT_ARG_DgDp, j, l); if (!dgdp_support.none()) { const Thyra::ModelEvaluatorBase::Derivative<Scalar> dgdp_deriv = outArgs.get_DgDp(j, l); if (Teuchos::nonnull(dgdp_deriv.getLinearOp())) { dfdp_request.plus(Thyra::ModelEvaluatorBase::DERIV_LINEAR_OP); } else if (Teuchos::nonnull(dgdp_deriv.getMultiVector())) { dfdp_request.plus(Thyra::ModelEvaluatorBase::DERIV_MV_JACOBIAN_FORM); } } } if (!dfdp_request.none()) { Thyra::ModelEvaluatorBase::Derivative<Scalar> dfdp_deriv; if (dfdp_request.supports(Thyra::ModelEvaluatorBase::DERIV_MV_JACOBIAN_FORM)) { dfdp_deriv = Thyra::create_DfDp_mv(*model_, l, Thyra::ModelEvaluatorBase::DERIV_MV_JACOBIAN_FORM); } else if (dfdp_request.supports(Thyra::ModelEvaluatorBase::DERIV_LINEAR_OP)) { dfdp_deriv = model_->create_DfDp_op(l); } modelOutArgs.set_DfDp(l, dfdp_deriv); } } // DgDx derivatives for (int j = 0; j < num_g_; ++j) { Thyra::ModelEvaluatorBase::DerivativeSupport dgdx_request; for (int l = 0; l < num_p_; ++l) { const Thyra::ModelEvaluatorBase::DerivativeSupport dgdp_support = outArgs.supports(Thyra::ModelEvaluatorBase::OUT_ARG_DgDp, j, l); if (!dgdp_support.none()) { const Thyra::ModelEvaluatorBase::Derivative<Scalar> dgdp_deriv = outArgs.get_DgDp(j, l); if (!dgdp_deriv.isEmpty()) { const bool dgdp_mvGrad_required = Teuchos::nonnull(dgdp_deriv.getMultiVector()) && dgdp_deriv.getMultiVectorOrientation() == Thyra::ModelEvaluatorBase::DERIV_MV_GRADIENT_FORM; if (dgdp_mvGrad_required) { dgdx_request.plus(Thyra::ModelEvaluatorBase::DERIV_MV_GRADIENT_FORM); } else { dgdx_request.plus(Thyra::ModelEvaluatorBase::DERIV_LINEAR_OP); } } } } if (!dgdx_request.none()) { Thyra::ModelEvaluatorBase::Derivative<Scalar> dgdx_deriv; if (dgdx_request.supports(Thyra::ModelEvaluatorBase::DERIV_MV_GRADIENT_FORM)) { dgdx_deriv = Thyra::create_DgDx_mv(*model_, j, Thyra::ModelEvaluatorBase::DERIV_MV_GRADIENT_FORM); } else if (dgdx_request.supports(Thyra::ModelEvaluatorBase::DERIV_LINEAR_OP)) { dgdx_deriv = model_->create_DgDx_op(j); } modelOutArgs.set_DgDx(j, dgdx_deriv); } } // DgDp derivatives for (int l = 0; l < num_p_; ++l) { for (int j = 0; j < num_g_; ++j) { const Thyra::ModelEvaluatorBase::DerivativeSupport dgdp_support = outArgs.supports(Thyra::ModelEvaluatorBase::OUT_ARG_DgDp, j, l); if (!dgdp_support.none()) { const Thyra::ModelEvaluatorBase::Derivative<Scalar> dgdp_deriv = outArgs.get_DgDp(j, l); Thyra::ModelEvaluatorBase::Derivative<Scalar> model_dgdp_deriv; const RCP<Thyra::LinearOpBase<Scalar> > dgdp_op = dgdp_deriv.getLinearOp(); if (Teuchos::nonnull(dgdp_op)) { model_dgdp_deriv = model_->create_DgDp_op(j, l); } else { model_dgdp_deriv = dgdp_deriv; } if (!model_dgdp_deriv.isEmpty()) { modelOutArgs.set_DgDp(j, l, model_dgdp_deriv); } } } } } // Evaluate underlying model model_->evalModel(modelInArgs, modelOutArgs); // Assemble user-requested sensitivities if (modelOutArgs.supports(Thyra::ModelEvaluatorBase::OUT_ARG_W)) { const RCP<Thyra::LinearOpWithSolveBase<Scalar> > jacobian = modelOutArgs.get_W(); if (Teuchos::nonnull(jacobian)) { for (int l = 0; l < num_p_; ++l) { const Thyra::ModelEvaluatorBase::DerivativeSupport dfdp_support = modelOutArgs.supports(Thyra::ModelEvaluatorBase::OUT_ARG_DfDp, l); if (!dfdp_support.none()) { const Thyra::ModelEvaluatorBase::Derivative<Scalar> dfdp_deriv = modelOutArgs.get_DfDp(l); const RCP<Thyra::MultiVectorBase<Scalar> > dfdp_mv = dfdp_deriv.getMultiVector(); RCP<Thyra::LinearOpBase<Scalar> > dfdp_op = dfdp_deriv.getLinearOp(); if (Teuchos::is_null(dfdp_op)) { dfdp_op = dfdp_mv; } const Thyra::ModelEvaluatorBase::Derivative<Scalar> dxdp_deriv = outArgs.get_DgDp(num_g_, l); const RCP<Thyra::LinearOpBase<Scalar> > dxdp_op = dxdp_deriv.getLinearOp(); const RCP<Thyra::MultiVectorBase<Scalar> > dxdp_mv = dxdp_deriv.getMultiVector(); RCP<const Thyra::LinearOpBase<Scalar> > minus_dxdp_op; RCP<Thyra::MultiVectorBase<Scalar> > minus_dxdp_mv; if (Teuchos::nonnull(dfdp_mv)) { if (Teuchos::nonnull(dxdp_mv)) { minus_dxdp_mv = dxdp_mv; // Use user-provided object as temporary } else { minus_dxdp_mv = Thyra::createMembers(model_->get_x_space(), model_->get_p_space(l)); minus_dxdp_op = minus_dxdp_mv; } } if (Teuchos::is_null(minus_dxdp_op)) { const RCP<const Thyra::LinearOpBase<Scalar> > dfdx_inv_op = Thyra::inverse<Scalar>(jacobian); minus_dxdp_op = Thyra::multiply<Scalar>(dfdx_inv_op, dfdp_op); } if (Teuchos::nonnull(minus_dxdp_mv)) { Thyra::assign(minus_dxdp_mv.ptr(), Teuchos::ScalarTraits<Scalar>::zero()); const Thyra::SolveCriteria<Scalar> defaultSolveCriteria; const Thyra::SolveStatus<Scalar> solveStatus = Thyra::solve( *jacobian, Thyra::NOTRANS, *dfdp_mv, minus_dxdp_mv.ptr(), Teuchos::ptr(&defaultSolveCriteria)); TEUCHOS_TEST_FOR_EXCEPTION( solveStatus.solveStatus == Thyra::SOLVE_STATUS_UNCONVERGED, std::runtime_error, "Jacobian solver failed to converge"); } // Solution sensitivities if (Teuchos::nonnull(dxdp_mv)) { minus_dxdp_mv = Teuchos::null; // Invalidates temporary Thyra::scale(-Teuchos::ScalarTraits<Scalar>::one(), dxdp_mv.ptr()); } else if (Teuchos::nonnull(dxdp_op)) { const RCP<Thyra::DefaultMultipliedLinearOp<Scalar> > dxdp_op_downcasted = Teuchos::rcp_dynamic_cast<Thyra::DefaultMultipliedLinearOp<Scalar> >(dxdp_op); TEUCHOS_TEST_FOR_EXCEPTION( Teuchos::is_null(dxdp_op_downcasted), std::invalid_argument, "Illegal operator for DgDp(" << "j = " << num_g_ << ", " << "index l = " << l << ")\n"); const RCP<const Thyra::LinearOpBase<Scalar> > minus_id_op = Thyra::scale<Scalar>(-Teuchos::ScalarTraits<Scalar>::one(), Thyra::identity(dfdp_op->domain())); dxdp_op_downcasted->initialize(Teuchos::tuple(minus_dxdp_op, minus_id_op)); } // Response sensitivities for (int j = 0; j < num_g_; ++j) { const Thyra::ModelEvaluatorBase::DerivativeSupport dgdp_support = outArgs.supports(Thyra::ModelEvaluatorBase::OUT_ARG_DgDp, j, l); if (!dgdp_support.none()) { const Thyra::ModelEvaluatorBase::Derivative<Scalar> dgdp_deriv = outArgs.get_DgDp(j, l); if (!dgdp_deriv.isEmpty()) { const Thyra::ModelEvaluatorBase::Derivative<Scalar> dgdx_deriv = modelOutArgs.get_DgDx(j); const RCP<const Thyra::MultiVectorBase<Scalar> > dgdx_mv = dgdx_deriv.getMultiVector(); RCP<const Thyra::LinearOpBase<Scalar> > dgdx_op = dgdx_deriv.getLinearOp(); if (Teuchos::is_null(dgdx_op)) { dgdx_op = Thyra::adjoint<Scalar>(dgdx_mv); } const RCP<Thyra::LinearOpBase<Scalar> > dgdp_op = dgdp_deriv.getLinearOp(); if (Teuchos::nonnull(dgdp_op)) { const RCP<Thyra::DefaultAddedLinearOp<Scalar> > dgdp_op_downcasted = Teuchos::rcp_dynamic_cast<Thyra::DefaultAddedLinearOp<Scalar> >(dgdp_op); TEUCHOS_TEST_FOR_EXCEPTION( Teuchos::is_null(dgdp_op_downcasted), std::invalid_argument, "Illegal operator for DgDp(" << "j = " << j << ", " << "index l = " << l << ")\n"); dgdp_op_downcasted->uninitialize(); const RCP<const Thyra::LinearOpBase<Scalar> > implicit_dgdp_op = Thyra::multiply<Scalar>( Thyra::scale<Scalar>(-Teuchos::ScalarTraits<Scalar>::one(), dgdx_op), minus_dxdp_op); const RCP<const Thyra::LinearOpBase<Scalar> > model_dgdp_op = modelOutArgs.get_DgDp(j, l).getLinearOp(); Teuchos::Array<RCP<const Thyra::LinearOpBase<Scalar> > > op_args(2); op_args[0] = model_dgdp_op; op_args[1] = implicit_dgdp_op; dgdp_op_downcasted->initialize(op_args); } const RCP<Thyra::MultiVectorBase<Scalar> > dgdp_mv = dgdp_deriv.getMultiVector(); if (Teuchos::nonnull(dgdp_mv)) { if (dgdp_deriv.getMultiVectorOrientation() == Thyra::ModelEvaluatorBase::DERIV_MV_GRADIENT_FORM) { if (Teuchos::nonnull(dxdp_mv)) { Thyra::apply( *dxdp_mv, Thyra::TRANS, *dgdx_mv, dgdp_mv.ptr(), Teuchos::ScalarTraits<Scalar>::one(), Teuchos::ScalarTraits<Scalar>::one()); } else { Thyra::apply( *minus_dxdp_mv, Thyra::TRANS, *dgdx_mv, dgdp_mv.ptr(), -Teuchos::ScalarTraits<Scalar>::one(), Teuchos::ScalarTraits<Scalar>::one()); } } else { if (Teuchos::nonnull(dxdp_mv)) { Thyra::apply( *dgdx_op, Thyra::NOTRANS, *dxdp_mv, dgdp_mv.ptr(), Teuchos::ScalarTraits<Scalar>::one(), Teuchos::ScalarTraits<Scalar>::one()); } else { Thyra::apply( *dgdx_op, Thyra::NOTRANS, *minus_dxdp_mv, dgdp_mv.ptr(), -Teuchos::ScalarTraits<Scalar>::one(), Teuchos::ScalarTraits<Scalar>::one()); } } } } } } } } } } }
void ForwardSensitivityExplicitModelEvaluator<Scalar>::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs, const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs ) const { using Teuchos::rcp_dynamic_cast; typedef Teuchos::ScalarTraits<Scalar> ST; typedef Thyra::ModelEvaluatorBase MEB; typedef Teuchos::VerboseObjectTempState<Thyra::ModelEvaluatorBase> VOTSME; THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_GEN_BEGIN( "ForwardSensitivityExplicitModelEvaluator", inArgs, outArgs, Teuchos::null ); // // Update the derivative matrices if they are not already updated for the // given time!. // { RYTHMOS_FUNC_TIME_MONITOR_DIFF( "Rythmos:ForwardSensitivityExplicitModelEvaluator::evalModel: computeMatrices", Rythmos_FSEME ); computeDerivativeMatrices(inArgs); } // // InArgs // RCP<const Thyra::DefaultMultiVectorProductVector<Scalar> > s_bar = rcp_dynamic_cast<const Thyra::DefaultMultiVectorProductVector<Scalar> >( inArgs.get_x().assert_not_null(), true ); RCP<const Thyra::MultiVectorBase<Scalar> > S = s_bar->getMultiVector(); // // OutArgs // RCP<Thyra::DefaultMultiVectorProductVector<Scalar> > f_sens = rcp_dynamic_cast<Thyra::DefaultMultiVectorProductVector<Scalar> >( outArgs.get_f(), true ); RCP<Thyra::MultiVectorBase<Scalar> > F_sens = f_sens->getNonconstMultiVector().assert_not_null(); // // Compute the requested functions // if(!is_null(F_sens)) { RYTHMOS_FUNC_TIME_MONITOR_DIFF( "Rythmos:ForwardSensitivityExplicitModelEvaluator::evalModel: computeSens", Rythmos_FSEME ); // Form the residual: df/dx * S + df/dp // F_sens = df/dx * S Thyra::apply( *DfDx_, Thyra::NOTRANS, *S, F_sens.ptr(), ST::one(), ST::zero() ); // F_sens += d(f)/d(p) Vp_V( F_sens.ptr(), *DfDp_ ); } THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_END(); }