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