00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef RYTHMOS_IMPLICITRK_MODEL_EVALUATOR_HPP
00031 #define RYTHMOS_IMPLICITRK_MODEL_EVALUATOR_HPP
00032
00033
00034 #include "Rythmos_Types.hpp"
00035 #include "Rythmos_RKButcherTableauHelpers.hpp"
00036 #include "Thyra_StateFuncModelEvaluatorBase.hpp"
00037 #include "Thyra_ModelEvaluatorHelpers.hpp"
00038 #include "Thyra_ModelEvaluatorDelegatorBase.hpp"
00039 #include "Thyra_DefaultProductVectorSpace.hpp"
00040 #include "Thyra_DefaultBlockedLinearOp.hpp"
00041 #include "Thyra_VectorStdOps.hpp"
00042 #include "Thyra_TestingTools.hpp"
00043 #include "Teuchos_as.hpp"
00044 #include "Teuchos_SerialDenseMatrix.hpp"
00045 #include "Teuchos_SerialDenseVector.hpp"
00046 #include "Teuchos_Assert.hpp"
00047
00048
00049 namespace Rythmos {
00050
00051
00053 template<class Scalar>
00054 class ImplicitRKModelEvaluator : virtual public Thyra::StateFuncModelEvaluatorBase<Scalar>
00055 {
00056 public:
00057
00060
00062 ImplicitRKModelEvaluator();
00063
00065 void initializeIRKModel(
00066 const RCP<const Thyra::ModelEvaluator<Scalar> > &daeModel,
00067 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &basePoint,
00068 const RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > &irk_W_factory,
00069 const RCP<const RKButcherTableauBase<Scalar> > &irkButcherTableau
00070 );
00071
00073 void setTimeStepPoint(
00074 const RCP<const Thyra::VectorBase<Scalar> > &x_old,
00075 const Scalar &t_old,
00076 const Scalar &delta_t
00077 );
00078
00080
00083
00085 RCP<const Thyra::VectorSpaceBase<Scalar> > get_x_space() const;
00087 RCP<const Thyra::VectorSpaceBase<Scalar> > get_f_space() const;
00089 RCP<Thyra::LinearOpBase<Scalar> > create_W_op() const;
00091 RCP<const Thyra::LinearOpWithSolveFactoryBase<Scalar> > get_W_factory() const;
00093 Thyra::ModelEvaluatorBase::InArgs<Scalar> getNominalValues() const;
00095 Thyra::ModelEvaluatorBase::InArgs<Scalar> createInArgs() const;
00096
00098
00099 private:
00100
00103
00105 Thyra::ModelEvaluatorBase::OutArgs<Scalar> createOutArgsImpl() const;
00107 void evalModelImpl(
00108 const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs,
00109 const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs
00110 ) const;
00111
00113
00114
00115 private:
00116
00117 RCP<const Thyra::ModelEvaluator<Scalar> > daeModel_;
00118 Thyra::ModelEvaluatorBase::InArgs<Scalar> basePoint_;
00119 RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > irk_W_factory_;
00120 RCP<const RKButcherTableauBase<Scalar> > irkButcherTableau_;
00121
00122 Thyra::ModelEvaluatorBase::InArgs<Scalar> inArgs_;
00123 Thyra::ModelEvaluatorBase::OutArgs<Scalar> outArgs_;
00124 Thyra::ModelEvaluatorBase::InArgs<Scalar> nominalValues_;
00125
00126 RCP<const Thyra::ProductVectorSpaceBase<Scalar> > x_bar_space_;
00127 RCP<const Thyra::ProductVectorSpaceBase<Scalar> > f_bar_space_;
00128 RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > W_bar_factory_;
00129
00130 bool setTimeStepPointCalled_;
00131 RCP<const Thyra::VectorBase<Scalar> > x_old_;
00132 Scalar t_old_;
00133 Scalar delta_t_;
00134
00135 bool isInitialized_;
00136
00137 };
00138
00139
00144 template<class Scalar>
00145 RCP<ImplicitRKModelEvaluator<Scalar> >
00146 implicitRKModelEvaluator(
00147 const RCP<const Thyra::ModelEvaluator<Scalar> > &daeModel,
00148 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &basePoint,
00149 const RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > &irk_W_factory,
00150 const RCP<const RKButcherTableauBase<Scalar> > &irkButcherTableau
00151 )
00152 {
00153 RCP<ImplicitRKModelEvaluator<Scalar> >
00154 irkModel = rcp(new ImplicitRKModelEvaluator<Scalar>());
00155 irkModel->initializeIRKModel(daeModel,basePoint,irk_W_factory,irkButcherTableau);
00156 return irkModel;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 template<class Scalar>
00168 ImplicitRKModelEvaluator<Scalar>::ImplicitRKModelEvaluator()
00169 {
00170 setTimeStepPointCalled_ = false;
00171 isInitialized_ = false;
00172 }
00173
00174
00175
00176
00177
00178 template<class Scalar>
00179 void ImplicitRKModelEvaluator<Scalar>::initializeIRKModel(
00180 const RCP<const Thyra::ModelEvaluator<Scalar> > &daeModel,
00181 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &basePoint,
00182 const RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > &irk_W_factory,
00183 const RCP<const RKButcherTableauBase<Scalar> > &irkButcherTableau
00184 )
00185 {
00186
00187
00188 TEST_FOR_EXCEPTION(
00189 is_null(basePoint.get_x()),
00190 std::logic_error,
00191 "Error! The basepoint x vector is null!"
00192 );
00193 TEST_FOR_EXCEPTION(
00194 is_null(daeModel),
00195 std::logic_error,
00196 "Error! The model evaluator pointer is null!"
00197 );
00198 TEST_FOR_EXCEPTION(
00199 !daeModel->get_x_space()->isCompatible(*(basePoint.get_x()->space())),
00200 std::logic_error,
00201 "Error! The basepoint input arguments are incompatible with the model evaluator vector space!"
00202 );
00203 TEST_FOR_EXCEPT(is_null(irk_W_factory));
00204
00205 daeModel_ = daeModel;
00206 basePoint_ = basePoint;
00207 irk_W_factory_ = irk_W_factory;
00208 irkButcherTableau_ = irkButcherTableau;
00209
00210 const int numStages = irkButcherTableau_->numStages();
00211
00212 x_bar_space_ = productVectorSpace(daeModel_->get_x_space(),numStages);
00213 f_bar_space_ = productVectorSpace(daeModel_->get_f_space(),numStages);
00214
00215
00216 if (irk_W_factory_->acceptsPreconditionerFactory())
00217 irk_W_factory_->unsetPreconditionerFactory();
00218
00219
00220
00221
00222
00223 {
00224 typedef Thyra::ModelEvaluatorBase MEB;
00225 MEB::InArgsSetup<Scalar> inArgs;
00226 inArgs.setModelEvalDescription(this->description());
00227 inArgs.setSupports(MEB::IN_ARG_x);
00228 inArgs_ = inArgs;
00229 }
00230
00231 {
00232 typedef Thyra::ModelEvaluatorBase MEB;
00233 MEB::OutArgsSetup<Scalar> outArgs;
00234 outArgs.setModelEvalDescription(this->description());
00235 outArgs.setSupports(MEB::OUT_ARG_f);
00236 outArgs.setSupports(MEB::OUT_ARG_W_op);
00237 outArgs_ = outArgs;
00238 }
00239
00240 nominalValues_ = inArgs_;
00241
00242 isInitialized_ = true;
00243 }
00244
00245
00246 template<class Scalar>
00247 void ImplicitRKModelEvaluator<Scalar>::setTimeStepPoint(
00248 const RCP<const Thyra::VectorBase<Scalar> > &x_old,
00249 const Scalar &t_old,
00250 const Scalar &delta_t
00251 )
00252 {
00253 typedef ScalarTraits<Scalar> ST;
00254 TEST_FOR_EXCEPT( is_null(x_old) );
00255 TEST_FOR_EXCEPT( delta_t <= ST::zero() );
00256
00257 TEST_FOR_EXCEPTION(!daeModel_->get_x_space()->isCompatible(*(x_old->space())), std::logic_error,
00258 "Error! The incoming VectorBase object is not compatible with the DAE model that was provided at initialization!");
00259 x_old_ = x_old;
00260 t_old_ = t_old;
00261 delta_t_ = delta_t;
00262 setTimeStepPointCalled_ = true;
00263 }
00264
00265
00266
00267
00268
00269 template<class Scalar>
00270 RCP<const Thyra::VectorSpaceBase<Scalar> >
00271 ImplicitRKModelEvaluator<Scalar>::get_x_space() const
00272 {
00273 TEST_FOR_EXCEPTION( !isInitialized_, std::logic_error,
00274 "Error, initializeIRKModel must be called first!\n"
00275 );
00276 return x_bar_space_;
00277 }
00278
00279
00280 template<class Scalar>
00281 RCP<const Thyra::VectorSpaceBase<Scalar> >
00282 ImplicitRKModelEvaluator<Scalar>::get_f_space() const
00283 {
00284 TEST_FOR_EXCEPTION( !isInitialized_, std::logic_error,
00285 "Error, initializeIRKModel must be called first!\n"
00286 );
00287 return f_bar_space_;
00288 }
00289
00290
00291 template<class Scalar>
00292 RCP<Thyra::LinearOpBase<Scalar> >
00293 ImplicitRKModelEvaluator<Scalar>::create_W_op() const
00294 {
00295 TEST_FOR_EXCEPTION( !isInitialized_, std::logic_error,
00296 "Error, initializeIRKModel must be called first!\n"
00297 );
00298
00299 const int numStages = irkButcherTableau_->numStages();
00300 RCP<Thyra::PhysicallyBlockedLinearOpBase<Scalar> >
00301 W_op_bar = Thyra::defaultBlockedLinearOp<Scalar>();
00302 W_op_bar->beginBlockFill( f_bar_space_, x_bar_space_ );
00303 for ( int i = 0; i < numStages; ++i )
00304 for ( int j = 0; j < numStages; ++j )
00305 W_op_bar->setNonconstBlock( i, j, daeModel_->create_W_op() );
00306 W_op_bar->endBlockFill();
00307 return W_op_bar;
00308 }
00309
00310
00311 template<class Scalar>
00312 RCP<const Thyra::LinearOpWithSolveFactoryBase<Scalar> >
00313 ImplicitRKModelEvaluator<Scalar>::get_W_factory() const
00314 {
00315 TEST_FOR_EXCEPTION( !isInitialized_, std::logic_error,
00316 "Error, initializeIRKModel must be called first!\n"
00317 );
00318 return irk_W_factory_;
00319 }
00320
00321
00322 template<class Scalar>
00323 Thyra::ModelEvaluatorBase::InArgs<Scalar>
00324 ImplicitRKModelEvaluator<Scalar>::getNominalValues() const
00325 {
00326 TEST_FOR_EXCEPTION( !isInitialized_, std::logic_error,
00327 "Error, initializeIRKModel must be called first!\n"
00328 );
00329 return nominalValues_;
00330 }
00331
00332
00333 template<class Scalar>
00334 Thyra::ModelEvaluatorBase::InArgs<Scalar>
00335 ImplicitRKModelEvaluator<Scalar>::createInArgs() const
00336 {
00337 TEST_FOR_EXCEPTION( !isInitialized_, std::logic_error,
00338 "Error, initializeIRKModel must be called first!\n"
00339 );
00340 return inArgs_;
00341 }
00342
00343
00344
00345
00346
00347 template<class Scalar>
00348 Thyra::ModelEvaluatorBase::OutArgs<Scalar>
00349 ImplicitRKModelEvaluator<Scalar>::createOutArgsImpl() const
00350 {
00351 TEST_FOR_EXCEPTION( !isInitialized_, std::logic_error,
00352 "Error, initializeIRKModel must be called first!\n"
00353 );
00354 return outArgs_;
00355 }
00356
00357
00358 template<class Scalar>
00359 void ImplicitRKModelEvaluator<Scalar>::evalModelImpl(
00360 const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs_bar,
00361 const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs_bar
00362 ) const
00363 {
00364
00365 using Teuchos::rcp_dynamic_cast;
00366 typedef ScalarTraits<Scalar> ST;
00367 typedef Thyra::ModelEvaluatorBase MEB;
00368 typedef Thyra::VectorBase<Scalar> VB;
00369 typedef Thyra::ProductVectorBase<Scalar> PVB;
00370 typedef Thyra::BlockedLinearOpBase<Scalar> BLWB;
00371
00372 TEST_FOR_EXCEPTION( !isInitialized_, std::logic_error,
00373 "Error! initializeIRKModel must be called before evalModel\n"
00374 );
00375
00376 TEST_FOR_EXCEPTION( !setTimeStepPointCalled_, std::logic_error,
00377 "Error! setTimeStepPoint must be called before evalModel"
00378 );
00379
00380 THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_GEN_BEGIN(
00381 "Rythmos::ImplicitRKModelEvaluator",inArgs_bar,outArgs_bar,daeModel_
00382 );
00383
00384
00385
00386
00387
00388 const RCP<const PVB> x_bar = rcp_dynamic_cast<const PVB>(inArgs_bar.get_x(), true);
00389 const RCP<PVB> f_bar = rcp_dynamic_cast<PVB>(outArgs_bar.get_f(), true);
00390 const RCP<BLWB> W_op_bar = rcp_dynamic_cast<BLWB>(outArgs_bar.get_W_op(), true);
00391
00392
00393
00394
00395
00396 MEB::InArgs<Scalar> daeInArgs = daeModel_->createInArgs();
00397 MEB::OutArgs<Scalar> daeOutArgs = daeModel_->createOutArgs();
00398 const RCP<VB> x_i = createMember(daeModel_->get_x_space());
00399 daeInArgs.setArgs(basePoint_);
00400
00401 const int numStages = irkButcherTableau_->numStages();
00402
00403 for ( int i = 0; i < numStages; ++i ) {
00404
00405
00406 assembleIRKState( i, irkButcherTableau_->A(), delta_t_, *x_old_, *x_bar, outArg(*x_i) );
00407 daeInArgs.set_x( x_i );
00408 daeInArgs.set_x_dot( x_bar->getVectorBlock(i) );
00409 daeInArgs.set_t( t_old_ + irkButcherTableau_->c()(i) * delta_t_ );
00410 Scalar alpha = ST::zero();
00411 if (i == 0) {
00412 alpha = ST::one();
00413 } else {
00414 alpha = ST::zero();
00415 }
00416 Scalar beta = delta_t_ * irkButcherTableau_->A()(i,0);
00417 daeInArgs.set_alpha( alpha );
00418 daeInArgs.set_beta( beta );
00419
00420
00421 if (!is_null(f_bar))
00422 daeOutArgs.set_f( f_bar->getNonconstVectorBlock(i) );
00423 if (!is_null(W_op_bar)) {
00424 daeOutArgs.set_W_op(W_op_bar->getNonconstBlock(i,0));
00425 }
00426
00427
00428 daeModel_->evalModel( daeInArgs, daeOutArgs );
00429 daeOutArgs.set_f(Teuchos::null);
00430 daeOutArgs.set_W_op(Teuchos::null);
00431
00432
00433 if (!is_null(W_op_bar)) {
00434 for ( int j = 1; j < numStages; ++j ) {
00435 Scalar alpha = ST::zero();
00436 if (i == j) {
00437 alpha = ST::one();
00438 } else {
00439 alpha = ST::zero();
00440 }
00441 Scalar beta = delta_t_ * irkButcherTableau_->A()(i,j);
00442 daeInArgs.set_alpha( alpha );
00443 daeInArgs.set_beta( beta );
00444 daeOutArgs.set_W_op(W_op_bar->getNonconstBlock(i,j));
00445 daeModel_->evalModel( daeInArgs, daeOutArgs );
00446 daeOutArgs.set_W_op(Teuchos::null);
00447 }
00448 }
00449
00450 }
00451
00452 THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_END();
00453
00454 }
00455
00456
00457 }
00458
00459
00460 #endif // RYTHMOS_IMPLICITRK_MODEL_EVALUATOR_HPP