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