Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_STK_ExodusReaderFactory.cpp
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 
44 #include <Teuchos_TimeMonitor.hpp>
45 #include <PanzerAdaptersSTK_config.hpp>
46 
48 #include "Panzer_STK_Interface.hpp"
49 
50 #ifdef PANZER_HAVE_IOSS
51 
52 #include <Ionit_Initializer.h>
53 #include <Ioss_ElementBlock.h>
54 #include <Ioss_Region.h>
55 #include <GetBuckets.hpp>
56 #include <stk_io/StkMeshIoBroker.hpp>
57 #include <stk_io/IossBridge.hpp>
58 #include <stk_mesh/base/FieldParallel.hpp>
59 
60 #include "Teuchos_StandardParameterEntryValidators.hpp"
61 
62 namespace panzer_stk {
63 
64 int getMeshDimension(const std::string & meshStr,
65  stk::ParallelMachine parallelMach,
66  const bool isExodus)
67 {
68  stk::io::StkMeshIoBroker meshData(parallelMach);
69  meshData.property_add(Ioss::Property("LOWER_CASE_VARIABLE_NAMES", false));
70  if (isExodus)
71  meshData.add_mesh_database(meshStr, "exodusII", stk::io::READ_MESH);
72  else
73  meshData.add_mesh_database(meshStr, "pamgen", stk::io::READ_MESH);
74  meshData.create_input_mesh();
75  return Teuchos::as<int>(meshData.meta_data_rcp()->spatial_dimension());
76 }
77 
78 STK_ExodusReaderFactory::STK_ExodusReaderFactory()
79  : fileName_(""), restartIndex_(0), isExodus_(true), userMeshScaling_(false), meshScaleFactor_(0.0),
80  levelsOfRefinement_(0)
81 { }
82 
83 STK_ExodusReaderFactory::STK_ExodusReaderFactory(const std::string & fileName,
84  const int restartIndex,
85  const bool isExodus)
86  : fileName_(fileName), restartIndex_(restartIndex), isExodus_(isExodus), userMeshScaling_(false), meshScaleFactor_(0.0),
87  levelsOfRefinement_(0)
88 { }
89 
90 Teuchos::RCP<STK_Interface> STK_ExodusReaderFactory::buildMesh(stk::ParallelMachine parallelMach) const
91 {
92  PANZER_FUNC_TIME_MONITOR("panzer::STK_ExodusReaderFactory::buildMesh()");
93 
94  using Teuchos::RCP;
95  using Teuchos::rcp;
96 
97  RCP<STK_Interface> mesh = buildUncommitedMesh(parallelMach);
98 
99  // in here you would add your fields...but it is better to use
100  // the two step construction
101 
102  // this calls commit on meta data
103  const bool buildRefinementSupport = levelsOfRefinement_ > 0 ? true : false;
104  mesh->initialize(parallelMach,false,buildRefinementSupport);
105 
106  completeMeshConstruction(*mesh,parallelMach);
107 
108  return mesh;
109 }
110 
115 Teuchos::RCP<STK_Interface> STK_ExodusReaderFactory::buildUncommitedMesh(stk::ParallelMachine parallelMach) const
116 {
117  PANZER_FUNC_TIME_MONITOR("panzer::STK_ExodusReaderFactory::buildUncomittedMesh()");
118 
119  using Teuchos::RCP;
120  using Teuchos::rcp;
121 
122  // read in meta data
123  stk::io::StkMeshIoBroker* meshData = new stk::io::StkMeshIoBroker(parallelMach);
124  meshData->property_add(Ioss::Property("LOWER_CASE_VARIABLE_NAMES", false));
125 
126  // add in "FAMILY_TREE" entity for doing refinement
127  std::vector<std::string> entity_rank_names = stk::mesh::entity_rank_names();
128  entity_rank_names.push_back("FAMILY_TREE");
129  meshData->set_rank_name_vector(entity_rank_names);
130 
131  if (isExodus_)
132  meshData->add_mesh_database(fileName_, "exodusII", stk::io::READ_MESH);
133  else
134  meshData->add_mesh_database(fileName_, "pamgen", stk::io::READ_MESH);
135 
136  meshData->create_input_mesh();
137  RCP<stk::mesh::MetaData> metaData = meshData->meta_data_rcp();
138 
139  RCP<STK_Interface> mesh = rcp(new STK_Interface(metaData));
140  mesh->initializeFromMetaData();
141  mesh->instantiateBulkData(parallelMach);
142  meshData->set_bulk_data(mesh->getBulkData());
143 
144  // read in other transient fields, these will be useful later when
145  // trying to read other fields for use in solve
146  meshData->add_all_mesh_fields_as_input_fields();
147 
148  // store mesh data pointer for later use in initializing
149  // bulk data
150  mesh->getMetaData()->declare_attribute_with_delete(meshData);
151 
152  // build element blocks
153  registerElementBlocks(*mesh,*meshData);
154  registerSidesets(*mesh);
155  registerNodesets(*mesh);
156 
157  mesh->addPeriodicBCs(periodicBCVec_);
158 
159  return mesh;
160 }
161 
162 void STK_ExodusReaderFactory::completeMeshConstruction(STK_Interface & mesh,stk::ParallelMachine parallelMach) const
163 {
164  PANZER_FUNC_TIME_MONITOR("panzer::STK_ExodusReaderFactory::completeMeshConstruction()");
165 
166  using Teuchos::RCP;
167  using Teuchos::rcp;
168 
169 
170  if(not mesh.isInitialized()) {
171  const bool buildRefinementSupport = levelsOfRefinement_ > 0 ? true : false;
172  mesh.initialize(parallelMach,true,buildRefinementSupport);
173  }
174 
175  // grab mesh data pointer to build the bulk data
176  stk::mesh::MetaData & metaData = *mesh.getMetaData();
177  stk::mesh::BulkData & bulkData = *mesh.getBulkData();
178  stk::io::StkMeshIoBroker * meshData =
179  const_cast<stk::io::StkMeshIoBroker *>(metaData.get_attribute<stk::io::StkMeshIoBroker>());
180  // if const_cast is wrong ... why does it feel so right?
181  // I believe this is safe since we are basically hiding this object under the covers
182  // until the mesh construction can be completed...below I cleanup the object myself.
183  TEUCHOS_ASSERT(metaData.remove_attribute(meshData));
184  // remove the MeshData attribute
185 
186  // build mesh bulk data
187  meshData->populate_bulk_data();
188 
189  const bool deleteParentElements = true;
190  if (levelsOfRefinement_ > 0)
191  mesh.refineMesh(levelsOfRefinement_,deleteParentElements);
192 
193  // The following section of code is applicable if mesh scaling is
194  // turned on from the input file.
195  if (userMeshScaling_)
196  {
197  stk::mesh::Field<double,stk::mesh::Cartesian>* coord_field =
198  metaData.get_field<stk::mesh::Field<double, stk::mesh::Cartesian> >(stk::topology::NODE_RANK, "coordinates");
199 
200  stk::mesh::Selector select_all_local = metaData.locally_owned_part() | metaData.globally_shared_part();
201  stk::mesh::BucketVector const& my_node_buckets = bulkData.get_buckets(stk::topology::NODE_RANK, select_all_local);
202 
203  int mesh_dim = mesh.getDimension();
204 
205  // Scale the mesh
206  const double inv_msf = 1.0/meshScaleFactor_;
207  for (size_t i=0; i < my_node_buckets.size(); ++i)
208  {
209  stk::mesh::Bucket& b = *(my_node_buckets[i]);
210  double* coordinate_data = field_data( *coord_field, b );
211 
212  for (size_t j=0; j < b.size(); ++j) {
213  for (int k=0; k < mesh_dim; ++k) {
214  coordinate_data[mesh_dim*j + k] *= inv_msf;
215  }
216  }
217  }
218  }
219 
220  // put in a negative index and (like python) the restart will be from the back
221  // (-1 is the last time step)
222  int restartIndex = restartIndex_;
223  if(restartIndex<0) {
224  std::pair<int,double> lastTimeStep = meshData->get_input_io_region()->get_max_time();
225  restartIndex = 1+restartIndex+lastTimeStep.first;
226  }
227 
228  // populate mesh fields with specific index
229  meshData->read_defined_input_fields(restartIndex);
230 
231  mesh.buildSubcells();
232  mesh.buildLocalElementIDs();
233 
234  if (userMeshScaling_) {
235  stk::mesh::Field<double,stk::mesh::Cartesian>* coord_field =
236  metaData.get_field<stk::mesh::Field<double, stk::mesh::Cartesian> >(stk::topology::NODE_RANK, "coordinates");
237  std::vector< const stk::mesh::FieldBase *> fields;
238  fields.push_back(coord_field);
239 
240  stk::mesh::communicate_field_data(bulkData, fields);
241  }
242 
243  if(restartIndex>0) // process_input_request is a no-op if restartIndex<=0 ... thus there would be no inital time
244  mesh.setInitialStateTime(meshData->get_input_io_region()->get_state_time(restartIndex));
245  else
246  mesh.setInitialStateTime(0.0); // no initial time to speak, might as well use 0.0
247 
248  // clean up mesh data object
249  delete meshData;
250 
251  // calls Stk_MeshFactory::rebalance
252  this->rebalance(mesh);
253 }
254 
256 void STK_ExodusReaderFactory::setParameterList(const Teuchos::RCP<Teuchos::ParameterList> & paramList)
257 {
258  TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(!paramList->isParameter("File Name"),
260  "Error, the parameter {name=\"File Name\","
261  "type=\"string\""
262  "\nis required in parameter (sub)list \""<< paramList->name() <<"\"."
263  "\n\nThe parsed parameter parameter list is: \n" << paramList->currentParametersString()
264  );
265 
266  // Set default values here. Not all the params should be set so this
267  // has to be done manually as opposed to using
268  // validateParametersAndSetDefaults().
269  if(!paramList->isParameter("Restart Index"))
270  paramList->set<int>("Restart Index", -1);
271 
272  if(!paramList->isParameter("File Type"))
273  paramList->set("File Type", "Exodus");
274 
275  if(!paramList->isSublist("Periodic BCs"))
276  paramList->sublist("Periodic BCs");
277 
278  Teuchos::ParameterList& p_bcs = paramList->sublist("Periodic BCs");
279  if (!p_bcs.isParameter("Count"))
280  p_bcs.set<int>("Count", 0);
281 
282  if(!paramList->isParameter("Levels of Uniform Refinement"))
283  paramList->set<int>("Levels of Uniform Refinement", 0);
284 
285  paramList->validateParameters(*getValidParameters(),0);
286 
287  setMyParamList(paramList);
288 
289  fileName_ = paramList->get<std::string>("File Name");
290 
291  restartIndex_ = paramList->get<int>("Restart Index");
292 
293  {
294  const auto fileType = paramList->get<std::string>("File Type");
295  isExodus_ = fileType == "Exodus";
296  }
297 
298  // get any mesh scale factor
299  if (paramList->isParameter("Scale Factor"))
300  {
301  meshScaleFactor_ = paramList->get<double>("Scale Factor");
302  userMeshScaling_ = true;
303  }
304 
305  // read in periodic boundary conditions
306  parsePeriodicBCList(Teuchos::rcpFromRef(paramList->sublist("Periodic BCs")),periodicBCVec_);
307 
308  levelsOfRefinement_ = paramList->get<int>("Levels of Uniform Refinement");
309 }
310 
312 Teuchos::RCP<const Teuchos::ParameterList> STK_ExodusReaderFactory::getValidParameters() const
313 {
314  static Teuchos::RCP<Teuchos::ParameterList> validParams;
315 
316  if(validParams==Teuchos::null) {
317  validParams = Teuchos::rcp(new Teuchos::ParameterList);
318  validParams->set<std::string>("File Name","<file name not set>","Name of exodus file to be read",
320 
321  validParams->set<int>("Restart Index",-1,"Index of solution to read in",
322  Teuchos::rcp(new Teuchos::AnyNumberParameterEntryValidator(Teuchos::AnyNumberParameterEntryValidator::PREFER_INT,Teuchos::AnyNumberParameterEntryValidator::AcceptedTypes(true))));
323 
324  Teuchos::setStringToIntegralParameter<int>("File Type",
325  "Exodus",
326  "Choose input file type - either \"Exodus\" or \"Pamgen\"",
327  Teuchos::tuple<std::string>("Exodus","Pamgen"),
328  validParams.get()
329  );
330 
331  validParams->set<double>("Scale Factor", 1.0, "Scale factor to apply to mesh after read",
332  Teuchos::rcp(new Teuchos::AnyNumberParameterEntryValidator(Teuchos::AnyNumberParameterEntryValidator::PREFER_DOUBLE,Teuchos::AnyNumberParameterEntryValidator::AcceptedTypes(true))));
333 
334  Teuchos::ParameterList & bcs = validParams->sublist("Periodic BCs");
335  bcs.set<int>("Count",0); // no default periodic boundary conditions
336 
337  validParams->set("Levels of Uniform Refinement",0,"Number of levels of inline uniform mesh refinement");
338  }
339 
340  return validParams.getConst();
341 }
342 
343 void STK_ExodusReaderFactory::registerElementBlocks(STK_Interface & mesh,stk::io::StkMeshIoBroker & meshData) const
344 {
345  using Teuchos::RCP;
346 
347  RCP<stk::mesh::MetaData> femMetaData = mesh.getMetaData();
348 
349  // here we use the Ioss interface because they don't add
350  // "bonus" element blocks and its easier to determine
351  // "real" element blocks versus STK-only blocks
352  const Ioss::ElementBlockContainer & elem_blocks = meshData.get_input_io_region()->get_element_blocks();
353  for(Ioss::ElementBlockContainer::const_iterator itr=elem_blocks.begin();itr!=elem_blocks.end();++itr) {
354  Ioss::GroupingEntity * entity = *itr;
355  const std::string & name = entity->name();
356 
357  const stk::mesh::Part * part = femMetaData->get_part(name);
358  shards::CellTopology cellTopo = stk::mesh::get_cell_topology(femMetaData->get_topology(*part));
359  const CellTopologyData * ct = cellTopo.getCellTopologyData();
360 
361  TEUCHOS_ASSERT(ct!=0);
362  mesh.addElementBlock(part->name(),ct);
363  }
364 }
365 
366 template <typename SetType>
367 void buildSetNames(const SetType & setData,std::vector<std::string> & names)
368 {
369  // pull out all names for this set
370  for(typename SetType::const_iterator itr=setData.begin();itr!=setData.end();++itr) {
371  Ioss::GroupingEntity * entity = *itr;
372  names.push_back(entity->name());
373  }
374 }
375 
376 void STK_ExodusReaderFactory::registerSidesets(STK_Interface & mesh) const
377 {
378  using Teuchos::RCP;
379 
380  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
381  const stk::mesh::PartVector & parts = metaData->get_parts();
382 
383  stk::mesh::PartVector::const_iterator partItr;
384  for(partItr=parts.begin();partItr!=parts.end();++partItr) {
385  const stk::mesh::Part * part = *partItr;
386  const stk::mesh::PartVector & subsets = part->subsets();
387  shards::CellTopology cellTopo = stk::mesh::get_cell_topology(metaData->get_topology(*part));
388  const CellTopologyData * ct = cellTopo.getCellTopologyData();
389 
390  // if a side part ==> this is a sideset: now storage is recursive
391  // on part contains all sub parts with consistent topology
392  if(part->primary_entity_rank()==mesh.getSideRank() && ct==0 && subsets.size()>0) {
393  TEUCHOS_TEST_FOR_EXCEPTION(subsets.size()!=1,std::runtime_error,
394  "STK_ExodusReaderFactory::registerSidesets error - part \"" << part->name() <<
395  "\" has more than one subset");
396 
397  // grab cell topology and name of subset part
398  const stk::mesh::Part * ss_part = subsets[0];
399  shards::CellTopology ss_cellTopo = stk::mesh::get_cell_topology(metaData->get_topology(*ss_part));
400  const CellTopologyData * ss_ct = ss_cellTopo.getCellTopologyData();
401 
402  // only add subset parts that have no topology
403  if(ss_ct!=0)
404  mesh.addSideset(part->name(),ss_ct);
405  }
406  }
407 }
408 
409 void STK_ExodusReaderFactory::registerNodesets(STK_Interface & mesh) const
410 {
411  using Teuchos::RCP;
412 
413  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
414  const stk::mesh::PartVector & parts = metaData->get_parts();
415 
416  stk::mesh::PartVector::const_iterator partItr;
417  for(partItr=parts.begin();partItr!=parts.end();++partItr) {
418  const stk::mesh::Part * part = *partItr;
419  shards::CellTopology cellTopo = stk::mesh::get_cell_topology(metaData->get_topology(*part));
420  const CellTopologyData * ct = cellTopo.getCellTopologyData();
421 
422  // if a side part ==> this is a sideset: now storage is recursive
423  // on part contains all sub parts with consistent topology
424  if(part->primary_entity_rank()==mesh.getNodeRank() && ct==0) {
425 
426  // only add subset parts that have no topology
427  if(part->name()!=STK_Interface::nodesString)
428  mesh.addNodeset(part->name());
429  }
430  }
431 }
432 
433 }
434 
435 #endif
RCP< const T > getConst() const
const std::string & name() const
std::string currentParametersString() const
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
T * get() const
static const std::string nodesString
bool isParameter(const std::string &name) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
bool isSublist(const std::string &name) const
void validateParameters(ParameterList const &validParamList, int const depth=1000, EValidateUsed const validateUsed=VALIDATE_USED_ENABLED, EValidateDefaults const validateDefaults=VALIDATE_DEFAULTS_ENABLED) const
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(throw_exception_test, Exception, msg)