Panzer Version of the Day
Loading...
Searching...
No Matches
Panzer_ModelEvaluator_Epetra.cpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Panzer: A partial differential equation assembly
4// engine for strongly coupled complex multiphysics systems
5//
6// Copyright 2011 NTESS and the Panzer contributors.
7// SPDX-License-Identifier: BSD-3-Clause
8// *****************************************************************************
9// @HEADER
10
11#include "PanzerDiscFE_config.hpp"
18#include "Panzer_GlobalData.hpp"
22
23#include "Epetra_CrsMatrix.h"
24#include "Epetra_MpiComm.h"
25#include "Epetra_LocalMap.h"
26
27#include "Teuchos_ScalarTraits.hpp"
28#include "Teuchos_DefaultMpiComm.hpp"
29#include "Teuchos_TimeMonitor.hpp"
30
31#include "Thyra_EpetraOperatorWrapper.hpp"
32#include "Thyra_EpetraThyraWrappers.hpp"
33#include "Thyra_VectorStdOps.hpp"
34#include "Thyra_ProductVectorBase.hpp"
35#include "Thyra_SpmdVectorBase.hpp"
36#include "Thyra_DefaultProductVector.hpp"
37#include "Thyra_ProductVectorSpaceBase.hpp"
38
39#include <sstream>
40
41namespace {
42
44class EpetraLOF_EOpFactory : public Teuchos::AbstractFactory<Epetra_Operator> {
45 Teuchos::RCP<Epetra_CrsGraph> W_graph_;
46public:
47 EpetraLOF_EOpFactory(const panzer::BlockedEpetraLinearObjFactory<panzer::Traits,int> & lof)
48 : W_graph_(lof.getGraph(0,0)) {}
49
50 virtual Teuchos::RCP<Epetra_Operator> create() const
51 { return Teuchos::rcp(new Epetra_CrsMatrix(::Copy,*W_graph_)); }
52};
53
54}
55
56
58ModelEvaluator_Epetra(const Teuchos::RCP<panzer::FieldManagerBuilder>& fmb,
59 const Teuchos::RCP<panzer::ResponseLibrary<panzer::Traits> >& rLibrary,
60 const Teuchos::RCP<panzer::LinearObjFactory<panzer::Traits> > & lof,
61 const std::vector<Teuchos::RCP<Teuchos::Array<std::string> > >& p_names,
62 const std::vector<Teuchos::RCP<Teuchos::Array<double> > >& p_values,
63 const Teuchos::RCP<panzer::GlobalData>& global_data,
64 bool build_transient_support)
65 : t_init_(0.0)
66 , fmb_(fmb)
67 , responseLibrary_(rLibrary)
68 , p_names_(p_names)
69 , global_data_(global_data)
70 , build_transient_support_(build_transient_support)
71 , lof_(lof)
72 , oneTimeDirichletBeta_on_(false)
73 , oneTimeDirichletBeta_(0.0)
74{
75 using Teuchos::rcp;
76 using Teuchos::rcp_dynamic_cast;
77
79 ae_tm_.buildObjects(builder);
80
81 // Setup parameters
82 this->initializeParameterVector(p_names_,p_values,global_data->pl);
83
84 // try to determine the runtime linear object factory
85
86 Teuchos::RCP<panzer::BlockedEpetraLinearObjFactory<panzer::Traits,int> > ep_lof =
87 Teuchos::rcp_dynamic_cast<panzer::BlockedEpetraLinearObjFactory<panzer::Traits,int> >(lof);
88
89 // initialize maps, x_dot_init, x0, p_init, g_map, and linear operator factory
90 if(ep_lof!=Teuchos::null)
91 initializeEpetraObjs(*ep_lof);
92 else {
93 TEUCHOS_ASSERT(false); // bad news!
94 }
95}
96
98ModelEvaluator_Epetra(const Teuchos::RCP<panzer::FieldManagerBuilder>& fmb,
99 const Teuchos::RCP<panzer::ResponseLibrary<panzer::Traits> >& rLibrary,
101 const std::vector<Teuchos::RCP<Teuchos::Array<std::string> > >& p_names,
102 const std::vector<Teuchos::RCP<Teuchos::Array<double> > >& p_values,
103 const Teuchos::RCP<panzer::GlobalData>& global_data,
104 bool build_transient_support)
105 : t_init_(0.0)
106 , fmb_(fmb)
107 , responseLibrary_(rLibrary)
108 , p_names_(p_names)
109 , global_data_(global_data)
110 , build_transient_support_(build_transient_support)
111 , lof_(lof)
112 , oneTimeDirichletBeta_on_(false)
113 , oneTimeDirichletBeta_(0.0)
114{
115 using Teuchos::rcp;
116 using Teuchos::rcp_dynamic_cast;
117
119 ae_tm_.buildObjects(builder);
120
121 // Setup parameters
122 this->initializeParameterVector(p_names_,p_values,global_data->pl);
123
124 // initailize maps, x_dot_init, x0, p_init, g_map, and linear operator factory
126}
127
129{
130 using Teuchos::RCP;
131 using Teuchos::rcp;
132 using Teuchos::rcp_dynamic_cast;
133
134 TEUCHOS_TEST_FOR_EXCEPTION(responseLibrary_==Teuchos::null,std::logic_error,
135 "panzer::ModelEvaluator_Epetra::initializeEpetraObjs: The response library "
136 "was not correctly initialized before calling initializeEpetraObjs.");
137
138 map_x_ = lof.getMap(0);
139 x0_ = rcp(new Epetra_Vector(*map_x_));
140 x_dot_init_ = rcp(new Epetra_Vector(*map_x_));
141 x_dot_init_->PutScalar(0.0);
142
143 // setup parameters (initialize vector from parameter library)
144 for (int i=0; i < parameter_vector_.size(); i++) {
145 RCP<Epetra_Map> local_map = rcp(new Epetra_LocalMap(static_cast<int>(parameter_vector_[i].size()), 0, map_x_->Comm())) ;
146 p_map_.push_back(local_map);
147
148 RCP<Epetra_Vector> ep_vec = rcp(new Epetra_Vector(*local_map));
149 ep_vec->PutScalar(0.0);
150
151 for (unsigned int j=0; j < parameter_vector_[i].size(); j++)
152 (*ep_vec)[j] = parameter_vector_[i][j].baseValue;
153
154 p_init_.push_back(ep_vec);
155 }
156
157 // Initialize the epetra operator factory
158 epetraOperatorFactory_ = Teuchos::rcp(new EpetraLOF_EOpFactory(lof));
159}
160
162initializeParameterVector(const std::vector<Teuchos::RCP<Teuchos::Array<std::string> > >& p_names,
163 const std::vector<Teuchos::RCP<Teuchos::Array<double> > >& p_values,
164 const Teuchos::RCP<panzer::ParamLib>& parameter_library)
165{
166 parameter_vector_.resize(p_names.size());
167 is_distributed_parameter_.resize(p_names.size(),false);
168 for (std::vector<Teuchos::RCP<Teuchos::Array<std::string> > >::size_type p = 0;
169 p < p_names.size(); ++p) {
170
171 // register all the scalar parameters, setting initial
172 for(int i=0;i<p_names[p]->size();i++)
173 registerScalarParameter((*p_names[p])[i],*parameter_library,(*p_values[p])[i]);
174
175 parameter_library->fillVector<panzer::Traits::Residual>(*(p_names[p]), parameter_vector_[p]);
176
177 for(int i=0;i<p_names[p]->size();i++) {
178 parameter_vector_[p][i].baseValue = (*p_values[p])[i];
179 parameter_vector_[p][i].family->setRealValueForAllTypes((*p_values[p])[i]);
180 }
181 }
182}
183
184// Post-Construction methods to add parameters and responses
185
187addDistributedParameter(const std::string name,
188 const Teuchos::RCP<Epetra_Map>& global_map,
189 const Teuchos::RCP<Epetra_Import>& importer,
190 const Teuchos::RCP<Epetra_Vector>& ghosted_vector)
191{
192 // Will push_back a new parameter entry
193 int index = static_cast<int>(p_map_.size());
194
195 p_map_.push_back(global_map);
196 Teuchos::RCP<Epetra_Vector> ep_vec = Teuchos::rcp(new Epetra_Vector(*global_map));
197 ep_vec->PutScalar(0.0);
198 p_init_.push_back(ep_vec);
199
200 Teuchos::RCP<Teuchos::Array<std::string> > tmp_names =
201 Teuchos::rcp(new Teuchos::Array<std::string>);
202 tmp_names->push_back(name);
203 p_names_.push_back(tmp_names);
204
205 is_distributed_parameter_.push_back(true);
206
207 // NOTE: we do not add this parameter to the sacado parameter
208 // library in the global data object. That library is for scalars.
209 // We will need to do something different if we need sensitivities
210 // wrt distributed parameters.
211
212 distributed_parameter_container_.push_back(std::make_tuple(name,index,importer,ghosted_vector));
213
214 return index;
215}
216
217// Overridden from EpetraExt::ModelEvaluator
218
219Teuchos::RCP<const Epetra_Map>
221{
222 return map_x_;
223}
224
225Teuchos::RCP<const Epetra_Map>
227{
228 return map_x_;
229}
230
231Teuchos::RCP<const Epetra_Vector>
233{
234 return x0_;
235}
236
237Teuchos::RCP<const Epetra_Vector>
239{
240 return x_dot_init_;
241}
242
243double
245{
246 return t_init_;
247}
248
249Teuchos::RCP<Epetra_Operator>
251{
252 return epetraOperatorFactory_->create();
253}
254
255Teuchos::RCP<const Epetra_Map>
257{
258 return p_map_[l];
259}
260
261Teuchos::RCP<const Teuchos::Array<std::string> >
263{
264 return p_names_[l];
265}
266
267Teuchos::RCP<const Epetra_Vector>
269{
270 return p_init_[l];
271}
272
273Teuchos::RCP<const Epetra_Map>
275{
276 return g_map_[l];
277}
278
281{
282 InArgsSetup inArgs;
283 inArgs.setModelEvalDescription(this->description());
284 inArgs.setSupports(IN_ARG_x,true);
285 if (build_transient_support_) {
286 inArgs.setSupports(IN_ARG_x_dot,true);
287 inArgs.setSupports(IN_ARG_t,true);
288 inArgs.setSupports(IN_ARG_alpha,true);
289 inArgs.setSupports(IN_ARG_beta,true);
290 }
291 inArgs.set_Np(p_init_.size());
292
293 return inArgs;
294}
295
298{
299 OutArgsSetup outArgs;
300 outArgs.setModelEvalDescription(this->description());
301 outArgs.set_Np_Ng(p_init_.size(), g_map_.size());
302 outArgs.setSupports(OUT_ARG_f,true);
303 outArgs.setSupports(OUT_ARG_W,true);
304 outArgs.set_W_properties(
305 DerivativeProperties(
306 DERIV_LINEARITY_NONCONST
307 ,DERIV_RANK_FULL
308 ,true // supportsAdjoint
309 )
310 );
311
312 // add in df/dp (if appropriate)
313 for(std::size_t i=0;i<p_init_.size();i++) {
314 if(!is_distributed_parameter_[i])
315 outArgs.setSupports(OUT_ARG_DfDp,i,EpetraExt::ModelEvaluator::DerivativeSupport(DERIV_MV_BY_COL));
316 }
317
318 // add in dg/dx (if appropriate)
319 for(std::size_t i=0;i<g_names_.size();i++) {
320 typedef panzer::Traits::Jacobian RespEvalT;
321
322 // check dg/dx and add it in if appropriate
323 Teuchos::RCP<panzer::ResponseBase> respJacBase = responseLibrary_->getResponse<RespEvalT>(g_names_[i]);
324 if(respJacBase!=Teuchos::null) {
325 // cast is guranteed to succeed because of check in addResponse
326 Teuchos::RCP<panzer::ResponseMESupportBase<RespEvalT> > resp = Teuchos::rcp_dynamic_cast<panzer::ResponseMESupportBase<RespEvalT> >(respJacBase);
327
328 // class must supoprt a derivative
329 if(resp->supportsDerivative())
330 outArgs.setSupports(OUT_ARG_DgDx,i,DerivativeSupport(DERIV_TRANS_MV_BY_ROW));
331 //outArgs.setSupports(OUT_ARG_DgDx,i,DerivativeSupport(DERIV_LINEAR_OP));
332 }
333 }
334
335 return outArgs;
336}
337
339applyDirichletBCs(const Teuchos::RCP<Thyra::VectorBase<double> > & x,
340 const Teuchos::RCP<Thyra::VectorBase<double> > & f) const
341{
342 using Teuchos::RCP;
343 using Teuchos::ArrayRCP;
344 using Teuchos::Array;
345 //using Teuchos::tuple;
346 using Teuchos::rcp_dynamic_cast;
347
348 // if neccessary build a ghosted container
349 if(Teuchos::is_null(ghostedContainer_)) {
350 ghostedContainer_ = lof_->buildGhostedLinearObjContainer();
351 lof_->initializeGhostedContainer(panzer::LinearObjContainer::X |
352 panzer::LinearObjContainer::F,*ghostedContainer_);
353 }
354
356 ae_inargs.container_ = lof_->buildLinearObjContainer(); // we use a new global container
357 ae_inargs.ghostedContainer_ = ghostedContainer_; // we can reuse the ghosted container
358 ae_inargs.alpha = 0.0;
359 ae_inargs.beta = 1.0;
360 ae_inargs.evaluate_transient_terms = false;
361
362 // this is the tempory target
363 lof_->initializeContainer(panzer::LinearObjContainer::F,*ae_inargs.container_);
364
365 // here we are building a container, this operation is fast, simply allocating a struct
366 const RCP<panzer::ThyraObjContainer<double> > thGlobalContainer =
367 Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<double> >(ae_inargs.container_,true);
368
369 TEUCHOS_ASSERT(!Teuchos::is_null(thGlobalContainer));
370
371 // Ghosted container objects are zeroed out below only if needed for
372 // a particular calculation. This makes it more efficient than
373 // zeroing out all objects in the container here.
374 const RCP<panzer::ThyraObjContainer<double> > thGhostedContainer =
375 Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<double> >(ae_inargs.ghostedContainer_,true);
376 TEUCHOS_ASSERT(!Teuchos::is_null(thGhostedContainer));
377 Thyra::assign(thGhostedContainer->get_f_th().ptr(),0.0);
378
379 // Set the solution vector (currently all targets require solution).
380 // In the future we may move these into the individual cases below.
381 // A very subtle (and fragile) point: A non-null pointer in global
382 // container triggers export operations during fill. Also, the
383 // introduction of the container is forcing us to cast away const on
384 // arguments that should be const. Another reason to redesign
385 // LinearObjContainer layers.
386 thGlobalContainer->set_x_th(x);
387
388 // evaluate dirichlet boundary conditions
389 RCP<panzer::LinearObjContainer> counter = ae_tm_.getAsObject<panzer::Traits::Residual>()->evaluateOnlyDirichletBCs(ae_inargs);
390
391 // allocate the result container
392 RCP<panzer::LinearObjContainer> result = lof_->buildLinearObjContainer(); // we use a new global container
393
394 // stuff the evaluate boundary conditions into the f spot of the counter ... the x is already filled
395 Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<double> >(counter)->set_f_th(thGlobalContainer->get_f_th());
396
397 // stuff the vector that needs applied dirichlet conditions in the the f spot of the result LOC
398 Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<double> >(result)->set_f_th(f);
399
400 // use the linear object factory to apply the result
401 lof_->applyDirichletBCs(*counter,*result);
402}
403
405 const OutArgs& outArgs ) const
406{
407 using Teuchos::RCP;
408 using Teuchos::rcp_dynamic_cast;
409
410 evalModel_basic(inArgs,outArgs);
411}
412
414 const OutArgs& outArgs ) const
415{
416 using Teuchos::RCP;
417 using Teuchos::rcp_dynamic_cast;
418
419 // Transient or steady-state evaluation is determined by the x_dot
420 // vector. If this RCP is null, then we are doing a steady-state
421 // fill.
422 bool has_x_dot = false;
423 if (inArgs.supports(EpetraExt::ModelEvaluator::IN_ARG_x_dot ))
424 has_x_dot = nonnull(inArgs.get_x_dot());
425
426 // Make sure construction built in transient support
427 TEUCHOS_TEST_FOR_EXCEPTION(has_x_dot && !build_transient_support_, std::runtime_error,
428 "ModelEvaluator was not built with transient support enabled!");
429
430 //
431 // Get the output arguments
432 //
433 const RCP<Epetra_Vector> f_out = outArgs.get_f();
434 const RCP<Epetra_Operator> W_out = outArgs.get_W();
435 bool requiredResponses = required_basic_g(outArgs);
436 bool requiredSensitivities = required_basic_dfdp(outArgs);
437
438 // see if the user wants us to do anything
439 if(Teuchos::is_null(f_out) && Teuchos::is_null(W_out) &&
440 !requiredResponses && !requiredSensitivities) {
441 return;
442 }
443
444 // the user requested work from this method
445 // keep on moving
446
447 // if neccessary build a ghosted container
448 if(Teuchos::is_null(ghostedContainer_)) {
449 ghostedContainer_ = lof_->buildGhostedLinearObjContainer();
450 lof_->initializeGhostedContainer(panzer::LinearObjContainer::X |
453 panzer::LinearObjContainer::Mat, *ghostedContainer_);
454 }
455
456 //
457 // Get the input arguments
458 //
459 const RCP<const Epetra_Vector> x = inArgs.get_x();
460 RCP<const Epetra_Vector> x_dot;
461
463 ae_inargs.container_ = lof_->buildLinearObjContainer(); // we use a new global container
464 ae_inargs.ghostedContainer_ = ghostedContainer_; // we can reuse the ghosted container
465 ae_inargs.alpha = 0.0;
466 ae_inargs.beta = 1.0;
467 ae_inargs.evaluate_transient_terms = false;
468 if (build_transient_support_) {
469 x_dot = inArgs.get_x_dot();
470 ae_inargs.alpha = inArgs.get_alpha();
471 ae_inargs.beta = inArgs.get_beta();
472 ae_inargs.time = inArgs.get_t();
473 ae_inargs.evaluate_transient_terms = true;
474 }
475
476 // handle application of the one time dirichlet beta in the
477 // assembly engine. Note that this has to be set explicitly
478 // each time because this badly breaks encapsulation. Essentially
479 // we must work around the model evaluator abstraction!
480 ae_inargs.apply_dirichlet_beta = false;
481 if(oneTimeDirichletBeta_on_) {
482 ae_inargs.dirichlet_beta = oneTimeDirichletBeta_;
483 ae_inargs.apply_dirichlet_beta = true;
484
485 oneTimeDirichletBeta_on_ = false;
486 }
487
488 // Set locally replicated scalar input parameters
489 for (int i=0; i<inArgs.Np(); i++) {
490 Teuchos::RCP<const Epetra_Vector> p = inArgs.get_p(i);
491 if ( nonnull(p) && !is_distributed_parameter_[i]) {
492 for (unsigned int j=0; j < parameter_vector_[i].size(); j++) {
493 parameter_vector_[i][j].baseValue = (*p)[j];
494 }
495 }
496 }
497
498 for (Teuchos::Array<panzer::ParamVec>::size_type i=0; i < parameter_vector_.size(); i++) {
499 for (unsigned int j=0; j < parameter_vector_[i].size(); j++) {
500 parameter_vector_[i][j].family->setRealValueForAllTypes(parameter_vector_[i][j].baseValue);
501 }
502 }
503
504 // Perform global to ghost and set distributed parameters
505 for (std::vector<std::tuple<std::string,int,Teuchos::RCP<Epetra_Import>,Teuchos::RCP<Epetra_Vector> > >::const_iterator i =
506 distributed_parameter_container_.begin(); i != distributed_parameter_container_.end(); ++i) {
507 // do export if parameter exists in inArgs
508 Teuchos::RCP<const Epetra_Vector> global_vec = inArgs.get_p(std::get<1>(*i));
509 if (nonnull(global_vec)) {
510 // Only import if the importer is nonnull
511 Teuchos::RCP<Epetra_Import> importer = std::get<2>(*i);
512 if (nonnull(importer))
513 std::get<3>(*i)->Import(*global_vec,*importer,Insert);
514 }
515
516 // set in ae_inargs_ string lookup container
517 Teuchos::RCP<panzer::EpetraLinearObjContainer> container =
518 Teuchos::rcp(new panzer::EpetraLinearObjContainer(p_map_[std::get<1>(*i)],p_map_[std::get<1>(*i)]));
519 container->set_x(std::get<3>(*i));
520 ae_inargs.addGlobalEvaluationData(std::get<0>(*i),container);
521 }
522
523 // here we are building a container, this operation is fast, simply allocating a struct
524 const RCP<panzer::EpetraLinearObjContainer> epGlobalContainer =
525 Teuchos::rcp_dynamic_cast<panzer::EpetraLinearObjContainer>(ae_inargs.container_);
526
527 TEUCHOS_ASSERT(!Teuchos::is_null(epGlobalContainer));
528
529 // Ghosted container objects are zeroed out below only if needed for
530 // a particular calculation. This makes it more efficient thatn
531 // zeroing out all objects in the container here.
532 const RCP<panzer::EpetraLinearObjContainer> epGhostedContainer =
533 Teuchos::rcp_dynamic_cast<panzer::EpetraLinearObjContainer>(ae_inargs.ghostedContainer_);
534
535 // Set the solution vector (currently all targets require solution).
536 // In the future we may move these into the individual cases below.
537 // A very subtle (and fragile) point: A non-null pointer in global
538 // container triggers export operations during fill. Also, the
539 // introduction of the container is forcing us to cast away const on
540 // arguments that should be const. Another reason to redesign
541 // LinearObjContainer layers.
542 epGlobalContainer->set_x(Teuchos::rcp_const_cast<Epetra_Vector>(x));
543 if (has_x_dot)
544 epGlobalContainer->set_dxdt(Teuchos::rcp_const_cast<Epetra_Vector>(x_dot));
545
546 if (!Teuchos::is_null(f_out) && !Teuchos::is_null(W_out)) {
547
548 PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::evalModel(f and J)");
549
550 // Set the targets
551 epGlobalContainer->set_f(f_out);
552 epGlobalContainer->set_A(Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(W_out));
553
554 // Zero values in ghosted container objects
555 epGhostedContainer->get_f()->PutScalar(0.0);
556 epGhostedContainer->get_A()->PutScalar(0.0);
557
558 ae_tm_.getAsObject<panzer::Traits::Jacobian>()->evaluate(ae_inargs);
559 }
560 else if(!Teuchos::is_null(f_out) && Teuchos::is_null(W_out)) {
561
562 PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::evalModel(f)");
563
564 epGlobalContainer->set_f(f_out);
565
566 // Zero values in ghosted container objects
567 epGhostedContainer->get_f()->PutScalar(0.0);
568
569 ae_tm_.getAsObject<panzer::Traits::Residual>()->evaluate(ae_inargs);
570
571 f_out->Update(1.0, *(epGlobalContainer->get_f()), 0.0);
572 }
573 else if(Teuchos::is_null(f_out) && !Teuchos::is_null(W_out)) {
574
575 PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::evalModel(J)");
576
577 // this dummy nonsense is needed only for scattering dirichlet conditions
578 if (Teuchos::is_null(dummy_f_))
579 dummy_f_ = Teuchos::rcp(new Epetra_Vector(*(this->get_f_map())));
580 epGlobalContainer->set_f(dummy_f_);
581 epGlobalContainer->set_A(Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(W_out));
582
583 // Zero values in ghosted container objects
584 epGhostedContainer->get_A()->PutScalar(0.0);
585
586 ae_tm_.getAsObject<panzer::Traits::Jacobian>()->evaluate(ae_inargs);
587 }
588 // HACK: set A to null before calling responses to avoid touching the
589 // the Jacobian after it has been properly assembled. Should be fixed
590 // by using a modified version of ae_inargs instead.
591 epGlobalContainer->set_A(Teuchos::null);
592
593 // evaluate responses...uses the stored assembly arguments and containers
594 if(requiredResponses) {
595 evalModel_basic_g(ae_inargs,inArgs,outArgs);
596
597 // evaluate response derivatives
598 if(required_basic_dgdx(outArgs))
599 evalModel_basic_dgdx(ae_inargs,inArgs,outArgs);
600 }
601
602 if(required_basic_dfdp(outArgs))
603 evalModel_basic_dfdp(ae_inargs,inArgs,outArgs);
604
605 // TODO: Clearing all references prevented a seg-fault with Rythmos,
606 // which is no longer used. Check if it's still needed.
607 epGlobalContainer->set_x(Teuchos::null);
608 epGlobalContainer->set_dxdt(Teuchos::null);
609 epGlobalContainer->set_f(Teuchos::null);
610 epGlobalContainer->set_A(Teuchos::null);
611
612 // forget previous containers
613 ae_inargs.container_ = Teuchos::null;
614 ae_inargs.ghostedContainer_ = Teuchos::null;
615}
616
617void
619evalModel_basic_g(AssemblyEngineInArgs ae_inargs, const InArgs& /* inArgs */, const OutArgs& outArgs) const
620{
621 // optional sanity check
622 // TEUCHOS_ASSERT(required_basic_g(outArgs));
623
624 for(std::size_t i=0;i<g_names_.size();i++) {
625 Teuchos::RCP<Epetra_Vector> vec = outArgs.get_g(i);
626 if(vec!=Teuchos::null) {
627 std::string responseName = g_names_[i];
628 Teuchos::RCP<panzer::ResponseMESupportBase<panzer::Traits::Residual> > resp
629 = Teuchos::rcp_dynamic_cast<panzer::ResponseMESupportBase<panzer::Traits::Residual> >(responseLibrary_->getResponse<panzer::Traits::Residual>(responseName));
630 resp->setVector(vec);
631 }
632 }
633
634 // evaluator responses
635 responseLibrary_->addResponsesToInArgs<panzer::Traits::Residual>(ae_inargs);
636 responseLibrary_->evaluate<panzer::Traits::Residual>(ae_inargs);
637}
638
639void
641evalModel_basic_dgdx(AssemblyEngineInArgs ae_inargs, const InArgs& /* inArgs */, const OutArgs& outArgs) const
642{
643 // optional sanity check
644 TEUCHOS_ASSERT(required_basic_dgdx(outArgs));
645
646 for(std::size_t i=0;i<g_names_.size();i++) {
647 // get "Vector" out of derivative, if its something else, throw an exception
648 EpetraExt::ModelEvaluator::Derivative deriv = outArgs.get_DgDx(i);
649 if(deriv.isEmpty())
650 continue;
651
652 Teuchos::RCP<Epetra_MultiVector> vec = deriv.getMultiVector();
653
654 if(vec!=Teuchos::null) {
655 std::string responseName = g_names_[i];
656 Teuchos::RCP<panzer::ResponseMESupportBase<panzer::Traits::Jacobian> > resp
657 = Teuchos::rcp_dynamic_cast<panzer::ResponseMESupportBase<panzer::Traits::Jacobian> >(responseLibrary_->getResponse<panzer::Traits::Jacobian>(responseName));
658 resp->setDerivative(vec);
659 }
660 }
661
662 // evaluator responses
663 responseLibrary_->addResponsesToInArgs<panzer::Traits::Jacobian>(ae_inargs);
664 responseLibrary_->evaluate<panzer::Traits::Jacobian>(ae_inargs);
665}
666
667void
669evalModel_basic_dfdp(AssemblyEngineInArgs ae_inargs, const InArgs& /* inArgs */, const OutArgs& outArgs) const
670{
671 using Teuchos::RCP;
672 using Teuchos::rcp_dynamic_cast;
673
674 TEUCHOS_ASSERT(required_basic_dfdp(outArgs));
675
676 // dynamic cast to blocked LOF for now
677 RCP<const Thyra::VectorSpaceBase<double> > glblVS = rcp_dynamic_cast<const ThyraObjFactory<double> >(lof_,true)->getThyraRangeSpace();;
678
679 std::vector<std::string> activeParameters;
680
681 // fill parameter vector containers
682 int totalParameterCount = 0;
683 for(Teuchos::Array<panzer::ParamVec>::size_type i=0; i < parameter_vector_.size(); i++) {
684 // have derivatives been requested?
685 EpetraExt::ModelEvaluator::Derivative deriv = outArgs.get_DfDp(i);
686 if(deriv.isEmpty())
687 continue;
688
689 // grab multivector, make sure its the right dimension
690 Teuchos::RCP<Epetra_MultiVector> mVec = deriv.getMultiVector();
691 TEUCHOS_ASSERT(mVec->NumVectors()==int(parameter_vector_[i].size()));
692
693 for (unsigned int j=0; j < parameter_vector_[i].size(); j++) {
694
695 // build containers for each vector
696 RCP<LOCPair_GlobalEvaluationData> loc_pair = Teuchos::rcp(new LOCPair_GlobalEvaluationData(lof_,LinearObjContainer::F));
697 RCP<LinearObjContainer> globalContainer = loc_pair->getGlobalLOC();
698
699 // stuff target vector into global container
700 RCP<Epetra_Vector> vec = Teuchos::rcpFromRef(*(*mVec)(j));
701 RCP<panzer::ThyraObjContainer<double> > thGlobalContainer =
702 Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<double> >(globalContainer);
703 thGlobalContainer->set_f_th(Thyra::create_Vector(vec,glblVS));
704
705 // add container into in args object
706 std::string name = "PARAMETER_SENSITIVIES: "+(*p_names_[i])[j];
707 ae_inargs.addGlobalEvaluationData(name,loc_pair->getGhostedLOC());
708 ae_inargs.addGlobalEvaluationData(name+"_pair",loc_pair);
709
710 activeParameters.push_back(name);
711 totalParameterCount++;
712 }
713 }
714
715 // this communicates to the scatter evaluators so that the appropriate parameters are scattered
716 RCP<GlobalEvaluationData> ged_activeParameters = Teuchos::rcp(new ParameterList_GlobalEvaluationData(activeParameters));
717 ae_inargs.addGlobalEvaluationData("PARAMETER_NAMES",ged_activeParameters);
718
719 int paramIndex = 0;
720 for (Teuchos::Array<panzer::ParamVec>::size_type i=0; i < parameter_vector_.size(); i++) {
721 // don't modify the parameter if its not needed
722 EpetraExt::ModelEvaluator::Derivative deriv = outArgs.get_DfDp(i);
723 if(deriv.isEmpty()) {
724 // reinitialize values that should not have sensitivities computed (this is a precaution)
725 for (unsigned int j=0; j < parameter_vector_[i].size(); j++) {
726 Traits::FadType p = Traits::FadType(totalParameterCount, parameter_vector_[i][j].baseValue);
727 parameter_vector_[i][j].family->setValue<panzer::Traits::Tangent>(p);
728 }
729 continue;
730 }
731 else {
732 // loop over each parameter in the vector, initializing the AD type
733 for (unsigned int j=0; j < parameter_vector_[i].size(); j++) {
734 Traits::FadType p = Traits::FadType(totalParameterCount, parameter_vector_[i][j].baseValue);
735 p.fastAccessDx(paramIndex) = 1.0;
736 parameter_vector_[i][j].family->setValue<panzer::Traits::Tangent>(p);
737 paramIndex++;
738 }
739 }
740 }
741
742 // make sure that the total parameter count and the total parameter index match up
743 TEUCHOS_ASSERT(paramIndex==totalParameterCount);
744
745 if(totalParameterCount>0) {
746 ae_tm_.getAsObject<panzer::Traits::Tangent>()->evaluate(ae_inargs);
747 }
748}
749
750bool panzer::ModelEvaluator_Epetra::required_basic_g(const OutArgs & outArgs) const
751{
752 // determine if any of the outArgs are not null!
753 bool activeGArgs = false;
754 for(int i=0;i<outArgs.Ng();i++)
755 activeGArgs |= (outArgs.get_g(i)!=Teuchos::null);
756
757 return activeGArgs | required_basic_dgdx(outArgs);
758}
759
760bool panzer::ModelEvaluator_Epetra::required_basic_dgdx(const OutArgs & outArgs) const
761{
762 // determine if any of the outArgs are not null!
763 bool activeGArgs = false;
764 for(int i=0;i<outArgs.Ng();i++) {
765 // no derivatives are supported
766 if(outArgs.supports(OUT_ARG_DgDx,i).none())
767 continue;
768
769 // this is basically a redundant computation
770 activeGArgs |= (!outArgs.get_DgDx(i).isEmpty());
771 }
772
773 return activeGArgs;
774}
775
776bool panzer::ModelEvaluator_Epetra::required_basic_dfdp(const OutArgs & outArgs) const
777{
778 // determine if any of the outArgs are not null!
779 bool activeFPArgs = false;
780 for(int i=0;i<outArgs.Np();i++) {
781 // no derivatives are supported
782 if(outArgs.supports(OUT_ARG_DfDp,i).none())
783 continue;
784
785 // this is basically a redundant computation
786 activeFPArgs |= (!outArgs.get_DfDp(i).isEmpty());
787 }
788
789 return activeFPArgs;
790}
791
793{
794 t_init_ = t;
795}
796
799{
800
801 using Teuchos::rcpFromRef;
802 using Teuchos::rcp_dynamic_cast;
803 using Teuchos::RCP;
804 using Teuchos::ArrayView;
805 using Teuchos::rcp_dynamic_cast;
806
807 const int numVecs = x.NumVectors();
808
809 TEUCHOS_TEST_FOR_EXCEPTION(numVecs != 1, std::runtime_error,
810 "epetraToThyra does not work with MV dimension != 1");
811
812 const RCP<const Thyra::ProductVectorBase<double> > prodThyraVec =
813 Thyra::castOrCreateProductVectorBase(rcpFromRef(thyraVec));
814
815 const Teuchos::ArrayView<double> epetraData(x[0], x.Map().NumMyElements());
816 // NOTE: See above!
817
818 std::size_t offset = 0;
819 const int numBlocks = prodThyraVec->productSpace()->numBlocks();
820 for (int b = 0; b < numBlocks; ++b) {
821 const RCP<const Thyra::VectorBase<double> > vec_b = prodThyraVec->getVectorBlock(b);
822 const RCP<const Thyra::SpmdVectorBase<double> > spmd_b =
823 rcp_dynamic_cast<const Thyra::SpmdVectorBase<double> >(vec_b, true);
824
825 Teuchos::ArrayRCP<const double> thyraData;
826 spmd_b->getLocalData(Teuchos::ptrFromRef(thyraData));
827
828 for (Teuchos::ArrayRCP<const double>::size_type i=0; i < thyraData.size(); ++i) {
829 epetraData[i+offset] = thyraData[i];
830 }
831 offset += thyraData.size();
832 }
833
834}
835
836
838copyEpetraIntoThyra(const Epetra_MultiVector& x, const Teuchos::Ptr<Thyra::VectorBase<double> > &thyraVec) const
839{
840 using Teuchos::RCP;
841 using Teuchos::ArrayView;
842 using Teuchos::rcpFromPtr;
843 using Teuchos::rcp_dynamic_cast;
844
845 const int numVecs = x.NumVectors();
846
847 TEUCHOS_TEST_FOR_EXCEPTION(numVecs != 1, std::runtime_error,
848 "ModelEvaluator_Epetra::copyEpetraToThyra does not work with MV dimension != 1");
849
850 const RCP<Thyra::ProductVectorBase<double> > prodThyraVec =
851 Thyra::castOrCreateNonconstProductVectorBase(rcpFromPtr(thyraVec));
852
853 const Teuchos::ArrayView<const double> epetraData(x[0], x.Map().NumMyElements());
854 // NOTE: I tried using Epetra_MultiVector::operator()(int) to return an
855 // Epetra_Vector object but it has a defect when Reset(...) is called which
856 // results in a memory access error (see bug 4700).
857
858 std::size_t offset = 0;
859 const int numBlocks = prodThyraVec->productSpace()->numBlocks();
860 for (int b = 0; b < numBlocks; ++b) {
861 const RCP<Thyra::VectorBase<double> > vec_b = prodThyraVec->getNonconstVectorBlock(b);
862 const RCP<Thyra::SpmdVectorBase<double> > spmd_b =
863 rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(vec_b, true);
864
865 Teuchos::ArrayRCP<double> thyraData;
866 spmd_b->getNonconstLocalData(Teuchos::ptrFromRef(thyraData));
867
868 for (Teuchos::ArrayRCP<double>::size_type i=0; i < thyraData.size(); ++i) {
869 thyraData[i] = epetraData[i+offset];
870 }
871 offset += thyraData.size();
872 }
873
874}
875
876
877Teuchos::RCP<panzer::ModelEvaluator_Epetra>
878panzer::buildEpetraME(const Teuchos::RCP<panzer::FieldManagerBuilder>& fmb,
879 const Teuchos::RCP<panzer::ResponseLibrary<panzer::Traits> >& rLibrary,
880 const Teuchos::RCP<panzer::LinearObjFactory<panzer::Traits> >& lof,
881 const std::vector<Teuchos::RCP<Teuchos::Array<std::string> > >& p_names,
882 const std::vector<Teuchos::RCP<Teuchos::Array<double> > >& p_values,
883 const Teuchos::RCP<panzer::GlobalData>& global_data,
884 bool build_transient_support)
885{
886 using Teuchos::RCP;
887 using Teuchos::rcp_dynamic_cast;
888 using Teuchos::rcp;
889
890 std::stringstream ss;
891 ss << "panzer::buildEpetraME: Linear object factory is incorrect type. Should be one of: ";
892
893 RCP<BlockedEpetraLinearObjFactory<panzer::Traits,int> > ep_lof
894 = rcp_dynamic_cast<BlockedEpetraLinearObjFactory<panzer::Traits,int> >(lof);
895
896 // if you can, build from an epetra linear object factory
897 if(ep_lof!=Teuchos::null)
898 return rcp(new ModelEvaluator_Epetra(fmb,rLibrary,ep_lof,p_names,p_values,global_data,build_transient_support));
899
900 ss << "\"BlockedEpetraLinearObjFactory\", ";
901
902 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,ss.str());
903}
904
906setOneTimeDirichletBeta(const double & beta) const
907{
908 oneTimeDirichletBeta_on_ = true;
909 oneTimeDirichletBeta_ = beta;
910}
Insert
PHX::MDField< ScalarT, panzer::Cell, panzer::IP > result
A field that will be used to build up the result of the integral we're performing.
Teuchos::RCP< Epetra_MultiVector > getMultiVector() const
int NumMyElements() const
const Epetra_BlockMap & Map() const
int NumVectors() const
void addGlobalEvaluationData(const std::string &key, const Teuchos::RCP< GlobalEvaluationData > &ged)
Teuchos::RCP< panzer::LinearObjContainer > ghostedContainer_
Teuchos::RCP< panzer::LinearObjContainer > container_
virtual const Teuchos::RCP< Epetra_Map > getMap(int i) const
get the map from the matrix
Teuchos::RCP< const Epetra_Map > get_f_map() const
Teuchos::RCP< const Epetra_Map > get_x_map() const
Teuchos::RCP< const Epetra_Vector > get_x_init() const
Teuchos::RCP< const Epetra_Vector > get_x_dot_init() const
Teuchos::RCP< Epetra_Operator > create_W() const
Teuchos::RCP< const Epetra_Map > get_g_map(int l) const
void evalModel(const InArgs &inArgs, const OutArgs &outArgs) const
Teuchos::RCP< const Teuchos::Array< std::string > > get_p_names(int l) const
void set_t_init(double t)
Set initial time value.
ModelEvaluator_Epetra(const Teuchos::RCP< panzer::FieldManagerBuilder > &fmb, const Teuchos::RCP< panzer::ResponseLibrary< panzer::Traits > > &rLibrary, const Teuchos::RCP< panzer::LinearObjFactory< panzer::Traits > > &lof, const std::vector< Teuchos::RCP< Teuchos::Array< std::string > > > &p_names, const std::vector< Teuchos::RCP< Teuchos::Array< double > > > &p_values, const Teuchos::RCP< panzer::GlobalData > &global_data, bool build_transient_support)
Teuchos::RCP< const Epetra_Map > get_p_map(int l) const
Teuchos::RCP< const Epetra_Vector > get_p_init(int l) const
void evalModel_basic_dgdx(AssemblyEngineInArgs ae_inargs, const InArgs &inArgs, const OutArgs &outArgs) const
void initializeEpetraObjs(panzer::BlockedEpetraLinearObjFactory< panzer::Traits, int > &lof)
void setOneTimeDirichletBeta(const double &beta) const
bool required_basic_dgdx(const OutArgs &outArgs) const
Are their required responses in the out args? DgDx.
void evalModel_basic_dfdp(AssemblyEngineInArgs ae_inargs, const InArgs &inArgs, const OutArgs &outArgs) const
bool required_basic_g(const OutArgs &outArgs) const
Are their required responses in the out args? g and DgDx.
int addDistributedParameter(const std::string name, const Teuchos::RCP< Epetra_Map > &global_map, const Teuchos::RCP< Epetra_Import > &importer, const Teuchos::RCP< Epetra_Vector > &ghosted_vector)
void evalModel_basic_g(AssemblyEngineInArgs ae_inargs, const InArgs &inArgs, const OutArgs &outArgs) const
bool required_basic_dfdp(const OutArgs &outArgs) const
Are derivatives of the residual with respect to the parameters in the out args? DfDp.
void evalModel_basic(const InArgs &inArgs, const OutArgs &outArgs) const
for evaluation and handling of normal quantities, x,f,W, etc
void initializeParameterVector(const std::vector< Teuchos::RCP< Teuchos::Array< std::string > > > &p_names, const std::vector< Teuchos::RCP< Teuchos::Array< double > > > &p_values, const Teuchos::RCP< panzer::ParamLib > &parameter_library)
void copyEpetraIntoThyra(const Epetra_MultiVector &x, const Teuchos::Ptr< Thyra::VectorBase< double > > &thyraVec) const
panzer::AssemblyEngine_TemplateManager< panzer::Traits > ae_tm_
void applyDirichletBCs(const Teuchos::RCP< Thyra::VectorBase< double > > &x, const Teuchos::RCP< Thyra::VectorBase< double > > &f) const
std::vector< Teuchos::RCP< Teuchos::Array< std::string > > > p_names_
void copyThyraIntoEpetra(const Thyra::VectorBase< double > &thyraVec, Epetra_MultiVector &x) const
Teuchos::RCP< ModelEvaluator_Epetra > buildEpetraME(const Teuchos::RCP< FieldManagerBuilder > &fmb, const Teuchos::RCP< ResponseLibrary< panzer::Traits > > &rLibrary, const Teuchos::RCP< LinearObjFactory< panzer::Traits > > &lof, const std::vector< Teuchos::RCP< Teuchos::Array< std::string > > > &p_names, const std::vector< Teuchos::RCP< Teuchos::Array< double > > > &p_values, const Teuchos::RCP< panzer::GlobalData > &global_data, bool build_transient_support)
void registerScalarParameter(const std::string name, panzer::ParamLib &pl, double realValue)
PANZER_FADTYPE FadType