Thyra Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
Thyra_EpetraModelEvaluator.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines