Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_InitialCondition_Builder.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 
12 
13 #include "Teuchos_Assert.hpp"
14 
15 #include "Panzer_EquationSet_DefaultImpl.hpp"
20 
21 namespace panzer {
22 
23 void
25  const std::vector<Teuchos::RCP<panzer::PhysicsBlock> >& physicsBlocks,
27  const Teuchos::ParameterList& ic_block_closure_models,
29  const Teuchos::ParameterList& user_data,
30  const bool write_graphviz_file,
31  const std::string& graphviz_file_prefix,
32  std::map< std::string, Teuchos::RCP< PHX::FieldManager<panzer::Traits> > >& phx_ic_field_managers)
33 {
34  std::vector<Teuchos::RCP<panzer::PhysicsBlock> >::const_iterator blkItr;
35  for (blkItr=physicsBlocks.begin();blkItr!=physicsBlocks.end();++blkItr) {
37  std::string blockId = pb->elementBlockID();
38 
39  // build a field manager object
42 
43  // Choose model sublist for this element block
44  std::string closure_model_name = "";
45  if (ic_block_closure_models.isSublist(blockId))
46  closure_model_name = blockId;
47  else if (ic_block_closure_models.isSublist("Default"))
48  closure_model_name = "Default";
49  else
50  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Failed to find initial condition for element block \"" << blockId
51  << "\". You must provide an initial condition for each element block or set a default!"
52  << ic_block_closure_models);
53 
54  // Only the residual is used by initial conditions
55  std::vector<bool> active_evaluation_types(Sacado::mpl::size<panzer::Traits::EvalTypes>::value,false);
56  int residual_index = Sacado::mpl::find<panzer::Traits::EvalTypes,panzer::Traits::Residual>::value;
57  active_evaluation_types[residual_index] = true;
58  pb->setActiveEvaluationTypes(active_evaluation_types);
59 
60  // use the physics block to register evaluators
61  pb->buildAndRegisterInitialConditionEvaluators(*fm, cm_factory, closure_model_name, ic_block_closure_models, lo_factory, user_data);
62 
64 
65  // build the setup data using passed in information
66  Traits::SD setupData;
67  const WorksetDescriptor wd = blockDescriptor(blockId);
68  setupData.worksets_ = wkstContainer.getWorksets(wd);
69  setupData.orientations_ = wkstContainer.getOrientations();
70 
71  int i=0;
72  for (auto eval_type=fm->begin(); eval_type != fm->end(); ++eval_type,++i) {
73  if (active_evaluation_types[i])
74  eval_type->postRegistrationSetup(setupData,*fm,false,false,nullptr);
75  }
76 
77  phx_ic_field_managers[blockId] = fm;
78 
79  if (write_graphviz_file)
80  fm->writeGraphvizFile(graphviz_file_prefix+"_IC_"+blockId);
81  }
82 }
83 
84 void
86  const std::vector<Teuchos::RCP<panzer::PhysicsBlock> >& physicsBlocks,
88  const Teuchos::ParameterList& closure_models,
89  const Teuchos::ParameterList& ic_block_closure_models,
91  const Teuchos::ParameterList& user_data,
92  const bool write_graphviz_file,
93  const std::string& graphviz_file_prefix,
94  std::map< std::string, Teuchos::RCP< PHX::FieldManager<panzer::Traits> > >& phx_ic_field_managers)
95 {
96  std::vector<Teuchos::RCP<panzer::PhysicsBlock> >::const_iterator blkItr;
97  for (blkItr=physicsBlocks.begin();blkItr!=physicsBlocks.end();++blkItr) {
99  std::string blockId = pb->elementBlockID();
100 
101  // build a field manager object
104 
105  // Choose model sublist for this element block
106  std::string closure_model_name = "";
107  if (ic_block_closure_models.isSublist(blockId))
108  closure_model_name = blockId;
109  else if (ic_block_closure_models.isSublist("Default"))
110  closure_model_name = "Default";
111  else
112  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Failed to find initial condition for element block \"" << blockId
113  << "\". You must provide an initial condition for each element block or set a default!"
114  << ic_block_closure_models);
115 
116  // Only the residual is used by initial conditions
117  std::vector<bool> active_evaluation_types(Sacado::mpl::size<panzer::Traits::EvalTypes>::value,false);
118  int residual_index = Sacado::mpl::find<panzer::Traits::EvalTypes,panzer::Traits::Residual>::value;
119  active_evaluation_types[residual_index] = true;
120  pb->setActiveEvaluationTypes(active_evaluation_types);
121 
122  // build and register all closure models
123  pb->buildAndRegisterClosureModelEvaluators(*fm,cm_factory,closure_models,user_data);
124 
125  // use the physics block to register evaluators
126  pb->buildAndRegisterInitialConditionEvaluators(*fm, cm_factory, closure_model_name, ic_block_closure_models, lo_factory, user_data);
127 
129 
130  // build the setup data using passed in information
131  Traits::SD setupData;
132  const WorksetDescriptor wd = blockDescriptor(blockId);
133  setupData.worksets_ = wkstContainer.getWorksets(wd);
134  setupData.orientations_ = wkstContainer.getOrientations();
135 
136  int i=0;
137  for (auto eval_type=fm->begin(); eval_type != fm->end(); ++eval_type,++i) {
138  if (active_evaluation_types[i])
139  eval_type->postRegistrationSetup(setupData,*fm,false,false,nullptr);
140  }
141 
142  phx_ic_field_managers[blockId] = fm;
143 
144  if (write_graphviz_file)
145  fm->writeGraphvizFile(graphviz_file_prefix+"_IC_"+blockId);
146  }
147 }
148 
149 void
151  const std::map< std::string,Teuchos::RCP< PHX::FieldManager<panzer::Traits> > >& phx_ic_field_managers,
154  const double time_stamp)
155 {
156  typedef LinearObjContainer LOC;
158 
159  // allocate a ghosted container for the initial condition
160  Teuchos::RCP<LOC> ghostedloc = lo_factory.buildGhostedLinearObjContainer();
161  lo_factory.initializeGhostedContainer(LOC::X,*ghostedloc);
162 
163  // allocate a counter to keep track of where this processor set initial conditions
165  Teuchos::RCP<LOC> globalCounter = lo_factory.buildPrimitiveLinearObjContainer();
166  Teuchos::RCP<LOC> summedGhostedCounter = lo_factory.buildPrimitiveGhostedLinearObjContainer();
167 
168  lo_factory.initializeGhostedContainer(LOC::F,*localCounter); // store counter in F
169  localCounter->initialize();
170 
171  ped.gedc->addDataObject("Residual Scatter Container",ghostedloc);
172  ped.gedc->addDataObject("Dirichlet Counter",localCounter);
173  ped.first_sensitivities_name = "";
174 
175  for(std::map< std::string,Teuchos::RCP< PHX::FieldManager<panzer::Traits> > >::const_iterator itr=phx_ic_field_managers.begin();
176  itr!=phx_ic_field_managers.end();++itr) {
177  std::string blockId = itr->first;
179 
180  fm->preEvaluate<panzer::Traits::Residual>(ped);
181 
182  // Loop over worksets in this element block
183  const WorksetDescriptor wd = blockDescriptor(blockId);
184  std::vector<panzer::Workset>& w = *wkstContainer.getWorksets(wd);
185  for (std::size_t i = 0; i < w.size(); ++i) {
186  panzer::Workset& workset = w[i];
187  workset.time = time_stamp;
188 
189  fm->evaluateFields<panzer::Traits::Residual>(workset);
190  }
191  }
192 
193  lo_factory.initializeGhostedContainer(LOC::F,*summedGhostedCounter); // store counter in F
194  summedGhostedCounter->initialize();
195 
196  // do communication to build summed ghosted counter for dirichlet conditions
197  {
198  lo_factory.initializeContainer(LOC::F,*globalCounter); // store counter in F
199  globalCounter->initialize();
200  lo_factory.ghostToGlobalContainer(*localCounter,*globalCounter,LOC::F);
201  // Here we do the reduction across all processors so that the number of times
202  // a dirichlet condition is applied is summed into the global counter
203 
204  lo_factory.globalToGhostContainer(*globalCounter,*summedGhostedCounter,LOC::F);
205  // finally we move the summed global vector into a local ghosted vector
206  // so that the dirichlet conditions can be applied to both the ghosted
207  // right hand side and the ghosted matrix
208  }
209 
211  gedc.addDataObject("Residual Scatter Container",ghostedloc);
212 
213  // adjust ghosted system for boundary conditions
214  for(GlobalEvaluationDataContainer::iterator itr=gedc.begin();itr!=gedc.end();itr++) {
215  Teuchos::RCP<LOC> loc2 = Teuchos::rcp_dynamic_cast<LOC>(itr->second);
216  if(loc2!=Teuchos::null) {
217  bool zeroVectorRows = false;
218  bool adjustX = true;
219  lo_factory.adjustForDirichletConditions(*localCounter,*summedGhostedCounter,*loc2, zeroVectorRows, adjustX);
220  }
221  }
222 
223  // gather the ghosted solution back into the global container, which performs the sum
224  lo_factory.ghostToGlobalContainer(*ghostedloc,*loc,LOC::X);
225 }
226 
227 // This is an anonymous namespace that hides a few helper classes for the control
228 // initial condition construction. In particual an IC Equation set is defined that
229 // is useful for building initial condition vectors.
230 namespace {
231 
232 template <typename EvalT>
233 class EquationSet_IC : public EquationSet_DefaultImpl<EvalT> {
234 public:
235 
239  EquationSet_IC(const Teuchos::RCP<Teuchos::ParameterList>& params,
240  const int& default_integration_order,
241  const CellData& cell_data,
242  const Teuchos::RCP<GlobalData>& global_data,
243  const bool build_transient_support);
244 
247  void buildAndRegisterEquationSetEvaluators(PHX::FieldManager<Traits>& /* fm */,
248  const FieldLibrary& /* field_library */,
249  const Teuchos::ParameterList& /* user_data */) const {}
250 
251 };
252 
253 // ***********************************************************************
254 template <typename EvalT>
255 EquationSet_IC<EvalT>::
256 EquationSet_IC(const Teuchos::RCP<Teuchos::ParameterList>& params,
257  const int& default_integration_order,
258  const CellData& cell_data,
259  const Teuchos::RCP<GlobalData>& global_data,
260  const bool build_transient_support) :
261  EquationSet_DefaultImpl<EvalT>(params, default_integration_order, cell_data, global_data, build_transient_support )
262 {
263  // ********************
264  // Validate and parse parameter list
265  // ********************
266  Teuchos::ParameterList valid_parameters_sublist;
267  valid_parameters_sublist.set("Basis Type","HGrad","Type of Basis to use");
268  valid_parameters_sublist.set("Basis Order",1,"Order of the basis");
269 
270  for(auto itr=params->begin();itr!=params->end();++itr) {
271 
272  const std::string field = params->name(itr);
273  const Teuchos::ParameterEntry & entry = params->entry(itr);
274 
275  // only process lists
276  if(!entry.isList()) continue;
277 
278  Teuchos::ParameterList & basisPL = entry.getValue((Teuchos::ParameterList *) 0);
279  basisPL.validateParametersAndSetDefaults(valid_parameters_sublist);
280 
281  std::string basis_type = basisPL.get<std::string>("Basis Type");
282  int basis_order = basisPL.get<int>("Basis Order");
283 
284  this->addDOF(field,basis_type,basis_order,default_integration_order);
285  }
286 
287  this->addClosureModel("");
288 
289  this->setupDOFs();
290 }
291 
292 PANZER_DECLARE_EQSET_TEMPLATE_BUILDER(EquationSet_IC, EquationSet_IC)
293 
294 // A user written factory that creates each equation set. The key member here
295 // is buildEquationSet
296 class IC_EquationSetFactory : public EquationSetFactory {
297 public:
298 
300  buildEquationSet(const Teuchos::RCP<Teuchos::ParameterList>& params,
301  const int& default_integration_order,
302  const CellData& cell_data,
303  const Teuchos::RCP<GlobalData>& global_data,
304  const bool build_transient_support) const
305  {
307  Teuchos::rcp(new EquationSet_TemplateManager<Traits>);
308 
309  bool found = false; // this is used by PANZER_BUILD_EQSET_OBJECTS
310 
311  // macro checks if(ies.name=="Poisson") then an EquationSet_Energy object is constructed
312  PANZER_BUILD_EQSET_OBJECTS("IC", EquationSet_IC)
313 
314  // make sure your equation set has been found
315  if(!found) {
316  std::string msg = "Error - the \"Equation Set\" called \"" + params->get<std::string>("Type") +
317  "\" is not a valid equation set identifier. Please supply the correct factory.\n";
318  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, msg);
319  }
320 
321  return eq_set;
322  }
323 
324 };
325 
326 } // end anonymous namespace
327 
328 void
329 setupControlInitialCondition(const std::map<std::string,Teuchos::RCP<const shards::CellTopology> > & block_ids_to_cell_topo,
330  const std::map<std::string,std::vector<ICFieldDescriptor> > & block_ids_to_fields,
331  WorksetContainer & wkstContainer,
332  const LinearObjFactory<Traits> & lof,
334  const Teuchos::ParameterList & ic_closure_models,
335  const Teuchos::ParameterList & user_data,
336  int workset_size,
337  double t0,
339 {
340  std::vector<Teuchos::RCP<PhysicsBlock> > physics_blocks;
341  buildICPhysicsBlocks(block_ids_to_cell_topo,block_ids_to_fields,workset_size,physics_blocks);
342 
343  std::map<std::string, Teuchos::RCP< PHX::FieldManager<Traits> > > phx_ic_field_managers;
345  physics_blocks,
346  cm_factory,
347  ic_closure_models,
348  lof,
349  user_data,
350  false,
351  "initial_condition_control_test",
352  phx_ic_field_managers);
353 
354 
356  Teuchos::rcp_dynamic_cast<ThyraObjContainer<double> >(loc)->set_x_th(vec);
357 
358  evaluateInitialCondition(wkstContainer, phx_ic_field_managers, loc, lof, t0);
359 }
360 
361 
362 void
363 buildICPhysicsBlocks(const std::map<std::string,Teuchos::RCP<const shards::CellTopology> > & block_ids_to_cell_topo,
364  const std::map<std::string,std::vector<ICFieldDescriptor> > & block_ids_to_fields,
365  int workset_size,
366  std::vector<Teuchos::RCP<PhysicsBlock> > & physics_blocks)
367 {
368  using Teuchos::RCP;
369  using Teuchos::rcp;
370 
371  std::map<std::string,std::string> block_ids_to_physics_ids;
372 
374 
375  for(auto itr=block_ids_to_cell_topo.begin();itr!=block_ids_to_cell_topo.end();++itr) {
376  std::string eblock = itr->first;
377  RCP<const shards::CellTopology> ct = itr->second;
378 
379  // get the field descriptor vector, check to make sure block is represented
380  auto fds_itr = block_ids_to_fields.find(eblock);
381  TEUCHOS_ASSERT(fds_itr!=block_ids_to_fields.end());
382 
383  const std::vector<ICFieldDescriptor> & fd_vec = fds_itr->second;
384 
385  std::string physics_id = "ic_"+eblock;
386  block_ids_to_physics_ids[eblock] = physics_id;
387 
388  // start building a physics block named "ic_"+eblock, with one anonymous list
389  Teuchos::ParameterList & physics_block = ipb->sublist(physics_id).sublist("");
390  physics_block.set("Type","IC"); // point IC type
391 
392  for(std::size_t i=0;i<fd_vec.size();i++) {
393  const ICFieldDescriptor & fd = fd_vec[i];
394 
395  // number the lists, these should be anonymous
396  physics_block.sublist(fd.fieldName).set("Basis Type", fd.basisName);
397  physics_block.sublist(fd.fieldName).set("Basis Order",fd.basisOrder);
398  }
399  }
400 
401  RCP<EquationSetFactory> eqset_factory = Teuchos::rcp(new IC_EquationSetFactory);
402 
404  buildPhysicsBlocks(block_ids_to_physics_ids,
405  block_ids_to_cell_topo,
406  ipb,1,workset_size,eqset_factory,gd,false,physics_blocks);
407 }
408 
409 } // end namespace panzer
void buildICPhysicsBlocks(const std::map< std::string, Teuchos::RCP< const shards::CellTopology > > &block_ids_to_cell_topo, const std::map< std::string, std::vector< ICFieldDescriptor > > &block_ids_to_fields, int workset_size, std::vector< Teuchos::RCP< PhysicsBlock > > &physics_blocks)
Teuchos::RCP< GlobalEvaluationDataContainer > gedc
const std::string & name() const
Teuchos::RCP< const std::vector< Intrepid2::Orientation > > orientations_
ConstIterator end() const
void addDataObject(const std::string &key, const Teuchos::RCP< GlobalEvaluationData > &ged)
std::unordered_map< std::string, Teuchos::RCP< GlobalEvaluationData > >::iterator iterator
T & get(const std::string &name, T def_value)
FieldManager::iterator begin()
void setupControlInitialCondition(const std::map< std::string, Teuchos::RCP< const shards::CellTopology > > &block_ids_to_cell_topo, const std::map< std::string, std::vector< ICFieldDescriptor > > &block_ids_to_fields, WorksetContainer &wkstContainer, const LinearObjFactory< Traits > &lof, const ClosureModelFactory_TemplateManager< Traits > &cm_factory, const Teuchos::ParameterList &ic_closure_models, const Teuchos::ParameterList &user_data, int workset_size, double t0, const Teuchos::RCP< Thyra::VectorBase< double > > &vec)
#define PANZER_BUILD_EQSET_OBJECTS(key, fType)
void buildAndRegisterClosureModelEvaluators(PHX::FieldManager< panzer::Traits > &fm, const panzer::ClosureModelFactory_TemplateManager< panzer::Traits > &factory, const Teuchos::ParameterList &models, const Teuchos::ParameterList &user_data) const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual void adjustForDirichletConditions(const LinearObjContainer &localBCRows, const LinearObjContainer &globalBCRows, LinearObjContainer &ghostedObjs, bool zeroVectorRows=false, bool adjustX=false) const =0
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
void buildAndRegisterInitialConditionEvaluators(PHX::FieldManager< panzer::Traits > &fm, const panzer::ClosureModelFactory_TemplateManager< panzer::Traits > &factory, const std::string &model_name, const Teuchos::ParameterList &models, const panzer::LinearObjFactory< panzer::Traits > &lof, const Teuchos::ParameterList &user_data) const
Teuchos::RCP< const std::vector< Intrepid2::Orientation > > getOrientations() const
T & getValue(T *ptr) const
Class that provides access to worksets on each element block and side set.
virtual Teuchos::RCP< LinearObjContainer > buildPrimitiveGhostedLinearObjContainer() const =0
void setActiveEvaluationTypes(const std::vector< bool > &aet)
Used to save memory by disabling unneeded evaluation types.
std::string first_sensitivities_name
virtual void initializeContainer(int, LinearObjContainer &loc) const =0
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
bool isSublist(const std::string &name) const
std::string elementBlockID() const
void buildPhysicsBlocks(const std::map< std::string, std::string > &block_ids_to_physics_ids, const std::map< std::string, Teuchos::RCP< const shards::CellTopology > > &block_ids_to_cell_topo, const Teuchos::RCP< Teuchos::ParameterList > &physics_blocks_plist, const int default_integration_order, const std::size_t workset_size, const Teuchos::RCP< const panzer::EquationSetFactory > &eqset_factory, const Teuchos::RCP< panzer::GlobalData > &global_data, const bool build_transient_support, std::vector< Teuchos::RCP< panzer::PhysicsBlock > > &physicsBlocks, const std::vector< std::string > &tangent_param_names=std::vector< std::string >())
Nonmember function for building the physics blocks from a Teuchos::ParameterList for a given list of ...
Teuchos::RCP< panzer::GlobalData > createGlobalData(bool build_default_os=true, int print_process=0)
Nonmember constructor.
Teuchos::RCP< std::vector< Workset > > getWorksets(const WorksetDescriptor &wd)
Access to volume worksets.
virtual Teuchos::RCP< LinearObjContainer > buildLinearObjContainer() const =0
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
ConstIterator begin() const
#define PANZER_DECLARE_EQSET_TEMPLATE_BUILDER(fClass, fType)
const ParameterEntry & entry(ConstIterator i) const
void activateAllEvaluationTypes()
Used to reactivate all evaluation types if some were temporarily disabled with a call to setActiveEva...
void setupInitialConditionFieldManagers(WorksetContainer &wkstContainer, const std::vector< Teuchos::RCP< panzer::PhysicsBlock > > &physicsBlocks, const panzer::ClosureModelFactory_TemplateManager< panzer::Traits > &cm_factory, const Teuchos::ParameterList &ic_block_closure_models, const panzer::LinearObjFactory< panzer::Traits > &lo_factory, const Teuchos::ParameterList &user_data, const bool write_graphviz_file, const std::string &graphviz_file_prefix, std::map< std::string, Teuchos::RCP< PHX::FieldManager< panzer::Traits > > > &phx_ic_field_managers)
Builds PHX::FieldManager objects for inital conditions and registers evaluators.
PHX::MDField< ScalarT, panzer::Cell, panzer::BASIS > field
A field to which we&#39;ll contribute, or in which we&#39;ll store, the result of computing this integral...
virtual Teuchos::RCP< LinearObjContainer > buildPrimitiveLinearObjContainer() const =0
virtual void globalToGhostContainer(const LinearObjContainer &container, LinearObjContainer &ghostContainer, int) const =0
virtual void initializeGhostedContainer(int, LinearObjContainer &loc) const =0
WorksetDescriptor blockDescriptor(const std::string &eBlock)
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
virtual Teuchos::RCP< LinearObjContainer > buildGhostedLinearObjContainer() const =0
#define TEUCHOS_ASSERT(assertion_test)
void evaluateInitialCondition(WorksetContainer &wkstContainer, const std::map< std::string, Teuchos::RCP< PHX::FieldManager< panzer::Traits > > > &phx_ic_field_managers, Teuchos::RCP< panzer::LinearObjContainer > loc, const panzer::LinearObjFactory< panzer::Traits > &lo_factory, const double time_stamp)
virtual void ghostToGlobalContainer(const LinearObjContainer &ghostContainer, LinearObjContainer &container, int) const =0
Teuchos::RCP< const std::vector< panzer::Workset > > worksets_