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 
248  {
249  const bool find_and_set_shared_nodes_in_stk = false;
250  mesh.endModification(find_and_set_shared_nodes_in_stk);
251  }
252 
253  if (userMeshScaling_) {
254  stk::mesh::Field<double>* coord_field = metaData.get_field<double>(stk::topology::NODE_RANK, "coordinates");
255  std::vector< const stk::mesh::FieldBase *> fields;
256  fields.push_back(coord_field);
257 
258  stk::mesh::communicate_field_data(bulkData, fields);
259  }
260 
261  if(restartIndex>0) // process_input_request is a no-op if restartIndex<=0 ... thus there would be no inital time
262  mesh.setInitialStateTime(meshData->get_input_ioss_region()->get_state_time(restartIndex));
263  else
264  mesh.setInitialStateTime(0.0); // no initial time to speak, might as well use 0.0
265 
266  // clean up mesh data object
267  delete meshData;
268 
269  if(rebalancing_ == "default")
270  // calls Stk_MeshFactory::rebalance
271  this->rebalance(mesh);
272  else if(rebalancing_ != "none")
273  {
274  TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
275  "ERROR: Rebalancing was not set to a valid choice");
276  }
277 }
278 
280 void STK_ExodusReaderFactory::setParameterList(const Teuchos::RCP<Teuchos::ParameterList> & paramList)
281 {
282  TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(!paramList->isParameter("File Name"),
284  "Error, the parameter {name=\"File Name\","
285  "type=\"string\""
286  "\nis required in parameter (sub)list \""<< paramList->name() <<"\"."
287  "\n\nThe parsed parameter parameter list is: \n" << paramList->currentParametersString()
288  );
289 
290  // Set default values here. Not all the params should be set so this
291  // has to be done manually as opposed to using
292  // validateParametersAndSetDefaults().
293  if(!paramList->isParameter("Restart Index"))
294  paramList->set<int>("Restart Index", -1);
295 
296  if(!paramList->isParameter("File Type"))
297  paramList->set("File Type", "Exodus");
298 
299  if(!paramList->isSublist("Periodic BCs"))
300  paramList->sublist("Periodic BCs");
301 
302  Teuchos::ParameterList& p_bcs = paramList->sublist("Periodic BCs");
303  if (!p_bcs.isParameter("Count"))
304  p_bcs.set<int>("Count", 0);
305 
306  if(!paramList->isParameter("Levels of Uniform Refinement"))
307  paramList->set<int>("Levels of Uniform Refinement", 0);
308 
309  if(!paramList->isParameter("Keep Percept Data"))
310  paramList->set<bool>("Keep Percept Data", false);
311 
312  if(!paramList->isParameter("Keep Percept Parent Elements"))
313  paramList->set<bool>("Keep Percept Parent Elements", false);
314 
315  if(!paramList->isParameter("Rebalancing"))
316  paramList->set<std::string>("Rebalancing", "default");
317 
318  if(!paramList->isParameter("Create Edge Blocks"))
319  // default to false to prevent massive exodiff test failures
320  paramList->set<bool>("Create Edge Blocks", false);
321 
322  if(!paramList->isParameter("Create Face Blocks"))
323  // default to false to prevent massive exodiff test failures
324  paramList->set<bool>("Create Face Blocks", false);
325 
326  if(!paramList->isParameter("Geometry File Name"))
327  paramList->set("Geometry File Name", "");
328 
329  paramList->validateParameters(*getValidParameters(),0);
330 
331  setMyParamList(paramList);
332 
333  fileName_ = paramList->get<std::string>("File Name");
334 
335  geometryName_ = paramList->get<std::string>("Geometry File Name");
336 
337  restartIndex_ = paramList->get<int>("Restart Index");
338 
339  fileType_ = paramList->get<std::string>("File Type");
340 
341  // get any mesh scale factor
342  if (paramList->isParameter("Scale Factor"))
343  {
344  meshScaleFactor_ = paramList->get<double>("Scale Factor");
345  userMeshScaling_ = true;
346  }
347 
348  // read in periodic boundary conditions
349  parsePeriodicBCList(Teuchos::rcpFromRef(paramList->sublist("Periodic BCs")),periodicBCVec_,useBBoxSearch_);
350 
351  keepPerceptData_ = paramList->get<bool>("Keep Percept Data");
352 
353  keepPerceptParentElements_ = paramList->get<bool>("Keep Percept Parent Elements");
354 
355  rebalancing_ = paramList->get<std::string>("Rebalancing");
356 
357  levelsOfRefinement_ = paramList->get<int>("Levels of Uniform Refinement");
358 
359  createEdgeBlocks_ = paramList->get<bool>("Create Edge Blocks");
360  createFaceBlocks_ = paramList->get<bool>("Create Face Blocks");
361 }
362 
364 Teuchos::RCP<const Teuchos::ParameterList> STK_ExodusReaderFactory::getValidParameters() const
365 {
366  static Teuchos::RCP<Teuchos::ParameterList> validParams;
367 
368  if(validParams==Teuchos::null) {
369  validParams = Teuchos::rcp(new Teuchos::ParameterList);
370  validParams->set<std::string>("File Name","<file name not set>","Name of exodus file to be read",
372  validParams->set<std::string>("Geometry File Name","<file name not set>","Name of geometry file for refinement",
374 
375  validParams->set<int>("Restart Index",-1,"Index of solution to read in",
376  Teuchos::rcp(new Teuchos::AnyNumberParameterEntryValidator(Teuchos::AnyNumberParameterEntryValidator::PREFER_INT,Teuchos::AnyNumberParameterEntryValidator::AcceptedTypes(true))));
377 
378  validParams->set<std::string>("File Type", "Exodus",
379  "Choose input file type - either \"Exodus\", \"Exodus Refinement\" or \"Pamgen\"",
380  rcp(new Teuchos::StringValidator(Teuchos::tuple<std::string>("Exodus", "Pamgen"
381 #ifdef PANZER_HAVE_UMR
382  ,"Exodus Refinement"
383 #endif
384  ))));
385 
386  validParams->set<double>("Scale Factor", 1.0, "Scale factor to apply to mesh after read",
387  Teuchos::rcp(new Teuchos::AnyNumberParameterEntryValidator(Teuchos::AnyNumberParameterEntryValidator::PREFER_DOUBLE,Teuchos::AnyNumberParameterEntryValidator::AcceptedTypes(true))));
388 
389  Teuchos::ParameterList & bcs = validParams->sublist("Periodic BCs");
390  bcs.set<int>("Count",0); // no default periodic boundary conditions
391 
392  validParams->set("Levels of Uniform Refinement",0,"Number of levels of inline uniform mesh refinement");
393 
394  validParams->set("Keep Percept Data",false,"Keep the Percept mesh after uniform refinement is applied");
395 
396  validParams->set("Keep Percept Parent Elements",false,"Keep the parent element information in the Percept data");
397 
398  validParams->set("Rebalancing","default","The type of rebalancing to be performed on the mesh after creation (default, none)");
399 
400  // default to false for backward compatibility
401  validParams->set("Create Edge Blocks",false,"Create or copy edge blocks in the mesh");
402  validParams->set("Create Face Blocks",false,"Create or copy face blocks in the mesh");
403  }
404 
405  return validParams.getConst();
406 }
407 
408 void STK_ExodusReaderFactory::registerElementBlocks(STK_Interface & mesh,stk::io::StkMeshIoBroker & meshData) const
409 {
410  using Teuchos::RCP;
411 
412  RCP<stk::mesh::MetaData> femMetaData = mesh.getMetaData();
413 
414  // here we use the Ioss interface because they don't add
415  // "bonus" element blocks and its easier to determine
416  // "real" element blocks versus STK-only blocks
417  const Ioss::ElementBlockContainer & elem_blocks = meshData.get_input_ioss_region()->get_element_blocks();
418  for(Ioss::ElementBlockContainer::const_iterator itr=elem_blocks.begin();itr!=elem_blocks.end();++itr) {
419  Ioss::GroupingEntity * entity = *itr;
420  const std::string & name = entity->name();
421 
422  const stk::mesh::Part * part = femMetaData->get_part(name);
423  shards::CellTopology cellTopo = stk::mesh::get_cell_topology(femMetaData->get_topology(*part));
424  const CellTopologyData * ct = cellTopo.getCellTopologyData();
425 
426  TEUCHOS_ASSERT(ct!=0);
427  mesh.addElementBlock(part->name(),ct);
428 
429  if (createEdgeBlocks_) {
430  createUniqueEdgeTopologyMap(mesh, part);
431  }
432  if (createFaceBlocks_ && mesh.getMetaData()->spatial_dimension() > 2) {
433  createUniqueFaceTopologyMap(mesh, part);
434  }
435  }
436 }
437 
438 template <typename SetType>
439 void buildSetNames(const SetType & setData,std::vector<std::string> & names)
440 {
441  // pull out all names for this set
442  for(typename SetType::const_iterator itr=setData.begin();itr!=setData.end();++itr) {
443  Ioss::GroupingEntity * entity = *itr;
444  names.push_back(entity->name());
445  }
446 }
447 
448 void STK_ExodusReaderFactory::registerSidesets(STK_Interface & mesh) const
449 {
450  using Teuchos::RCP;
451 
452  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
453  const stk::mesh::PartVector & parts = metaData->get_parts();
454 
455  stk::mesh::PartVector::const_iterator partItr;
456  for(partItr=parts.begin();partItr!=parts.end();++partItr) {
457  const stk::mesh::Part * part = *partItr;
458  const stk::mesh::PartVector & subsets = part->subsets();
459  shards::CellTopology cellTopo = stk::mesh::get_cell_topology(metaData->get_topology(*part));
460  const CellTopologyData * ct = cellTopo.getCellTopologyData();
461 
462  // if a side part ==> this is a sideset: now storage is recursive
463  // on part contains all sub parts with consistent topology
464  if(part->primary_entity_rank()==mesh.getSideRank() && ct==0 && subsets.size()>0) {
465  TEUCHOS_TEST_FOR_EXCEPTION(subsets.size()!=1,std::runtime_error,
466  "STK_ExodusReaderFactory::registerSidesets error - part \"" << part->name() <<
467  "\" has more than one subset");
468 
469  // grab cell topology and name of subset part
470  const stk::mesh::Part * ss_part = subsets[0];
471  shards::CellTopology ss_cellTopo = stk::mesh::get_cell_topology(metaData->get_topology(*ss_part));
472  const CellTopologyData * ss_ct = ss_cellTopo.getCellTopologyData();
473 
474  // only add subset parts that have no topology
475  if(ss_ct!=0)
476  mesh.addSideset(part->name(),ss_ct);
477  }
478  }
479 }
480 
481 void STK_ExodusReaderFactory::registerNodesets(STK_Interface & mesh) const
482 {
483  using Teuchos::RCP;
484 
485  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
486  const stk::mesh::PartVector & parts = metaData->get_parts();
487 
488  stk::mesh::PartVector::const_iterator partItr;
489  for(partItr=parts.begin();partItr!=parts.end();++partItr) {
490  const stk::mesh::Part * part = *partItr;
491  shards::CellTopology cellTopo = stk::mesh::get_cell_topology(metaData->get_topology(*part));
492  const CellTopologyData * ct = cellTopo.getCellTopologyData();
493 
494  // if a side part ==> this is a sideset: now storage is recursive
495  // on part contains all sub parts with consistent topology
496  if(part->primary_entity_rank()==mesh.getNodeRank() && ct==0) {
497 
498  // only add subset parts that have no topology
499  if(part->name()!=STK_Interface::nodesString)
500  mesh.addNodeset(part->name());
501  }
502  }
503 }
504 
505 void STK_ExodusReaderFactory::registerEdgeBlocks(STK_Interface & mesh,stk::io::StkMeshIoBroker & meshData) const
506 {
507  using Teuchos::RCP;
508 
509  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
510 
511  /* For each edge block in the exodus file, check it's topology
512  * against the list of edge topologies for each element block.
513  * If it matches, add the edge block for that element block.
514  * This will add the edge block as a subset of the element
515  * block in the STK mesh.
516  */
517  const Ioss::EdgeBlockContainer & edge_blocks = meshData.get_input_ioss_region()->get_edge_blocks();
518  for(Ioss::EdgeBlockContainer::const_iterator ebc_iter=edge_blocks.begin();ebc_iter!=edge_blocks.end();++ebc_iter) {
519  Ioss::GroupingEntity * entity = *ebc_iter;
520  const stk::mesh::Part * edgeBlockPart = metaData->get_part(entity->name());
521  const stk::topology edgeBlockTopo = metaData->get_topology(*edgeBlockPart);
522 
523  for (auto ebuet_iter : elemBlockUniqueEdgeTopologies_) {
524  std::string elemBlockName = ebuet_iter.first;
525  std::vector<stk::topology> uniqueEdgeTopologies = ebuet_iter.second;
526 
527  auto find_result = std::find(uniqueEdgeTopologies.begin(), uniqueEdgeTopologies.end(), edgeBlockTopo);
528  if (find_result != uniqueEdgeTopologies.end()) {
529  mesh.addEdgeBlock(elemBlockName, edgeBlockPart->name(), edgeBlockTopo);
530  }
531  }
532  }
533 }
534 
535 void STK_ExodusReaderFactory::registerFaceBlocks(STK_Interface & mesh,stk::io::StkMeshIoBroker & meshData) const
536 {
537  using Teuchos::RCP;
538 
539  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
540 
541  /* For each face block in the exodus file, check it's topology
542  * against the list of face topologies for each element block.
543  * If it matches, add the face block for that element block.
544  * This will add the face block as a subset of the element
545  * block in the STK mesh.
546  */
547  const Ioss::FaceBlockContainer & face_blocks = meshData.get_input_ioss_region()->get_face_blocks();
548  for(Ioss::FaceBlockContainer::const_iterator fbc_itr=face_blocks.begin();fbc_itr!=face_blocks.end();++fbc_itr) {
549  Ioss::GroupingEntity * entity = *fbc_itr;
550  const stk::mesh::Part * faceBlockPart = metaData->get_part(entity->name());
551  const stk::topology faceBlockTopo = metaData->get_topology(*faceBlockPart);
552 
553  for (auto ebuft_iter : elemBlockUniqueFaceTopologies_) {
554  std::string elemBlockName = ebuft_iter.first;
555  std::vector<stk::topology> uniqueFaceTopologies = ebuft_iter.second;
556 
557  auto find_result = std::find(uniqueFaceTopologies.begin(), uniqueFaceTopologies.end(), faceBlockTopo);
558  if (find_result != uniqueFaceTopologies.end()) {
559  mesh.addFaceBlock(elemBlockName, faceBlockPart->name(), faceBlockTopo);
560  }
561  }
562  }
563 }
564 
565 bool topo_less (stk::topology &i,stk::topology &j) { return (i.value() < j.value()); }
566 bool topo_equal (stk::topology &i,stk::topology &j) { return (i.value() == j.value()); }
567 
568 void STK_ExodusReaderFactory::createUniqueEdgeTopologyMap(STK_Interface & mesh, const stk::mesh::Part *elemBlockPart) const
569 {
570  using Teuchos::RCP;
571 
572  /* For a given element block, add it's edge topologies to a vector,
573  * sort it, dedupe it and save it to the "unique topo" map.
574  */
575  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
576  const stk::topology elemBlockTopo = metaData->get_topology(*elemBlockPart);
577 
578  std::vector<stk::topology> edge_topologies;
579  for (unsigned i=0;i<elemBlockTopo.num_edges();i++) {
580  edge_topologies.push_back(elemBlockTopo.edge_topology(i));
581  }
582  std::sort(edge_topologies.begin(), edge_topologies.end(), topo_less);
583  std::vector<stk::topology>::iterator new_end;
584  new_end = std::unique(edge_topologies.begin(), edge_topologies.end(), topo_equal);
585  edge_topologies.resize( std::distance(edge_topologies.begin(),new_end) );
586 
587  elemBlockUniqueEdgeTopologies_[elemBlockPart->name()] = edge_topologies;
588 }
589 
590 void STK_ExodusReaderFactory::createUniqueFaceTopologyMap(STK_Interface & mesh, const stk::mesh::Part *elemBlockPart) const
591 {
592  using Teuchos::RCP;
593 
594  /* For a given element block, add it's face topologies to a vector,
595  * sort it, dedupe it and save it to the "unique topo" map.
596  */
597  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
598  const stk::topology elemBlockTopo = metaData->get_topology(*elemBlockPart);
599 
600  std::vector<stk::topology> face_topologies;
601  for (unsigned i=0;i<elemBlockTopo.num_faces();i++) {
602  face_topologies.push_back(elemBlockTopo.face_topology(i));
603  }
604  std::sort(face_topologies.begin(), face_topologies.end(), topo_less);
605  std::vector<stk::topology>::iterator new_end;
606  new_end = std::unique(face_topologies.begin(), face_topologies.end(), topo_equal);
607  face_topologies.resize( std::distance(face_topologies.begin(),new_end) );
608 
609  elemBlockUniqueFaceTopologies_[elemBlockPart->name()] = face_topologies;
610 }
611 
612 // Pre-Condition: call beginModification() before entry
613 // Post-Condition: call endModification() after exit
614 void STK_ExodusReaderFactory::addEdgeBlocks(STK_Interface & mesh) const
615 {
616  Teuchos::RCP<stk::mesh::BulkData> bulkData = mesh.getBulkData();
617  Teuchos::RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
618 
619  /* For each element block, iterate over it's edge topologies.
620  * For each edge topology, get the matching edge block and
621  * add all edges of that topology to the edge block. Make sure to include
622  * aura values - when they are marked shared, the part membership
623  * gets updated, if only ghosted the part memberships are not
624  * automatically updated.
625  */
626  for (auto iter : elemBlockUniqueEdgeTopologies_) {
627  std::string elemBlockName = iter.first;
628  std::vector<stk::topology> uniqueEdgeTopologies = iter.second;
629 
630  for (auto topo : uniqueEdgeTopologies ) {
631  const stk::mesh::Part * elemBlockPart = metaData->get_part(elemBlockName);
632  const stk::mesh::Part & edgeTopoPart = metaData->get_topology_root_part(topo);
633 
634  stk::mesh::Selector owned_block;
635  owned_block = *elemBlockPart;
636  owned_block &= edgeTopoPart;
637 
638  std::string edge_block_name = mkBlockName(panzer_stk::STK_Interface::edgeBlockString, topo.name());
639  stk::mesh::Part * edge_block = mesh.getEdgeBlock(edge_block_name);
640 
641  bulkData->change_entity_parts(owned_block, mesh.getEdgeRank(), stk::mesh::PartVector{edge_block});
642  }
643  }
644 }
645 
646 // Pre-Condition: call beginModification() before entry
647 // Post-Condition: call endModification() after exit
648 void STK_ExodusReaderFactory::addFaceBlocks(STK_Interface & mesh) const
649 {
650  Teuchos::RCP<stk::mesh::BulkData> bulkData = mesh.getBulkData();
651  Teuchos::RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
652 
653  /* For each element block, iterate over it's face topologies. For
654  * each face topology, get the matching face block and add all
655  * faces of that topology to the face block. Make sure to include
656  * aura values - when they are marked shared, the part membership
657  * gets updated, if only ghosted the part memberships are not
658  * automatically updated.
659  */
660  for (auto iter : elemBlockUniqueFaceTopologies_) {
661  std::string elemBlockName = iter.first;
662  std::vector<stk::topology> uniqueFaceTopologies = iter.second;
663 
664  for (auto topo : uniqueFaceTopologies ) {
665  const stk::mesh::Part * elemBlockPart = metaData->get_part(elemBlockName);
666  const stk::mesh::Part & faceTopoPart = metaData->get_topology_root_part(topo);
667 
668  stk::mesh::Selector owned_block;
669  owned_block = *elemBlockPart;
670  owned_block &= faceTopoPart;
671 
672  std::string face_block_name = mkBlockName(panzer_stk::STK_Interface::faceBlockString, topo.name());
673  stk::mesh::Part * face_block = mesh.getFaceBlock(face_block_name);
674 
675  bulkData->change_entity_parts(owned_block, mesh.getFaceRank(), stk::mesh::PartVector{face_block});
676  }
677  }
678 }
679 
680 void STK_ExodusReaderFactory::buildMetaData(stk::ParallelMachine /* parallelMach */, STK_Interface & mesh) const
681 {
682  if (createEdgeBlocks_) {
683  /* For each element block, iterate over it's edge topologies.
684  * For each edge topology, create an edge block for that topology.
685  */
686  for (auto iter : elemBlockUniqueEdgeTopologies_) {
687  std::string elemBlockName = iter.first;
688  std::vector<stk::topology> uniqueEdgeTopologies = iter.second;
689 
690  for (auto topo : uniqueEdgeTopologies ) {
691  std::string edge_block_name = mkBlockName(panzer_stk::STK_Interface::edgeBlockString, topo.name());
692  mesh.addEdgeBlock(elemBlockName, edge_block_name, topo);
693  }
694  }
695  }
696  if (createFaceBlocks_ && mesh.getMetaData()->spatial_dimension() > 2) {
697  /* For each element block, iterate over it's face topologies.
698  * For each face topology, create a face block for that topology.
699  */
700  for (auto iter : elemBlockUniqueFaceTopologies_) {
701  std::string elemBlockName = iter.first;
702  std::vector<stk::topology> uniqueFaceTopologies = iter.second;
703 
704  for (auto topo : uniqueFaceTopologies ) {
705  std::string face_block_name = mkBlockName(panzer_stk::STK_Interface::faceBlockString, topo.name());
706  mesh.addFaceBlock(elemBlockName, face_block_name, topo);
707  }
708  }
709  }
710 }
711 
712 bool STK_ExodusReaderFactory::doPerceptRefinement() const
713 {
714  return (fileType_!="Exodus Refinement") && (levelsOfRefinement_ > 0);
715 }
716 
717 std::string STK_ExodusReaderFactory::mkBlockName(std::string base, std::string topo_name) const
718 {
719  std::string name;
720  name = topo_name+"_"+base;
721  std::transform(name.begin(), name.end(), name.begin(),
722  [](const char c)
723  { return char(std::tolower(c)); });
724  return name;
725 }
726 
727 }
728 
729 #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)