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 //
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_ASSEMBLY_ENGINE_IMPL_HPP
44 #define PANZER_ASSEMBLY_ENGINE_IMPL_HPP
45 
46 #include "Phalanx_FieldManager.hpp"
50 #include <sstream>
51 
52 //===========================================================================
53 //===========================================================================
54 template <typename EvalT>
58  : m_field_manager_builder(fmb), m_lin_obj_factory(lof), countersInitialized_(false)
59 {
60 
61 }
62 
63 //===========================================================================
64 //===========================================================================
65 template <typename EvalT>
68 {
69  typedef LinearObjContainer LOC;
70 
71  // make sure this container gets a dirichlet adjustment
73 
75 
76  if ( flags.getValue() & EvaluationFlags::Initialize ) {
77  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::evaluate_gather("+PHX::print<EvalT>()+")", eval_gather);
78 
80  gedc.initialize(); // make sure all ghosted data is ready to go
81  gedc.globalToGhost(LOC::X | LOC::DxDt);
82 
83  // Push solution, x and dxdt into ghosted domain
84  m_lin_obj_factory->globalToGhostContainer(*in.container_,*in.ghostedContainer_,LOC::X | LOC::DxDt);
85  m_lin_obj_factory->beginFill(*in.ghostedContainer_);
86  }
87 
88  // *********************
89  // Volumetric fill
90  // *********************
91  if ( flags.getValue() & EvaluationFlags::VolumetricFill) {
92  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::evaluate_volume("+PHX::print<EvalT>()+")", eval_vol);
93  this->evaluateVolume(in);
94  }
95 
96  // *********************
97  // BC fill
98  // *********************
99  // NOTE: We have to split neumann and dirichlet bcs since dirichlet
100  // bcs overwrite equations where neumann sum into equations. Make
101  // sure all neumann are done before dirichlet.
102 
103  if ( flags.getValue() & EvaluationFlags::BoundaryFill) {
104  {
105  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::evaluate_neumannbcs("+PHX::print<EvalT>()+")",eval_neumannbcs);
106  this->evaluateNeumannBCs(in);
107  }
108 
109  {
110  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::evaluate_interfacebcs("+PHX::print<EvalT>()+")",eval_interfacebcs);
111  this->evaluateInterfaceBCs(in);
112  }
113 
114  // Dirchlet conditions require a global matrix
115  {
116  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::evaluate_dirichletbcs("+PHX::print<EvalT>()+")",eval_dirichletbcs);
117  this->evaluateDirichletBCs(in);
118  }
119  }
120 
121  if ( flags.getValue() & EvaluationFlags::Scatter) {
122  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::evaluate_scatter("+PHX::print<EvalT>()+")",eval_scatter);
123  {
124  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::lof->ghostToGlobalContainer("+PHX::print<EvalT>()+")",lof_gtgc);
125  m_lin_obj_factory->ghostToGlobalContainer(*in.ghostedContainer_,*in.container_,LOC::F | LOC::Mat);
126  }
127  {
128  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::AssemblyEngine::gedc.ghostToGlobal("+PHX::print<EvalT>()+")",gedc_gtg);
129  m_lin_obj_factory->beginFill(*in.container_);
130  gedc.ghostToGlobal(LOC::F | LOC::Mat);
131  m_lin_obj_factory->endFill(*in.container_);
132  }
133  m_lin_obj_factory->endFill(*in.ghostedContainer_);
134  }
135 
136  return;
137 }
138 
139 //===========================================================================
140 //===========================================================================
141 template <typename EvalT>
144 {
145  typedef LinearObjContainer LOC;
146 
147  // make sure this container gets a dirichlet adjustment
149 
152  gedc.initialize(); // make sure all ghosted data is ready to go
153  gedc.globalToGhost(LOC::X | LOC::DxDt);
154 
155  // Push solution, x and dxdt into ghosted domain
156  m_lin_obj_factory->globalToGhostContainer(*in.container_,*in.ghostedContainer_,LOC::X | LOC::DxDt);
157  m_lin_obj_factory->beginFill(*in.ghostedContainer_);
158 
159  // Dirchlet conditions require a global matrix
160  Teuchos::RCP<LOC> counter = this->evaluateDirichletBCs(in);
161 
162  m_lin_obj_factory->ghostToGlobalContainer(*in.ghostedContainer_,*in.container_,LOC::F | LOC::Mat);
163 
164  m_lin_obj_factory->beginFill(*in.container_);
165  gedc.ghostToGlobal(LOC::F | LOC::Mat);
166  m_lin_obj_factory->endFill(*in.container_);
167 
168  m_lin_obj_factory->endFill(*in.ghostedContainer_);
169 
170  return counter;
171 }
172 
173 //===========================================================================
174 //===========================================================================
175 template <typename EvalT>
178 {
179  const std::vector< Teuchos::RCP< PHX::FieldManager<panzer::Traits> > > &
180  volume_field_managers = m_field_manager_builder->getVolumeFieldManagers();
181  const std::vector<WorksetDescriptor> & wkstDesc = m_field_manager_builder->getVolumeWorksetDescriptors();
182 
183  Teuchos::RCP<panzer::WorksetContainer> wkstContainer = m_field_manager_builder->getWorksetContainer();
184 
186  ped.gedc->addDataObject("Solution Gather Container",in.ghostedContainer_);
187  ped.gedc->addDataObject("Residual Scatter Container",in.ghostedContainer_);
191 
192  // Loop over volume field managers
193  for (std::size_t block = 0; block < volume_field_managers.size(); ++block) {
194  const WorksetDescriptor & wd = wkstDesc[block];
195  Teuchos::RCP< PHX::FieldManager<panzer::Traits> > fm = volume_field_managers[block];
196  std::vector<panzer::Workset>& w = *wkstContainer->getWorksets(wd);
197 
198  fm->template preEvaluate<EvalT>(ped);
199 
200  // Loop over worksets in this element block
201  for (std::size_t i = 0; i < w.size(); ++i) {
202  panzer::Workset& workset = w[i];
203 
204  workset.alpha = in.alpha;
205  workset.beta = in.beta;
206  workset.time = in.time;
207  workset.step_size = in.step_size;
208  workset.stage_number = in.stage_number;
209  workset.gather_seeds = in.gather_seeds;
211 
212 
213  fm->template evaluateFields<EvalT>(workset);
214  }
215 
216  // double s = 0.;
217  // double p = 0.;
218  // fm->template analyzeGraph<EvalT>(s,p);
219  // std::cout << "Analyze Graph: " << PHX::print<EvalT>() << ",b=" << block << ", s=" << s << ", p=" << p << std::endl;
220 
221  fm->template postEvaluate<EvalT>(NULL);
222  }
223 }
224 
225 //===========================================================================
226 //===========================================================================
227 template <typename EvalT>
230 {
231  this->evaluateBCs(panzer::BCT_Neumann, in);
232 }
233 
234 //===========================================================================
235 //===========================================================================
236 template <typename EvalT>
239 {
240  this->evaluateBCs(panzer::BCT_Interface, in);
241 }
242 
243 //===========================================================================
244 //===========================================================================
245 template <typename EvalT>
248 {
249  typedef LinearObjContainer LOC;
250 
251  if(!countersInitialized_) {
252  localCounter_ = m_lin_obj_factory->buildPrimitiveGhostedLinearObjContainer();
253  globalCounter_ = m_lin_obj_factory->buildPrimitiveLinearObjContainer();
254  summedGhostedCounter_ = m_lin_obj_factory->buildPrimitiveGhostedLinearObjContainer();
255  countersInitialized_ = true;
256 
257  m_lin_obj_factory->initializeGhostedContainer(LinearObjContainer::F,*localCounter_); // store counter in F
258  m_lin_obj_factory->initializeContainer( LinearObjContainer::F,*globalCounter_); // store counter in X
259  m_lin_obj_factory->initializeGhostedContainer(LinearObjContainer::F,*summedGhostedCounter_); // store counter in X
260  }
261 
262  {
263  localCounter_->initialize();
264  summedGhostedCounter_->initialize();
265  globalCounter_->initialize();
266  }
267 
268  // apply dirichlet conditions, make sure to keep track of the local counter
269  this->evaluateBCs(panzer::BCT_Dirichlet, in,localCounter_);
270 
271  // do communication to build summed ghosted counter for dirichlet conditions
272  {
273  m_lin_obj_factory->ghostToGlobalContainer(*localCounter_,*globalCounter_,LOC::F);
274  // Here we do the reduction across all processors so that the number of times
275  // a dirichlet condition is applied is summed into the global counter
276 
277  m_lin_obj_factory->globalToGhostContainer(*globalCounter_,*summedGhostedCounter_,LOC::F);
278  // finally we move the summed global vector into a local ghosted vector
279  // so that the dirichlet conditions can be applied to both the ghosted
280  // right hand side and the ghosted matrix
281  }
282 
284  gedc.addDataObject("Residual Scatter Container",in.ghostedContainer_);
286 
287  // adjust ghosted system for boundary conditions
288  for(GlobalEvaluationDataContainer::iterator itr=gedc.begin();itr!=gedc.end();itr++) {
289 
290  if(itr->second->requiresDirichletAdjustment()) {
291  Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LinearObjContainer>(itr->second);
292  if(loc!=Teuchos::null) {
293  m_lin_obj_factory->adjustForDirichletConditions(*localCounter_,*summedGhostedCounter_,*loc);
294  }
295  else {
296  // it was not a linear object container, so if you want an adjustment it better be a GED_BCAdjustment object
297  Teuchos::RCP<GlobalEvaluationData_BCAdjustment> bc_adjust = Teuchos::rcp_dynamic_cast<GlobalEvaluationData_BCAdjustment>(itr->second,true);
298  bc_adjust->adjustForDirichletConditions(*localCounter_,*summedGhostedCounter_);
299  }
300  }
301  }
302 
303  return globalCounter_;
304 }
305 
306 //===========================================================================
307 //===========================================================================
308 template <typename EvalT>
312  const Teuchos::RCP<LinearObjContainer> preEval_loc)
313 {
314  Teuchos::RCP<panzer::WorksetContainer> wkstContainer = m_field_manager_builder->getWorksetContainer();
315 
317  ped.gedc->addDataObject("Dirichlet Counter",preEval_loc);
318  ped.gedc->addDataObject("Solution Gather Container",in.ghostedContainer_);
319  ped.gedc->addDataObject("Residual Scatter Container",in.ghostedContainer_);
323 
324  // this helps work around issues when constructing a mass
325  // matrix using an evaluation of only the transient terms.
326  // In particular, the terms associated with the dirichlet
327  // conditions.
328  double betaValue = in.beta; // default to the passed in beta
329  if(bc_type==panzer::BCT_Dirichlet && in.apply_dirichlet_beta) {
330  betaValue = in.dirichlet_beta;
331  }
332 
333  {
334  const std::map<panzer::BC,
335  std::map<unsigned,PHX::FieldManager<panzer::Traits> >,
336  panzer::LessBC>& bc_field_managers =
337  m_field_manager_builder->getBCFieldManagers();
338 
339  // Must do all neumann before all dirichlet so we need a double loop
340  // here over all bcs
341  typedef typename std::map<panzer::BC,
342  std::map<unsigned,PHX::FieldManager<panzer::Traits> >,
343  panzer::LessBC>::const_iterator bcfm_it_type;
344 
345  // loop over bcs
346  for (bcfm_it_type bcfm_it = bc_field_managers.begin();
347  bcfm_it != bc_field_managers.end(); ++bcfm_it) {
348 
349  const panzer::BC& bc = bcfm_it->first;
350  const std::map<unsigned,PHX::FieldManager<panzer::Traits> > bc_fm =
351  bcfm_it->second;
352 
354  Teuchos::RCP<const std::map<unsigned,panzer::Workset> > bc_wkst_ptr = wkstContainer->getSideWorksets(desc);
355  TEUCHOS_TEST_FOR_EXCEPTION(bc_wkst_ptr == Teuchos::null, std::logic_error,
356  "Failed to find corresponding bc workset!");
357  const std::map<unsigned,panzer::Workset>& bc_wkst = *bc_wkst_ptr;
358 
359  // Only process bcs of the appropriate type (neumann or dirichlet)
360  if (bc.bcType() == bc_type) {
361  std::ostringstream timerName;
362  timerName << "panzer::AssemblyEngine::evaluateBCs: " << bc.identifier();
363 #ifdef PANZER_TEUCHOS_TIME_MONITOR
364  auto timer1 = Teuchos::TimeMonitor::getNewTimer(timerName.str());
365  Teuchos::TimeMonitor tm1(*timer1);
366 #endif
367 
368  // Loop over local faces
369  for (std::map<unsigned,PHX::FieldManager<panzer::Traits> >::const_iterator side = bc_fm.begin(); side != bc_fm.end(); ++side) {
370  std::ostringstream timerSideName;
371  timerSideName << "panzer::AssemblyEngine::evaluateBCs: " << bc.identifier() << ", side=" << side->first;
372 #ifdef PANZER_TEUCHOS_TIME_MONITOR
373  auto timer2 = Teuchos::TimeMonitor::getNewTimer(timerSideName.str());
374  Teuchos::TimeMonitor tm2(*timer2);
375 #endif
376 
377  // extract field manager for this side
378  unsigned local_side_index = side->first;
379  PHX::FieldManager<panzer::Traits>& local_side_fm =
380  const_cast<PHX::FieldManager<panzer::Traits>& >(side->second);
381 
382  // extract workset for this side: only one workset per face
383  std::map<unsigned,panzer::Workset>::const_iterator wkst_it =
384  bc_wkst.find(local_side_index);
385 
386  TEUCHOS_TEST_FOR_EXCEPTION(wkst_it == bc_wkst.end(), std::logic_error,
387  "Failed to find corresponding bc workset side!");
388 
389  panzer::Workset& workset =
390  const_cast<panzer::Workset&>(wkst_it->second);
391 
392  // run prevaluate
393  local_side_fm.template preEvaluate<EvalT>(ped);
394 
395  // build and evaluate fields for the workset: only one workset per face
396  workset.alpha = in.alpha;
397  workset.beta = betaValue;
398  workset.time = in.time;
399  workset.gather_seeds = in.gather_seeds;
400  workset.evaluate_transient_terms = in.evaluate_transient_terms;
401 
402  local_side_fm.template evaluateFields<EvalT>(workset);
403 
404  // run postevaluate for consistency
405  local_side_fm.template postEvaluate<EvalT>(NULL);
406 
407  }
408  }
409  }
410  }
411 
412 }
413 
414 #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:74
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:257
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:186
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:332
Stores input information for a boundary condition.
Definition: Panzer_BC.hpp:81
Teuchos::RCP< LinearObjContainer > evaluateOnlyDirichletBCs(const panzer::AssemblyEngineInArgs &input_arguments)
void evaluateNeumannBCs(const panzer::AssemblyEngineInArgs &input_arguments)