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; // unused
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 #ifdef TEUCHOS_DEBUG
00217   typedef ModelEvaluatorBase MEB;
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<PreconditionerBase<double> >
00489 EpetraModelEvaluator::create_W_prec() const
00490 {
00491   return Teuchos::null;
00492 }
00493 
00494 
00495 RCP<const LinearOpWithSolveFactoryBase<double> >
00496 EpetraModelEvaluator::get_W_factory() const
00497 {
00498   return W_factory_;
00499 }
00500 
00501 
00502 ModelEvaluatorBase::InArgs<double> EpetraModelEvaluator::createInArgs() const
00503 {
00504   if (!currentInArgsOutArgs_)
00505     updateInArgsOutArgs();
00506   return prototypeInArgs_;
00507 }
00508 
00509 
00510 void EpetraModelEvaluator::reportFinalPoint(
00511   const ModelEvaluatorBase::InArgs<double> &finalPoint,
00512   const bool wasSolved
00513   )
00514 {
00515   finalPoint_ = this->createInArgs();
00516   finalPoint_.setArgs(finalPoint);
00517   finalPointWasSolved_ = wasSolved;
00518 }
00519 
00520 
00521 // Private functions overridden from ModelEvaulatorDefaultBase
00522 
00523 
00524 RCP<LinearOpBase<double> >
00525 EpetraModelEvaluator::create_DfDp_op_impl(int l) const
00526 {
00527   TEUCHOS_TEST_FOR_EXCEPT(true);
00528   return Teuchos::null;
00529 }
00530 
00531 
00532 RCP<LinearOpBase<double> >
00533 EpetraModelEvaluator::create_DgDx_dot_op_impl(int j) const
00534 {
00535   TEUCHOS_TEST_FOR_EXCEPT(true);
00536   return Teuchos::null;
00537 }
00538 
00539 
00540 RCP<LinearOpBase<double> >
00541 EpetraModelEvaluator::create_DgDx_op_impl(int j) const
00542 {
00543   TEUCHOS_TEST_FOR_EXCEPT(true);
00544   return Teuchos::null;
00545 }
00546 
00547 
00548 RCP<LinearOpBase<double> >
00549 EpetraModelEvaluator::create_DgDp_op_impl( int j, int l ) const
00550 {
00551   TEUCHOS_TEST_FOR_EXCEPT(true);
00552   return Teuchos::null;
00553 }
00554 
00555 
00556 ModelEvaluatorBase::OutArgs<double>
00557 EpetraModelEvaluator::createOutArgsImpl() const
00558 {
00559   if (!currentInArgsOutArgs_)
00560     updateInArgsOutArgs();
00561   return prototypeOutArgs_;
00562 }
00563 
00564 
00565 void EpetraModelEvaluator::evalModelImpl(
00566   const ModelEvaluatorBase::InArgs<double>& inArgs_in,
00567   const ModelEvaluatorBase::OutArgs<double>& outArgs
00568   ) const
00569 {
00570 
00571   using Teuchos::rcp;
00572   using Teuchos::rcp_const_cast;
00573   using Teuchos::rcp_dynamic_cast;
00574   using Teuchos::OSTab;
00575   using Teuchos::includesVerbLevel;
00576   typedef EpetraExt::ModelEvaluator EME;
00577 
00578   //
00579   // A) Initial setup
00580   //
00581 
00582   // Make sure that we are fully initialized!
00583   this->updateNominalValuesAndBounds();
00584 
00585   // Make sure we grab the initial guess first!
00586   InArgs<double> inArgs = this->getNominalValues();
00587   // Now, copy the parameters from the input inArgs_in object to the inArgs
00588   // object.  Any input objects that are set in inArgs_in will overwrite those
00589   // in inArgs that will already contain the nominal values.  This will insure
00590   // that all input parameters are set and those that are not set by the
00591   // client will be at their nominal values (as defined by the underlying
00592   // EpetraExt::ModelEvaluator object).  The full set of Thyra input arguments
00593   // must be set before these can be translated into Epetra input arguments.
00594   inArgs.setArgs(inArgs_in);
00595 
00596   // This is a special exception: see evalModel() in Thyra::ME
00597   // documentation.  If inArgs() supports x_dot but the evaluate call
00598   // passes in a null value, then we need to make sure the null value
00599   // gets passed on instead of the nominal value.
00600   if (inArgs.supports(Thyra::ModelEvaluatorBase::IN_ARG_x_dot)) {
00601     if (is_null(inArgs_in.get_x_dot()))
00602       inArgs.set_x_dot(Teuchos::null);
00603   }
00604 
00605   // Print the header and the values of the inArgs and outArgs objects!
00606   typedef double Scalar; // Needed for below macro!
00607   THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_GEN_BEGIN(
00608     "Thyra::EpetraModelEvaluator",inArgs,outArgs,Teuchos::null
00609     );
00610 
00611   // State function Scaling
00612   const bool firstTimeStateFuncScaling
00613     = (
00614       stateFunctionScaling_ != STATE_FUNC_SCALING_NONE
00615       && is_null(stateFunctionScalingVec_)
00616       );
00617 
00618   typedef Teuchos::VerboseObjectTempState<LinearOpWithSolveFactoryBase<double> > VOTSLOWSF;
00619   VOTSLOWSF W_factory_outputTempState(W_factory_,out,verbLevel);
00620 
00621   Teuchos::Time timer("");
00622 
00623   //
00624   // B) Prepressess the InArgs and OutArgs in preparation to call
00625   // the underlying EpetraExt::ModelEvaluator
00626   //
00627 
00628   //
00629   // B.1) Translate InArgs from Thyra to Epetra objects
00630   //
00631 
00632   if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW))
00633     *out << "\nSetting-up/creating input arguments ...\n";
00634   timer.start(true);
00635 
00636   // Unwrap input Thyra objects to get Epetra objects
00637   EME::InArgs epetraScaledInArgs = epetraModel_->createInArgs();
00638   convertInArgsFromThyraToEpetra( inArgs, &epetraScaledInArgs );
00639 
00640   // Unscale the input Epetra objects which will be passed to the underlying
00641   // EpetraExt::ModelEvaluator object.
00642   EME::InArgs epetraInArgs = epetraModel_->createInArgs();
00643   EpetraExt::unscaleModelVars(
00644     epetraScaledInArgs, epetraInArgsScaling_, &epetraInArgs,
00645     out.get(), verbLevel
00646     );
00647 
00648   timer.stop();
00649   if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW))
00650     OSTab(out).o() << "\nTime to setup InArgs = "<<timer.totalElapsedTime()<<" sec\n";
00651 
00652   //
00653   // B.2) Convert from Thyra to Epetra OutArgs
00654   //
00655 
00656   if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW))
00657     *out << "\nSetting-up/creating output arguments ...\n";
00658   timer.start(true);
00659 
00660   // The unscaled Epetra OutArgs that will be passed to the
00661   // underlying EpetraExt::ModelEvaluator object
00662   EME::OutArgs epetraUnscaledOutArgs = epetraModel_->createOutArgs();
00663 
00664   // Various objects that are needed later (see documentation in
00665   // the function convertOutArgsFromThyraToEpetra(...)
00666   RCP<LinearOpBase<double> > W_op;
00667   RCP<EpetraLinearOp> efwdW;
00668   RCP<Epetra_Operator> eW;
00669 
00670   // Convert from Thyra to Epetra OutArgs and grap some of the intermediate
00671   // objects accessed along the way that are needed later.
00672   convertOutArgsFromThyraToEpetra(
00673     outArgs,
00674     &epetraUnscaledOutArgs,
00675     &W_op, &efwdW, &eW
00676     );
00677 
00678   //
00679   // B.3) Setup OutArgs to computing scaling if needed
00680   //
00681 
00682   if (firstTimeStateFuncScaling) {
00683     preEvalScalingSetup(&epetraInArgs,&epetraUnscaledOutArgs,out,verbLevel);
00684   }
00685 
00686   timer.stop();
00687   if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW))
00688     OSTab(out).o()
00689       << "\nTime to setup OutArgs = "
00690       << timer.totalElapsedTime() <<" sec\n";
00691 
00692   //
00693   // C) Evaluate the underlying EpetraExt model to compute the Epetra outputs
00694   //
00695 
00696   if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW))
00697     *out << "\nEvaluating the Epetra output functions ...\n";
00698   timer.start(true);
00699 
00700   epetraModel_->evalModel(epetraInArgs,epetraUnscaledOutArgs);
00701 
00702   timer.stop();
00703   if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW))
00704     OSTab(out).o()
00705       << "\nTime to evaluate Epetra output functions = "
00706       << timer.totalElapsedTime() <<" sec\n";
00707 
00708   //
00709   // D) Postprocess the output objects
00710   //
00711 
00712   //
00713   // D.1) Compute the scaling factors if needed
00714   //
00715 
00716   if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW))
00717     *out << "\nCompute scale factors if needed ...\n";
00718   timer.start(true);
00719 
00720   if (firstTimeStateFuncScaling) {
00721     postEvalScalingSetup(epetraUnscaledOutArgs,out,verbLevel);
00722   }
00723 
00724   timer.stop();
00725   if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW))
00726     OSTab(out).o()
00727       << "\nTime to compute scale factors = "
00728       << timer.totalElapsedTime() <<" sec\n";
00729 
00730   //
00731   // D.2) Scale the output Epetra objects
00732   //
00733 
00734   if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW))
00735     *out << "\nScale the output objects ...\n";
00736   timer.start(true);
00737 
00738   EME::OutArgs epetraOutArgs = epetraModel_->createOutArgs();
00739   bool allFuncsWhereScaled = false;
00740   EpetraExt::scaleModelFuncs(
00741     epetraUnscaledOutArgs, epetraInArgsScaling_, epetraOutArgsScaling_,
00742     &epetraOutArgs, &allFuncsWhereScaled,
00743     out.get(), verbLevel
00744     );
00745   // AGS: This test precluded use of matrix-free Operators (vs. RowMatrix)
00746   if (stateFunctionScaling_ != STATE_FUNC_SCALING_NONE)
00747     TEUCHOS_TEST_FOR_EXCEPTION(
00748       !allFuncsWhereScaled, std::logic_error,
00749       "Error, we can not currently handle epetra output objects that could not be"
00750       " scaled.  Special code will have to be added to handle this (i.e. using"
00751       " implicit diagonal and multiplied linear operators to implicitly do"
00752       " the scaling."
00753       );
00754 
00755   timer.stop();
00756   if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW))
00757     OSTab(out).o()
00758       << "\nTime to scale the output objects = "
00759       << timer.totalElapsedTime() << " sec\n";
00760 
00761   //
00762   // D.3) Convert any Epetra objects to Thyra OutArgs objects that still need to
00763   // be converted
00764   //
00765 
00766   if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW))
00767     *out << "\nFinish processing and wrapping the output objects ...\n";
00768   timer.start(true);
00769 
00770   finishConvertingOutArgsFromEpetraToThyra(
00771     epetraOutArgs, W_op, efwdW, eW,
00772     outArgs
00773     );
00774 
00775   timer.stop();
00776   if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW))
00777     OSTab(out).o()
00778       << "\nTime to finish processing and wrapping the output objects = "
00779       << timer.totalElapsedTime() <<" sec\n";
00780 
00781   //
00782   // E) Print footer to end the function
00783   //
00784 
00785   THYRA_MODEL_EVALUATOR_DECORATOR_EVAL_MODEL_END();
00786 
00787 }
00788 
00789 
00790 // private
00791 
00792 
00793 void EpetraModelEvaluator::convertInArgsFromEpetraToThyra(
00794   const EpetraExt::ModelEvaluator::InArgs &epetraInArgs,
00795   ModelEvaluatorBase::InArgs<double> *inArgs
00796   ) const
00797 {
00798 
00799   using Teuchos::implicit_cast;
00800   typedef ModelEvaluatorBase MEB;
00801 
00802   TEUCHOS_TEST_FOR_EXCEPT(!inArgs);
00803 
00804   if(inArgs->supports(MEB::IN_ARG_x)) {
00805     inArgs->set_x( create_Vector( epetraInArgs.get_x(), x_space_ ) );
00806   }
00807 
00808   if(inArgs->supports(MEB::IN_ARG_x_dot)) {
00809     inArgs->set_x_dot( create_Vector( epetraInArgs.get_x_dot(), x_space_ ) );
00810   }
00811 
00812   const int l_Np = inArgs->Np();
00813   for( int l = 0; l < l_Np; ++l ) {
00814     inArgs->set_p( l, create_Vector( epetraInArgs.get_p(l), p_space_[l] ) );
00815   }
00816 
00817   if(inArgs->supports(MEB::IN_ARG_t)) {
00818     inArgs->set_t(epetraInArgs.get_t());
00819   }
00820 
00821 }
00822 
00823 
00824 void EpetraModelEvaluator::convertInArgsFromThyraToEpetra(
00825   const ModelEvaluatorBase::InArgs<double> &inArgs,
00826   EpetraExt::ModelEvaluator::InArgs *epetraInArgs
00827   ) const
00828 {
00829 
00830   using Teuchos::rcp;
00831   using Teuchos::rcp_const_cast;
00832 #ifdef HAVE_THYRA_ME_POLYNOMIAL
00833   using Teuchos::Polynomial;
00834 #endif // HAVE_THYRA_ME_POLYNOMIAL
00835 
00836 
00837   TEUCHOS_TEST_FOR_EXCEPT(0==epetraInArgs);
00838 
00839   RCP<const VectorBase<double> > x_dot;
00840   if( inArgs.supports(IN_ARG_x_dot) && (x_dot = inArgs.get_x_dot()).get() ) {
00841     RCP<const Epetra_Vector> e_x_dot = get_Epetra_Vector(*x_map_,x_dot);
00842     epetraInArgs->set_x_dot(e_x_dot);
00843   }
00844 
00845   RCP<const VectorBase<double> > x;
00846   if( inArgs.supports(IN_ARG_x) && (x = inArgs.get_x()).get() ) {
00847     RCP<const Epetra_Vector> e_x = get_Epetra_Vector(*x_map_,x);
00848     epetraInArgs->set_x(e_x);
00849   }
00850 
00851   RCP<const VectorBase<double> > p_l;
00852   for(int l = 0;  l < inArgs.Np(); ++l ) {
00853     p_l = inArgs.get_p(l);
00854     if(p_l.get()) epetraInArgs->set_p(l,get_Epetra_Vector(*p_map_[l],p_l));
00855   }
00856 
00857 #ifdef HAVE_THYRA_ME_POLYNOMIAL
00858 
00859   RCP<const Polynomial< VectorBase<double> > > x_dot_poly;
00860   RCP<Epetra_Vector> epetra_ptr;
00861   if(
00862     inArgs.supports(IN_ARG_x_dot_poly)
00863     && (x_dot_poly = inArgs.get_x_dot_poly()).get()
00864     )
00865   {
00866     RCP<Polynomial<Epetra_Vector> > epetra_x_dot_poly =
00867       rcp(new Polynomial<Epetra_Vector>(x_dot_poly->degree()));
00868     for (unsigned int i=0; i<=x_dot_poly->degree(); i++) {
00869       epetra_ptr = rcp_const_cast<Epetra_Vector>(
00870         get_Epetra_Vector(*x_map_, x_dot_poly->getCoefficient(i)) );
00871       epetra_x_dot_poly->setCoefficientPtr(i,epetra_ptr);
00872     }
00873     epetraInArgs->set_x_dot_poly(epetra_x_dot_poly);
00874   }
00875 
00876   RCP<const Polynomial< VectorBase<double> > > x_poly;
00877   if(
00878     inArgs.supports(IN_ARG_x_poly)
00879     && (x_poly = inArgs.get_x_poly()).get()
00880     )
00881   {
00882     RCP<Polynomial<Epetra_Vector> > epetra_x_poly =
00883       rcp(new Polynomial<Epetra_Vector>(x_poly->degree()));
00884     for (unsigned int i=0; i<=x_poly->degree(); i++) {
00885       epetra_ptr = rcp_const_cast<Epetra_Vector>(
00886         get_Epetra_Vector(*x_map_, x_poly->getCoefficient(i)) );
00887       epetra_x_poly->setCoefficientPtr(i,epetra_ptr);
00888     }
00889     epetraInArgs->set_x_poly(epetra_x_poly);
00890   }
00891 
00892 #endif // HAVE_THYRA_ME_POLYNOMIAL
00893 
00894   if( inArgs.supports(IN_ARG_t) )
00895     epetraInArgs->set_t(inArgs.get_t());
00896 
00897   if( inArgs.supports(IN_ARG_alpha) )
00898     epetraInArgs->set_alpha(inArgs.get_alpha());
00899 
00900   if( inArgs.supports(IN_ARG_beta) )
00901     epetraInArgs->set_beta(inArgs.get_beta());
00902 
00903 }
00904 
00905 
00906 void EpetraModelEvaluator::convertOutArgsFromThyraToEpetra(
00907   const ModelEvaluatorBase::OutArgs<double> &outArgs,
00908   EpetraExt::ModelEvaluator::OutArgs *epetraUnscaledOutArgs_inout,
00909   RCP<LinearOpBase<double> > *W_op_out,
00910   RCP<EpetraLinearOp> *efwdW_out,
00911   RCP<Epetra_Operator> *eW_out
00912   ) const
00913 {
00914 
00915   using Teuchos::rcp;
00916   using Teuchos::rcp_const_cast;
00917   using Teuchos::rcp_dynamic_cast;
00918   using Teuchos::OSTab;
00919   using Teuchos::implicit_cast;
00920   using Thyra::get_Epetra_Vector;
00921   //typedef EpetraExt::ModelEvaluator EME; // unused
00922 
00923   // Assert input
00924 #ifdef TEUCHOS_DEBUG
00925   TEUCHOS_ASSERT(epetraUnscaledOutArgs_inout);
00926   TEUCHOS_ASSERT(W_op_out);
00927   TEUCHOS_ASSERT(efwdW_out);
00928   TEUCHOS_ASSERT(eW_out);
00929 #endif
00930 
00931   // Create easy to use references
00932   EpetraExt::ModelEvaluator::OutArgs &epetraUnscaledOutArgs = *epetraUnscaledOutArgs_inout;
00933   RCP<LinearOpBase<double> > &W_op = *W_op_out;
00934   RCP<EpetraLinearOp> &efwdW = *efwdW_out;
00935   RCP<Epetra_Operator> &eW = *eW_out;
00936 
00937   // f
00938   {
00939     RCP<VectorBase<double> > f;
00940     if( outArgs.supports(OUT_ARG_f) && (f = outArgs.get_f()).get() )
00941       epetraUnscaledOutArgs.set_f(get_Epetra_Vector(*f_map_,f));
00942   }
00943 
00944   // g
00945   {
00946     RCP<VectorBase<double> > g_j;
00947     for(int j = 0;  j < outArgs.Ng(); ++j ) {
00948       g_j = outArgs.get_g(j);
00949       if(g_j.get()) epetraUnscaledOutArgs.set_g(j,get_Epetra_Vector(*g_map_[j],g_j));
00950     }
00951   }
00952 
00953   // W_op
00954   {
00955 
00956     if (outArgs.supports(OUT_ARG_W_op) && nonnull(W_op = outArgs.get_W_op())) {
00957       if (nonnull(W_op) && is_null(efwdW)) {
00958         efwdW = rcp_const_cast<EpetraLinearOp>(
00959           rcp_dynamic_cast<const EpetraLinearOp>(W_op, true));
00960       }
00961     }
00962 
00963     if (nonnull(efwdW)) {
00964       // By the time we get here, if we have an object in efwdW, then it
00965       // should already be embeadded with an underlying Epetra_Operator object
00966       // that was allocated by the EpetraExt::ModelEvaluator object.
00967       // Therefore, we should just have to grab this object and be on our way.
00968       eW = efwdW->epetra_op();
00969       epetraUnscaledOutArgs.set_W(eW);
00970     }
00971 
00972     // Note: The following derivative objects update in place!
00973 
00974   }
00975 
00976   // DfDp
00977   {
00978     Derivative<double> DfDp_l;
00979     for(int l = 0;  l < outArgs.Np(); ++l ) {
00980       if( !outArgs.supports(OUT_ARG_DfDp,l).none()
00981         && !(DfDp_l = outArgs.get_DfDp(l)).isEmpty() )
00982       {
00983         epetraUnscaledOutArgs.set_DfDp(l,convert(DfDp_l,f_map_,p_map_[l]));
00984       }
00985     }
00986   }
00987 
00988   // DgDx_dot
00989   {
00990     Derivative<double> DgDx_dot_j;
00991     for(int j = 0;  j < outArgs.Ng(); ++j ) {
00992       if( !outArgs.supports(OUT_ARG_DgDx_dot,j).none()
00993         && !(DgDx_dot_j = outArgs.get_DgDx_dot(j)).isEmpty() )
00994       {
00995         epetraUnscaledOutArgs.set_DgDx_dot(j,convert(DgDx_dot_j,g_map_[j],x_map_));
00996       }
00997     }
00998   }
00999 
01000   // DgDx
01001   {
01002     Derivative<double> DgDx_j;
01003     for(int j = 0;  j < outArgs.Ng(); ++j ) {
01004       if( !outArgs.supports(OUT_ARG_DgDx,j).none()
01005         && !(DgDx_j = outArgs.get_DgDx(j)).isEmpty() )
01006       {
01007         epetraUnscaledOutArgs.set_DgDx(j,convert(DgDx_j,g_map_[j],x_map_));
01008       }
01009     }
01010   }
01011 
01012   // DgDp
01013   {
01014     DerivativeSupport DgDp_j_l_support;
01015     Derivative<double> DgDp_j_l;
01016     for (int j = 0;  j < outArgs.Ng(); ++j ) {
01017       for (int l = 0;  l < outArgs.Np(); ++l ) {
01018         if (!(DgDp_j_l_support = outArgs.supports(OUT_ARG_DgDp,j,l)).none()
01019           && !(DgDp_j_l = outArgs.get_DgDp(j,l)).isEmpty() )
01020         {
01021           epetraUnscaledOutArgs.set_DgDp(j,l,convert(DgDp_j_l,g_map_[j],p_map_[l]));
01022         }
01023       }
01024     }
01025   }
01026 
01027 #ifdef HAVE_THYRA_ME_POLYNOMIAL
01028 
01029   // f_poly
01030   RCP<const Teuchos::Polynomial< VectorBase<double> > > f_poly;
01031   if( outArgs.supports(OUT_ARG_f_poly) && (f_poly = outArgs.get_f_poly()).get() )
01032   {
01033     RCP<Teuchos::Polynomial<Epetra_Vector> > epetra_f_poly =
01034       Teuchos::rcp(new Teuchos::Polynomial<Epetra_Vector>(f_poly->degree()));
01035     for (unsigned int i=0; i<=f_poly->degree(); i++) {
01036       RCP<Epetra_Vector> epetra_ptr
01037         = Teuchos::rcp_const_cast<Epetra_Vector>(get_Epetra_Vector(*f_map_,
01038             f_poly->getCoefficient(i)));
01039       epetra_f_poly->setCoefficientPtr(i,epetra_ptr);
01040     }
01041     epetraUnscaledOutArgs.set_f_poly(epetra_f_poly);
01042   }
01043 
01044 #endif // HAVE_THYRA_ME_POLYNOMIAL
01045 
01046 }
01047 
01048 
01049 void EpetraModelEvaluator::preEvalScalingSetup(
01050   EpetraExt::ModelEvaluator::InArgs *epetraInArgs_inout,
01051   EpetraExt::ModelEvaluator::OutArgs *epetraUnscaledOutArgs_inout,
01052   const RCP<Teuchos::FancyOStream> &out,
01053   const Teuchos::EVerbosityLevel verbLevel
01054   ) const
01055 {
01056 
01057   typedef EpetraExt::ModelEvaluator EME;
01058 
01059 #ifdef TEUCHOS_DEBUG
01060   TEUCHOS_ASSERT(epetraInArgs_inout);
01061   TEUCHOS_ASSERT(epetraUnscaledOutArgs_inout);
01062 #endif
01063 
01064   EpetraExt::ModelEvaluator::InArgs
01065     &epetraInArgs = *epetraInArgs_inout;
01066   EpetraExt::ModelEvaluator::OutArgs
01067     &epetraUnscaledOutArgs = *epetraUnscaledOutArgs_inout;
01068 
01069   if (
01070     ( stateFunctionScaling_ == STATE_FUNC_SCALING_ROW_SUM )
01071     &&
01072     (
01073       epetraUnscaledOutArgs.supports(EME::OUT_ARG_f)
01074       &&
01075       epetraUnscaledOutArgs.funcOrDerivesAreSet(EME::OUT_ARG_f)
01076       )
01077     &&
01078     (
01079       epetraUnscaledOutArgs.supports(EME::OUT_ARG_W)
01080       &&
01081       is_null(epetraUnscaledOutArgs.get_W())
01082       )
01083     )
01084   {
01085     // This is the first pass through with scaling turned on and the client
01086     // turned on automatic scaling but did not ask for W.  We must compute W
01087     // in order to compute the scale factors so we must allocate a temporary W
01088     // just to compute the scale factors and then throw it away.  If the
01089     // client wants to evaluate W at the same point, then it should have
01090     // passed W in but that is not our problem here.  The ModelEvaluator
01091     // relies on the client to set up the calls to allow for efficient
01092     // evaluation.
01093 
01094     if(out.get() && verbLevel >= Teuchos::VERB_LOW)
01095       *out
01096         << "\nCreating a temporary Epetra W to compute scale factors"
01097         << " for f(...) ...\n";
01098     epetraUnscaledOutArgs.set_W(create_and_assert_W(*epetraModel_));
01099     if( epetraInArgs.supports(EME::IN_ARG_beta) )
01100       epetraInArgs.set_beta(1.0);
01101     if( epetraInArgs.supports(EME::IN_ARG_alpha) )
01102       epetraInArgs.set_alpha(0.0);
01103   }
01104 
01105 }
01106 
01107 
01108 void EpetraModelEvaluator::postEvalScalingSetup(
01109   const EpetraExt::ModelEvaluator::OutArgs &epetraUnscaledOutArgs,
01110   const RCP<Teuchos::FancyOStream> &out,
01111   const Teuchos::EVerbosityLevel verbLevel
01112   ) const
01113 {
01114 
01115   using Teuchos::OSTab;
01116   using Teuchos::rcp;
01117   using Teuchos::rcp_const_cast;
01118   using Teuchos::includesVerbLevel;
01119 
01120   // Compute the scale factors for the state function f(...)
01121   switch(stateFunctionScaling_) {
01122 
01123     case STATE_FUNC_SCALING_ROW_SUM: {
01124 
01125       // Compute the inverse row-sum scaling from W
01126 
01127       const RCP<Epetra_RowMatrix>
01128         ermW = get_Epetra_RowMatrix(epetraUnscaledOutArgs);
01129       // Note: Above, we get the Epetra W object directly from the Epetra
01130       // OutArgs object since this might be a temporary matrix just to
01131       // compute scaling factors.  In this case, the stack funtion variable
01132       // eW might be empty!
01133 
01134       RCP<Epetra_Vector>
01135         invRowSums = rcp(new Epetra_Vector(ermW->OperatorRangeMap()));
01136       // Above: From the documentation is seems that the RangeMap should be
01137       // okay but who knows for sure!
01138 
01139       ermW->InvRowSums(*invRowSums);
01140 
01141       if (out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW)) {
01142         *out
01143           << "\nComputed inverse row sum scaling from W that"
01144           " will be used to scale f(...) and its derivatives:\n";
01145         double minVal = 0, maxVal = 0, avgVal = 0;
01146         invRowSums->MinValue(&minVal);
01147         invRowSums->MaxValue(&maxVal);
01148         invRowSums->MeanValue(&avgVal);
01149         OSTab tab(out);
01150         *out
01151           << "min(invRowSums) = " << minVal << "\n"
01152           << "max(invRowSums) = " << maxVal << "\n"
01153           << "avg(invRowSums) = " << avgVal << "\n";
01154       }
01155 
01156       stateFunctionScalingVec_ = invRowSums;
01157 
01158       break;
01159 
01160     }
01161 
01162     default:
01163       TEUCHOS_TEST_FOR_EXCEPT("Should never get here!");
01164 
01165   }
01166 
01167   epetraOutArgsScaling_ = epetraModel_->createOutArgs();
01168 
01169   epetraOutArgsScaling_.set_f(
01170     rcp_const_cast<Epetra_Vector>(stateFunctionScalingVec_) );
01171 
01172 }
01173 
01174 
01175 void EpetraModelEvaluator::finishConvertingOutArgsFromEpetraToThyra(
01176   const EpetraExt::ModelEvaluator::OutArgs &epetraOutArgs,
01177   RCP<LinearOpBase<double> > &W_op,
01178   RCP<EpetraLinearOp> &efwdW,
01179   RCP<Epetra_Operator> &eW,
01180   const ModelEvaluatorBase::OutArgs<double> &outArgs
01181   ) const
01182 {
01183 
01184   using Teuchos::rcp_dynamic_cast;
01185   //typedef EpetraExt::ModelEvaluator EME; // unused
01186 
01187   if (nonnull(efwdW)) {
01188     efwdW->setFullyInitialized(true);
01189     // NOTE: Above will directly update W_op also if W.get()==NULL!
01190   }
01191 
01192   if (nonnull(W_op)) {
01193     if (W_op.shares_resource(efwdW)) {
01194       // W_op was already updated above since *efwdW is the same object as *W_op
01195     }
01196     else {
01197       rcp_dynamic_cast<EpetraLinearOp>(W_op, true)->setFullyInitialized(true);
01198     }
01199   }
01200 
01201 }
01202 
01203 
01204 void EpetraModelEvaluator::updateNominalValuesAndBounds() const
01205 {
01206 
01207   using Teuchos::rcp;
01208   using Teuchos::implicit_cast;
01209   //typedef ModelEvaluatorBase MEB; // unused
01210   typedef EpetraExt::ModelEvaluator EME;
01211 
01212   if( !nominalValuesAndBoundsAreUpdated_ ) {
01213 
01214     // Gather the nominal values and bounds into Epetra InArgs objects
01215 
01216     EME::InArgs epetraOrigNominalValues;
01217     EpetraExt::gatherModelNominalValues(
01218       *epetraModel_, &epetraOrigNominalValues );
01219 
01220     EME::InArgs epetraOrigLowerBounds;
01221     EME::InArgs epetraOrigUpperBounds;
01222     EpetraExt::gatherModelBounds(
01223       *epetraModel_, &epetraOrigLowerBounds, &epetraOrigUpperBounds );
01224 
01225     // Set up Epetra InArgs scaling object
01226 
01227     epetraInArgsScaling_ = epetraModel_->createInArgs();
01228 
01229     if( !is_null(stateVariableScalingVec_) ) {
01230       invStateVariableScalingVec_
01231         = EpetraExt::createInverseModelScalingVector(stateVariableScalingVec_);
01232       if( epetraOrigNominalValues.supports(EME::IN_ARG_x_dot) ) {
01233         epetraInArgsScaling_.set_x_dot(invStateVariableScalingVec_);
01234       }
01235       if( epetraOrigNominalValues.supports(EME::IN_ARG_x) ) {
01236         epetraInArgsScaling_.set_x(invStateVariableScalingVec_);
01237       }
01238     }
01239 
01240     // Scale the original variables and bounds
01241 
01242     EME::InArgs epetraScaledNominalValues = epetraModel_->createInArgs();
01243     EpetraExt::scaleModelVars(
01244       epetraOrigNominalValues, epetraInArgsScaling_, &epetraScaledNominalValues
01245       );
01246 
01247     EME::InArgs epetraScaledLowerBounds = epetraModel_->createInArgs();
01248     EME::InArgs epetraScaledUpperBounds = epetraModel_->createInArgs();
01249     EpetraExt::scaleModelBounds(
01250       epetraOrigLowerBounds, epetraOrigUpperBounds, epetraModel_->getInfBound(),
01251       epetraInArgsScaling_,
01252       &epetraScaledLowerBounds, &epetraScaledUpperBounds
01253       );
01254 
01255     // Wrap the scaled epetra InArgs objects as Thyra InArgs objects!
01256 
01257     nominalValues_ = this->createInArgs();
01258     lowerBounds_ = this->createInArgs();
01259     upperBounds_ = this->createInArgs();
01260     convertInArgsFromEpetraToThyra(epetraScaledNominalValues, &nominalValues_);
01261     convertInArgsFromEpetraToThyra(epetraScaledLowerBounds, &lowerBounds_);
01262     convertInArgsFromEpetraToThyra(epetraScaledUpperBounds, &upperBounds_);
01263 
01264     nominalValuesAndBoundsAreUpdated_ = true;
01265 
01266   }
01267   else {
01268 
01269     // The nominal values and bounds should already be updated an should have
01270     // the currect scaling!
01271 
01272   }
01273 
01274 }
01275 
01276 
01277 void EpetraModelEvaluator::updateInArgsOutArgs() const
01278 {
01279 
01280   typedef EpetraExt::ModelEvaluator EME;
01281 
01282   const EpetraExt::ModelEvaluator &epetraModel = *epetraModel_;
01283   EME::InArgs  epetraInArgs  = epetraModel.createInArgs();
01284   EME::OutArgs epetraOutArgs = epetraModel.createOutArgs();
01285   const int l_Np = epetraOutArgs.Np();
01286   const int l_Ng = epetraOutArgs.Ng();
01287 
01288   //
01289   // InArgs
01290   //
01291 
01292   InArgsSetup<double> inArgs;
01293   inArgs.setModelEvalDescription(this->description());
01294   inArgs.set_Np(epetraInArgs.Np());
01295   inArgs.setSupports(IN_ARG_x_dot, epetraInArgs.supports(EME::IN_ARG_x_dot));
01296   inArgs.setSupports(IN_ARG_x, epetraInArgs.supports(EME::IN_ARG_x));
01297 #ifdef HAVE_THYRA_ME_POLYNOMIAL
01298   inArgs.setSupports(IN_ARG_x_dot_poly,
01299     epetraInArgs.supports(EME::IN_ARG_x_dot_poly));
01300   inArgs.setSupports(IN_ARG_x_poly, epetraInArgs.supports(EME::IN_ARG_x_poly));
01301 #endif // HAVE_THYRA_ME_POLYNOMIAL
01302   inArgs.setSupports(IN_ARG_t, epetraInArgs.supports(EME::IN_ARG_t));
01303   inArgs.setSupports(IN_ARG_alpha, epetraInArgs.supports(EME::IN_ARG_alpha));
01304   inArgs.setSupports(IN_ARG_beta, epetraInArgs.supports(EME::IN_ARG_beta));
01305   prototypeInArgs_ = inArgs;
01306 
01307   //
01308   // OutArgs
01309   //
01310 
01311   OutArgsSetup<double> outArgs;
01312   outArgs.setModelEvalDescription(this->description());
01313   outArgs.set_Np_Ng(l_Np, l_Ng);
01314   // f
01315   outArgs.setSupports(OUT_ARG_f, epetraOutArgs.supports(EME::OUT_ARG_f));
01316   if (outArgs.supports(OUT_ARG_f)) {
01317     // W_op
01318     outArgs.setSupports(OUT_ARG_W_op,  epetraOutArgs.supports(EME::OUT_ARG_W));
01319     outArgs.set_W_properties(convert(epetraOutArgs.get_W_properties()));
01320     // DfDp
01321     for(int l=0; l<l_Np; ++l) {
01322       outArgs.setSupports(OUT_ARG_DfDp, l,
01323         convert(epetraOutArgs.supports(EME::OUT_ARG_DfDp, l)));
01324       if(!outArgs.supports(OUT_ARG_DfDp, l).none())
01325         outArgs.set_DfDp_properties(l,
01326           convert(epetraOutArgs.get_DfDp_properties(l)));
01327     }
01328   }
01329   // DgDx_dot and DgDx
01330   for(int j=0; j<l_Ng; ++j) {
01331     if (inArgs.supports(IN_ARG_x_dot))
01332       outArgs.setSupports(OUT_ARG_DgDx_dot, j,
01333         convert(epetraOutArgs.supports(EME::OUT_ARG_DgDx_dot, j)));
01334     if(!outArgs.supports(OUT_ARG_DgDx_dot, j).none())
01335       outArgs.set_DgDx_dot_properties(j,
01336         convert(epetraOutArgs.get_DgDx_dot_properties(j)));
01337     if (inArgs.supports(IN_ARG_x))
01338       outArgs.setSupports(OUT_ARG_DgDx, j,
01339         convert(epetraOutArgs.supports(EME::OUT_ARG_DgDx, j)));
01340     if(!outArgs.supports(OUT_ARG_DgDx, j).none())
01341       outArgs.set_DgDx_properties(j,
01342         convert(epetraOutArgs.get_DgDx_properties(j)));
01343   }
01344   // DgDp
01345   for(int j=0; j < l_Ng; ++j) for(int l=0; l < l_Np; ++l) {
01346     const EME::DerivativeSupport epetra_DgDp_j_l_support =
01347       epetraOutArgs.supports(EME::OUT_ARG_DgDp, j, l);
01348     outArgs.setSupports(OUT_ARG_DgDp, j, l,
01349       convert(epetra_DgDp_j_l_support));
01350     if(!outArgs.supports(OUT_ARG_DgDp, j, l).none())
01351       outArgs.set_DgDp_properties(j, l,
01352         convert(epetraOutArgs.get_DgDp_properties(j, l)));
01353   }
01354 #ifdef HAVE_THYRA_ME_POLYNOMIAL
01355   outArgs.setSupports(OUT_ARG_f_poly,
01356     epetraOutArgs.supports(EME::OUT_ARG_f_poly));
01357 #endif // HAVE_THYRA_ME_POLYNOMIAL
01358   prototypeOutArgs_ = outArgs;
01359 
01360   // We are current!
01361   currentInArgsOutArgs_ = true;
01362 
01363 }
01364 
01365 
01366 RCP<EpetraLinearOp>
01367 EpetraModelEvaluator::create_epetra_W_op() const
01368 {
01369   return Thyra::partialNonconstEpetraLinearOp(
01370     this->get_f_space(), this->get_x_space(),
01371     create_and_assert_W(*epetraModel_)
01372     );
01373 }
01374 
01375 
01376 } // namespace Thyra
01377 
01378 
01379 //
01380 // Non-member utility functions
01381 //
01382 
01383 
01384 Teuchos::RCP<Thyra::EpetraModelEvaluator>
01385 Thyra::epetraModelEvaluator(
01386   const RCP<const EpetraExt::ModelEvaluator> &epetraModel,
01387   const RCP<LinearOpWithSolveFactoryBase<double> > &W_factory
01388   )
01389 {
01390   return Teuchos::rcp(new EpetraModelEvaluator(epetraModel,W_factory));
01391 }
01392 
01393 
01394 Thyra::ModelEvaluatorBase::EDerivativeMultiVectorOrientation
01395 Thyra::convert(
01396   const EpetraExt::ModelEvaluator::EDerivativeMultiVectorOrientation &mvOrientation
01397   )
01398 {
01399   switch(mvOrientation) {
01400     case EpetraExt::ModelEvaluator::DERIV_MV_BY_COL :
01401       return ModelEvaluatorBase::DERIV_MV_BY_COL;
01402     case EpetraExt::ModelEvaluator::DERIV_TRANS_MV_BY_ROW :
01403       return ModelEvaluatorBase::DERIV_TRANS_MV_BY_ROW;
01404     default:
01405       TEUCHOS_TEST_FOR_EXCEPT(true);
01406   }
01407   return ModelEvaluatorBase::DERIV_MV_BY_COL; // Should never be called!
01408 }
01409 
01410 
01411 EpetraExt::ModelEvaluator::EDerivativeMultiVectorOrientation
01412 Thyra::convert(
01413   const ModelEvaluatorBase::EDerivativeMultiVectorOrientation &mvOrientation
01414   )
01415 {
01416   switch(mvOrientation) {
01417     case ModelEvaluatorBase::DERIV_MV_BY_COL :
01418       return EpetraExt::ModelEvaluator::DERIV_MV_BY_COL;
01419     case ModelEvaluatorBase::DERIV_TRANS_MV_BY_ROW :
01420       return EpetraExt::ModelEvaluator::DERIV_TRANS_MV_BY_ROW;
01421     default:
01422       TEUCHOS_TEST_FOR_EXCEPT(true);
01423   }
01424   return EpetraExt::ModelEvaluator::DERIV_MV_BY_COL; // Should never be called!
01425 }
01426 
01427 
01428 Thyra::ModelEvaluatorBase::DerivativeProperties
01429 Thyra::convert(
01430   const EpetraExt::ModelEvaluator::DerivativeProperties &derivativeProperties
01431   )
01432 {
01433   ModelEvaluatorBase::EDerivativeLinearity linearity;
01434   switch(derivativeProperties.linearity) {
01435     case EpetraExt::ModelEvaluator::DERIV_LINEARITY_UNKNOWN:
01436       linearity = ModelEvaluatorBase::DERIV_LINEARITY_UNKNOWN;
01437       break;
01438     case EpetraExt::ModelEvaluator::DERIV_LINEARITY_CONST:
01439       linearity = ModelEvaluatorBase::DERIV_LINEARITY_CONST;
01440       break;
01441     case  EpetraExt::ModelEvaluator::DERIV_LINEARITY_NONCONST:
01442       linearity = ModelEvaluatorBase::DERIV_LINEARITY_NONCONST;
01443       break;
01444     default:
01445       TEUCHOS_TEST_FOR_EXCEPT(true);
01446   }
01447   ModelEvaluatorBase::ERankStatus rank;
01448   switch(derivativeProperties.rank) {
01449     case EpetraExt::ModelEvaluator::DERIV_RANK_UNKNOWN:
01450       rank = ModelEvaluatorBase::DERIV_RANK_UNKNOWN;
01451       break;
01452     case EpetraExt::ModelEvaluator::DERIV_RANK_FULL:
01453       rank = ModelEvaluatorBase::DERIV_RANK_FULL;
01454       break;
01455     case EpetraExt::ModelEvaluator::DERIV_RANK_DEFICIENT:
01456       rank = ModelEvaluatorBase::DERIV_RANK_DEFICIENT;
01457       break;
01458     default:
01459       TEUCHOS_TEST_FOR_EXCEPT(true);
01460   }
01461   return ModelEvaluatorBase::DerivativeProperties(
01462     linearity,rank,derivativeProperties.supportsAdjoint);
01463 }
01464 
01465 
01466 Thyra::ModelEvaluatorBase::DerivativeSupport
01467 Thyra::convert(
01468   const EpetraExt::ModelEvaluator::DerivativeSupport &derivativeSupport
01469   )
01470 {
01471   ModelEvaluatorBase::DerivativeSupport ds;
01472   if(derivativeSupport.supports(EpetraExt::ModelEvaluator::DERIV_LINEAR_OP))
01473     ds.plus(ModelEvaluatorBase::DERIV_LINEAR_OP);
01474   if(derivativeSupport.supports(EpetraExt::ModelEvaluator::DERIV_MV_BY_COL))
01475     ds.plus(ModelEvaluatorBase::DERIV_MV_BY_COL);
01476   if(derivativeSupport.supports(EpetraExt::ModelEvaluator::DERIV_TRANS_MV_BY_ROW))
01477     ds.plus(ModelEvaluatorBase::DERIV_TRANS_MV_BY_ROW);
01478   return ds;
01479 }
01480 
01481 
01482 EpetraExt::ModelEvaluator::Derivative
01483 Thyra::convert(
01484   const ModelEvaluatorBase::Derivative<double> &derivative,
01485   const RCP<const Epetra_Map> &fnc_map,
01486   const RCP<const Epetra_Map> &var_map
01487   )
01488 {
01489   typedef ModelEvaluatorBase MEB;
01490   if(derivative.getLinearOp().get()) {
01491     return EpetraExt::ModelEvaluator::Derivative(
01492       Teuchos::rcp_const_cast<Epetra_Operator>(
01493         Teuchos::dyn_cast<const EpetraLinearOp>(*derivative.getLinearOp()).epetra_op()
01494         )
01495       );
01496   }
01497   else if(derivative.getDerivativeMultiVector().getMultiVector().get()) {
01498     return EpetraExt::ModelEvaluator::Derivative(
01499       EpetraExt::ModelEvaluator::DerivativeMultiVector(
01500         get_Epetra_MultiVector(
01501           ( derivative.getDerivativeMultiVector().getOrientation() == MEB::DERIV_MV_BY_COL
01502             ? *fnc_map
01503             : *var_map
01504             )
01505           ,derivative.getDerivativeMultiVector().getMultiVector()
01506           )
01507         ,convert(derivative.getDerivativeMultiVector().getOrientation())
01508         )
01509       );
01510   }
01511   return EpetraExt::ModelEvaluator::Derivative();
01512 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines