|
Rythmos - Transient Integration for Differential Equations Version of the Day
|
00001 //@HEADER 00002 // *********************************************************************** 00003 // 00004 // Rythmos Package 00005 // Copyright (2006) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // This library is free software; you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as 00012 // published by the Free Software Foundation; either version 2.1 of the 00013 // License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, but 00016 // WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00023 // USA 00024 // Questions? Contact Todd S. Coffey (tscoffe@sandia.gov) 00025 // 00026 // *********************************************************************** 00027 //@HEADER 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: // Data members 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: // Functions 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 // Implementations 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 // ToDo: Validate input! 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 // ToDo: Validate that responseFunc is the same structure as the one already 00247 // set! 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 // private 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 // A) Setup for output 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 // B) Initialize storage 00358 // 00359 00360 const bool computeSens = ( D_g_hat_D_p != 0 ); 00361 createCache(computeSens); 00362 00363 // 00364 // C) Evaluate the response function 00365 // 00366 00367 // 00368 // C.1) Setup input/output and evaluate the response function 00369 // 00370 00371 if (trace) 00372 *out << "\nEvaluating response function at time t = " << t << " ...\n"; 00373 00374 // C.1.a) Setup the input arguments 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 // C.1.b) Setup output arguments 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 // D_g_D_x_dot 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 // D_g_D_x 00400 responseOutArgs.set_DgDx( 00401 g_index_, 00402 MEB::Derivative<Scalar>(D_g_D_x_) 00403 ); 00404 00405 // D_g_D_p 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 // C.1.c) Evaluate the response function k 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 // C.1.d) Print the outputs just coputed 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 // C.2) Assemble the output response function sensitivity D_d_hat_D_p 00447 // 00448 00449 // D_g_hat_D_p = DgDx_dot * S_dot + DgDx * S + DgDp 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 // D_g_hat_D_p += DgDx_dot * S_dot 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 // D_g_hat_D_p += DgDx * S 00469 apply( *D_g_D_x_, Thyra::NOTRANS, *S, 00470 D_g_hat_D_p, ST::one(), ST::one() ); 00471 00472 // D_g_hat_D_p += DgDp 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 } // namespace Rythmos 00487 00488 00489 #endif // RYTHMOS_FORWARD_RESPONSE_SENSITIVITY_COMPUTER_HPP
1.7.4