|
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 00023 // USA 00024 // Questions? Contact Todd S. Coffey (tscoffe@sandia.gov) 00025 // 00026 // *********************************************************************** 00027 //@HEADER 00028 00029 #ifndef RYTHMOS_ADJOINT_MODEL_EVALUATOR_HPP 00030 #define RYTHMOS_ADJOINT_MODEL_EVALUATOR_HPP 00031 00032 00033 #include "Rythmos_IntegratorBase.hpp" 00034 #include "Thyra_ModelEvaluator.hpp" // Interface 00035 #include "Thyra_StateFuncModelEvaluatorBase.hpp" // Implementation 00036 #include "Thyra_ModelEvaluatorDelegatorBase.hpp" 00037 #include "Thyra_DefaultScaledAdjointLinearOp.hpp" 00038 #include "Thyra_DefaultAdjointLinearOpWithSolve.hpp" 00039 #include "Thyra_VectorStdOps.hpp" 00040 #include "Thyra_MultiVectorStdOps.hpp" 00041 #include "Teuchos_implicit_cast.hpp" 00042 #include "Teuchos_Assert.hpp" 00043 00044 00045 namespace Rythmos { 00046 00047 00172 template<class Scalar> 00173 class AdjointModelEvaluator 00174 : virtual public Thyra::StateFuncModelEvaluatorBase<Scalar> 00175 { 00176 public: 00177 00180 00182 AdjointModelEvaluator(); 00183 00185 void setFwdStateModel( 00186 const RCP<const Thyra::ModelEvaluator<Scalar> > &fwdStateModel, 00187 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &basePoint ); 00188 00192 void setFwdTimeRange( const TimeRange<Scalar> &fwdTimeRange ); 00193 00206 void setFwdStateSolutionBuffer( 00207 const RCP<const InterpolationBufferBase<Scalar> > &fwdStateSolutionBuffer ); 00208 00210 00213 00215 RCP<const Thyra::VectorSpaceBase<Scalar> > get_x_space() const; 00217 RCP<const Thyra::VectorSpaceBase<Scalar> > get_f_space() const; 00219 Thyra::ModelEvaluatorBase::InArgs<Scalar> getNominalValues() const; 00221 RCP<Thyra::LinearOpWithSolveBase<Scalar> > create_W() const; 00223 RCP<Thyra::LinearOpBase<Scalar> > create_W_op() const; 00225 Thyra::ModelEvaluatorBase::InArgs<Scalar> createInArgs() const; 00226 00228 00229 private: 00230 00233 00235 Thyra::ModelEvaluatorBase::OutArgs<Scalar> createOutArgsImpl() const; 00237 void evalModelImpl( 00238 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs_bar, 00239 const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs_bar 00240 ) const; 00241 00243 00244 private: 00245 00246 // ///////////////////////// 00247 // Private data members 00248 00249 RCP<const Thyra::ModelEvaluator<Scalar> > fwdStateModel_; 00250 Thyra::ModelEvaluatorBase::InArgs<Scalar> basePoint_; 00251 TimeRange<Scalar> fwdTimeRange_; 00252 RCP<const InterpolationBufferBase<Scalar> > fwdStateSolutionBuffer_; 00253 00254 mutable bool isInitialized_; 00255 mutable Thyra::ModelEvaluatorBase::InArgs<Scalar> prototypeInArgs_bar_; 00256 mutable Thyra::ModelEvaluatorBase::OutArgs<Scalar> prototypeOutArgs_bar_; 00257 mutable Thyra::ModelEvaluatorBase::InArgs<Scalar> adjointNominalValues_; 00258 mutable RCP<Thyra::LinearOpBase<Scalar> > my_W_bar_adj_op_; 00259 mutable RCP<Thyra::LinearOpBase<Scalar> > my_d_f_d_x_dot_op_; 00260 00261 // ///////////////////////// 00262 // Private member functions 00263 00264 // Just-in-time initialization function 00265 void initialize() const; 00266 00267 }; 00268 00269 00274 template<class Scalar> 00275 RCP<AdjointModelEvaluator<Scalar> > 00276 adjointModelEvaluator( 00277 const RCP<const Thyra::ModelEvaluator<Scalar> > &fwdStateModel, 00278 const TimeRange<Scalar> &fwdTimeRange 00279 ) 00280 { 00281 RCP<AdjointModelEvaluator<Scalar> > 00282 adjointModel = Teuchos::rcp(new AdjointModelEvaluator<Scalar>); 00283 adjointModel->setFwdStateModel(fwdStateModel, fwdStateModel->getNominalValues()); 00284 adjointModel->setFwdTimeRange(fwdTimeRange); 00285 return adjointModel; 00286 } 00287 00288 00289 // ///////////////////////////////// 00290 // Implementations 00291 00292 00293 // Constructors/Intializers/Accessors 00294 00295 00296 template<class Scalar> 00297 AdjointModelEvaluator<Scalar>::AdjointModelEvaluator() 00298 :isInitialized_(false) 00299 {} 00300 00301 00302 template<class Scalar> 00303 void AdjointModelEvaluator<Scalar>::setFwdStateModel( 00304 const RCP<const Thyra::ModelEvaluator<Scalar> > &fwdStateModel, 00305 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &basePoint 00306 ) 00307 { 00308 TEUCHOS_TEST_FOR_EXCEPT(is_null(fwdStateModel)); 00309 fwdStateModel_ = fwdStateModel; 00310 basePoint_ = basePoint; 00311 isInitialized_ = false; 00312 } 00313 00314 00315 template<class Scalar> 00316 void AdjointModelEvaluator<Scalar>::setFwdTimeRange( 00317 const TimeRange<Scalar> &fwdTimeRange ) 00318 { 00319 fwdTimeRange_ = fwdTimeRange; 00320 } 00321 00322 00323 template<class Scalar> 00324 void AdjointModelEvaluator<Scalar>::setFwdStateSolutionBuffer( 00325 const RCP<const InterpolationBufferBase<Scalar> > &fwdStateSolutionBuffer ) 00326 { 00327 TEUCHOS_TEST_FOR_EXCEPT(is_null(fwdStateSolutionBuffer)); 00328 fwdStateSolutionBuffer_ = fwdStateSolutionBuffer; 00329 } 00330 00331 00332 // Public functions overridden from ModelEvaulator 00333 00334 00335 template<class Scalar> 00336 RCP<const Thyra::VectorSpaceBase<Scalar> > 00337 AdjointModelEvaluator<Scalar>::get_x_space() const 00338 { 00339 initialize(); 00340 return fwdStateModel_->get_f_space(); 00341 } 00342 00343 00344 template<class Scalar> 00345 RCP<const Thyra::VectorSpaceBase<Scalar> > 00346 AdjointModelEvaluator<Scalar>::get_f_space() const 00347 { 00348 initialize(); 00349 return fwdStateModel_->get_x_space(); 00350 } 00351 00352 00353 template<class Scalar> 00354 Thyra::ModelEvaluatorBase::InArgs<Scalar> 00355 AdjointModelEvaluator<Scalar>::getNominalValues() const 00356 { 00357 initialize(); 00358 return adjointNominalValues_; 00359 } 00360 00361 00362 template<class Scalar> 00363 RCP<Thyra::LinearOpWithSolveBase<Scalar> > 00364 AdjointModelEvaluator<Scalar>::create_W() const 00365 { 00366 initialize(); 00367 return Thyra::nonconstAdjointLows<Scalar>(fwdStateModel_->create_W()); 00368 } 00369 00370 00371 template<class Scalar> 00372 RCP<Thyra::LinearOpBase<Scalar> > 00373 AdjointModelEvaluator<Scalar>::create_W_op() const 00374 { 00375 initialize(); 00376 return Thyra::nonconstAdjoint<Scalar>(fwdStateModel_->create_W_op()); 00377 } 00378 00379 00380 template<class Scalar> 00381 Thyra::ModelEvaluatorBase::InArgs<Scalar> 00382 AdjointModelEvaluator<Scalar>::createInArgs() const 00383 { 00384 initialize(); 00385 return prototypeInArgs_bar_; 00386 } 00387 00388 00389 // Private functions overridden from ModelEvaulatorDefaultBase 00390 00391 00392 template<class Scalar> 00393 Thyra::ModelEvaluatorBase::OutArgs<Scalar> 00394 AdjointModelEvaluator<Scalar>::createOutArgsImpl() const 00395 { 00396 initialize(); 00397 return prototypeOutArgs_bar_; 00398 } 00399 00400 00401 template<class Scalar> 00402 void AdjointModelEvaluator<Scalar>::evalModelImpl( 00403 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs_bar, 00404 const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs_bar 00405 ) const 00406 { 00407 00408 using Teuchos::rcp_dynamic_cast; 00409 using Teuchos::describe; 00410 typedef Teuchos::ScalarTraits<Scalar> ST; 00411 typedef Thyra::ModelEvaluatorBase MEB; 00412 typedef Thyra::DefaultScaledAdjointLinearOp<Scalar> DSALO; 00413 typedef Thyra::DefaultAdjointLinearOpWithSolve<Scalar> DALOWS; 00414 typedef Teuchos::VerboseObjectTempState<Thyra::ModelEvaluatorBase> VOTSME; 00415 00416 // 00417 // A) Header stuff 00418 // 00419 00420 THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_GEN_BEGIN( 00421 "AdjointModelEvaluator", inArgs_bar, outArgs_bar, Teuchos::null ); 00422 00423 initialize(); 00424 00425 VOTSME fwdStateModel_outputTempState(fwdStateModel_,out,verbLevel); 00426 00427 //const bool trace = includesVerbLevel(verbLevel, Teuchos::VERB_LOW); 00428 const bool dumpAll = includesVerbLevel(localVerbLevel, Teuchos::VERB_EXTREME); 00429 00430 // 00431 // B) Unpack the input and output arguments to see what we have to compute 00432 // 00433 00434 // B.1) InArgs 00435 00436 const Scalar t_bar = inArgs_bar.get_t(); 00437 const RCP<const Thyra::VectorBase<Scalar> > 00438 lambda_rev_dot = inArgs_bar.get_x_dot().assert_not_null(), // x_bar_dot 00439 lambda = inArgs_bar.get_x().assert_not_null(); // x_bar 00440 const Scalar alpha_bar = inArgs_bar.get_alpha(); 00441 const Scalar beta_bar = inArgs_bar.get_beta(); 00442 00443 if (dumpAll) { 00444 *out << "\nlambda_rev_dot = " << describe(*lambda_rev_dot, Teuchos::VERB_EXTREME); 00445 *out << "\nlambda = " << describe(*lambda, Teuchos::VERB_EXTREME); 00446 *out << "\nalpha_bar = " << alpha_bar << "\n"; 00447 *out << "\nbeta_bar = " << beta_bar << "\n"; 00448 } 00449 00450 // B.2) OutArgs 00451 00452 const RCP<Thyra::VectorBase<Scalar> > f_bar = outArgs_bar.get_f(); 00453 00454 RCP<DALOWS> W_bar; 00455 if (outArgs_bar.supports(MEB::OUT_ARG_W)) 00456 W_bar = rcp_dynamic_cast<DALOWS>(outArgs_bar.get_W(), true); 00457 00458 RCP<DSALO> W_bar_op; 00459 if (outArgs_bar.supports(MEB::OUT_ARG_W_op)) 00460 W_bar_op = rcp_dynamic_cast<DSALO>(outArgs_bar.get_W_op(), true); 00461 00462 if (dumpAll) { 00463 if (!is_null(W_bar)) { 00464 *out << "\nW_bar = " << describe(*W_bar, Teuchos::VERB_EXTREME); 00465 } 00466 if (!is_null(W_bar_op)) { 00467 *out << "\nW_bar_op = " << describe(*W_bar_op, Teuchos::VERB_EXTREME); 00468 } 00469 } 00470 00471 // 00472 // C) Evaluate the needed quantities from the underlying forward Model 00473 // 00474 00475 MEB::InArgs<Scalar> fwdInArgs = fwdStateModel_->createInArgs(); 00476 00477 // C.1) Set the required input arguments 00478 00479 fwdInArgs = basePoint_; 00480 00481 if (!is_null(fwdStateSolutionBuffer_)) { 00482 const Scalar t = fwdTimeRange_.length() - t_bar; 00483 RCP<const Thyra::VectorBase<Scalar> > x, x_dot; 00484 get_x_and_x_dot<Scalar>( *fwdStateSolutionBuffer_, t, 00485 outArg(x), outArg(x_dot) ); 00486 fwdInArgs.set_x(x); 00487 fwdInArgs.set_x_dot(x); 00488 } 00489 else { 00490 // If we don't have an IB object to get the state from, we will assume 00491 // that the problem is linear and, therefore, we can pass in any old value 00492 // of x, x_dot, and t and get the W_bar_adj object that we need. For this 00493 // purpose, we will assume the model's base point will do. 00494 00495 // 2008/05/14: rabartl: ToDo: Implement real variable dependancy 00496 // communication support to make sure that this is okay! If the model is 00497 // really nonlinear we need to check for this and throw if the user did 00498 // not set up a fwdStateSolutionBuffer object! 00499 } 00500 00501 00502 // C.2) Evaluate W_bar_adj if needed 00503 00504 RCP<Thyra::LinearOpWithSolveBase<Scalar> > W_bar_adj; 00505 RCP<Thyra::LinearOpBase<Scalar> > W_bar_adj_op; 00506 { 00507 00508 MEB::OutArgs<Scalar> fwdOutArgs = fwdStateModel_->createOutArgs(); 00509 00510 // Get or create W_bar_adj or W_bar_adj_op if needed 00511 if (!is_null(W_bar)) { 00512 // If we have W_bar, the W_bar_adj was already created in 00513 // this->create_W() 00514 W_bar_adj = W_bar->getNonconstOp(); 00515 W_bar_adj_op = W_bar_adj; 00516 } 00517 else if (!is_null(W_bar_op)) { 00518 // If we have W_bar_op, the W_bar_adj_op was already created in 00519 // this->create_W_op() 00520 W_bar_adj_op = W_bar_op->getNonconstOp(); 00521 } 00522 else if (!is_null(f_bar)) { 00523 TEUCHOS_TEST_FOR_EXCEPT_MSG(true, "ToDo: Unit test this code!"); 00524 // If the user did not pass in W_bar or W_bar_op, then we need to create 00525 // our own local LOB form W_bar_adj_op of W_bar_adj in order to evaluate 00526 // the residual f_bar 00527 if (is_null(my_W_bar_adj_op_)) { 00528 my_W_bar_adj_op_ = fwdStateModel_->create_W_op(); 00529 } 00530 W_bar_adj_op = my_W_bar_adj_op_; 00531 } 00532 00533 // Set W_bar_adj or W_bar_adj_op on the OutArgs object 00534 if (!is_null(W_bar_adj)) { 00535 fwdOutArgs.set_W(W_bar_adj); 00536 } 00537 else if (!is_null(W_bar_adj_op)) { 00538 fwdOutArgs.set_W_op(W_bar_adj_op); 00539 } 00540 00541 // Set alpha and beta on OutArgs object 00542 if (!is_null(W_bar_adj) || !is_null(W_bar_adj_op)) { 00543 fwdInArgs.set_alpha(alpha_bar); 00544 fwdInArgs.set_beta(beta_bar); 00545 } 00546 00547 // Evaluate the model 00548 if (!is_null(W_bar_adj) || !is_null(W_bar_adj_op)) { 00549 fwdStateModel_->evalModel( fwdInArgs, fwdOutArgs ); 00550 } 00551 00552 // Print the objects if requested 00553 if (!is_null(W_bar_adj) && dumpAll) 00554 *out << "\nW_bar_adj = " << describe(*W_bar_adj, Teuchos::VERB_EXTREME); 00555 if (!is_null(W_bar_adj_op) && dumpAll) 00556 *out << "\nW_bar_adj_op = " << describe(*W_bar_adj_op, Teuchos::VERB_EXTREME); 00557 00558 } 00559 00560 // C.3) Evaluate d(f)/d(x_dot) if needed 00561 00562 RCP<Thyra::LinearOpBase<Scalar> > d_f_d_x_dot_op; 00563 if (!is_null(f_bar)) { 00564 if (is_null(my_d_f_d_x_dot_op_)) { 00565 my_d_f_d_x_dot_op_ = fwdStateModel_->create_W_op(); 00566 } 00567 d_f_d_x_dot_op = my_d_f_d_x_dot_op_; 00568 MEB::OutArgs<Scalar> fwdOutArgs = fwdStateModel_->createOutArgs(); 00569 fwdOutArgs.set_W_op(d_f_d_x_dot_op); 00570 fwdInArgs.set_alpha(ST::one()); 00571 fwdInArgs.set_beta(ST::zero()); 00572 fwdStateModel_->evalModel( fwdInArgs, fwdOutArgs ); 00573 if (dumpAll) { 00574 *out << "\nd_f_d_x_dot_op = " << describe(*d_f_d_x_dot_op, Teuchos::VERB_EXTREME); 00575 } 00576 } 00577 00578 // 00579 // D) Evaluate the adjoint equation residual: 00580 // 00581 // f_bar = d(f)/d(x_dot)^T * lambda_hat + 1/beta_bar * W_bar_adj^T * lambda 00582 // - d(g)/d(x)^T 00583 // 00584 00585 if (!is_null(f_bar)) { 00586 00587 // D.1) lambda_hat = lambda_rev_dot - alpha_bar/beta_bar * lambda 00588 const RCP<Thyra::VectorBase<Scalar> > 00589 lambda_hat = createMember(lambda_rev_dot->space()); 00590 Thyra::V_VpStV<Scalar>( outArg(*lambda_hat), 00591 *lambda_rev_dot, -alpha_bar/beta_bar, *lambda ); 00592 if (dumpAll) 00593 *out << "\nlambda_hat = " << describe(*lambda_hat, Teuchos::VERB_EXTREME); 00594 00595 // D.2) f_bar = d(f)/d(x_dot)^T * lambda_hat 00596 Thyra::apply<Scalar>( *d_f_d_x_dot_op, Thyra::CONJTRANS, *lambda_hat, 00597 outArg(*f_bar) ); 00598 00599 // D.3) f_bar += 1/beta_bar * W_bar_adj^T * lambda 00600 Thyra::apply<Scalar>( *W_bar_adj_op, Thyra::CONJTRANS, *lambda, 00601 outArg(*f_bar), 1.0/beta_bar, ST::one() ); 00602 00603 // D.4) f_bar += - d(g)/d(x)^T 00604 // 2008/05/15: rabart: ToDo: Implement once we add support for 00605 // distributed response functions 00606 00607 if (dumpAll) 00608 *out << "\nf_bar = " << describe(*f_bar, Teuchos::VERB_EXTREME); 00609 00610 } 00611 00612 if (dumpAll) { 00613 if (!is_null(W_bar)) { 00614 *out << "\nW_bar = " << describe(*W_bar, Teuchos::VERB_EXTREME); 00615 } 00616 if (!is_null(W_bar_op)) { 00617 *out << "\nW_bar_op = " << describe(*W_bar_op, Teuchos::VERB_EXTREME); 00618 } 00619 } 00620 00621 00622 // 00623 // E) Do any remaining post processing 00624 // 00625 00626 THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_END(); 00627 00628 } 00629 00630 00631 // private 00632 00633 00634 template<class Scalar> 00635 void AdjointModelEvaluator<Scalar>::initialize() const 00636 { 00637 00638 typedef Thyra::ModelEvaluatorBase MEB; 00639 00640 if (isInitialized_) 00641 return; 00642 00643 // 00644 // A) Validate the that forward Model is of the correct form! 00645 // 00646 00647 MEB::InArgs<Scalar> fwdStateModelInArgs = fwdStateModel_->createInArgs(); 00648 MEB::OutArgs<Scalar> fwdStateModelOutArgs = fwdStateModel_->createOutArgs(); 00649 00650 #ifdef HAVE_RYTHMOS_DEBUG 00651 TEUCHOS_ASSERT( fwdStateModelInArgs.supports(MEB::IN_ARG_x_dot) ); 00652 TEUCHOS_ASSERT( fwdStateModelInArgs.supports(MEB::IN_ARG_x) ); 00653 TEUCHOS_ASSERT( fwdStateModelInArgs.supports(MEB::IN_ARG_t) ); 00654 TEUCHOS_ASSERT( fwdStateModelInArgs.supports(MEB::IN_ARG_alpha) ); 00655 TEUCHOS_ASSERT( fwdStateModelInArgs.supports(MEB::IN_ARG_beta) ); 00656 TEUCHOS_ASSERT( fwdStateModelOutArgs.supports(MEB::OUT_ARG_f) ); 00657 TEUCHOS_ASSERT( fwdStateModelOutArgs.supports(MEB::OUT_ARG_W) ); 00658 #endif 00659 00660 // 00661 // B) Set up the prototypical InArgs and OutArgs 00662 // 00663 00664 { 00665 MEB::InArgsSetup<Scalar> inArgs_bar; 00666 inArgs_bar.setModelEvalDescription(this->description()); 00667 inArgs_bar.setSupports( MEB::IN_ARG_x_dot ); 00668 inArgs_bar.setSupports( MEB::IN_ARG_x ); 00669 inArgs_bar.setSupports( MEB::IN_ARG_t ); 00670 inArgs_bar.setSupports( MEB::IN_ARG_alpha ); 00671 inArgs_bar.setSupports( MEB::IN_ARG_beta ); 00672 prototypeInArgs_bar_ = inArgs_bar; 00673 } 00674 00675 { 00676 MEB::OutArgsSetup<Scalar> outArgs_bar; 00677 outArgs_bar.setModelEvalDescription(this->description()); 00678 outArgs_bar.setSupports(MEB::OUT_ARG_f); 00679 if (fwdStateModelOutArgs.supports(MEB::OUT_ARG_W) ) { 00680 outArgs_bar.setSupports(MEB::OUT_ARG_W); 00681 outArgs_bar.set_W_properties(fwdStateModelOutArgs.get_W_properties()); 00682 } 00683 if (fwdStateModelOutArgs.supports(MEB::OUT_ARG_W_op) ) { 00684 outArgs_bar.setSupports(MEB::OUT_ARG_W_op); 00685 outArgs_bar.set_W_properties(fwdStateModelOutArgs.get_W_properties()); 00686 } 00687 prototypeOutArgs_bar_ = outArgs_bar; 00688 } 00689 00690 // 00691 // D) Set up the nominal values for the adjoint 00692 // 00693 00694 // Copy structure 00695 adjointNominalValues_ = prototypeInArgs_bar_; 00696 // Just set a zero initial condition for the adjoint 00697 const RCP<Thyra::VectorBase<Scalar> > zero_lambda_vec = 00698 createMember(fwdStateModel_->get_f_space()); 00699 V_S( zero_lambda_vec.ptr(), ScalarTraits<Scalar>::zero() ); 00700 adjointNominalValues_.set_x_dot(zero_lambda_vec); 00701 adjointNominalValues_.set_x(zero_lambda_vec); 00702 00703 // 00704 // E) Wipe out other cached objects 00705 // 00706 00707 my_W_bar_adj_op_ = Teuchos::null; 00708 my_d_f_d_x_dot_op_ = Teuchos::null; 00709 00710 // 00711 // F) We are initialized! 00712 // 00713 00714 isInitialized_ = true; 00715 00716 } 00717 00718 00719 } // namespace Rythmos 00720 00721 00722 #endif // RYTHMOS_ADJOINT_MODEL_EVALUATOR_HPP
1.7.6.1