Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_AssemblyEngine_impl.hpp
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 #ifndef PANZER_ASSEMBLY_ENGINE_IMPL_HPP
12 #define PANZER_ASSEMBLY_ENGINE_IMPL_HPP
13 
14 #include "Phalanx_FieldManager.hpp"
18 #include <sstream>
19 
20 //===========================================================================
21 //===========================================================================
22 template <typename EvalT>
26  : m_field_manager_builder(fmb), m_lin_obj_factory(lof), countersInitialized_(false)
27 {
28 
29 }
30 
31 //===========================================================================
32 //===========================================================================
33 template <typename EvalT>
36 {
37  typedef LinearObjContainer LOC;
38 
39  // make sure this container gets a dirichlet adjustment
41 
43 
44  if ( flags.getValue() & EvaluationFlags::Initialize ) {
45  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::evaluate_gather("+PHX::print<EvalT>()+")", eval_gather);
46 
48  gedc.initialize(); // make sure all ghosted data is ready to go
49  gedc.globalToGhost(LOC::X | LOC::DxDt);
50 
51  // Push solution, x and dxdt into ghosted domain
52  m_lin_obj_factory->globalToGhostContainer(*in.container_,*in.ghostedContainer_,LOC::X | LOC::DxDt);
53  m_lin_obj_factory->beginFill(*in.ghostedContainer_);
54  }
55 
56  // *********************
57  // Volumetric fill
58  // *********************
59  if ( flags.getValue() & EvaluationFlags::VolumetricFill) {
60  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::evaluate_volume("+PHX::print<EvalT>()+")", eval_vol);
61  this->evaluateVolume(in);
62  }
63 
64  // *********************
65  // BC fill
66  // *********************
67  // NOTE: We have to split neumann and dirichlet bcs since dirichlet
68  // bcs overwrite equations where neumann sum into equations. Make
69  // sure all neumann are done before dirichlet.
70 
71  if ( flags.getValue() & EvaluationFlags::BoundaryFill) {
72  {
73  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::evaluate_neumannbcs("+PHX::print<EvalT>()+")",eval_neumannbcs);
74  this->evaluateNeumannBCs(in);
75  }
76 
77  {
78  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::evaluate_interfacebcs("+PHX::print<EvalT>()+")",eval_interfacebcs);
79  this->evaluateInterfaceBCs(in);
80  }
81 
82  // Dirchlet conditions require a global matrix
83  {
84  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::evaluate_dirichletbcs("+PHX::print<EvalT>()+")",eval_dirichletbcs);
85  this->evaluateDirichletBCs(in);
86  }
87  }
88 
89  if ( flags.getValue() & EvaluationFlags::Scatter) {
90  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::evaluate_scatter("+PHX::print<EvalT>()+")",eval_scatter);
91  {
92  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::lof->ghostToGlobalContainer("+PHX::print<EvalT>()+")",lof_gtgc);
93  m_lin_obj_factory->ghostToGlobalContainer(*in.ghostedContainer_,*in.container_,LOC::F | LOC::Mat);
94  }
95  {
96  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::gedc.ghostToGlobal("+PHX::print<EvalT>()+")",gedc_gtg);
97  m_lin_obj_factory->beginFill(*in.container_);
98  gedc.ghostToGlobal(LOC::F | LOC::Mat);
99  m_lin_obj_factory->endFill(*in.container_);
100  }
101  m_lin_obj_factory->endFill(*in.ghostedContainer_);
102  }
103 
104  return;
105 }
106 
107 //===========================================================================
108 //===========================================================================
109 template <typename EvalT>
112 {
113  typedef LinearObjContainer LOC;
114 
115  // make sure this container gets a dirichlet adjustment
117 
120  gedc.initialize(); // make sure all ghosted data is ready to go
121  gedc.globalToGhost(LOC::X | LOC::DxDt);
122 
123  // Push solution, x and dxdt into ghosted domain
124  m_lin_obj_factory->globalToGhostContainer(*in.container_,*in.ghostedContainer_,LOC::X | LOC::DxDt);
125  m_lin_obj_factory->beginFill(*in.ghostedContainer_);
126 
127  // Dirchlet conditions require a global matrix
128  Teuchos::RCP<LOC> counter = this->evaluateDirichletBCs(in);
129 
130  m_lin_obj_factory->ghostToGlobalContainer(*in.ghostedContainer_,*in.container_,LOC::F | LOC::Mat);
131 
132  m_lin_obj_factory->beginFill(*in.container_);
133  gedc.ghostToGlobal(LOC::F | LOC::Mat);
134  m_lin_obj_factory->endFill(*in.container_);
135 
136  m_lin_obj_factory->endFill(*in.ghostedContainer_);
137 
138  return counter;
139 }
140 
141 //===========================================================================
142 //===========================================================================
143 template <typename EvalT>
146 {
147  const std::vector< Teuchos::RCP< PHX::FieldManager<panzer::Traits> > > &
148  volume_field_managers = m_field_manager_builder->getVolumeFieldManagers();
149  const std::vector<WorksetDescriptor> & wkstDesc = m_field_manager_builder->getVolumeWorksetDescriptors();
150 
151  Teuchos::RCP<panzer::WorksetContainer> wkstContainer = m_field_manager_builder->getWorksetContainer();
152 
154  ped.gedc->addDataObject("Solution Gather Container",in.ghostedContainer_);
155  ped.gedc->addDataObject("Residual Scatter Container",in.ghostedContainer_);
159 
160  // Loop over volume field managers
161  for (std::size_t block = 0; block < volume_field_managers.size(); ++block) {
162  const WorksetDescriptor & wd = wkstDesc[block];
163  Teuchos::RCP< PHX::FieldManager<panzer::Traits> > fm = volume_field_managers[block];
164  std::vector<panzer::Workset>& w = *wkstContainer->getWorksets(wd);
165 
166  fm->template preEvaluate<EvalT>(ped);
167 
168  // Loop over worksets in this element block
169  for (std::size_t i = 0; i < w.size(); ++i) {
170  panzer::Workset& workset = w[i];
171 
172  workset.alpha = in.alpha;
173  workset.beta = in.beta;
174  workset.time = in.time;
175  workset.step_size = in.step_size;
176  workset.stage_number = in.stage_number;
177  workset.gather_seeds = in.gather_seeds;
179 
180 
181  fm->template evaluateFields<EvalT>(workset);
182  }
183 
184  // double s = 0.;
185  // double p = 0.;
186  // fm->template analyzeGraph<EvalT>(s,p);
187  // std::cout << "Analyze Graph: " << PHX::print<EvalT>() << ",b=" << block << ", s=" << s << ", p=" << p << std::endl;
188 
189  fm->template postEvaluate<EvalT>(NULL);
190  }
191 }
192 
193 //===========================================================================
194 //===========================================================================
195 template <typename EvalT>
198 {
199  this->evaluateBCs(panzer::BCT_Neumann, in);
200 }
201 
202 //===========================================================================
203 //===========================================================================
204 template <typename EvalT>
207 {
208  this->evaluateBCs(panzer::BCT_Interface, in);
209 }
210 
211 //===========================================================================
212 //===========================================================================
213 template <typename EvalT>
216 {
217  typedef LinearObjContainer LOC;
218 
219  if(!countersInitialized_) {
220  localCounter_ = m_lin_obj_factory->buildPrimitiveGhostedLinearObjContainer();
221  globalCounter_ = m_lin_obj_factory->buildPrimitiveLinearObjContainer();
222  summedGhostedCounter_ = m_lin_obj_factory->buildPrimitiveGhostedLinearObjContainer();
223  countersInitialized_ = true;
224 
225  m_lin_obj_factory->initializeGhostedContainer(LinearObjContainer::F,*localCounter_); // store counter in F
226  m_lin_obj_factory->initializeContainer( LinearObjContainer::F,*globalCounter_); // store counter in X
227  m_lin_obj_factory->initializeGhostedContainer(LinearObjContainer::F,*summedGhostedCounter_); // store counter in X
228  }
229 
230  {
231  localCounter_->initialize();
232  summedGhostedCounter_->initialize();
233  globalCounter_->initialize();
234  }
235 
236  // apply dirichlet conditions, make sure to keep track of the local counter
237  this->evaluateBCs(panzer::BCT_Dirichlet, in,localCounter_);
238 
239  // do communication to build summed ghosted counter for dirichlet conditions
240  {
241  m_lin_obj_factory->ghostToGlobalContainer(*localCounter_,*globalCounter_,LOC::F);
242  // Here we do the reduction across all processors so that the number of times
243  // a dirichlet condition is applied is summed into the global counter
244 
245  m_lin_obj_factory->globalToGhostContainer(*globalCounter_,*summedGhostedCounter_,LOC::F);
246  // finally we move the summed global vector into a local ghosted vector
247  // so that the dirichlet conditions can be applied to both the ghosted
248  // right hand side and the ghosted matrix
249  }
250 
252  gedc.addDataObject("Residual Scatter Container",in.ghostedContainer_);
254 
255  // adjust ghosted system for boundary conditions
256  for(GlobalEvaluationDataContainer::iterator itr=gedc.begin();itr!=gedc.end();itr++) {
257 
258  if(itr->second->requiresDirichletAdjustment()) {
259  Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LinearObjContainer>(itr->second);
260  if(loc!=Teuchos::null) {
261  m_lin_obj_factory->adjustForDirichletConditions(*localCounter_,*summedGhostedCounter_,*loc);
262  }
263  else {
264  // it was not a linear object container, so if you want an adjustment it better be a GED_BCAdjustment object
265  Teuchos::RCP<GlobalEvaluationData_BCAdjustment> bc_adjust = Teuchos::rcp_dynamic_cast<GlobalEvaluationData_BCAdjustment>(itr->second,true);
266  bc_adjust->adjustForDirichletConditions(*localCounter_,*summedGhostedCounter_);
267  }
268  }
269  }
270 
271  return globalCounter_;
272 }
273 
274 //===========================================================================
275 //===========================================================================
276 template <typename EvalT>
280  const Teuchos::RCP<LinearObjContainer> preEval_loc)
281 {
282  Teuchos::RCP<panzer::WorksetContainer> wkstContainer = m_field_manager_builder->getWorksetContainer();
283 
285  ped.gedc->addDataObject("Dirichlet Counter",preEval_loc);
286  ped.gedc->addDataObject("Solution Gather Container",in.ghostedContainer_);
287  ped.gedc->addDataObject("Residual Scatter Container",in.ghostedContainer_);
291 
292  // this helps work around issues when constructing a mass
293  // matrix using an evaluation of only the transient terms.
294  // In particular, the terms associated with the dirichlet
295  // conditions.
296  double betaValue = in.beta; // default to the passed in beta
297  if(bc_type==panzer::BCT_Dirichlet && in.apply_dirichlet_beta) {
298  betaValue = in.dirichlet_beta;
299  }
300 
301  {
302  const std::map<panzer::BC,
303  std::map<unsigned,PHX::FieldManager<panzer::Traits> >,
304  panzer::LessBC>& bc_field_managers =
305  m_field_manager_builder->getBCFieldManagers();
306 
307  // Must do all neumann before all dirichlet so we need a double loop
308  // here over all bcs
309  typedef typename std::map<panzer::BC,
310  std::map<unsigned,PHX::FieldManager<panzer::Traits> >,
311  panzer::LessBC>::const_iterator bcfm_it_type;
312 
313  // loop over bcs
314  for (bcfm_it_type bcfm_it = bc_field_managers.begin();
315  bcfm_it != bc_field_managers.end(); ++bcfm_it) {
316 
317  const panzer::BC& bc = bcfm_it->first;
318  const std::map<unsigned,PHX::FieldManager<panzer::Traits> > bc_fm =
319  bcfm_it->second;
320 
322  Teuchos::RCP<const std::map<unsigned,panzer::Workset> > bc_wkst_ptr = wkstContainer->getSideWorksets(desc);
323  TEUCHOS_TEST_FOR_EXCEPTION(bc_wkst_ptr == Teuchos::null, std::logic_error,
324  "Failed to find corresponding bc workset!");
325  const std::map<unsigned,panzer::Workset>& bc_wkst = *bc_wkst_ptr;
326 
327  // Only process bcs of the appropriate type (neumann or dirichlet)
328  if (bc.bcType() == bc_type) {
329  std::ostringstream timerName;
330  timerName << "panzer::AssemblyEngine::evaluateBCs: " << bc.identifier();
331 #ifdef PANZER_TEUCHOS_TIME_MONITOR
332  auto timer1 = Teuchos::TimeMonitor::getNewTimer(timerName.str());
333  Teuchos::TimeMonitor tm1(*timer1);
334 #endif
335 
336  // Loop over local faces
337  for (std::map<unsigned,PHX::FieldManager<panzer::Traits> >::const_iterator side = bc_fm.begin(); side != bc_fm.end(); ++side) {
338  std::ostringstream timerSideName;
339  timerSideName << "panzer::AssemblyEngine::evaluateBCs: " << bc.identifier() << ", side=" << side->first;
340 #ifdef PANZER_TEUCHOS_TIME_MONITOR
341  auto timer2 = Teuchos::TimeMonitor::getNewTimer(timerSideName.str());
342  Teuchos::TimeMonitor tm2(*timer2);
343 #endif
344 
345  // extract field manager for this side
346  unsigned local_side_index = side->first;
347  PHX::FieldManager<panzer::Traits>& local_side_fm =
348  const_cast<PHX::FieldManager<panzer::Traits>& >(side->second);
349 
350  // extract workset for this side: only one workset per face
351  std::map<unsigned,panzer::Workset>::const_iterator wkst_it =
352  bc_wkst.find(local_side_index);
353 
354  TEUCHOS_TEST_FOR_EXCEPTION(wkst_it == bc_wkst.end(), std::logic_error,
355  "Failed to find corresponding bc workset side!");
356 
357  panzer::Workset& workset =
358  const_cast<panzer::Workset&>(wkst_it->second);
359 
360  // run prevaluate
361  local_side_fm.template preEvaluate<EvalT>(ped);
362 
363  // build and evaluate fields for the workset: only one workset per face
364  workset.alpha = in.alpha;
365  workset.beta = betaValue;
366  workset.time = in.time;
367  workset.gather_seeds = in.gather_seeds;
368  workset.evaluate_transient_terms = in.evaluate_transient_terms;
369 
370  local_side_fm.template evaluateFields<EvalT>(workset);
371 
372  // run postevaluate for consistency
373  local_side_fm.template postEvaluate<EvalT>(NULL);
374 
375  }
376  }
377  }
378  }
379 
380 }
381 
382 #endif
Teuchos::RCP< GlobalEvaluationDataContainer > gedc
void addDataObject(const std::string &key, const Teuchos::RCP< GlobalEvaluationData > &ged)
BCType
Type of boundary condition.
Definition: Panzer_BC.hpp:41
std::unordered_map< std::string, Teuchos::RCP< GlobalEvaluationData > >::iterator iterator
FieldManager::iterator begin()
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
std::string second_sensitivities_name
virtual void adjustForDirichletConditions(const GlobalEvaluationData &localBCRows, const GlobalEvaluationData &globalBCRows)=0
void initialize()
Call initialize on all containers.
Teuchos::RCP< panzer::LinearObjContainer > ghostedContainer_
void evaluate(const panzer::AssemblyEngineInArgs &input_arguments, const EvaluationFlags flags=EvaluationFlags(EvaluationFlags::All))
void globalToGhost(int p)
Call global to ghost on all the containers.
static RCP< Time > getNewTimer(const std::string &name)
Teuchos::RCP< panzer::LinearObjContainer > container_
std::string identifier() const
A unique string identifier for this boundary condition.
Definition: Panzer_BC.cpp:225
std::string first_sensitivities_name
Teuchos::RCP< std::map< unsigned, Workset > > getSideWorksets(const WorksetDescriptor &desc)
Access, and construction of side worksets.
void evaluateInterfaceBCs(const panzer::AssemblyEngineInArgs &input_arguments)
void evaluateVolume(const panzer::AssemblyEngineInArgs &input_arguments)
FieldManager::iterator end()
Teuchos::RCP< std::vector< Workset > > getWorksets(const WorksetDescriptor &wd)
Access to volume worksets.
std::vector< double > gather_seeds
BCType bcType() const
Returns the boundary condition type (Dirichlet or Neumann or Interface).
Definition: Panzer_BC.cpp:154
Teuchos::RCP< LinearObjContainer > evaluateDirichletBCs(const panzer::AssemblyEngineInArgs &input_arguments)
This method returns the global counter used to indicate which rows are boundary conditions.
void evaluateBCs(const panzer::BCType bc_type, const panzer::AssemblyEngineInArgs &input_arguments, const Teuchos::RCP< LinearObjContainer > preEval_loc=Teuchos::null)
void ghostToGlobal(int p)
Call ghost to global on all the containers.
void fillGlobalEvaluationDataContainer(GlobalEvaluationDataContainer &gedc) const
Using internal map fill the global evaluation data container object.
AssemblyEngine(const Teuchos::RCP< panzer::FieldManagerBuilder > &fmb, const Teuchos::RCP< const panzer::LinearObjFactory< panzer::Traits > > &lof)
virtual void initialize()=0
WorksetDescriptor bcDescriptor(const panzer::BC &bc)
Definition: Panzer_BC.cpp:300
Stores input information for a boundary condition.
Definition: Panzer_BC.hpp:48
Teuchos::RCP< LinearObjContainer > evaluateOnlyDirichletBCs(const panzer::AssemblyEngineInArgs &input_arguments)
void evaluateNeumannBCs(const panzer::AssemblyEngineInArgs &input_arguments)