Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_ExplicitModelEvaluator_impl.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Panzer: A partial differential equation assembly
5 // engine for strongly coupled complex multiphysics systems
6 // Copyright (2011) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Roger P. Pawlowski (rppawlo@sandia.gov) and
39 // Eric C. Cyr (eccyr@sandia.gov)
40 // ***********************************************************************
41 // @HEADER
42 
43 #ifndef PANZER_EXPLICIT_MODEL_EVALUATOR_IMPL_HPP
44 #define PANZER_EXPLICIT_MODEL_EVALUATOR_IMPL_HPP
45 
46 #include "Thyra_EpetraModelEvaluator.hpp"
47 #include "Thyra_DefaultDiagonalLinearOp.hpp"
48 #include "Thyra_LinearOpWithSolveFactoryBase.hpp"
49 
50 #include "Thyra_get_Epetra_Operator.hpp"
51 #include "EpetraExt_RowMatrixOut.h"
52 
53 namespace panzer {
54 
55 template<typename Scalar>
58  bool constantMassMatrix,
59  bool useLumpedMass,
60  bool applyMassInverse)
61  : Thyra::ModelEvaluatorDelegatorBase<Scalar>(model)
62  , constantMassMatrix_(constantMassMatrix)
63  , massLumping_(useLumpedMass)
64 {
65  using Teuchos::RCP;
66  using Teuchos::rcp_dynamic_cast;
67 
68  this->applyMassInverse_ = applyMassInverse;
69 
70  // extract a panzer::ModelEvaluator if appropriate
71  panzerModel_ = rcp_dynamic_cast<panzer::ModelEvaluator<Scalar> >(model);
72 
73  // extract a panzer::ModelEvaluator_Epetra if appropriate
74  RCP<Thyra::EpetraModelEvaluator> epME = rcp_dynamic_cast<Thyra::EpetraModelEvaluator>(model);
75  if(epME!=Teuchos::null)
76  panzerEpetraModel_ = rcp_dynamic_cast<const panzer::ModelEvaluator_Epetra>(epME->getEpetraModel());
77 
78  // note at this point its possible that panzerModel_ = panzerEpetraModel_ = Teuchos::null
79 
81 }
82 
83 template<typename Scalar>
84 Thyra::ModelEvaluatorBase::InArgs<Scalar> ExplicitModelEvaluator<Scalar>::
86 {
87  typedef Thyra::ModelEvaluatorBase MEB;
88 
89  MEB::InArgs<Scalar> nomVals = createInArgs();
90  nomVals.setArgs(this->getUnderlyingModel()->getNominalValues(),true);
91 
92  return nomVals;
93 }
94 
95 template<typename Scalar>
96 Thyra::ModelEvaluatorBase::InArgs<Scalar> ExplicitModelEvaluator<Scalar>::
97 createInArgs() const
98 {
99  return prototypeInArgs_;
100 }
101 
102 template<typename Scalar>
103 Thyra::ModelEvaluatorBase::OutArgs<Scalar> ExplicitModelEvaluator<Scalar>::
105 {
106  return prototypeOutArgs_;
107 }
108 
109 template<typename Scalar>
112 {
113  return Teuchos::rcp_dynamic_cast<panzer::ModelEvaluator<Scalar> >(this->getNonconstUnderlyingModel());
114 }
115 
116 template<typename Scalar>
118 evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs,
119  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
120 {
121  typedef Thyra::ModelEvaluatorBase MEB;
122  using Teuchos::RCP;
123  RCP<const Thyra::ModelEvaluator<Scalar> > under_me = this->getUnderlyingModel();
124 
125  MEB::InArgs<Scalar> under_inArgs = under_me->createInArgs();
126  under_inArgs.setArgs(inArgs);
127 
128  // read in the supplied time derivative in case it is needed by the explicit model (e.g. for stabilization) and make sure alpha is set to zero
129  under_inArgs.set_x_dot(inArgs.get_x_dot());
130  under_inArgs.set_alpha(0.0);
131 
132  Teuchos::RCP<Thyra::VectorBase<Scalar> > f = outArgs.get_f();
133 
134  MEB::OutArgs<Scalar> under_outArgs = under_me->createOutArgs();
135  under_outArgs.setArgs(outArgs);
136  if(f!=Teuchos::null) {
137  // build a scrap vector that will contain the weak residual
138  if(scrap_f_==Teuchos::null)
139  scrap_f_ = Thyra::createMember(*under_me->get_f_space());
140 
141  Thyra::assign(scrap_f_.ptr(),0.0);
142  under_outArgs.set_f(scrap_f_);
143  }
144 
145  under_me->evalModel(under_inArgs,under_outArgs);
146 
147  // build the mass matrix
148  if(invMassMatrix_==Teuchos::null || constantMassMatrix_==false)
149  buildInverseMassMatrix(inArgs);
150 
151  if(f!=Teuchos::null)
152  Thyra::Vt_S(scrap_f_.ptr(),-1.0);
153 
154  // invert the mass matrix
155  if(f!=Teuchos::null && this->applyMassInverse_) {
156  Thyra::apply(*invMassMatrix_,Thyra::NOTRANS,*scrap_f_,f.ptr());
157  }
158  else if(f!=Teuchos::null){
159  Thyra::V_V(f.ptr(),*scrap_f_);
160  }
161 }
162 
163 template<typename Scalar>
165 buildInverseMassMatrix(const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs) const
166 {
167  typedef Thyra::ModelEvaluatorBase MEB;
168  using Teuchos::RCP;
169  using Thyra::createMember;
170 
171  RCP<const Thyra::ModelEvaluator<Scalar> > me = this->getUnderlyingModel();
172 
173  // first allocate space for the mass matrix
174  mass_ = me->create_W_op();
175 
176  // intialize a zero to get rid of the x-dot
177  if(zero_==Teuchos::null) {
178  zero_ = Thyra::createMember(*me->get_x_space());
179  Thyra::assign(zero_.ptr(),0.0);
180  }
181 
182  // request only the mass matrix from the physics
183  // Model evaluator builds: alpha*u_dot + beta*F(u) = 0
184  MEB::InArgs<Scalar> inArgs_new = me->createInArgs();
185  inArgs_new.setArgs(inArgs);
186  inArgs_new.set_x_dot(inArgs.get_x_dot());
187  inArgs_new.set_alpha(1.0);
188  inArgs_new.set_beta(0.0);
189 
190  // set the one time beta to ensure dirichlet conditions
191  // are correctly included in the mass matrix: do it for
192  // both epetra and Tpetra.
193  if(panzerModel_!=Teuchos::null)
194  panzerModel_->setOneTimeDirichletBeta(1.0);
195  else if(panzerEpetraModel_!=Teuchos::null)
196  panzerEpetraModel_->setOneTimeDirichletBeta(1.0);
197  else {
198  // assuming the underlying model is a delegator, walk through
199  // the decerator hierarchy until you find a panzer::ME or panzer::EpetraME.
200  // If you don't find one, then throw because you are in a load of trouble anyway!
201  setOneTimeDirichletBeta(1.0,*this->getUnderlyingModel());
202  }
203 
204  // set only the mass matrix
205  MEB::OutArgs<Scalar> outArgs = me->createOutArgs();
206  outArgs.set_W_op(mass_);
207 
208  // this will fill the mass matrix operator
209  me->evalModel(inArgs_new,outArgs);
210 
211  // Teuchos::RCP<const Epetra_CrsMatrix> crsMat = Teuchos::rcp_dynamic_cast<const Epetra_CrsMatrix>(Thyra::get_Epetra_Operator(*mass));
212  // EpetraExt::RowMatrixToMatrixMarketFile("expmat.mm",*crsMat);
213 
214  if(!massLumping_) {
215  invMassMatrix_ = Thyra::inverse<Scalar>(*me->get_W_factory(),mass_);
216  }
217  else {
218  // build lumped mass matrix (assumes all positive mass entries, does a simple sum)
219  Teuchos::RCP<Thyra::VectorBase<Scalar> > ones = Thyra::createMember(*mass_->domain());
220  Thyra::assign(ones.ptr(),1.0);
221 
222  RCP<Thyra::VectorBase<Scalar> > invLumpMass = Thyra::createMember(*mass_->range());
223  Thyra::apply(*mass_,Thyra::NOTRANS,*ones,invLumpMass.ptr());
224  Thyra::reciprocal(*invLumpMass,invLumpMass.ptr());
225 
226  invMassMatrix_ = Thyra::diagonal(invLumpMass);
227  }
228 }
229 
230 template<typename Scalar>
233 {
234  typedef Thyra::ModelEvaluatorBase MEB;
235 
236  MEB::InArgsSetup<Scalar> inArgs(this->getUnderlyingModel()->createInArgs());
237  inArgs.setModelEvalDescription(this->description());
238  inArgs.setSupports(MEB::IN_ARG_alpha,true);
239  inArgs.setSupports(MEB::IN_ARG_beta,true);
240  inArgs.setSupports(MEB::IN_ARG_x_dot,true);
241  prototypeInArgs_ = inArgs;
242 
243  MEB::OutArgsSetup<Scalar> outArgs(this->getUnderlyingModel()->createOutArgs());
244  outArgs.setModelEvalDescription(this->description());
245  outArgs.setSupports(MEB::OUT_ARG_W,false);
246  outArgs.setSupports(MEB::OUT_ARG_W_op,false);
247  prototypeOutArgs_ = outArgs;
248 }
249 
250 template<typename Scalar>
253 {
254  using Teuchos::Ptr;
255  using Teuchos::ptrFromRef;
256  using Teuchos::ptr_dynamic_cast;
257 
258  // try to extract base classes that support setOneTimeDirichletBeta
259  Ptr<const panzer::ModelEvaluator<Scalar> > panzerModel = ptr_dynamic_cast<const panzer::ModelEvaluator<Scalar> >(ptrFromRef(me));
260  if(panzerModel!=Teuchos::null) {
261  panzerModel->setOneTimeDirichletBeta(beta);
262  return;
263  }
264  else {
265  Ptr<const Thyra::EpetraModelEvaluator> epModel = ptr_dynamic_cast<const Thyra::EpetraModelEvaluator>(ptrFromRef(me));
266  if(epModel!=Teuchos::null) {
267  Ptr<const panzer::ModelEvaluator_Epetra> panzerEpetraModel
268  = ptr_dynamic_cast<const panzer::ModelEvaluator_Epetra>(epModel->getEpetraModel().ptr());
269 
270  if(panzerEpetraModel!=Teuchos::null) {
271  panzerEpetraModel->setOneTimeDirichletBeta(beta);
272  return;
273  }
274  }
275  }
276 
277  // if you get here then the ME is not a panzer::ME or panzer::EpetraME, check
278  // to see if its a delegator
279 
280  Ptr<const Thyra::ModelEvaluatorDelegatorBase<Scalar> > delegator
281  = ptr_dynamic_cast<const Thyra::ModelEvaluatorDelegatorBase<Scalar> >(ptrFromRef(me));
282  if(delegator!=Teuchos::null) {
283  setOneTimeDirichletBeta(beta,*delegator->getUnderlyingModel());
284  return;
285  }
286 
287  TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
288  "panzer::ExplicitModelEvaluator::setOneTimeDirichletBeta can't find a panzer::ME or a panzer::EpetraME. "
289  "The deepest model is also not a delegator. Thus the recursion failed and an exception was generated.");
290 }
291 
292 } // end namespace panzer
293 
294 #endif
Thyra::ModelEvaluatorBase::InArgs< Scalar > createInArgs() const
Build the in args, modifies the underlying models in args slightly.
void buildArgsPrototypes()
Build prototype in/out args.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void setOneTimeDirichletBeta(const Scalar &beta) const
Teuchos::RCP< panzer::ModelEvaluator< Scalar > > getPanzerUnderlyingModel()
Get the underlying panzer::ModelEvaluator.
void evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
Evaluation of model, applies the mass matrix to the RHS.
Thyra::ModelEvaluatorBase::InArgs< Scalar > getNominalValues() const
Build the nominal values, modifies the underlying models in args slightly.
Ptr< T > ptr() const
Teuchos::RCP< const panzer::ModelEvaluator_Epetra > panzerEpetraModel_
Access to the epetra panzer model evaluator pointer.
void setOneTimeDirichletBeta(double beta, const Thyra::ModelEvaluator< Scalar > &me) const
bool applyMassInverse_
Apply mass matrix inverse within the evaluator.
Teuchos::RCP< const panzer::ModelEvaluator< Scalar > > panzerModel_
Access to the panzer model evaluator pointer (thyra version)
Thyra::ModelEvaluatorBase::OutArgs< Scalar > createOutArgs() const
Build the out args, modifies the underlying models in args slightly.
void buildInverseMassMatrix(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs) const
void setOneTimeDirichletBeta(const double &beta) const