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 #ifndef RYTHMOS_FORWARD_RESPONSE_SENSITIVITY_COMPUTER_HPP
00030 #define RYTHMOS_FORWARD_RESPONSE_SENSITIVITY_COMPUTER_HPP
00031
00032
00033 #include "Rythmos_Types.hpp"
00034 #include "Thyra_ModelEvaluator.hpp"
00035 #include "Teuchos_VerboseObject.hpp"
00036 #include "Teuchos_StandardMemberCompositionMacros.hpp"
00037
00038
00039 namespace Rythmos {
00040
00041
00048 template<class Scalar>
00049 class ForwardResponseSensitivityComputer
00050 : public Teuchos::VerboseObject<ForwardResponseSensitivityComputer<Scalar> >
00051 {
00052 public:
00053
00055 ForwardResponseSensitivityComputer();
00056
00058 STANDARD_MEMBER_COMPOSITION_MEMBERS( bool, dumpSensitivities );
00059
00076 void setResponseFunction(
00077 const RCP<const Thyra::ModelEvaluator<Scalar> > &responseFunc,
00078 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &basePoint,
00079 const int p_index,
00080 const int g_index
00081 );
00082
00087 void resetResponseFunction(
00088 const RCP<const Thyra::ModelEvaluator<Scalar> > &responseFunc,
00089 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &basePoint
00090 );
00091
00093 const RCP<Thyra::VectorBase<Scalar> > create_g_hat() const;
00094
00096 const RCP<Thyra::MultiVectorBase<Scalar> > create_D_g_hat_D_p() const;
00097
00110 void computeResponse(
00111 const Thyra::VectorBase<Scalar> *x_dot,
00112 const Thyra::VectorBase<Scalar> &x,
00113 const Scalar t,
00114 Thyra::VectorBase<Scalar> *g_hat
00115 ) const;
00116
00136 void computeResponseAndSensitivity(
00137 const Thyra::VectorBase<Scalar> *x_dot,
00138 const Thyra::MultiVectorBase<Scalar> *S_dot,
00139 const Thyra::VectorBase<Scalar> &x,
00140 const Thyra::MultiVectorBase<Scalar> &S,
00141 const Scalar t,
00142 Thyra::VectorBase<Scalar> *g_hat,
00143 Thyra::MultiVectorBase<Scalar> *D_g_hat_D_p
00144 ) const;
00145
00146 private:
00147
00148 RCP<const Thyra::ModelEvaluator<Scalar> > responseFunc_;
00149 Thyra::ModelEvaluatorBase::InArgs<Scalar> basePoint_;
00150 int p_index_;
00151 int g_index_;
00152
00153 RCP<const Thyra::VectorSpaceBase<Scalar> > p_space_;
00154 RCP<const Thyra::VectorSpaceBase<Scalar> > g_space_;
00155
00156 bool response_func_supports_x_dot_;
00157 bool response_func_supports_D_x_dot_;
00158 bool response_func_supports_D_p_;
00159
00160 mutable Thyra::ModelEvaluatorBase::InArgs<Scalar> responseInArgs_;
00161 mutable Thyra::ModelEvaluatorBase::OutArgs<Scalar> responseOutArgs_;
00162
00163 mutable RCP<Thyra::LinearOpBase<Scalar> > D_g_D_x_dot_;
00164 mutable RCP<Thyra::LinearOpBase<Scalar> > D_g_D_x_;
00165 mutable RCP<Thyra::MultiVectorBase<Scalar> > D_g_D_p_;
00166
00167 private:
00168
00169 void clearCache();
00170
00171 void createCache(const bool computeSens) const;
00172
00173 void computeResponseAndSensitivityImpl(
00174 const Thyra::VectorBase<Scalar> *x_dot,
00175 const Thyra::MultiVectorBase<Scalar> *S_dot,
00176 const Thyra::VectorBase<Scalar> &x,
00177 const Thyra::MultiVectorBase<Scalar> *S,
00178 const Scalar t,
00179 Thyra::VectorBase<Scalar> *g_hat,
00180 Thyra::MultiVectorBase<Scalar> *D_g_hat_D_p
00181 ) const;
00182
00183 };
00184
00185
00186
00187
00188
00189
00190
00191 template<class Scalar>
00192 ForwardResponseSensitivityComputer<Scalar>::ForwardResponseSensitivityComputer()
00193 :dumpSensitivities_(false),
00194 p_index_(-1),
00195 g_index_(-1),
00196 response_func_supports_x_dot_(false),
00197 response_func_supports_D_x_dot_(false),
00198 response_func_supports_D_p_(false)
00199 {}
00200
00201
00202 template<class Scalar>
00203 void ForwardResponseSensitivityComputer<Scalar>::setResponseFunction(
00204 const RCP<const Thyra::ModelEvaluator<Scalar> > &responseFunc,
00205 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &basePoint,
00206 const int p_index,
00207 const int g_index
00208 )
00209 {
00210
00211 typedef Thyra::ModelEvaluatorBase MEB;
00212
00213
00214
00215 responseFunc_ = responseFunc;
00216 basePoint_ = basePoint;
00217 p_index_ = p_index;
00218 g_index_ = g_index;
00219
00220 p_space_ = responseFunc_->get_p_space(p_index_);
00221 g_space_ = responseFunc_->get_g_space(g_index_);
00222
00223
00224 MEB::InArgs<Scalar>
00225 responseInArgs = responseFunc_->createInArgs();
00226 response_func_supports_x_dot_ =
00227 responseInArgs.supports(MEB::IN_ARG_x_dot);
00228 MEB::OutArgs<Scalar>
00229 responseOutArgs = responseFunc_->createOutArgs();
00230 response_func_supports_D_x_dot_ =
00231 !responseOutArgs.supports(MEB::OUT_ARG_DgDx_dot,g_index_).none();
00232 response_func_supports_D_p_ =
00233 !responseOutArgs.supports(MEB::OUT_ARG_DgDp,g_index_,p_index_).none();
00234
00235 clearCache();
00236
00237 }
00238
00239
00240 template<class Scalar>
00241 void ForwardResponseSensitivityComputer<Scalar>::resetResponseFunction(
00242 const RCP<const Thyra::ModelEvaluator<Scalar> > &responseFunc,
00243 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &basePoint
00244 )
00245 {
00246
00247
00248 responseFunc_ = responseFunc;
00249 basePoint_ = basePoint;
00250 }
00251
00252
00253 template<class Scalar>
00254 const RCP<Thyra::VectorBase<Scalar> >
00255 ForwardResponseSensitivityComputer<Scalar>::create_g_hat() const
00256 {
00257 return Thyra::createMember(g_space_);
00258 }
00259
00260
00261 template<class Scalar>
00262 const RCP<Thyra::MultiVectorBase<Scalar> >
00263 ForwardResponseSensitivityComputer<Scalar>::create_D_g_hat_D_p() const
00264 {
00265 return Thyra::createMembers(g_space_,p_space_->dim());
00266 }
00267
00268
00269 template<class Scalar>
00270 void ForwardResponseSensitivityComputer<Scalar>::computeResponse(
00271 const Thyra::VectorBase<Scalar> *x_dot,
00272 const Thyra::VectorBase<Scalar> &x,
00273 const Scalar t,
00274 Thyra::VectorBase<Scalar> *g_hat
00275 ) const
00276 {
00277 computeResponseAndSensitivityImpl(x_dot,0,x,0,t,g_hat,0);
00278 }
00279
00280
00281 template<class Scalar>
00282 void ForwardResponseSensitivityComputer<Scalar>::computeResponseAndSensitivity(
00283 const Thyra::VectorBase<Scalar> *x_dot,
00284 const Thyra::MultiVectorBase<Scalar> *S_dot,
00285 const Thyra::VectorBase<Scalar> &x,
00286 const Thyra::MultiVectorBase<Scalar> &S,
00287 const Scalar t,
00288 Thyra::VectorBase<Scalar> *g_hat,
00289 Thyra::MultiVectorBase<Scalar> *D_g_hat_D_p
00290 ) const
00291 {
00292 computeResponseAndSensitivityImpl(x_dot,S_dot,x,&S,t,g_hat,D_g_hat_D_p);
00293 }
00294
00295
00296
00297
00298
00299 template<class Scalar>
00300 void ForwardResponseSensitivityComputer<Scalar>::clearCache()
00301 {
00302 D_g_D_x_dot_ = Teuchos::null;
00303 D_g_D_x_ = Teuchos::null;
00304 D_g_D_p_ = Teuchos::null;
00305 }
00306
00307
00308 template<class Scalar>
00309 void ForwardResponseSensitivityComputer<Scalar>::createCache(
00310 const bool computeSens
00311 ) const
00312 {
00313 if (computeSens) {
00314 if (response_func_supports_D_x_dot_ && is_null(D_g_D_x_dot_))
00315 D_g_D_x_dot_ = responseFunc_->create_DgDx_dot_op(g_index_);
00316 D_g_D_x_ = responseFunc_->create_DgDx_op(g_index_);
00317 if (response_func_supports_D_p_ && is_null(D_g_D_p_))
00318 D_g_D_p_ = createMembers(g_space_,p_space_->dim());
00319 }
00320 }
00321
00322
00323 template<class Scalar>
00324 void ForwardResponseSensitivityComputer<Scalar>::computeResponseAndSensitivityImpl(
00325 const Thyra::VectorBase<Scalar> *x_dot,
00326 const Thyra::MultiVectorBase<Scalar> *S_dot,
00327 const Thyra::VectorBase<Scalar> &x,
00328 const Thyra::MultiVectorBase<Scalar> *S,
00329 const Scalar t,
00330 Thyra::VectorBase<Scalar> *g_hat,
00331 Thyra::MultiVectorBase<Scalar> *D_g_hat_D_p
00332 ) const
00333 {
00334
00335 using Teuchos::rcp;
00336 using Teuchos::includesVerbLevel;
00337 typedef ScalarTraits<Scalar> ST;
00338 using Thyra::apply;
00339 using Thyra::Vp_V;
00340 typedef Thyra::ModelEvaluatorBase MEB;
00341
00342
00343
00344
00345
00346 const RCP<Teuchos::FancyOStream> out = this->getOStream();
00347 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00348
00349 const bool trace =
00350 out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW);
00351 const bool print_norms =
00352 out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_MEDIUM);
00353 const bool print_x =
00354 out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_EXTREME);
00355
00356
00357
00358
00359
00360 const bool computeSens = ( D_g_hat_D_p != 0 );
00361 createCache(computeSens);
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 if (trace)
00372 *out << "\nEvaluating response function at time t = " << t << " ...\n";
00373
00374
00375
00376 MEB::InArgs<Scalar> responseInArgs = responseFunc_->createInArgs();
00377 responseInArgs.setArgs(basePoint_);
00378 responseInArgs.set_x(rcp(&x,false));
00379 if (response_func_supports_x_dot_)
00380 responseInArgs.set_x_dot(rcp(x_dot,false));
00381
00382
00383
00384 MEB::OutArgs<Scalar> responseOutArgs = responseFunc_->createOutArgs();
00385
00386 if (g_hat)
00387 responseOutArgs.set_g(g_index_,rcp(g_hat,false));
00388
00389 if (computeSens) {
00390
00391
00392 if (response_func_supports_D_x_dot_) {
00393 responseOutArgs.set_DgDx_dot(
00394 g_index_,
00395 MEB::Derivative<Scalar>(D_g_D_x_dot_)
00396 );
00397 }
00398
00399
00400 responseOutArgs.set_DgDx(
00401 g_index_,
00402 MEB::Derivative<Scalar>(D_g_D_x_)
00403 );
00404
00405
00406 if (response_func_supports_D_p_) {
00407 responseOutArgs.set_DgDp(
00408 g_index_, p_index_,
00409 MEB::Derivative<Scalar>(D_g_D_p_,MEB::DERIV_MV_BY_COL)
00410 );
00411 }
00412
00413 }
00414
00415
00416
00417 {
00418 #ifdef ENABLE_RYTHMOS_TIMERS
00419 TEUCHOS_FUNC_TIME_MONITOR("Rythmos:ForwardResponseSensitivityComputer::evalModel: evalResponse");
00420 #endif
00421 responseFunc_->evalModel( responseInArgs, responseOutArgs );
00422 }
00423
00424
00425
00426 if (print_norms) {
00427 if (g_hat)
00428 *out << "\n||g_hat||inf = " << norm_inf(*g_hat) << endl;
00429 if (computeSens && !is_null(D_g_D_p_))
00430 *out << "\n||D_g_D_p_||inf = " << norms_inf(*D_g_D_p_) << endl;
00431 }
00432
00433 if ( g_hat && (dumpSensitivities_ || print_x) )
00434 *out << "\ng_hat = " << *g_hat;
00435
00436 if (computeSens && print_x) {
00437 if (!is_null(D_g_D_x_dot_))
00438 *out << "\nD_g_D_x_dot = " << *D_g_D_x_ << endl;
00439 if (!is_null(D_g_D_x_))
00440 *out << "\nD_g_D_x = " << *D_g_D_x_ << endl;
00441 if (!is_null(D_g_D_p_))
00442 *out << "\nD_g_D_p = " << *D_g_D_p_ << endl;
00443 }
00444
00445
00446
00447
00448
00449
00450
00451 if (computeSens) {
00452
00453 #ifdef ENABLE_RYTHMOS_TIMERS
00454 TEUCHOS_FUNC_TIME_MONITOR("Rythmos:ForwardResponseSensitivityComputer::evalModel: computeSens");
00455 #endif
00456
00457 if (trace)
00458 *out << "\nD_g_hat_D_p = DgDx_dot * S_dot + DgDx * S + DgDp ...\n";
00459
00460 assign( D_g_hat_D_p, ST::zero() );
00461
00462
00463 if (response_func_supports_D_x_dot_) {
00464 apply( *D_g_D_x_dot_, Thyra::NOTRANS, *S_dot,
00465 D_g_hat_D_p, ST::one(), ST::one() );
00466 }
00467
00468
00469 apply( *D_g_D_x_, Thyra::NOTRANS, *S,
00470 D_g_hat_D_p, ST::one(), ST::one() );
00471
00472
00473 if (response_func_supports_D_p_) {
00474 Vp_V( &*D_g_hat_D_p, *D_g_D_p_ );
00475 }
00476
00477 if (dumpSensitivities_ || print_x)
00478 *out << "\nD_g_hat_D_p = "
00479 << Teuchos::describe(*D_g_hat_D_p,Teuchos::VERB_EXTREME);
00480
00481 }
00482
00483 }
00484
00485
00486 }
00487
00488
00489 #endif // RYTHMOS_FORWARD_RESPONSE_SENSITIVITY_COMPUTER_HPP