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 // 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 <Teuchos_TimeMonitor.hpp>
12 #include <Teuchos_RCP.hpp>
13 #include <Teuchos_RCPStdSharedPtrConversions.hpp>
14 #include <PanzerAdaptersSTK_config.hpp>
15 
17 #include "Panzer_STK_Interface.hpp"
18 
19 #ifdef PANZER_HAVE_IOSS
20 
21 #include <Ionit_Initializer.h>
22 #include <Ioss_ElementBlock.h>
23 #include <Ioss_EdgeBlock.h>
24 #include <Ioss_FaceBlock.h>
25 #include <Ioss_Region.h>
26 #include <stk_mesh/base/GetBuckets.hpp>
27 #include <stk_io/StkMeshIoBroker.hpp>
28 #include <stk_io/IossBridge.hpp>
29 #include <stk_mesh/base/FieldParallel.hpp>
30 
31 #ifdef PANZER_HAVE_UMR
32 #include <Ioumr_DatabaseIO.hpp>
33 #endif
34 
35 #include "Teuchos_StandardParameterEntryValidators.hpp"
36 
37 namespace panzer_stk {
38 
39 int getMeshDimension(const std::string & meshStr,
40  stk::ParallelMachine parallelMach,
41  const std::string & typeStr)
42 {
43  stk::io::StkMeshIoBroker meshData(parallelMach);
44  meshData.use_simple_fields();
45  meshData.property_add(Ioss::Property("LOWER_CASE_VARIABLE_NAMES", false));
46  meshData.add_mesh_database(meshStr, fileTypeToIOSSType(typeStr), stk::io::READ_MESH);
47  meshData.create_input_mesh();
48  return Teuchos::as<int>(meshData.meta_data_ptr()->spatial_dimension());
49 }
50 
51 std::string fileTypeToIOSSType(const std::string & fileType)
52 {
53  std::string IOSSType;
54  if (fileType=="Exodus")
55  IOSSType = "exodusii";
56 #ifdef PANZER_HAVE_UMR
57  else if (fileType=="Exodus Refinement")
58  IOSSType = "Refinement";
59 #endif
60  else if (fileType=="Pamgen")
61  IOSSType = "pamgen";
62 
63  return IOSSType;
64 }
65 
66 STK_ExodusReaderFactory::STK_ExodusReaderFactory()
67  : fileName_(""), fileType_(""), restartIndex_(0), userMeshScaling_(false), keepPerceptData_(false),
68  keepPerceptParentElements_(false), rebalancing_("default"),
69 meshScaleFactor_(0.0), levelsOfRefinement_(0),
70  createEdgeBlocks_(false), createFaceBlocks_(false), geometryName_("")
71 { }
72 
73 STK_ExodusReaderFactory::STK_ExodusReaderFactory(const std::string & fileName,
74  const int restartIndex)
75  : fileName_(fileName), fileType_("Exodus"), restartIndex_(restartIndex), userMeshScaling_(false),
76  keepPerceptData_(false), keepPerceptParentElements_(false), rebalancing_("default"),
77  meshScaleFactor_(0.0), levelsOfRefinement_(0), createEdgeBlocks_(false), createFaceBlocks_(false), geometryName_("")
78 { }
79 
80 Teuchos::RCP<STK_Interface> STK_ExodusReaderFactory::buildMesh(stk::ParallelMachine parallelMach) const
81 {
82  PANZER_FUNC_TIME_MONITOR("panzer::STK_ExodusReaderFactory::buildMesh()");
83 
84  using Teuchos::RCP;
85  using Teuchos::rcp;
86 
87  RCP<STK_Interface> mesh = buildUncommitedMesh(parallelMach);
88 
89  // in here you would add your fields...but it is better to use
90  // the two step construction
91 
92  // this calls commit on meta data
93  mesh->initialize(parallelMach,false,doPerceptRefinement());
94 
95  completeMeshConstruction(*mesh,parallelMach);
96 
97  return mesh;
98 }
99 
104 Teuchos::RCP<STK_Interface> STK_ExodusReaderFactory::buildUncommitedMesh(stk::ParallelMachine parallelMach) const
105 {
106  PANZER_FUNC_TIME_MONITOR("panzer::STK_ExodusReaderFactory::buildUncomittedMesh()");
107 
108  using Teuchos::RCP;
109  using Teuchos::rcp;
110 
111  // read in meta data
112  stk::io::StkMeshIoBroker* meshData = new stk::io::StkMeshIoBroker(parallelMach);
113  meshData->use_simple_fields();
114  meshData->property_add(Ioss::Property("LOWER_CASE_VARIABLE_NAMES", false));
115 
116  // add in "FAMILY_TREE" entity for doing refinement
117  std::vector<std::string> entity_rank_names = stk::mesh::entity_rank_names();
118  entity_rank_names.push_back("FAMILY_TREE");
119  meshData->set_rank_name_vector(entity_rank_names);
120 
121 #ifdef PANZER_HAVE_UMR
122  // this line registers Ioumr with Ioss
123  Ioumr::IOFactory::factory();
124 
125  meshData->property_add(Ioss::Property("GEOMETRY_FILE", geometryName_));
126  meshData->property_add(Ioss::Property("NUMBER_REFINEMENTS", levelsOfRefinement_));
127 #endif
128 
129  meshData->add_mesh_database(fileName_, fileTypeToIOSSType(fileType_), stk::io::READ_MESH);
130 
131  meshData->create_input_mesh();
132  RCP<stk::mesh::MetaData> metaData = Teuchos::rcp(meshData->meta_data_ptr());
133 
134  RCP<STK_Interface> mesh = rcp(new STK_Interface(metaData));
135  mesh->initializeFromMetaData();
136  mesh->instantiateBulkData(parallelMach);
137  meshData->set_bulk_data(Teuchos::get_shared_ptr(mesh->getBulkData()));
138 
139  // read in other transient fields, these will be useful later when
140  // trying to read other fields for use in solve
141  meshData->add_all_mesh_fields_as_input_fields();
142 
143  // store mesh data pointer for later use in initializing
144  // bulk data
145  mesh->getMetaData()->declare_attribute_with_delete(meshData);
146 
147  // build element blocks
148  registerElementBlocks(*mesh,*meshData);
149  registerSidesets(*mesh);
150  registerNodesets(*mesh);
151 
152  if (createEdgeBlocks_) {
153  registerEdgeBlocks(*mesh,*meshData);
154  }
155  if (createFaceBlocks_ && mesh->getMetaData()->spatial_dimension() > 2) {
156  registerFaceBlocks(*mesh,*meshData);
157  }
158 
159  buildMetaData(parallelMach, *mesh);
160 
161  mesh->addPeriodicBCs(periodicBCVec_);
162  mesh->setBoundingBoxSearchFlag(useBBoxSearch_);
163 
164  return mesh;
165 }
166 
167 void STK_ExodusReaderFactory::completeMeshConstruction(STK_Interface & mesh,stk::ParallelMachine parallelMach) const
168 {
169  PANZER_FUNC_TIME_MONITOR("panzer::STK_ExodusReaderFactory::completeMeshConstruction()");
170 
171  using Teuchos::RCP;
172  using Teuchos::rcp;
173 
174 
175  if(not mesh.isInitialized()) {
176  mesh.initialize(parallelMach,true,doPerceptRefinement());
177  }
178 
179  // grab mesh data pointer to build the bulk data
180  stk::mesh::MetaData & metaData = *mesh.getMetaData();
181  stk::mesh::BulkData & bulkData = *mesh.getBulkData();
182  stk::io::StkMeshIoBroker * meshData =
183  const_cast<stk::io::StkMeshIoBroker *>(metaData.get_attribute<stk::io::StkMeshIoBroker>());
184  // if const_cast is wrong ... why does it feel so right?
185  // I believe this is safe since we are basically hiding this object under the covers
186  // until the mesh construction can be completed...below I cleanup the object myself.
187  TEUCHOS_ASSERT(metaData.remove_attribute(meshData));
188  // remove the MeshData attribute
189 
190  // build mesh bulk data
191  meshData->populate_bulk_data();
192 
193  if (doPerceptRefinement()) {
194  const bool deleteParentElements = !keepPerceptParentElements_;
195  mesh.refineMesh(levelsOfRefinement_,deleteParentElements);
196  }
197 
198  // The following section of code is applicable if mesh scaling is
199  // turned on from the input file.
200  if (userMeshScaling_)
201  {
202  stk::mesh::Field<double>* coord_field = metaData.get_field<double>(stk::topology::NODE_RANK, "coordinates");
203 
204  stk::mesh::Selector select_all_local = metaData.locally_owned_part() | metaData.globally_shared_part();
205  stk::mesh::BucketVector const& my_node_buckets = bulkData.get_buckets(stk::topology::NODE_RANK, select_all_local);
206 
207  int mesh_dim = mesh.getDimension();
208 
209  // Scale the mesh
210  const double inv_msf = 1.0/meshScaleFactor_;
211  for (size_t i=0; i < my_node_buckets.size(); ++i)
212  {
213  stk::mesh::Bucket& b = *(my_node_buckets[i]);
214  double* coordinate_data = field_data( *coord_field, b );
215 
216  for (size_t j=0; j < b.size(); ++j) {
217  for (int k=0; k < mesh_dim; ++k) {
218  coordinate_data[mesh_dim*j + k] *= inv_msf;
219  }
220  }
221  }
222  }
223 
224  // put in a negative index and (like python) the restart will be from the back
225  // (-1 is the last time step)
226  int restartIndex = restartIndex_;
227  if(restartIndex<0) {
228  std::pair<int,double> lastTimeStep = meshData->get_input_ioss_region()->get_max_time();
229  restartIndex = 1+restartIndex+lastTimeStep.first;
230  }
231 
232  // populate mesh fields with specific index
233  meshData->read_defined_input_fields(restartIndex);
234 
235  mesh.buildSubcells();
236  mesh.buildLocalElementIDs();
237 
238  mesh.beginModification();
239  if (createEdgeBlocks_) {
240  mesh.buildLocalEdgeIDs();
241  addEdgeBlocks(mesh);
242  }
243  if (createFaceBlocks_ && mesh.getMetaData()->spatial_dimension() > 2) {
244  mesh.buildLocalFaceIDs();
245  addFaceBlocks(mesh);
246  }
247  mesh.endModification();
248 
249  if (userMeshScaling_) {
250  stk::mesh::Field<double>* coord_field = metaData.get_field<double>(stk::topology::NODE_RANK, "coordinates");
251  std::vector< const stk::mesh::FieldBase *> fields;
252  fields.push_back(coord_field);
253 
254  stk::mesh::communicate_field_data(bulkData, fields);
255  }
256 
257  if(restartIndex>0) // process_input_request is a no-op if restartIndex<=0 ... thus there would be no inital time
258  mesh.setInitialStateTime(meshData->get_input_ioss_region()->get_state_time(restartIndex));
259  else
260  mesh.setInitialStateTime(0.0); // no initial time to speak, might as well use 0.0
261 
262  // clean up mesh data object
263  delete meshData;
264 
265  if(rebalancing_ == "default")
266  // calls Stk_MeshFactory::rebalance
267  this->rebalance(mesh);
268  else if(rebalancing_ != "none")
269  {
270  TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
271  "ERROR: Rebalancing was not set to a valid choice");
272  }
273 }
274 
276 void STK_ExodusReaderFactory::setParameterList(const Teuchos::RCP<Teuchos::ParameterList> & paramList)
277 {
278  TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(!paramList->isParameter("File Name"),
280  "Error, the parameter {name=\"File Name\","
281  "type=\"string\""
282  "\nis required in parameter (sub)list \""<< paramList->name() <<"\"."
283  "\n\nThe parsed parameter parameter list is: \n" << paramList->currentParametersString()
284  );
285 
286  // Set default values here. Not all the params should be set so this
287  // has to be done manually as opposed to using
288  // validateParametersAndSetDefaults().
289  if(!paramList->isParameter("Restart Index"))
290  paramList->set<int>("Restart Index", -1);
291 
292  if(!paramList->isParameter("File Type"))
293  paramList->set("File Type", "Exodus");
294 
295  if(!paramList->isSublist("Periodic BCs"))
296  paramList->sublist("Periodic BCs");
297 
298  Teuchos::ParameterList& p_bcs = paramList->sublist("Periodic BCs");
299  if (!p_bcs.isParameter("Count"))
300  p_bcs.set<int>("Count", 0);
301 
302  if(!paramList->isParameter("Levels of Uniform Refinement"))
303  paramList->set<int>("Levels of Uniform Refinement", 0);
304 
305  if(!paramList->isParameter("Keep Percept Data"))
306  paramList->set<bool>("Keep Percept Data", false);
307 
308  if(!paramList->isParameter("Keep Percept Parent Elements"))
309  paramList->set<bool>("Keep Percept Parent Elements", false);
310 
311  if(!paramList->isParameter("Rebalancing"))
312  paramList->set<std::string>("Rebalancing", "default");
313 
314  if(!paramList->isParameter("Create Edge Blocks"))
315  // default to false to prevent massive exodiff test failures
316  paramList->set<bool>("Create Edge Blocks", false);
317 
318  if(!paramList->isParameter("Create Face Blocks"))
319  // default to false to prevent massive exodiff test failures
320  paramList->set<bool>("Create Face Blocks", false);
321 
322  if(!paramList->isParameter("Geometry File Name"))
323  paramList->set("Geometry File Name", "");
324 
325  paramList->validateParameters(*getValidParameters(),0);
326 
327  setMyParamList(paramList);
328 
329  fileName_ = paramList->get<std::string>("File Name");
330 
331  geometryName_ = paramList->get<std::string>("Geometry File Name");
332 
333  restartIndex_ = paramList->get<int>("Restart Index");
334 
335  fileType_ = paramList->get<std::string>("File Type");
336 
337  // get any mesh scale factor
338  if (paramList->isParameter("Scale Factor"))
339  {
340  meshScaleFactor_ = paramList->get<double>("Scale Factor");
341  userMeshScaling_ = true;
342  }
343 
344  // read in periodic boundary conditions
345  parsePeriodicBCList(Teuchos::rcpFromRef(paramList->sublist("Periodic BCs")),periodicBCVec_,useBBoxSearch_);
346 
347  keepPerceptData_ = paramList->get<bool>("Keep Percept Data");
348 
349  keepPerceptParentElements_ = paramList->get<bool>("Keep Percept Parent Elements");
350 
351  rebalancing_ = paramList->get<std::string>("Rebalancing");
352 
353  levelsOfRefinement_ = paramList->get<int>("Levels of Uniform Refinement");
354 
355  createEdgeBlocks_ = paramList->get<bool>("Create Edge Blocks");
356  createFaceBlocks_ = paramList->get<bool>("Create Face Blocks");
357 }
358 
360 Teuchos::RCP<const Teuchos::ParameterList> STK_ExodusReaderFactory::getValidParameters() const
361 {
362  static Teuchos::RCP<Teuchos::ParameterList> validParams;
363 
364  if(validParams==Teuchos::null) {
365  validParams = Teuchos::rcp(new Teuchos::ParameterList);
366  validParams->set<std::string>("File Name","<file name not set>","Name of exodus file to be read",
368  validParams->set<std::string>("Geometry File Name","<file name not set>","Name of geometry file for refinement",
370 
371  validParams->set<int>("Restart Index",-1,"Index of solution to read in",
372  Teuchos::rcp(new Teuchos::AnyNumberParameterEntryValidator(Teuchos::AnyNumberParameterEntryValidator::PREFER_INT,Teuchos::AnyNumberParameterEntryValidator::AcceptedTypes(true))));
373 
374  validParams->set<std::string>("File Type", "Exodus",
375  "Choose input file type - either \"Exodus\", \"Exodus Refinement\" or \"Pamgen\"",
376  rcp(new Teuchos::StringValidator(Teuchos::tuple<std::string>("Exodus", "Pamgen"
377 #ifdef PANZER_HAVE_UMR
378  ,"Exodus Refinement"
379 #endif
380  ))));
381 
382  validParams->set<double>("Scale Factor", 1.0, "Scale factor to apply to mesh after read",
383  Teuchos::rcp(new Teuchos::AnyNumberParameterEntryValidator(Teuchos::AnyNumberParameterEntryValidator::PREFER_DOUBLE,Teuchos::AnyNumberParameterEntryValidator::AcceptedTypes(true))));
384 
385  Teuchos::ParameterList & bcs = validParams->sublist("Periodic BCs");
386  bcs.set<int>("Count",0); // no default periodic boundary conditions
387 
388  validParams->set("Levels of Uniform Refinement",0,"Number of levels of inline uniform mesh refinement");
389 
390  validParams->set("Keep Percept Data",false,"Keep the Percept mesh after uniform refinement is applied");
391 
392  validParams->set("Keep Percept Parent Elements",false,"Keep the parent element information in the Percept data");
393 
394  validParams->set("Rebalancing","default","The type of rebalancing to be performed on the mesh after creation (default, none)");
395 
396  // default to false for backward compatibility
397  validParams->set("Create Edge Blocks",false,"Create or copy edge blocks in the mesh");
398  validParams->set("Create Face Blocks",false,"Create or copy face blocks in the mesh");
399  }
400 
401  return validParams.getConst();
402 }
403 
404 void STK_ExodusReaderFactory::registerElementBlocks(STK_Interface & mesh,stk::io::StkMeshIoBroker & meshData) const
405 {
406  using Teuchos::RCP;
407 
408  RCP<stk::mesh::MetaData> femMetaData = mesh.getMetaData();
409 
410  // here we use the Ioss interface because they don't add
411  // "bonus" element blocks and its easier to determine
412  // "real" element blocks versus STK-only blocks
413  const Ioss::ElementBlockContainer & elem_blocks = meshData.get_input_ioss_region()->get_element_blocks();
414  for(Ioss::ElementBlockContainer::const_iterator itr=elem_blocks.begin();itr!=elem_blocks.end();++itr) {
415  Ioss::GroupingEntity * entity = *itr;
416  const std::string & name = entity->name();
417 
418  const stk::mesh::Part * part = femMetaData->get_part(name);
419  shards::CellTopology cellTopo = stk::mesh::get_cell_topology(femMetaData->get_topology(*part));
420  const CellTopologyData * ct = cellTopo.getCellTopologyData();
421 
422  TEUCHOS_ASSERT(ct!=0);
423  mesh.addElementBlock(part->name(),ct);
424 
425  if (createEdgeBlocks_) {
426  createUniqueEdgeTopologyMap(mesh, part);
427  }
428  if (createFaceBlocks_ && mesh.getMetaData()->spatial_dimension() > 2) {
429  createUniqueFaceTopologyMap(mesh, part);
430  }
431  }
432 }
433 
434 template <typename SetType>
435 void buildSetNames(const SetType & setData,std::vector<std::string> & names)
436 {
437  // pull out all names for this set
438  for(typename SetType::const_iterator itr=setData.begin();itr!=setData.end();++itr) {
439  Ioss::GroupingEntity * entity = *itr;
440  names.push_back(entity->name());
441  }
442 }
443 
444 void STK_ExodusReaderFactory::registerSidesets(STK_Interface & mesh) const
445 {
446  using Teuchos::RCP;
447 
448  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
449  const stk::mesh::PartVector & parts = metaData->get_parts();
450 
451  stk::mesh::PartVector::const_iterator partItr;
452  for(partItr=parts.begin();partItr!=parts.end();++partItr) {
453  const stk::mesh::Part * part = *partItr;
454  const stk::mesh::PartVector & subsets = part->subsets();
455  shards::CellTopology cellTopo = stk::mesh::get_cell_topology(metaData->get_topology(*part));
456  const CellTopologyData * ct = cellTopo.getCellTopologyData();
457 
458  // if a side part ==> this is a sideset: now storage is recursive
459  // on part contains all sub parts with consistent topology
460  if(part->primary_entity_rank()==mesh.getSideRank() && ct==0 && subsets.size()>0) {
461  TEUCHOS_TEST_FOR_EXCEPTION(subsets.size()!=1,std::runtime_error,
462  "STK_ExodusReaderFactory::registerSidesets error - part \"" << part->name() <<
463  "\" has more than one subset");
464 
465  // grab cell topology and name of subset part
466  const stk::mesh::Part * ss_part = subsets[0];
467  shards::CellTopology ss_cellTopo = stk::mesh::get_cell_topology(metaData->get_topology(*ss_part));
468  const CellTopologyData * ss_ct = ss_cellTopo.getCellTopologyData();
469 
470  // only add subset parts that have no topology
471  if(ss_ct!=0)
472  mesh.addSideset(part->name(),ss_ct);
473  }
474  }
475 }
476 
477 void STK_ExodusReaderFactory::registerNodesets(STK_Interface & mesh) const
478 {
479  using Teuchos::RCP;
480 
481  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
482  const stk::mesh::PartVector & parts = metaData->get_parts();
483 
484  stk::mesh::PartVector::const_iterator partItr;
485  for(partItr=parts.begin();partItr!=parts.end();++partItr) {
486  const stk::mesh::Part * part = *partItr;
487  shards::CellTopology cellTopo = stk::mesh::get_cell_topology(metaData->get_topology(*part));
488  const CellTopologyData * ct = cellTopo.getCellTopologyData();
489 
490  // if a side part ==> this is a sideset: now storage is recursive
491  // on part contains all sub parts with consistent topology
492  if(part->primary_entity_rank()==mesh.getNodeRank() && ct==0) {
493 
494  // only add subset parts that have no topology
495  if(part->name()!=STK_Interface::nodesString)
496  mesh.addNodeset(part->name());
497  }
498  }
499 }
500 
501 void STK_ExodusReaderFactory::registerEdgeBlocks(STK_Interface & mesh,stk::io::StkMeshIoBroker & meshData) const
502 {
503  using Teuchos::RCP;
504 
505  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
506 
507  /* For each edge block in the exodus file, check it's topology
508  * against the list of edge topologies for each element block.
509  * If it matches, add the edge block for that element block.
510  * This will add the edge block as a subset of the element
511  * block in the STK mesh.
512  */
513  const Ioss::EdgeBlockContainer & edge_blocks = meshData.get_input_ioss_region()->get_edge_blocks();
514  for(Ioss::EdgeBlockContainer::const_iterator ebc_iter=edge_blocks.begin();ebc_iter!=edge_blocks.end();++ebc_iter) {
515  Ioss::GroupingEntity * entity = *ebc_iter;
516  const stk::mesh::Part * edgeBlockPart = metaData->get_part(entity->name());
517  const stk::topology edgeBlockTopo = metaData->get_topology(*edgeBlockPart);
518 
519  for (auto ebuet_iter : elemBlockUniqueEdgeTopologies_) {
520  std::string elemBlockName = ebuet_iter.first;
521  std::vector<stk::topology> uniqueEdgeTopologies = ebuet_iter.second;
522 
523  auto find_result = std::find(uniqueEdgeTopologies.begin(), uniqueEdgeTopologies.end(), edgeBlockTopo);
524  if (find_result != uniqueEdgeTopologies.end()) {
525  mesh.addEdgeBlock(elemBlockName, edgeBlockPart->name(), edgeBlockTopo);
526  }
527  }
528  }
529 }
530 
531 void STK_ExodusReaderFactory::registerFaceBlocks(STK_Interface & mesh,stk::io::StkMeshIoBroker & meshData) const
532 {
533  using Teuchos::RCP;
534 
535  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
536 
537  /* For each face block in the exodus file, check it's topology
538  * against the list of face topologies for each element block.
539  * If it matches, add the face block for that element block.
540  * This will add the face block as a subset of the element
541  * block in the STK mesh.
542  */
543  const Ioss::FaceBlockContainer & face_blocks = meshData.get_input_ioss_region()->get_face_blocks();
544  for(Ioss::FaceBlockContainer::const_iterator fbc_itr=face_blocks.begin();fbc_itr!=face_blocks.end();++fbc_itr) {
545  Ioss::GroupingEntity * entity = *fbc_itr;
546  const stk::mesh::Part * faceBlockPart = metaData->get_part(entity->name());
547  const stk::topology faceBlockTopo = metaData->get_topology(*faceBlockPart);
548 
549  for (auto ebuft_iter : elemBlockUniqueFaceTopologies_) {
550  std::string elemBlockName = ebuft_iter.first;
551  std::vector<stk::topology> uniqueFaceTopologies = ebuft_iter.second;
552 
553  auto find_result = std::find(uniqueFaceTopologies.begin(), uniqueFaceTopologies.end(), faceBlockTopo);
554  if (find_result != uniqueFaceTopologies.end()) {
555  mesh.addFaceBlock(elemBlockName, faceBlockPart->name(), faceBlockTopo);
556  }
557  }
558  }
559 }
560 
561 bool topo_less (stk::topology &i,stk::topology &j) { return (i.value() < j.value()); }
562 bool topo_equal (stk::topology &i,stk::topology &j) { return (i.value() == j.value()); }
563 
564 void STK_ExodusReaderFactory::createUniqueEdgeTopologyMap(STK_Interface & mesh, const stk::mesh::Part *elemBlockPart) const
565 {
566  using Teuchos::RCP;
567 
568  /* For a given element block, add it's edge topologies to a vector,
569  * sort it, dedupe it and save it to the "unique topo" map.
570  */
571  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
572  const stk::topology elemBlockTopo = metaData->get_topology(*elemBlockPart);
573 
574  std::vector<stk::topology> edge_topologies;
575  for (unsigned i=0;i<elemBlockTopo.num_edges();i++) {
576  edge_topologies.push_back(elemBlockTopo.edge_topology(i));
577  }
578  std::sort(edge_topologies.begin(), edge_topologies.end(), topo_less);
579  std::vector<stk::topology>::iterator new_end;
580  new_end = std::unique(edge_topologies.begin(), edge_topologies.end(), topo_equal);
581  edge_topologies.resize( std::distance(edge_topologies.begin(),new_end) );
582 
583  elemBlockUniqueEdgeTopologies_[elemBlockPart->name()] = edge_topologies;
584 }
585 
586 void STK_ExodusReaderFactory::createUniqueFaceTopologyMap(STK_Interface & mesh, const stk::mesh::Part *elemBlockPart) const
587 {
588  using Teuchos::RCP;
589 
590  /* For a given element block, add it's face topologies to a vector,
591  * sort it, dedupe it and save it to the "unique topo" map.
592  */
593  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
594  const stk::topology elemBlockTopo = metaData->get_topology(*elemBlockPart);
595 
596  std::vector<stk::topology> face_topologies;
597  for (unsigned i=0;i<elemBlockTopo.num_faces();i++) {
598  face_topologies.push_back(elemBlockTopo.face_topology(i));
599  }
600  std::sort(face_topologies.begin(), face_topologies.end(), topo_less);
601  std::vector<stk::topology>::iterator new_end;
602  new_end = std::unique(face_topologies.begin(), face_topologies.end(), topo_equal);
603  face_topologies.resize( std::distance(face_topologies.begin(),new_end) );
604 
605  elemBlockUniqueFaceTopologies_[elemBlockPart->name()] = face_topologies;
606 }
607 
608 // Pre-Condition: call beginModification() before entry
609 // Post-Condition: call endModification() after exit
610 void STK_ExodusReaderFactory::addEdgeBlocks(STK_Interface & mesh) const
611 {
612  Teuchos::RCP<stk::mesh::BulkData> bulkData = mesh.getBulkData();
613  Teuchos::RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
614 
615  /* For each element block, iterate over it's edge topologies.
616  * For each edge topology, get the matching edge block and
617  * add all edges of that topology to the edge block.
618  */
619  for (auto iter : elemBlockUniqueEdgeTopologies_) {
620  std::string elemBlockName = iter.first;
621  std::vector<stk::topology> uniqueEdgeTopologies = iter.second;
622 
623  for (auto topo : uniqueEdgeTopologies ) {
624  const stk::mesh::Part * elemBlockPart = metaData->get_part(elemBlockName);
625  const stk::mesh::Part & edgeTopoPart = metaData->get_topology_root_part(topo);
626 
627  stk::mesh::Selector owned_block;
628  owned_block = *elemBlockPart;
629  owned_block &= edgeTopoPart;
630  owned_block &= metaData->locally_owned_part();
631 
632  std::string edge_block_name = mkBlockName(panzer_stk::STK_Interface::edgeBlockString, topo.name());
633  stk::mesh::Part * edge_block = mesh.getEdgeBlock(edge_block_name);
634 
635  std::vector<stk::mesh::Entity> all_edges_for_topo;
636  bulkData->get_entities(mesh.getEdgeRank(),owned_block,all_edges_for_topo);
637  mesh.addEntitiesToEdgeBlock(all_edges_for_topo, edge_block);
638  }
639  }
640 }
641 
642 // Pre-Condition: call beginModification() before entry
643 // Post-Condition: call endModification() after exit
644 void STK_ExodusReaderFactory::addFaceBlocks(STK_Interface & mesh) const
645 {
646  Teuchos::RCP<stk::mesh::BulkData> bulkData = mesh.getBulkData();
647  Teuchos::RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
648 
649  /* For each element block, iterate over it's face topologies.
650  * For each face topology, get the matching face block and
651  * add all faces of that topology to the face block.
652  */
653  for (auto iter : elemBlockUniqueFaceTopologies_) {
654  std::string elemBlockName = iter.first;
655  std::vector<stk::topology> uniqueFaceTopologies = iter.second;
656 
657  for (auto topo : uniqueFaceTopologies ) {
658  const stk::mesh::Part * elemBlockPart = metaData->get_part(elemBlockName);
659  const stk::mesh::Part & faceTopoPart = metaData->get_topology_root_part(topo);
660 
661  stk::mesh::Selector owned_block;
662  owned_block = *elemBlockPart;
663  owned_block &= faceTopoPart;
664  owned_block &= metaData->locally_owned_part();
665 
666  std::string face_block_name = mkBlockName(panzer_stk::STK_Interface::faceBlockString, topo.name());
667  stk::mesh::Part * face_block = mesh.getFaceBlock(face_block_name);
668 
669  std::vector<stk::mesh::Entity> all_faces_for_topo;
670  bulkData->get_entities(mesh.getFaceRank(),owned_block,all_faces_for_topo);
671  mesh.addEntitiesToFaceBlock(all_faces_for_topo, face_block);
672  }
673  }
674 }
675 
676 void STK_ExodusReaderFactory::buildMetaData(stk::ParallelMachine /* parallelMach */, STK_Interface & mesh) const
677 {
678  if (createEdgeBlocks_) {
679  /* For each element block, iterate over it's edge topologies.
680  * For each edge topology, create an edge block for that topology.
681  */
682  for (auto iter : elemBlockUniqueEdgeTopologies_) {
683  std::string elemBlockName = iter.first;
684  std::vector<stk::topology> uniqueEdgeTopologies = iter.second;
685 
686  for (auto topo : uniqueEdgeTopologies ) {
687  std::string edge_block_name = mkBlockName(panzer_stk::STK_Interface::edgeBlockString, topo.name());
688  mesh.addEdgeBlock(elemBlockName, edge_block_name, topo);
689  }
690  }
691  }
692  if (createFaceBlocks_ && mesh.getMetaData()->spatial_dimension() > 2) {
693  /* For each element block, iterate over it's face topologies.
694  * For each face topology, create a face block for that topology.
695  */
696  for (auto iter : elemBlockUniqueFaceTopologies_) {
697  std::string elemBlockName = iter.first;
698  std::vector<stk::topology> uniqueFaceTopologies = iter.second;
699 
700  for (auto topo : uniqueFaceTopologies ) {
701  std::string face_block_name = mkBlockName(panzer_stk::STK_Interface::faceBlockString, topo.name());
702  mesh.addFaceBlock(elemBlockName, face_block_name, topo);
703  }
704  }
705  }
706 }
707 
708 bool STK_ExodusReaderFactory::doPerceptRefinement() const
709 {
710  return (fileType_!="Exodus Refinement") && (levelsOfRefinement_ > 0);
711 }
712 
713 std::string STK_ExodusReaderFactory::mkBlockName(std::string base, std::string topo_name) const
714 {
715  std::string name;
716  name = topo_name+"_"+base;
717  std::transform(name.begin(), name.end(), name.begin(),
718  [](const char c)
719  { return char(std::tolower(c)); });
720  return name;
721 }
722 
723 }
724 
725 #endif
RCP< const T > getConst() const
const std::string & name() const
std::string currentParametersString() const
T & get(const std::string &name, T def_value)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
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
static const std::string edgeBlockString
void validateParameters(ParameterList const &validParamList, int const depth=1000, EValidateUsed const validateUsed=VALIDATE_USED_ENABLED, EValidateDefaults const validateDefaults=VALIDATE_DEFAULTS_ENABLED) const
TransListIter iter
static const std::string faceBlockString
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)