|
Thyra Package Browser (Single Doxygen Collection)
Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Thyra: Interfaces and Support for Abstract Numerical Algorithms 00005 // Copyright (2004) 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 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Roscoe A. Bartlett (bartlettra@ornl.gov) 00038 // 00039 // *********************************************************************** 00040 // @HEADER 00041 00042 #include "Thyra_EpetraModelEvaluator.hpp" 00043 #include "Thyra_LinearOpWithSolveFactoryHelpers.hpp" 00044 #include "Thyra_EpetraThyraWrappers.hpp" 00045 #include "Thyra_EpetraLinearOp.hpp" 00046 #include "Thyra_DetachedMultiVectorView.hpp" 00047 #include "Thyra_ModelEvaluatorDelegatorBase.hpp" // Gives verbose macros! 00048 #include "EpetraExt_ModelEvaluatorScalingTools.h" 00049 #include "Epetra_RowMatrix.h" 00050 #include "Teuchos_Time.hpp" 00051 #include "Teuchos_implicit_cast.hpp" 00052 #include "Teuchos_Assert.hpp" 00053 #include "Teuchos_StandardParameterEntryValidators.hpp" 00054 #include "Teuchos_VerboseObjectParameterListHelpers.hpp" 00055 00056 00057 namespace { 00058 00059 00060 const std::string StateFunctionScaling_name = "State Function Scaling"; 00061 Teuchos::RCP< 00062 Teuchos::StringToIntegralParameterEntryValidator< 00063 Thyra::EpetraModelEvaluator::EStateFunctionScaling 00064 > 00065 > 00066 stateFunctionScalingValidator; 00067 const std::string StateFunctionScaling_default = "None"; 00068 00069 00070 // Extract out the Epetra_RowMatrix from the set W in an Epetra OutArgs object 00071 Teuchos::RCP<Epetra_RowMatrix> 00072 get_Epetra_RowMatrix( 00073 const EpetraExt::ModelEvaluator::OutArgs &epetraOutArgs 00074 ) 00075 { 00076 using Teuchos::RCP; 00077 const RCP<Epetra_Operator> 00078 eW = epetraOutArgs.get_W(); 00079 const RCP<Epetra_RowMatrix> 00080 ermW = Teuchos::rcp_dynamic_cast<Epetra_RowMatrix>(eW,false); 00081 TEUCHOS_TEST_FOR_EXCEPTION( 00082 is_null(ermW), std::logic_error, 00083 "Thyra::EpetraModelEvaluator::evalModel(...): Error, if\n" 00084 "scaling is turned on, the underlying Epetra_Operator created\n" 00085 "an initialized by the underlying epetra model evaluator\n" 00086 "\"" << epetraOutArgs.modelEvalDescription() << "\"\n" 00087 "must support the Epetra_RowMatrix interface through a dynamic cast.\n" 00088 "The concrete type " << Teuchos::typeName(*eW) << " does not support\n" 00089 "Epetra_RowMatrix!" 00090 ); 00091 return ermW; 00092 } 00093 00094 00095 Teuchos::RCP<Epetra_Operator> 00096 create_and_assert_W( 00097 const EpetraExt::ModelEvaluator &epetraModel 00098 ) 00099 { 00100 using Teuchos::RCP; 00101 RCP<Epetra_Operator> 00102 eW = epetraModel.create_W(); 00103 TEUCHOS_TEST_FOR_EXCEPTION( 00104 is_null(eW), std::logic_error, 00105 "Error, the call to create_W() returned null on the " 00106 "EpetraExt::ModelEvaluator object " 00107 "\"" << epetraModel.description() << "\". This may mean that " 00108 "the underlying model does not support more than one copy of " 00109 "W at one time!" ); 00110 return eW; 00111 } 00112 00113 00114 } // namespace 00115 00116 00117 namespace Thyra { 00118 00119 00120 // Constructors/initializers/accessors. 00121 00122 00123 EpetraModelEvaluator::EpetraModelEvaluator() 00124 :nominalValuesAndBoundsAreUpdated_(false), stateFunctionScaling_(STATE_FUNC_SCALING_NONE), 00125 currentInArgsOutArgs_(false), finalPointWasSolved_(false) 00126 {} 00127 00128 00129 EpetraModelEvaluator::EpetraModelEvaluator( 00130 const RCP<const EpetraExt::ModelEvaluator> &epetraModel, 00131 const RCP<LinearOpWithSolveFactoryBase<double> > &W_factory 00132 ) 00133 :nominalValuesAndBoundsAreUpdated_(false), stateFunctionScaling_(STATE_FUNC_SCALING_NONE), 00134 currentInArgsOutArgs_(false), finalPointWasSolved_(false) 00135 { 00136 initialize(epetraModel,W_factory); 00137 } 00138 00139 00140 void EpetraModelEvaluator::initialize( 00141 const RCP<const EpetraExt::ModelEvaluator> &epetraModel, 00142 const RCP<LinearOpWithSolveFactoryBase<double> > &W_factory 00143 ) 00144 { 00145 using Teuchos::implicit_cast; 00146 typedef ModelEvaluatorBase MEB; 00147 // 00148 epetraModel_ = epetraModel; 00149 // 00150 W_factory_ = W_factory; 00151 // 00152 x_map_ = epetraModel_->get_x_map(); 00153 f_map_ = epetraModel_->get_f_map(); 00154 if (!is_null(x_map_)) { 00155 x_space_ = create_VectorSpace(x_map_); 00156 f_space_ = create_VectorSpace(f_map_); 00157 } 00158 // 00159 EpetraExt::ModelEvaluator::InArgs inArgs = epetraModel_->createInArgs(); 00160 p_map_.resize(inArgs.Np()); p_space_.resize(inArgs.Np()); 00161 p_map_is_local_.resize(inArgs.Np(),false); 00162 for( int l = 0; l < implicit_cast<int>(p_space_.size()); ++l ) { 00163 RCP<const Epetra_Map> 00164 p_map_l = ( p_map_[l] = epetraModel_->get_p_map(l) ); 00165 #ifdef TEUCHOS_DEBUG 00166 TEUCHOS_TEST_FOR_EXCEPTION( 00167 is_null(p_map_l), std::logic_error, 00168 "Error, the the map p["<<l<<"] for the model \"" 00169 <<epetraModel->description()<<"\" can not be null!"); 00170 #endif 00171 00172 p_map_is_local_[l] = !p_map_l->DistributedGlobal(); 00173 p_space_[l] = create_VectorSpace(p_map_l); 00174 } 00175 // 00176 EpetraExt::ModelEvaluator::OutArgs outArgs = epetraModel_->createOutArgs(); 00177 g_map_.resize(outArgs.Ng()); g_space_.resize(outArgs.Ng()); 00178 g_map_is_local_.resize(outArgs.Ng(),false); 00179 for( int j = 0; j < implicit_cast<int>(g_space_.size()); ++j ) { 00180 RCP<const Epetra_Map> 00181 g_map_j = ( g_map_[j] = epetraModel_->get_g_map(j) ); 00182 g_map_is_local_[j] = !g_map_j->DistributedGlobal(); 00183 g_space_[j] = create_VectorSpace( g_map_j ); 00184 } 00185 // 00186 epetraInArgsScaling_ = epetraModel_->createInArgs(); 00187 epetraOutArgsScaling_ = epetraModel_->createOutArgs(); 00188 nominalValuesAndBoundsAreUpdated_ = false; 00189 finalPointWasSolved_ = false; 00190 stateFunctionScalingVec_ = Teuchos::null; // Must set new scaling! 00191 // 00192 currentInArgsOutArgs_ = false; 00193 } 00194 00195 00196 RCP<const EpetraExt::ModelEvaluator> 00197 EpetraModelEvaluator::getEpetraModel() const 00198 { 00199 return epetraModel_; 00200 } 00201 00202 00203 void EpetraModelEvaluator::setNominalValues( 00204 const ModelEvaluatorBase::InArgs<double>& nominalValues 00205 ) 00206 { 00207 nominalValues_.setArgs(nominalValues); 00208 // Note: These must be the scaled values so we don't need to scale! 00209 } 00210 00211 00212 void EpetraModelEvaluator::setStateVariableScalingVec( 00213 const RCP<const Epetra_Vector> &stateVariableScalingVec 00214 ) 00215 { 00216 typedef ModelEvaluatorBase MEB; 00217 #ifdef TEUCHOS_DEBUG 00218 TEUCHOS_TEST_FOR_EXCEPT( !this->createInArgs().supports(MEB::IN_ARG_x) ); 00219 #endif 00220 stateVariableScalingVec_ = stateVariableScalingVec.assert_not_null(); 00221 invStateVariableScalingVec_ = Teuchos::null; 00222 nominalValuesAndBoundsAreUpdated_ = false; 00223 } 00224 00225 00226 RCP<const Epetra_Vector> 00227 EpetraModelEvaluator::getStateVariableScalingVec() const 00228 { 00229 return stateVariableScalingVec_; 00230 } 00231 00232 00233 RCP<const Epetra_Vector> 00234 EpetraModelEvaluator::getStateVariableInvScalingVec() const 00235 { 00236 updateNominalValuesAndBounds(); 00237 return invStateVariableScalingVec_; 00238 } 00239 00240 00241 void EpetraModelEvaluator::setStateFunctionScalingVec( 00242 const RCP<const Epetra_Vector> &stateFunctionScalingVec 00243 ) 00244 { 00245 stateFunctionScalingVec_ = stateFunctionScalingVec; 00246 } 00247 00248 00249 RCP<const Epetra_Vector> 00250 EpetraModelEvaluator::getStateFunctionScalingVec() const 00251 { 00252 return stateFunctionScalingVec_; 00253 } 00254 00255 00256 void EpetraModelEvaluator::uninitialize( 00257 RCP<const EpetraExt::ModelEvaluator> *epetraModel, 00258 RCP<LinearOpWithSolveFactoryBase<double> > *W_factory 00259 ) 00260 { 00261 if(epetraModel) *epetraModel = epetraModel_; 00262 if(W_factory) *W_factory = W_factory_; 00263 epetraModel_ = Teuchos::null; 00264 W_factory_ = Teuchos::null; 00265 stateFunctionScalingVec_ = Teuchos::null; 00266 stateVariableScalingVec_ = Teuchos::null; 00267 invStateVariableScalingVec_ = Teuchos::null; 00268 currentInArgsOutArgs_ = false; 00269 } 00270 00271 00272 const ModelEvaluatorBase::InArgs<double>& 00273 EpetraModelEvaluator::getFinalPoint() const 00274 { 00275 return finalPoint_; 00276 } 00277 00278 00279 bool EpetraModelEvaluator::finalPointWasSolved() const 00280 { 00281 return finalPointWasSolved_; 00282 } 00283 00284 00285 // Public functions overridden from Teuchos::Describable 00286 00287 00288 std::string EpetraModelEvaluator::description() const 00289 { 00290 std::ostringstream oss; 00291 oss << "Thyra::EpetraModelEvaluator{"; 00292 oss << "epetraModel="; 00293 if(epetraModel_.get()) 00294 oss << "\'"<<epetraModel_->description()<<"\'"; 00295 else 00296 oss << "NULL"; 00297 oss << ",W_factory="; 00298 if(W_factory_.get()) 00299 oss << "\'"<<W_factory_->description()<<"\'"; 00300 else 00301 oss << "NULL"; 00302 oss << "}"; 00303 return oss.str(); 00304 } 00305 00306 00307 // Overridden from Teuchos::ParameterListAcceptor 00308 00309 00310 void EpetraModelEvaluator::setParameterList( 00311 RCP<Teuchos::ParameterList> const& paramList 00312 ) 00313 { 00314 TEUCHOS_TEST_FOR_EXCEPT(is_null(paramList)); 00315 paramList->validateParameters(*getValidParameters(),0); // Just validate my params 00316 paramList_ = paramList; 00317 const EStateFunctionScaling stateFunctionScaling_old = stateFunctionScaling_; 00318 stateFunctionScaling_ = stateFunctionScalingValidator->getIntegralValue( 00319 *paramList_, StateFunctionScaling_name, StateFunctionScaling_default 00320 ); 00321 if( stateFunctionScaling_ != stateFunctionScaling_old ) 00322 stateFunctionScalingVec_ = Teuchos::null; 00323 Teuchos::readVerboseObjectSublist(&*paramList_,this); 00324 #ifdef TEUCHOS_DEBUG 00325 paramList_->validateParameters(*getValidParameters(),0); 00326 #endif // TEUCHOS_DEBUG 00327 } 00328 00329 00330 RCP<Teuchos::ParameterList> 00331 EpetraModelEvaluator::getNonconstParameterList() 00332 { 00333 return paramList_; 00334 } 00335 00336 00337 RCP<Teuchos::ParameterList> 00338 EpetraModelEvaluator::unsetParameterList() 00339 { 00340 RCP<Teuchos::ParameterList> _paramList = paramList_; 00341 paramList_ = Teuchos::null; 00342 return _paramList; 00343 } 00344 00345 00346 RCP<const Teuchos::ParameterList> 00347 EpetraModelEvaluator::getParameterList() const 00348 { 00349 return paramList_; 00350 } 00351 00352 00353 RCP<const Teuchos::ParameterList> 00354 EpetraModelEvaluator::getValidParameters() const 00355 { 00356 using Teuchos::rcp; 00357 using Teuchos::StringToIntegralParameterEntryValidator; 00358 using Teuchos::tuple; 00359 using Teuchos::rcp_implicit_cast; 00360 typedef Teuchos::ParameterEntryValidator PEV; 00361 static RCP<const Teuchos::ParameterList> validPL; 00362 if(is_null(validPL)) { 00363 RCP<Teuchos::ParameterList> 00364 pl = Teuchos::rcp(new Teuchos::ParameterList()); 00365 stateFunctionScalingValidator = rcp( 00366 new StringToIntegralParameterEntryValidator<EStateFunctionScaling>( 00367 tuple<std::string>( 00368 "None", 00369 "Row Sum" 00370 ), 00371 tuple<std::string>( 00372 "Do not scale the state function f(...) in this class.", 00373 00374 "Scale the state function f(...) and all its derivatives\n" 00375 "using the row sum scaling from the initial Jacobian\n" 00376 "W=d(f)/d(x). Note, this only works with Epetra_CrsMatrix\n" 00377 "currently." 00378 ), 00379 tuple<EStateFunctionScaling>( 00380 STATE_FUNC_SCALING_NONE, 00381 STATE_FUNC_SCALING_ROW_SUM 00382 ), 00383 StateFunctionScaling_name 00384 ) 00385 ); 00386 pl->set(StateFunctionScaling_name,StateFunctionScaling_default, 00387 "Determines if and how the state function f(...) and all of its\n" 00388 "derivatives are scaled. The scaling is done explicitly so there should\n" 00389 "be no impact on the meaning of inner products or tolerances for\n" 00390 "linear solves.", 00391 rcp_implicit_cast<const PEV>(stateFunctionScalingValidator) 00392 ); 00393 Teuchos::setupVerboseObjectSublist(&*pl); 00394 validPL = pl; 00395 } 00396 return validPL; 00397 } 00398 00399 00400 // Overridden from ModelEvaulator. 00401 00402 00403 int EpetraModelEvaluator::Np() const 00404 { 00405 return p_space_.size(); 00406 } 00407 00408 00409 int EpetraModelEvaluator::Ng() const 00410 { 00411 return g_space_.size(); 00412 } 00413 00414 00415 RCP<const VectorSpaceBase<double> > 00416 EpetraModelEvaluator::get_x_space() const 00417 { 00418 return x_space_; 00419 } 00420 00421 00422 RCP<const VectorSpaceBase<double> > 00423 EpetraModelEvaluator::get_f_space() const 00424 { 00425 return f_space_; 00426 } 00427 00428 00429 RCP<const VectorSpaceBase<double> > 00430 EpetraModelEvaluator::get_p_space(int l) const 00431 { 00432 #ifdef TEUCHOS_DEBUG 00433 TEUCHOS_ASSERT_IN_RANGE_UPPER_EXCLUSIVE( l, 0, this->Np() ); 00434 #endif 00435 return p_space_[l]; 00436 } 00437 00438 00439 RCP<const Teuchos::Array<std::string> > 00440 EpetraModelEvaluator::get_p_names(int l) const 00441 { 00442 #ifdef TEUCHOS_DEBUG 00443 TEUCHOS_ASSERT_IN_RANGE_UPPER_EXCLUSIVE( l, 0, this->Np() ); 00444 #endif 00445 return epetraModel_->get_p_names(l); 00446 } 00447 00448 00449 RCP<const VectorSpaceBase<double> > 00450 EpetraModelEvaluator::get_g_space(int j) const 00451 { 00452 TEUCHOS_TEST_FOR_EXCEPT( ! ( 0 <= j && j < this->Ng() ) ); 00453 return g_space_[j]; 00454 } 00455 00456 00457 ModelEvaluatorBase::InArgs<double> 00458 EpetraModelEvaluator::getNominalValues() const 00459 { 00460 updateNominalValuesAndBounds(); 00461 return nominalValues_; 00462 } 00463 00464 00465 ModelEvaluatorBase::InArgs<double> 00466 EpetraModelEvaluator::getLowerBounds() const 00467 { 00468 updateNominalValuesAndBounds(); 00469 return lowerBounds_; 00470 } 00471 00472 00473 ModelEvaluatorBase::InArgs<double> 00474 EpetraModelEvaluator::getUpperBounds() const 00475 { 00476 updateNominalValuesAndBounds(); 00477 return upperBounds_; 00478 } 00479 00480 00481 RCP<LinearOpBase<double> > 00482 EpetraModelEvaluator::create_W_op() const 00483 { 00484 return this->create_epetra_W_op(); 00485 } 00486 00487 00488 RCP<const LinearOpWithSolveFactoryBase<double> > 00489 EpetraModelEvaluator::get_W_factory() const 00490 { 00491 return W_factory_; 00492 } 00493 00494 00495 ModelEvaluatorBase::InArgs<double> EpetraModelEvaluator::createInArgs() const 00496 { 00497 if (!currentInArgsOutArgs_) 00498 updateInArgsOutArgs(); 00499 return prototypeInArgs_; 00500 } 00501 00502 00503 void EpetraModelEvaluator::reportFinalPoint( 00504 const ModelEvaluatorBase::InArgs<double> &finalPoint, 00505 const bool wasSolved 00506 ) 00507 { 00508 finalPoint_ = this->createInArgs(); 00509 finalPoint_.setArgs(finalPoint); 00510 finalPointWasSolved_ = wasSolved; 00511 } 00512 00513 00514 // Private functions overridden from ModelEvaulatorDefaultBase 00515 00516 00517 RCP<LinearOpBase<double> > 00518 EpetraModelEvaluator::create_DfDp_op_impl(int l) const 00519 { 00520 TEUCHOS_TEST_FOR_EXCEPT(true); 00521 return Teuchos::null; 00522 } 00523 00524 00525 RCP<LinearOpBase<double> > 00526 EpetraModelEvaluator::create_DgDx_dot_op_impl(int j) const 00527 { 00528 TEUCHOS_TEST_FOR_EXCEPT(true); 00529 return Teuchos::null; 00530 } 00531 00532 00533 RCP<LinearOpBase<double> > 00534 EpetraModelEvaluator::create_DgDx_op_impl(int j) const 00535 { 00536 TEUCHOS_TEST_FOR_EXCEPT(true); 00537 return Teuchos::null; 00538 } 00539 00540 00541 RCP<LinearOpBase<double> > 00542 EpetraModelEvaluator::create_DgDp_op_impl( int j, int l ) const 00543 { 00544 TEUCHOS_TEST_FOR_EXCEPT(true); 00545 return Teuchos::null; 00546 } 00547 00548 00549 ModelEvaluatorBase::OutArgs<double> 00550 EpetraModelEvaluator::createOutArgsImpl() const 00551 { 00552 if (!currentInArgsOutArgs_) 00553 updateInArgsOutArgs(); 00554 return prototypeOutArgs_; 00555 } 00556 00557 00558 void EpetraModelEvaluator::evalModelImpl( 00559 const ModelEvaluatorBase::InArgs<double>& inArgs_in, 00560 const ModelEvaluatorBase::OutArgs<double>& outArgs 00561 ) const 00562 { 00563 00564 using Teuchos::rcp; 00565 using Teuchos::rcp_const_cast; 00566 using Teuchos::rcp_dynamic_cast; 00567 using Teuchos::OSTab; 00568 using Teuchos::includesVerbLevel; 00569 typedef EpetraExt::ModelEvaluator EME; 00570 00571 // 00572 // A) Initial setup 00573 // 00574 00575 // Make sure that we are fully initialized! 00576 this->updateNominalValuesAndBounds(); 00577 00578 // Make sure we grab the initial guess first! 00579 InArgs<double> inArgs = this->getNominalValues(); 00580 // Now, copy the parameters from the input inArgs_in object to the inArgs 00581 // object. Any input objects that are set in inArgs_in will overwrite those 00582 // in inArgs that will already contain the nominal values. This will insure 00583 // that all input parameters are set and those that are not set by the 00584 // client will be at their nominal values (as defined by the underlying 00585 // EpetraExt::ModelEvaluator object). The full set of Thyra input arguments 00586 // must be set before these can be translated into Epetra input arguments. 00587 inArgs.setArgs(inArgs_in); 00588 00589 // This is a special exception: see evalModel() in Thyra::ME 00590 // documentation. If inArgs() supports x_dot but the evaluate call 00591 // passes in a null value, then we need to make sure the null value 00592 // gets passed on instead of the nominal value. 00593 if (inArgs.supports(Thyra::ModelEvaluatorBase::IN_ARG_x_dot)) { 00594 if (is_null(inArgs_in.get_x_dot())) 00595 inArgs.set_x_dot(Teuchos::null); 00596 } 00597 00598 // Print the header and the values of the inArgs and outArgs objects! 00599 typedef double Scalar; // Needed for below macro! 00600 THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_GEN_BEGIN( 00601 "Thyra::EpetraModelEvaluator",inArgs,outArgs,Teuchos::null 00602 ); 00603 00604 // State function Scaling 00605 const bool firstTimeStateFuncScaling 00606 = ( 00607 stateFunctionScaling_ != STATE_FUNC_SCALING_NONE 00608 && is_null(stateFunctionScalingVec_) 00609 ); 00610 00611 typedef Teuchos::VerboseObjectTempState<LinearOpWithSolveFactoryBase<double> > VOTSLOWSF; 00612 VOTSLOWSF W_factory_outputTempState(W_factory_,out,verbLevel); 00613 00614 Teuchos::Time timer(""); 00615 00616 // 00617 // B) Prepressess the InArgs and OutArgs in preparation to call 00618 // the underlying EpetraExt::ModelEvaluator 00619 // 00620 00621 // 00622 // B.1) Translate InArgs from Thyra to Epetra objects 00623 // 00624 00625 if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) 00626 *out << "\nSetting-up/creating input arguments ...\n"; 00627 timer.start(true); 00628 00629 // Unwrap input Thyra objects to get Epetra objects 00630 EME::InArgs epetraScaledInArgs = epetraModel_->createInArgs(); 00631 convertInArgsFromThyraToEpetra( inArgs, &epetraScaledInArgs ); 00632 00633 // Unscale the input Epetra objects which will be passed to the underlying 00634 // EpetraExt::ModelEvaluator object. 00635 EME::InArgs epetraInArgs = epetraModel_->createInArgs(); 00636 EpetraExt::unscaleModelVars( 00637 epetraScaledInArgs, epetraInArgsScaling_, &epetraInArgs, 00638 out.get(), verbLevel 00639 ); 00640 00641 timer.stop(); 00642 if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) 00643 OSTab(out).o() << "\nTime to setup InArgs = "<<timer.totalElapsedTime()<<" sec\n"; 00644 00645 // 00646 // B.2) Convert from Thyra to Epetra OutArgs 00647 // 00648 00649 if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) 00650 *out << "\nSetting-up/creating output arguments ...\n"; 00651 timer.start(true); 00652 00653 // The unscaled Epetra OutArgs that will be passed to the 00654 // underlying EpetraExt::ModelEvaluator object 00655 EME::OutArgs epetraUnscaledOutArgs = epetraModel_->createOutArgs(); 00656 00657 // Various objects that are needed later (see documentation in 00658 // the function convertOutArgsFromThyraToEpetra(...) 00659 RCP<LinearOpBase<double> > W_op; 00660 RCP<EpetraLinearOp> efwdW; 00661 RCP<Epetra_Operator> eW; 00662 00663 // Convert from Thyra to Epetra OutArgs and grap some of the intermediate 00664 // objects accessed along the way that are needed later. 00665 convertOutArgsFromThyraToEpetra( 00666 outArgs, 00667 &epetraUnscaledOutArgs, 00668 &W_op, &efwdW, &eW 00669 ); 00670 00671 // 00672 // B.3) Setup OutArgs to computing scaling if needed 00673 // 00674 00675 if (firstTimeStateFuncScaling) { 00676 preEvalScalingSetup(&epetraInArgs,&epetraUnscaledOutArgs,out,verbLevel); 00677 } 00678 00679 timer.stop(); 00680 if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) 00681 OSTab(out).o() 00682 << "\nTime to setup OutArgs = " 00683 << timer.totalElapsedTime() <<" sec\n"; 00684 00685 // 00686 // C) Evaluate the underlying EpetraExt model to compute the Epetra outputs 00687 // 00688 00689 if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) 00690 *out << "\nEvaluating the Epetra output functions ...\n"; 00691 timer.start(true); 00692 00693 epetraModel_->evalModel(epetraInArgs,epetraUnscaledOutArgs); 00694 00695 timer.stop(); 00696 if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) 00697 OSTab(out).o() 00698 << "\nTime to evaluate Epetra output functions = " 00699 << timer.totalElapsedTime() <<" sec\n"; 00700 00701 // 00702 // D) Postprocess the output objects 00703 // 00704 00705 // 00706 // D.1) Compute the scaling factors if needed 00707 // 00708 00709 if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) 00710 *out << "\nCompute scale factors if needed ...\n"; 00711 timer.start(true); 00712 00713 if (firstTimeStateFuncScaling) { 00714 postEvalScalingSetup(epetraUnscaledOutArgs,out,verbLevel); 00715 } 00716 00717 timer.stop(); 00718 if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) 00719 OSTab(out).o() 00720 << "\nTime to compute scale factors = " 00721 << timer.totalElapsedTime() <<" sec\n"; 00722 00723 // 00724 // D.2) Scale the output Epetra objects 00725 // 00726 00727 if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) 00728 *out << "\nScale the output objects ...\n"; 00729 timer.start(true); 00730 00731 EME::OutArgs epetraOutArgs = epetraModel_->createOutArgs(); 00732 bool allFuncsWhereScaled = false; 00733 EpetraExt::scaleModelFuncs( 00734 epetraUnscaledOutArgs, epetraInArgsScaling_, epetraOutArgsScaling_, 00735 &epetraOutArgs, &allFuncsWhereScaled, 00736 out.get(), verbLevel 00737 ); 00738 TEUCHOS_TEST_FOR_EXCEPTION( 00739 !allFuncsWhereScaled, std::logic_error, 00740 "Error, we can not currently handle epetra output objects that could not be" 00741 " scaled. Special code will have to be added to handle this (i.e. using" 00742 " implicit diagonal and multiplied linear operators to implicitly do" 00743 " the scaling." 00744 ); 00745 00746 timer.stop(); 00747 if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) 00748 OSTab(out).o() 00749 << "\nTime to scale the output objects = " 00750 << timer.totalElapsedTime() << " sec\n"; 00751 00752 // 00753 // D.3) Convert any Epetra objects to Thyra OutArgs objects that still need to 00754 // be converted 00755 // 00756 00757 if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) 00758 *out << "\nFinish processing and wrapping the output objects ...\n"; 00759 timer.start(true); 00760 00761 finishConvertingOutArgsFromEpetraToThyra( 00762 epetraOutArgs, W_op, efwdW, eW, 00763 outArgs 00764 ); 00765 00766 timer.stop(); 00767 if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) 00768 OSTab(out).o() 00769 << "\nTime to finish processing and wrapping the output objects = " 00770 << timer.totalElapsedTime() <<" sec\n"; 00771 00772 // 00773 // E) Print footer to end the function 00774 // 00775 00776 THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_END(); 00777 00778 } 00779 00780 00781 // private 00782 00783 00784 void EpetraModelEvaluator::convertInArgsFromEpetraToThyra( 00785 const EpetraExt::ModelEvaluator::InArgs &epetraInArgs, 00786 ModelEvaluatorBase::InArgs<double> *inArgs 00787 ) const 00788 { 00789 00790 using Teuchos::implicit_cast; 00791 typedef ModelEvaluatorBase MEB; 00792 00793 TEUCHOS_TEST_FOR_EXCEPT(!inArgs); 00794 00795 if(inArgs->supports(MEB::IN_ARG_x)) { 00796 inArgs->set_x( create_Vector( epetraInArgs.get_x(), x_space_ ) ); 00797 } 00798 00799 if(inArgs->supports(MEB::IN_ARG_x_dot)) { 00800 inArgs->set_x_dot( create_Vector( epetraInArgs.get_x_dot(), x_space_ ) ); 00801 } 00802 00803 const int l_Np = inArgs->Np(); 00804 for( int l = 0; l < l_Np; ++l ) { 00805 inArgs->set_p( l, create_Vector( epetraInArgs.get_p(l), p_space_[l] ) ); 00806 } 00807 00808 if(inArgs->supports(MEB::IN_ARG_t)) { 00809 inArgs->set_t(epetraInArgs.get_t()); 00810 } 00811 00812 } 00813 00814 00815 void EpetraModelEvaluator::convertInArgsFromThyraToEpetra( 00816 const ModelEvaluatorBase::InArgs<double> &inArgs, 00817 EpetraExt::ModelEvaluator::InArgs *epetraInArgs 00818 ) const 00819 { 00820 00821 using Teuchos::rcp; 00822 using Teuchos::rcp_const_cast; 00823 #ifdef HAVE_THYRA_ME_POLYNOMIAL 00824 using Teuchos::Polynomial; 00825 #endif // HAVE_THYRA_ME_POLYNOMIAL 00826 00827 00828 TEUCHOS_TEST_FOR_EXCEPT(0==epetraInArgs); 00829 00830 RCP<const VectorBase<double> > x_dot; 00831 if( inArgs.supports(IN_ARG_x_dot) && (x_dot = inArgs.get_x_dot()).get() ) { 00832 RCP<const Epetra_Vector> e_x_dot = get_Epetra_Vector(*x_map_,x_dot); 00833 epetraInArgs->set_x_dot(e_x_dot); 00834 } 00835 00836 RCP<const VectorBase<double> > x; 00837 if( inArgs.supports(IN_ARG_x) && (x = inArgs.get_x()).get() ) { 00838 RCP<const Epetra_Vector> e_x = get_Epetra_Vector(*x_map_,x); 00839 epetraInArgs->set_x(e_x); 00840 } 00841 00842 RCP<const VectorBase<double> > p_l; 00843 for(int l = 0; l < inArgs.Np(); ++l ) { 00844 p_l = inArgs.get_p(l); 00845 if(p_l.get()) epetraInArgs->set_p(l,get_Epetra_Vector(*p_map_[l],p_l)); 00846 } 00847 00848 #ifdef HAVE_THYRA_ME_POLYNOMIAL 00849 00850 RCP<const Polynomial< VectorBase<double> > > x_dot_poly; 00851 RCP<Epetra_Vector> epetra_ptr; 00852 if( 00853 inArgs.supports(IN_ARG_x_dot_poly) 00854 && (x_dot_poly = inArgs.get_x_dot_poly()).get() 00855 ) 00856 { 00857 RCP<Polynomial<Epetra_Vector> > epetra_x_dot_poly = 00858 rcp(new Polynomial<Epetra_Vector>(x_dot_poly->degree())); 00859 for (unsigned int i=0; i<=x_dot_poly->degree(); i++) { 00860 epetra_ptr = rcp_const_cast<Epetra_Vector>( 00861 get_Epetra_Vector(*x_map_, x_dot_poly->getCoefficient(i)) ); 00862 epetra_x_dot_poly->setCoefficientPtr(i,epetra_ptr); 00863 } 00864 epetraInArgs->set_x_dot_poly(epetra_x_dot_poly); 00865 } 00866 00867 RCP<const Polynomial< VectorBase<double> > > x_poly; 00868 if( 00869 inArgs.supports(IN_ARG_x_poly) 00870 && (x_poly = inArgs.get_x_poly()).get() 00871 ) 00872 { 00873 RCP<Polynomial<Epetra_Vector> > epetra_x_poly = 00874 rcp(new Polynomial<Epetra_Vector>(x_poly->degree())); 00875 for (unsigned int i=0; i<=x_poly->degree(); i++) { 00876 epetra_ptr = rcp_const_cast<Epetra_Vector>( 00877 get_Epetra_Vector(*x_map_, x_poly->getCoefficient(i)) ); 00878 epetra_x_poly->setCoefficientPtr(i,epetra_ptr); 00879 } 00880 epetraInArgs->set_x_poly(epetra_x_poly); 00881 } 00882 00883 #endif // HAVE_THYRA_ME_POLYNOMIAL 00884 00885 if( inArgs.supports(IN_ARG_t) ) 00886 epetraInArgs->set_t(inArgs.get_t()); 00887 00888 if( inArgs.supports(IN_ARG_alpha) ) 00889 epetraInArgs->set_alpha(inArgs.get_alpha()); 00890 00891 if( inArgs.supports(IN_ARG_beta) ) 00892 epetraInArgs->set_beta(inArgs.get_beta()); 00893 00894 } 00895 00896 00897 void EpetraModelEvaluator::convertOutArgsFromThyraToEpetra( 00898 const ModelEvaluatorBase::OutArgs<double> &outArgs, 00899 EpetraExt::ModelEvaluator::OutArgs *epetraUnscaledOutArgs_inout, 00900 RCP<LinearOpBase<double> > *W_op_out, 00901 RCP<EpetraLinearOp> *efwdW_out, 00902 RCP<Epetra_Operator> *eW_out 00903 ) const 00904 { 00905 00906 using Teuchos::rcp; 00907 using Teuchos::rcp_const_cast; 00908 using Teuchos::rcp_dynamic_cast; 00909 using Teuchos::OSTab; 00910 using Teuchos::implicit_cast; 00911 using Thyra::get_Epetra_Vector; 00912 typedef EpetraExt::ModelEvaluator EME; 00913 00914 // Assert input 00915 #ifdef TEUCHOS_DEBUG 00916 TEUCHOS_ASSERT(epetraUnscaledOutArgs_inout); 00917 TEUCHOS_ASSERT(W_op_out); 00918 TEUCHOS_ASSERT(efwdW_out); 00919 TEUCHOS_ASSERT(eW_out); 00920 #endif 00921 00922 // Create easy to use references 00923 EpetraExt::ModelEvaluator::OutArgs &epetraUnscaledOutArgs = *epetraUnscaledOutArgs_inout; 00924 RCP<LinearOpBase<double> > &W_op = *W_op_out; 00925 RCP<EpetraLinearOp> &efwdW = *efwdW_out; 00926 RCP<Epetra_Operator> &eW = *eW_out; 00927 00928 // f 00929 { 00930 RCP<VectorBase<double> > f; 00931 if( outArgs.supports(OUT_ARG_f) && (f = outArgs.get_f()).get() ) 00932 epetraUnscaledOutArgs.set_f(get_Epetra_Vector(*f_map_,f)); 00933 } 00934 00935 // g 00936 { 00937 RCP<VectorBase<double> > g_j; 00938 for(int j = 0; j < outArgs.Ng(); ++j ) { 00939 g_j = outArgs.get_g(j); 00940 if(g_j.get()) epetraUnscaledOutArgs.set_g(j,get_Epetra_Vector(*g_map_[j],g_j)); 00941 } 00942 } 00943 00944 // W_op 00945 { 00946 00947 if (outArgs.supports(OUT_ARG_W_op) && nonnull(W_op = outArgs.get_W_op())) { 00948 if (nonnull(W_op) && is_null(efwdW)) { 00949 efwdW = rcp_const_cast<EpetraLinearOp>( 00950 rcp_dynamic_cast<const EpetraLinearOp>(W_op, true)); 00951 } 00952 } 00953 00954 if (nonnull(efwdW)) { 00955 // By the time we get here, if we have an object in efwdW, then it 00956 // should already be embeadded with an underlying Epetra_Operator object 00957 // that was allocated by the EpetraExt::ModelEvaluator object. 00958 // Therefore, we should just have to grab this object and be on our way. 00959 eW = efwdW->epetra_op(); 00960 epetraUnscaledOutArgs.set_W(eW); 00961 } 00962 00963 // Note: The following derivative objects update in place! 00964 00965 } 00966 00967 // DfDp 00968 { 00969 Derivative<double> DfDp_l; 00970 for(int l = 0; l < outArgs.Np(); ++l ) { 00971 if( !outArgs.supports(OUT_ARG_DfDp,l).none() 00972 && !(DfDp_l = outArgs.get_DfDp(l)).isEmpty() ) 00973 { 00974 epetraUnscaledOutArgs.set_DfDp(l,convert(DfDp_l,f_map_,p_map_[l])); 00975 } 00976 } 00977 } 00978 00979 // DgDx_dot 00980 { 00981 Derivative<double> DgDx_dot_j; 00982 for(int j = 0; j < outArgs.Ng(); ++j ) { 00983 if( !outArgs.supports(OUT_ARG_DgDx_dot,j).none() 00984 && !(DgDx_dot_j = outArgs.get_DgDx_dot(j)).isEmpty() ) 00985 { 00986 epetraUnscaledOutArgs.set_DgDx_dot(j,convert(DgDx_dot_j,g_map_[j],x_map_)); 00987 } 00988 } 00989 } 00990 00991 // DgDx 00992 { 00993 Derivative<double> DgDx_j; 00994 for(int j = 0; j < outArgs.Ng(); ++j ) { 00995 if( !outArgs.supports(OUT_ARG_DgDx,j).none() 00996 && !(DgDx_j = outArgs.get_DgDx(j)).isEmpty() ) 00997 { 00998 epetraUnscaledOutArgs.set_DgDx(j,convert(DgDx_j,g_map_[j],x_map_)); 00999 } 01000 } 01001 } 01002 01003 // DgDp 01004 { 01005 DerivativeSupport DgDp_j_l_support; 01006 Derivative<double> DgDp_j_l; 01007 for (int j = 0; j < outArgs.Ng(); ++j ) { 01008 for (int l = 0; l < outArgs.Np(); ++l ) { 01009 if (!(DgDp_j_l_support = outArgs.supports(OUT_ARG_DgDp,j,l)).none() 01010 && !(DgDp_j_l = outArgs.get_DgDp(j,l)).isEmpty() ) 01011 { 01012 epetraUnscaledOutArgs.set_DgDp(j,l,convert(DgDp_j_l,g_map_[j],p_map_[l])); 01013 } 01014 } 01015 } 01016 } 01017 01018 #ifdef HAVE_THYRA_ME_POLYNOMIAL 01019 01020 // f_poly 01021 RCP<const Teuchos::Polynomial< VectorBase<double> > > f_poly; 01022 if( outArgs.supports(OUT_ARG_f_poly) && (f_poly = outArgs.get_f_poly()).get() ) 01023 { 01024 RCP<Teuchos::Polynomial<Epetra_Vector> > epetra_f_poly = 01025 Teuchos::rcp(new Teuchos::Polynomial<Epetra_Vector>(f_poly->degree())); 01026 for (unsigned int i=0; i<=f_poly->degree(); i++) { 01027 RCP<Epetra_Vector> epetra_ptr 01028 = Teuchos::rcp_const_cast<Epetra_Vector>(get_Epetra_Vector(*f_map_, 01029 f_poly->getCoefficient(i))); 01030 epetra_f_poly->setCoefficientPtr(i,epetra_ptr); 01031 } 01032 epetraUnscaledOutArgs.set_f_poly(epetra_f_poly); 01033 } 01034 01035 #endif // HAVE_THYRA_ME_POLYNOMIAL 01036 01037 } 01038 01039 01040 void EpetraModelEvaluator::preEvalScalingSetup( 01041 EpetraExt::ModelEvaluator::InArgs *epetraInArgs_inout, 01042 EpetraExt::ModelEvaluator::OutArgs *epetraUnscaledOutArgs_inout, 01043 const RCP<Teuchos::FancyOStream> &out, 01044 const Teuchos::EVerbosityLevel verbLevel 01045 ) const 01046 { 01047 01048 typedef EpetraExt::ModelEvaluator EME; 01049 01050 #ifdef TEUCHOS_DEBUG 01051 TEUCHOS_ASSERT(epetraInArgs_inout); 01052 TEUCHOS_ASSERT(epetraUnscaledOutArgs_inout); 01053 #endif 01054 01055 EpetraExt::ModelEvaluator::InArgs 01056 &epetraInArgs = *epetraInArgs_inout; 01057 EpetraExt::ModelEvaluator::OutArgs 01058 &epetraUnscaledOutArgs = *epetraUnscaledOutArgs_inout; 01059 01060 if ( 01061 ( stateFunctionScaling_ == STATE_FUNC_SCALING_ROW_SUM ) 01062 && 01063 ( 01064 epetraUnscaledOutArgs.supports(EME::OUT_ARG_f) 01065 && 01066 epetraUnscaledOutArgs.funcOrDerivesAreSet(EME::OUT_ARG_f) 01067 ) 01068 && 01069 ( 01070 epetraUnscaledOutArgs.supports(EME::OUT_ARG_W) 01071 && 01072 is_null(epetraUnscaledOutArgs.get_W()) 01073 ) 01074 ) 01075 { 01076 // This is the first pass through with scaling turned on and the client 01077 // turned on automatic scaling but did not ask for W. We must compute W 01078 // in order to compute the scale factors so we must allocate a temporary W 01079 // just to compute the scale factors and then throw it away. If the 01080 // client wants to evaluate W at the same point, then it should have 01081 // passed W in but that is not our problem here. The ModelEvaluator 01082 // relies on the client to set up the calls to allow for efficient 01083 // evaluation. 01084 01085 if(out.get() && verbLevel >= Teuchos::VERB_LOW) 01086 *out 01087 << "\nCreating a temporary Epetra W to compute scale factors" 01088 << " for f(...) ...\n"; 01089 epetraUnscaledOutArgs.set_W(create_and_assert_W(*epetraModel_)); 01090 if( epetraInArgs.supports(EME::IN_ARG_beta) ) 01091 epetraInArgs.set_beta(1.0); 01092 if( epetraInArgs.supports(EME::IN_ARG_alpha) ) 01093 epetraInArgs.set_alpha(0.0); 01094 } 01095 01096 } 01097 01098 01099 void EpetraModelEvaluator::postEvalScalingSetup( 01100 const EpetraExt::ModelEvaluator::OutArgs &epetraUnscaledOutArgs, 01101 const RCP<Teuchos::FancyOStream> &out, 01102 const Teuchos::EVerbosityLevel verbLevel 01103 ) const 01104 { 01105 01106 using Teuchos::OSTab; 01107 using Teuchos::rcp; 01108 using Teuchos::rcp_const_cast; 01109 using Teuchos::includesVerbLevel; 01110 01111 // Compute the scale factors for the state function f(...) 01112 switch(stateFunctionScaling_) { 01113 01114 case STATE_FUNC_SCALING_ROW_SUM: { 01115 01116 // Compute the inverse row-sum scaling from W 01117 01118 const RCP<Epetra_RowMatrix> 01119 ermW = get_Epetra_RowMatrix(epetraUnscaledOutArgs); 01120 // Note: Above, we get the Epetra W object directly from the Epetra 01121 // OutArgs object since this might be a temporary matrix just to 01122 // compute scaling factors. In this case, the stack funtion variable 01123 // eW might be empty! 01124 01125 RCP<Epetra_Vector> 01126 invRowSums = rcp(new Epetra_Vector(ermW->OperatorRangeMap())); 01127 // Above: From the documentation is seems that the RangeMap should be 01128 // okay but who knows for sure! 01129 01130 ermW->InvRowSums(*invRowSums); 01131 01132 if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) { 01133 *out 01134 << "\nComputed inverse row sum scaling from W that" 01135 " will be used to scale f(...) and its derivatives:\n"; 01136 double minVal = 0, maxVal = 0, avgVal = 0; 01137 invRowSums->MinValue(&minVal); 01138 invRowSums->MaxValue(&maxVal); 01139 invRowSums->MeanValue(&avgVal); 01140 OSTab tab(out); 01141 *out 01142 << "min(invRowSums) = " << minVal << "\n" 01143 << "max(invRowSums) = " << maxVal << "\n" 01144 << "avg(invRowSums) = " << avgVal << "\n"; 01145 } 01146 01147 stateFunctionScalingVec_ = invRowSums; 01148 01149 break; 01150 01151 } 01152 01153 default: 01154 TEUCHOS_TEST_FOR_EXCEPT("Should never get here!"); 01155 01156 } 01157 01158 epetraOutArgsScaling_ = epetraModel_->createOutArgs(); 01159 01160 epetraOutArgsScaling_.set_f( 01161 rcp_const_cast<Epetra_Vector>(stateFunctionScalingVec_) ); 01162 01163 } 01164 01165 01166 void EpetraModelEvaluator::finishConvertingOutArgsFromEpetraToThyra( 01167 const EpetraExt::ModelEvaluator::OutArgs &epetraOutArgs, 01168 RCP<LinearOpBase<double> > &W_op, 01169 RCP<EpetraLinearOp> &efwdW, 01170 RCP<Epetra_Operator> &eW, 01171 const ModelEvaluatorBase::OutArgs<double> &outArgs 01172 ) const 01173 { 01174 01175 using Teuchos::rcp_dynamic_cast; 01176 typedef EpetraExt::ModelEvaluator EME; 01177 01178 if (nonnull(efwdW)) { 01179 efwdW->setFullyInitialized(true); 01180 // NOTE: Above will directly update W_op also if W.get()==NULL! 01181 } 01182 01183 if (nonnull(W_op)) { 01184 if (W_op.shares_resource(efwdW)) { 01185 // W_op was already updated above since *efwdW is the same object as *W_op 01186 } 01187 else { 01188 rcp_dynamic_cast<EpetraLinearOp>(W_op, true)->setFullyInitialized(true); 01189 } 01190 } 01191 01192 } 01193 01194 01195 void EpetraModelEvaluator::updateNominalValuesAndBounds() const 01196 { 01197 01198 using Teuchos::rcp; 01199 using Teuchos::implicit_cast; 01200 typedef ModelEvaluatorBase MEB; 01201 typedef EpetraExt::ModelEvaluator EME; 01202 01203 if( !nominalValuesAndBoundsAreUpdated_ ) { 01204 01205 // Gather the nominal values and bounds into Epetra InArgs objects 01206 01207 EME::InArgs epetraOrigNominalValues; 01208 EpetraExt::gatherModelNominalValues( 01209 *epetraModel_, &epetraOrigNominalValues ); 01210 01211 EME::InArgs epetraOrigLowerBounds; 01212 EME::InArgs epetraOrigUpperBounds; 01213 EpetraExt::gatherModelBounds( 01214 *epetraModel_, &epetraOrigLowerBounds, &epetraOrigUpperBounds ); 01215 01216 // Set up Epetra InArgs scaling object 01217 01218 epetraInArgsScaling_ = epetraModel_->createInArgs(); 01219 01220 if( !is_null(stateVariableScalingVec_) ) { 01221 invStateVariableScalingVec_ 01222 = EpetraExt::createInverseModelScalingVector(stateVariableScalingVec_); 01223 if( epetraOrigNominalValues.supports(EME::IN_ARG_x_dot) ) { 01224 epetraInArgsScaling_.set_x_dot(invStateVariableScalingVec_); 01225 } 01226 if( epetraOrigNominalValues.supports(EME::IN_ARG_x) ) { 01227 epetraInArgsScaling_.set_x(invStateVariableScalingVec_); 01228 } 01229 } 01230 01231 // Scale the original variables and bounds 01232 01233 EME::InArgs epetraScaledNominalValues = epetraModel_->createInArgs(); 01234 EpetraExt::scaleModelVars( 01235 epetraOrigNominalValues, epetraInArgsScaling_, &epetraScaledNominalValues 01236 ); 01237 01238 EME::InArgs epetraScaledLowerBounds = epetraModel_->createInArgs(); 01239 EME::InArgs epetraScaledUpperBounds = epetraModel_->createInArgs(); 01240 EpetraExt::scaleModelBounds( 01241 epetraOrigLowerBounds, epetraOrigUpperBounds, epetraModel_->getInfBound(), 01242 epetraInArgsScaling_, 01243 &epetraScaledLowerBounds, &epetraScaledUpperBounds 01244 ); 01245 01246 // Wrap the scaled epetra InArgs objects as Thyra InArgs objects! 01247 01248 nominalValues_ = this->createInArgs(); 01249 lowerBounds_ = this->createInArgs(); 01250 upperBounds_ = this->createInArgs(); 01251 convertInArgsFromEpetraToThyra(epetraScaledNominalValues, &nominalValues_); 01252 convertInArgsFromEpetraToThyra(epetraScaledLowerBounds, &lowerBounds_); 01253 convertInArgsFromEpetraToThyra(epetraScaledUpperBounds, &upperBounds_); 01254 01255 nominalValuesAndBoundsAreUpdated_ = true; 01256 01257 } 01258 else { 01259 01260 // The nominal values and bounds should already be updated an should have 01261 // the currect scaling! 01262 01263 } 01264 01265 } 01266 01267 01268 void EpetraModelEvaluator::updateInArgsOutArgs() const 01269 { 01270 01271 typedef EpetraExt::ModelEvaluator EME; 01272 01273 const EpetraExt::ModelEvaluator &epetraModel = *epetraModel_; 01274 EME::InArgs epetraInArgs = epetraModel.createInArgs(); 01275 EME::OutArgs epetraOutArgs = epetraModel.createOutArgs(); 01276 const int l_Np = epetraOutArgs.Np(); 01277 const int l_Ng = epetraOutArgs.Ng(); 01278 01279 // 01280 // InArgs 01281 // 01282 01283 InArgsSetup<double> inArgs; 01284 inArgs.setModelEvalDescription(this->description()); 01285 inArgs.set_Np(epetraInArgs.Np()); 01286 inArgs.setSupports(IN_ARG_x_dot, epetraInArgs.supports(EME::IN_ARG_x_dot)); 01287 inArgs.setSupports(IN_ARG_x, epetraInArgs.supports(EME::IN_ARG_x)); 01288 #ifdef HAVE_THYRA_ME_POLYNOMIAL 01289 inArgs.setSupports(IN_ARG_x_dot_poly, 01290 epetraInArgs.supports(EME::IN_ARG_x_dot_poly)); 01291 inArgs.setSupports(IN_ARG_x_poly, epetraInArgs.supports(EME::IN_ARG_x_poly)); 01292 #endif // HAVE_THYRA_ME_POLYNOMIAL 01293 inArgs.setSupports(IN_ARG_t, epetraInArgs.supports(EME::IN_ARG_t)); 01294 inArgs.setSupports(IN_ARG_alpha, epetraInArgs.supports(EME::IN_ARG_alpha)); 01295 inArgs.setSupports(IN_ARG_beta, epetraInArgs.supports(EME::IN_ARG_beta)); 01296 prototypeInArgs_ = inArgs; 01297 01298 // 01299 // OutArgs 01300 // 01301 01302 OutArgsSetup<double> outArgs; 01303 outArgs.setModelEvalDescription(this->description()); 01304 outArgs.set_Np_Ng(l_Np, l_Ng); 01305 // f 01306 outArgs.setSupports(OUT_ARG_f, epetraOutArgs.supports(EME::OUT_ARG_f)); 01307 if (outArgs.supports(OUT_ARG_f)) { 01308 // W_op 01309 outArgs.setSupports(OUT_ARG_W_op, epetraOutArgs.supports(EME::OUT_ARG_W)); 01310 outArgs.set_W_properties(convert(epetraOutArgs.get_W_properties())); 01311 // DfDp 01312 for(int l=0; l<l_Np; ++l) { 01313 outArgs.setSupports(OUT_ARG_DfDp, l, 01314 convert(epetraOutArgs.supports(EME::OUT_ARG_DfDp, l))); 01315 if(!outArgs.supports(OUT_ARG_DfDp, l).none()) 01316 outArgs.set_DfDp_properties(l, 01317 convert(epetraOutArgs.get_DfDp_properties(l))); 01318 } 01319 } 01320 // DgDx_dot and DgDx 01321 for(int j=0; j<l_Ng; ++j) { 01322 if (inArgs.supports(IN_ARG_x_dot)) 01323 outArgs.setSupports(OUT_ARG_DgDx_dot, j, 01324 convert(epetraOutArgs.supports(EME::OUT_ARG_DgDx_dot, j))); 01325 if(!outArgs.supports(OUT_ARG_DgDx_dot, j).none()) 01326 outArgs.set_DgDx_dot_properties(j, 01327 convert(epetraOutArgs.get_DgDx_dot_properties(j))); 01328 if (inArgs.supports(IN_ARG_x)) 01329 outArgs.setSupports(OUT_ARG_DgDx, j, 01330 convert(epetraOutArgs.supports(EME::OUT_ARG_DgDx, j))); 01331 if(!outArgs.supports(OUT_ARG_DgDx, j).none()) 01332 outArgs.set_DgDx_properties(j, 01333 convert(epetraOutArgs.get_DgDx_properties(j))); 01334 } 01335 // DgDp 01336 for(int j=0; j < l_Ng; ++j) for(int l=0; l < l_Np; ++l) { 01337 const EME::DerivativeSupport epetra_DgDp_j_l_support = 01338 epetraOutArgs.supports(EME::OUT_ARG_DgDp, j, l); 01339 outArgs.setSupports(OUT_ARG_DgDp, j, l, 01340 convert(epetra_DgDp_j_l_support)); 01341 if(!outArgs.supports(OUT_ARG_DgDp, j, l).none()) 01342 outArgs.set_DgDp_properties(j, l, 01343 convert(epetraOutArgs.get_DgDp_properties(j, l))); 01344 } 01345 #ifdef HAVE_THYRA_ME_POLYNOMIAL 01346 outArgs.setSupports(OUT_ARG_f_poly, 01347 epetraOutArgs.supports(EME::OUT_ARG_f_poly)); 01348 #endif // HAVE_THYRA_ME_POLYNOMIAL 01349 prototypeOutArgs_ = outArgs; 01350 01351 // We are current! 01352 currentInArgsOutArgs_ = true; 01353 01354 } 01355 01356 01357 RCP<EpetraLinearOp> 01358 EpetraModelEvaluator::create_epetra_W_op() const 01359 { 01360 return Thyra::partialNonconstEpetraLinearOp( 01361 this->get_f_space(), this->get_x_space(), 01362 create_and_assert_W(*epetraModel_) 01363 ); 01364 } 01365 01366 01367 } // namespace Thyra 01368 01369 01370 // 01371 // Non-member utility functions 01372 // 01373 01374 01375 Teuchos::RCP<Thyra::EpetraModelEvaluator> 01376 Thyra::epetraModelEvaluator( 01377 const RCP<const EpetraExt::ModelEvaluator> &epetraModel, 01378 const RCP<LinearOpWithSolveFactoryBase<double> > &W_factory 01379 ) 01380 { 01381 return Teuchos::rcp(new EpetraModelEvaluator(epetraModel,W_factory)); 01382 } 01383 01384 01385 Thyra::ModelEvaluatorBase::EDerivativeMultiVectorOrientation 01386 Thyra::convert( 01387 const EpetraExt::ModelEvaluator::EDerivativeMultiVectorOrientation &mvOrientation 01388 ) 01389 { 01390 switch(mvOrientation) { 01391 case EpetraExt::ModelEvaluator::DERIV_MV_BY_COL : 01392 return ModelEvaluatorBase::DERIV_MV_BY_COL; 01393 case EpetraExt::ModelEvaluator::DERIV_TRANS_MV_BY_ROW : 01394 return ModelEvaluatorBase::DERIV_TRANS_MV_BY_ROW; 01395 default: 01396 TEUCHOS_TEST_FOR_EXCEPT(true); 01397 } 01398 return ModelEvaluatorBase::DERIV_MV_BY_COL; // Should never be called! 01399 } 01400 01401 01402 EpetraExt::ModelEvaluator::EDerivativeMultiVectorOrientation 01403 Thyra::convert( 01404 const ModelEvaluatorBase::EDerivativeMultiVectorOrientation &mvOrientation 01405 ) 01406 { 01407 switch(mvOrientation) { 01408 case ModelEvaluatorBase::DERIV_MV_BY_COL : 01409 return EpetraExt::ModelEvaluator::DERIV_MV_BY_COL; 01410 case ModelEvaluatorBase::DERIV_TRANS_MV_BY_ROW : 01411 return EpetraExt::ModelEvaluator::DERIV_TRANS_MV_BY_ROW; 01412 default: 01413 TEUCHOS_TEST_FOR_EXCEPT(true); 01414 } 01415 return EpetraExt::ModelEvaluator::DERIV_MV_BY_COL; // Should never be called! 01416 } 01417 01418 01419 Thyra::ModelEvaluatorBase::DerivativeProperties 01420 Thyra::convert( 01421 const EpetraExt::ModelEvaluator::DerivativeProperties &derivativeProperties 01422 ) 01423 { 01424 ModelEvaluatorBase::EDerivativeLinearity linearity; 01425 switch(derivativeProperties.linearity) { 01426 case EpetraExt::ModelEvaluator::DERIV_LINEARITY_UNKNOWN: 01427 linearity = ModelEvaluatorBase::DERIV_LINEARITY_UNKNOWN; 01428 break; 01429 case EpetraExt::ModelEvaluator::DERIV_LINEARITY_CONST: 01430 linearity = ModelEvaluatorBase::DERIV_LINEARITY_CONST; 01431 break; 01432 case EpetraExt::ModelEvaluator::DERIV_LINEARITY_NONCONST: 01433 linearity = ModelEvaluatorBase::DERIV_LINEARITY_NONCONST; 01434 break; 01435 default: 01436 TEUCHOS_TEST_FOR_EXCEPT(true); 01437 } 01438 ModelEvaluatorBase::ERankStatus rank; 01439 switch(derivativeProperties.rank) { 01440 case EpetraExt::ModelEvaluator::DERIV_RANK_UNKNOWN: 01441 rank = ModelEvaluatorBase::DERIV_RANK_UNKNOWN; 01442 break; 01443 case EpetraExt::ModelEvaluator::DERIV_RANK_FULL: 01444 rank = ModelEvaluatorBase::DERIV_RANK_FULL; 01445 break; 01446 case EpetraExt::ModelEvaluator::DERIV_RANK_DEFICIENT: 01447 rank = ModelEvaluatorBase::DERIV_RANK_DEFICIENT; 01448 break; 01449 default: 01450 TEUCHOS_TEST_FOR_EXCEPT(true); 01451 } 01452 return ModelEvaluatorBase::DerivativeProperties( 01453 linearity,rank,derivativeProperties.supportsAdjoint); 01454 } 01455 01456 01457 Thyra::ModelEvaluatorBase::DerivativeSupport 01458 Thyra::convert( 01459 const EpetraExt::ModelEvaluator::DerivativeSupport &derivativeSupport 01460 ) 01461 { 01462 ModelEvaluatorBase::DerivativeSupport ds; 01463 if(derivativeSupport.supports(EpetraExt::ModelEvaluator::DERIV_LINEAR_OP)) 01464 ds.plus(ModelEvaluatorBase::DERIV_LINEAR_OP); 01465 if(derivativeSupport.supports(EpetraExt::ModelEvaluator::DERIV_MV_BY_COL)) 01466 ds.plus(ModelEvaluatorBase::DERIV_MV_BY_COL); 01467 if(derivativeSupport.supports(EpetraExt::ModelEvaluator::DERIV_TRANS_MV_BY_ROW)) 01468 ds.plus(ModelEvaluatorBase::DERIV_TRANS_MV_BY_ROW); 01469 return ds; 01470 } 01471 01472 01473 EpetraExt::ModelEvaluator::Derivative 01474 Thyra::convert( 01475 const ModelEvaluatorBase::Derivative<double> &derivative, 01476 const RCP<const Epetra_Map> &fnc_map, 01477 const RCP<const Epetra_Map> &var_map 01478 ) 01479 { 01480 typedef ModelEvaluatorBase MEB; 01481 if(derivative.getLinearOp().get()) { 01482 return EpetraExt::ModelEvaluator::Derivative( 01483 Teuchos::rcp_const_cast<Epetra_Operator>( 01484 Teuchos::dyn_cast<const EpetraLinearOp>(*derivative.getLinearOp()).epetra_op() 01485 ) 01486 ); 01487 } 01488 else if(derivative.getDerivativeMultiVector().getMultiVector().get()) { 01489 return EpetraExt::ModelEvaluator::Derivative( 01490 EpetraExt::ModelEvaluator::DerivativeMultiVector( 01491 get_Epetra_MultiVector( 01492 ( derivative.getDerivativeMultiVector().getOrientation() == MEB::DERIV_MV_BY_COL 01493 ? *fnc_map 01494 : *var_map 01495 ) 01496 ,derivative.getDerivativeMultiVector().getMultiVector() 01497 ) 01498 ,convert(derivative.getDerivativeMultiVector().getOrientation()) 01499 ) 01500 ); 01501 } 01502 return EpetraExt::ModelEvaluator::Derivative(); 01503 }
1.7.6.1