Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_STK_Interface.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 <PanzerAdaptersSTK_config.hpp>
12 #include <Panzer_STK_Interface.hpp>
13 
14 #include <Teuchos_as.hpp>
15 #include <Teuchos_RCPStdSharedPtrConversions.hpp>
16 
17 #include <limits>
18 
19 #include <stk_mesh/base/FieldBase.hpp>
20 #include <stk_mesh/base/Comm.hpp>
21 #include <stk_mesh/base/Selector.hpp>
22 #include <stk_mesh/base/GetEntities.hpp>
23 #include <stk_mesh/base/GetBuckets.hpp>
24 #include <stk_mesh/base/MeshBuilder.hpp>
25 #include <stk_mesh/base/CreateAdjacentEntities.hpp>
26 
27 // #include <stk_rebalance/Rebalance.hpp>
28 // #include <stk_rebalance/Partition.hpp>
29 // #include <stk_rebalance/ZoltanPartition.hpp>
30 // #include <stk_rebalance_utils/RebalanceUtils.hpp>
31 
32 #include <stk_util/parallel/ParallelReduce.hpp>
33 #include <stk_util/parallel/CommSparse.hpp>
34 
35 #include <stk_tools/mesh_tools/FixNodeSharingViaSearch.hpp>
36 
37 #ifdef PANZER_HAVE_IOSS
38 #include <Ionit_Initializer.h>
39 #include <stk_io/IossBridge.hpp>
40 #include <stk_io/WriteMesh.hpp>
41 #endif
42 
43 #ifdef PANZER_HAVE_PERCEPT
44 #include <percept/PerceptMesh.hpp>
45 #include <adapt/UniformRefinerPattern.hpp>
46 #include <adapt/UniformRefiner.hpp>
47 #endif
48 
50 
51 #include <set>
52 
53 using Teuchos::RCP;
54 using Teuchos::rcp;
55 
56 namespace panzer_stk {
57 
59 ElementDescriptor::ElementDescriptor(stk::mesh::EntityId gid,const std::vector<stk::mesh::EntityId> & nodes)
60  : gid_(gid), nodes_(nodes) {}
62 
66 buildElementDescriptor(stk::mesh::EntityId elmtId,std::vector<stk::mesh::EntityId> & nodes)
67 {
68  return Teuchos::rcp(new ElementDescriptor(elmtId,nodes));
69 }
70 
71 const std::string STK_Interface::coordsString = "coordinates";
72 const std::string STK_Interface::nodesString = "nodes";
73 const std::string STK_Interface::edgesString = "edges";
74 const std::string STK_Interface::facesString = "faces";
75 const std::string STK_Interface::edgeBlockString = "edge_block";
76 const std::string STK_Interface::faceBlockString = "face_block";
77 
79  : dimension_(0), initialized_(false), currentLocalId_(0), initialStateTime_(0.0), currentStateTime_(0.0), useFieldCoordinates_(false)
80 {
81  metaData_ = rcp(new stk::mesh::MetaData());
82  metaData_->use_simple_fields();
83 }
84 
86  : dimension_(0), initialized_(false), currentLocalId_(0), initialStateTime_(0.0), currentStateTime_(0.0), useFieldCoordinates_(false)
87 {
88  metaData_ = metaData;
89  metaData_->use_simple_fields();
90 }
91 
93  : dimension_(dim), initialized_(false), currentLocalId_(0), useFieldCoordinates_(false)
94 {
95  std::vector<std::string> entity_rank_names = stk::mesh::entity_rank_names();
96  entity_rank_names.push_back("FAMILY_TREE");
97 
98  metaData_ = rcp(new stk::mesh::MetaData(dimension_,entity_rank_names));
99  metaData_->use_simple_fields();
100 
102 }
103 
104 void STK_Interface::addSideset(const std::string & name,const CellTopologyData * ctData)
105 {
108 
109  stk::mesh::Part * sideset = metaData_->get_part(name);
110  if(sideset==nullptr)
111  sideset = &metaData_->declare_part_with_topology(name,
112  stk::mesh::get_topology(shards::CellTopology(ctData), dimension_));
113  sidesets_.insert(std::make_pair(name,sideset));
114 }
115 
116 void STK_Interface::addNodeset(const std::string & name)
117 {
120 
121  stk::mesh::Part * nodeset = metaData_->get_part(name);
122  if(nodeset==nullptr) {
123  const CellTopologyData * ctData = shards::getCellTopologyData<shards::Node>();
124  nodeset = &metaData_->declare_part_with_topology(name,
125  stk::mesh::get_topology(shards::CellTopology(ctData), dimension_));
126  }
127  nodesets_.insert(std::make_pair(name,nodeset));
128 }
129 
130 void STK_Interface::addSolutionField(const std::string & fieldName,const std::string & blockId)
131 {
133  "Unknown element block \"" << blockId << "\"");
134  std::pair<std::string,std::string> key = std::make_pair(fieldName,blockId);
135 
136  // add & declare field if not already added...currently assuming linears
137  if(fieldNameToSolution_.find(key)==fieldNameToSolution_.end()) {
138  SolutionFieldType * field = metaData_->get_field<double>(stk::topology::NODE_RANK, fieldName);
139  if(field==0)
140  field = &metaData_->declare_field<double>(stk::topology::NODE_RANK, fieldName);
141  if ( initialized_ ) {
142  metaData_->enable_late_fields();
143  stk::mesh::put_field_on_mesh(*field, metaData_->universal_part(), nullptr);
144  }
146  }
147 }
148 
149 void STK_Interface::addCellField(const std::string & fieldName,const std::string & blockId)
150 {
152  "Unknown element block \"" << blockId << "\"");
153  std::pair<std::string,std::string> key = std::make_pair(fieldName,blockId);
154 
155  // add & declare field if not already added...currently assuming linears
156  if(fieldNameToCellField_.find(key)==fieldNameToCellField_.end()) {
157  SolutionFieldType * field = metaData_->get_field<double>(stk::topology::ELEMENT_RANK, fieldName);
158  if(field==0)
159  field = &metaData_->declare_field<double>(stk::topology::ELEMENT_RANK, fieldName);
160 
161  if ( initialized_ ) {
162  metaData_->enable_late_fields();
163  stk::mesh::put_field_on_mesh(*field, metaData_->universal_part(), nullptr);
164  }
166  }
167 }
168 
169 void STK_Interface::addEdgeField(const std::string & fieldName,const std::string & blockId)
170 {
172  "Unknown element block \"" << blockId << "\"");
173  std::pair<std::string,std::string> key = std::make_pair(fieldName,blockId);
174 
175  // add & declare field if not already added...currently assuming linears
176  if(fieldNameToEdgeField_.find(key)==fieldNameToEdgeField_.end()) {
177  SolutionFieldType * field = metaData_->get_field<double>(stk::topology::EDGE_RANK, fieldName);
178  if(field==0) {
179  field = &metaData_->declare_field<double>(stk::topology::EDGE_RANK, fieldName);
180  }
181 
182  if ( initialized_ ) {
183  metaData_->enable_late_fields();
184  stk::mesh::put_field_on_mesh(*field, metaData_->universal_part(), nullptr);
185  }
187  }
188 }
189 
190 void STK_Interface::addFaceField(const std::string & fieldName,const std::string & blockId)
191 {
193  "Unknown element block \"" << blockId << "\"");
194  std::pair<std::string,std::string> key = std::make_pair(fieldName,blockId);
195 
196  // add & declare field if not already added...currently assuming linears
197  if(fieldNameToFaceField_.find(key)==fieldNameToFaceField_.end()) {
198  SolutionFieldType * field = metaData_->get_field<double>(stk::topology::FACE_RANK, fieldName);
199  if(field==0) {
200  field = &metaData_->declare_field<double>(stk::topology::FACE_RANK, fieldName);
201  }
202 
203  if ( initialized_ ) {
204  metaData_->enable_late_fields();
205  stk::mesh::put_field_on_mesh(*field, metaData_->universal_part(), nullptr);
206  }
208  }
209 }
210 
211 void STK_Interface::addMeshCoordFields(const std::string & blockId,
212  const std::vector<std::string> & coordNames,
213  const std::string & dispPrefix)
214 {
216  TEUCHOS_ASSERT(dimension_==coordNames.size());
219  "Unknown element block \"" << blockId << "\"");
220 
221  // we only allow one alternative coordinate field
222  TEUCHOS_TEST_FOR_EXCEPTION(meshCoordFields_.find(blockId)!=meshCoordFields_.end(),std::invalid_argument,
223  "STK_Interface::addMeshCoordFields: Can't set more than one set of coordinate "
224  "fields for element block \""+blockId+"\".");
225 
226  // Note that there is a distinction between the key which is used for lookups
227  // and the field that lives on the mesh, which is used for printing the displacement.
228 
229  // just copy the coordinate names
230  meshCoordFields_[blockId] = coordNames;
231 
232  // must fill in the displacement fields
233  std::vector<std::string> & dispFields = meshDispFields_[blockId];
234  dispFields.resize(dimension_);
235 
236  for(unsigned i=0;i<dimension_;i++) {
237  std::pair<std::string,std::string> key = std::make_pair(coordNames[i],blockId);
238  std::string dispName = dispPrefix+coordNames[i];
239 
240  dispFields[i] = dispName; // record this field as a
241  // displacement field
242 
243  // add & declare field if not already added...currently assuming linears
244  if(fieldNameToSolution_.find(key)==fieldNameToSolution_.end()) {
245 
246  SolutionFieldType * field = metaData_->get_field<double>(stk::topology::NODE_RANK, dispName);
247  if(field==0) {
248  field = &metaData_->declare_field<double>(stk::topology::NODE_RANK, dispName);
249  }
251  }
252  }
253 }
254 
255 void STK_Interface::addInformationRecords(const std::vector<std::string> & info_records)
256 {
257  informationRecords_.insert(info_records.begin(), info_records.end());
258 }
259 
260 void STK_Interface::initialize(stk::ParallelMachine parallelMach,bool setupIO,
261  const bool buildRefinementSupport)
262 {
264  TEUCHOS_ASSERT(dimension_!=0); // no zero dimensional meshes!
265 
266  if(mpiComm_==Teuchos::null)
267  mpiComm_ = getSafeCommunicator(parallelMach);
268 
269  procRank_ = stk::parallel_machine_rank(*mpiComm_->getRawMpiComm());
270 
271  // associating the field with a part: universal part!
272  stk::mesh::put_field_on_mesh( *coordinatesField_ , metaData_->universal_part(), getDimension(), nullptr);
273  stk::mesh::put_field_on_mesh( *edgesField_ , metaData_->universal_part(), getDimension(), nullptr);
274  if (dimension_ > 2)
275  stk::mesh::put_field_on_mesh( *facesField_ , metaData_->universal_part(), getDimension(), nullptr);
276  stk::mesh::put_field_on_mesh( *processorIdField_ , metaData_->universal_part(), nullptr);
277  stk::mesh::put_field_on_mesh( *loadBalField_ , metaData_->universal_part(), nullptr);
278 
283 
284 #ifdef PANZER_HAVE_IOSS
285  if(setupIO) {
286  // setup Exodus file IO
288 
289  // add element blocks
290  {
291  std::map<std::string, stk::mesh::Part*>::iterator itr;
292  for(itr=elementBlocks_.begin();itr!=elementBlocks_.end();++itr)
293  if(!stk::io::is_part_io_part(*itr->second))
294  stk::io::put_io_part_attribute(*itr->second); // this can only be called once per part
295  }
296 
297  // add edge blocks
298  {
299  std::map<std::string, stk::mesh::Part*>::iterator itr;
300  for(itr=edgeBlocks_.begin();itr!=edgeBlocks_.end();++itr)
301  if(!stk::io::is_part_edge_block_io_part(*itr->second))
302  stk::io::put_edge_block_io_part_attribute(*itr->second); // this can only be called once per part
303  }
304 
305  // add face blocks
306  {
307  std::map<std::string, stk::mesh::Part*>::iterator itr;
308  for(itr=faceBlocks_.begin();itr!=faceBlocks_.end();++itr)
309  if(!stk::io::is_part_face_block_io_part(*itr->second))
310  stk::io::put_face_block_io_part_attribute(*itr->second); // this can only be called once per part
311  }
312 
313  // add side sets
314  {
315  std::map<std::string, stk::mesh::Part*>::iterator itr;
316  for(itr=sidesets_.begin();itr!=sidesets_.end();++itr)
317  if(!stk::io::is_part_io_part(*itr->second))
318  stk::io::put_io_part_attribute(*itr->second); // this can only be called once per part
319  }
320 
321  // add node sets
322  {
323  std::map<std::string, stk::mesh::Part*>::iterator itr;
324  for(itr=nodesets_.begin();itr!=nodesets_.end();++itr)
325  if(!stk::io::is_part_io_part(*itr->second))
326  stk::io::put_io_part_attribute(*itr->second); // this can only be called once per part
327  }
328 
329  // add nodes
330  if(!stk::io::is_part_io_part(*nodesPart_))
331  stk::io::put_io_part_attribute(*nodesPart_);
332 
333  stk::io::set_field_role(*coordinatesField_, Ioss::Field::MESH);
334  stk::io::set_field_output_type(*coordinatesField_, stk::io::FieldOutputType::VECTOR_3D);
335  stk::io::set_field_role(*edgesField_, Ioss::Field::MESH);
336  stk::io::set_field_output_type(*edgesField_, stk::io::FieldOutputType::VECTOR_3D);
337  if (dimension_ > 2) {
338  stk::io::set_field_role(*facesField_, Ioss::Field::MESH);
339  stk::io::set_field_output_type(*facesField_, stk::io::FieldOutputType::VECTOR_3D);
340  }
341  stk::io::set_field_role(*processorIdField_, Ioss::Field::TRANSIENT);
342  // stk::io::set_field_role(*loadBalField_, Ioss::Field::TRANSIENT);
343 
344  }
345 #endif
346 
347  if (buildRefinementSupport) {
348 #ifdef PANZER_HAVE_PERCEPT
349  refinedMesh_ = Teuchos::rcp(new percept::PerceptMesh(this->getMetaData().get(),
350  this->getBulkData().get(),
351  true));
352 
353  breakPattern_ = Teuchos::rcp(new percept::URP_Heterogeneous_3D(*refinedMesh_));
354 #else
355  TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
356  "ERROR: Uniform refinement requested. This requires the Percept package to be enabled in Trilinos!");
357 #endif
358  }
359 
360  if(bulkData_==Teuchos::null)
361  instantiateBulkData(*mpiComm_->getRawMpiComm());
362 
363  metaData_->commit();
364 
365  initialized_ = true;
366 }
367 
368 void STK_Interface::initializeFieldsInSTK(const std::map<std::pair<std::string,std::string>,SolutionFieldType*> & nameToField,
369  bool setupIO)
370 {
371  std::set<SolutionFieldType*> uniqueFields;
372  std::map<std::pair<std::string,std::string>,SolutionFieldType*>::const_iterator fieldIter;
373  for(fieldIter=nameToField.begin();fieldIter!=nameToField.end();++fieldIter)
374  uniqueFields.insert(fieldIter->second); // this makes setting up IO easier!
375 
376  {
377  std::set<SolutionFieldType*>::const_iterator uniqueFieldIter;
378  for(uniqueFieldIter=uniqueFields.begin();uniqueFieldIter!=uniqueFields.end();++uniqueFieldIter)
379  stk::mesh::put_field_on_mesh(*(*uniqueFieldIter),metaData_->universal_part(),nullptr);
380  }
381 
382 #ifdef PANZER_HAVE_IOSS
383  if(setupIO) {
384  // add solution fields
385  std::set<SolutionFieldType*>::const_iterator uniqueFieldIter;
386  for(uniqueFieldIter=uniqueFields.begin();uniqueFieldIter!=uniqueFields.end();++uniqueFieldIter)
387  stk::io::set_field_role(*(*uniqueFieldIter), Ioss::Field::TRANSIENT);
388  }
389 #endif
390 }
391 
392 void STK_Interface::instantiateBulkData(stk::ParallelMachine parallelMach)
393 {
394  TEUCHOS_ASSERT(bulkData_==Teuchos::null);
395  if(mpiComm_==Teuchos::null)
396  mpiComm_ = getSafeCommunicator(parallelMach);
397 
398  std::unique_ptr<stk::mesh::BulkData> bulkUPtr = stk::mesh::MeshBuilder(*mpiComm_->getRawMpiComm()).create(Teuchos::get_shared_ptr(metaData_));
399  bulkData_ = rcp(bulkUPtr.release());
400 }
401 
403 {
404  TEUCHOS_TEST_FOR_EXCEPTION(bulkData_==Teuchos::null,std::logic_error,
405  "STK_Interface: Must call \"initialized\" or \"instantiateBulkData\" before \"beginModification\"");
406 
407  bulkData_->modification_begin();
408 }
409 
410 void STK_Interface::endModification(const bool find_and_set_shared_nodes_in_stk)
411 {
412  TEUCHOS_TEST_FOR_EXCEPTION(bulkData_==Teuchos::null,std::logic_error,
413  "STK_Interface: Must call \"initialized\" or \"instantiateBulkData\" before \"endModification\"");
414 
415  // Resolving sharing this way comes at a cost in performance. The
416  // STK mesh database requires users to declare their own node
417  // sharing. We should find where shared entities are being created
418  // in Panzer (the inline mesh factories) and declare it. Once this
419  // is done, the extra code below can be deleted. Note that the
420  // exodus reader already has shared nodes set up properly, so only
421  // the inline mesh factories need this.
422  if (find_and_set_shared_nodes_in_stk) {
423  const double radius = 10.0 * std::numeric_limits<double>::epsilon();
424  stk::tools::fix_node_sharing_via_search(*bulkData_,radius);
425  }
426 
427  bulkData_->modification_end();
428 
431 }
432 
433 void STK_Interface::addNode(stk::mesh::EntityId gid, const std::vector<double> & coord)
434 {
435  TEUCHOS_TEST_FOR_EXCEPTION(not isModifiable(),std::logic_error,
436  "STK_Interface::addNode: STK_Interface must be modifiable to add a node");
437  TEUCHOS_TEST_FOR_EXCEPTION(coord.size()!=getDimension(),std::logic_error,
438  "STK_Interface::addNode: number of coordinates in vector must mation dimension");
439  TEUCHOS_TEST_FOR_EXCEPTION(gid==0,std::logic_error,
440  "STK_Interface::addNode: STK has STUPID restriction of no zero GIDs, pick something else");
441  stk::mesh::EntityRank nodeRank = getNodeRank();
442 
443  stk::mesh::Entity node = bulkData_->declare_entity(nodeRank,gid,nodesPartVec_);
444 
445  // set coordinate vector
446  double * fieldCoords = stk::mesh::field_data(*coordinatesField_,node);
447  for(std::size_t i=0;i<coord.size();++i)
448  fieldCoords[i] = coord[i];
449 }
450 
451 void STK_Interface::addEntityToSideset(stk::mesh::Entity entity,stk::mesh::Part * sideset)
452 {
453  std::vector<stk::mesh::Part*> sidesetV;
454  sidesetV.push_back(sideset);
455 
456  bulkData_->change_entity_parts(entity,sidesetV);
457 }
458 
459 void STK_Interface::addEntityToNodeset(stk::mesh::Entity entity,stk::mesh::Part * nodeset)
460 {
461  std::vector<stk::mesh::Part*> nodesetV;
462  nodesetV.push_back(nodeset);
463 
464  bulkData_->change_entity_parts(entity,nodesetV);
465 }
466 
467 void STK_Interface::addEntityToEdgeBlock(stk::mesh::Entity entity,stk::mesh::Part * edgeblock)
468 {
469  std::vector<stk::mesh::Part*> edgeblockV;
470  edgeblockV.push_back(edgeblock);
471 
472  bulkData_->change_entity_parts(entity,edgeblockV);
473 }
474 void STK_Interface::addEntitiesToEdgeBlock(std::vector<stk::mesh::Entity> entities,stk::mesh::Part * edgeblock)
475 {
476  if (entities.size() > 0) {
477  std::vector<stk::mesh::Part*> edgeblockV;
478  edgeblockV.push_back(edgeblock);
479 
480  bulkData_->change_entity_parts(entities,edgeblockV);
481  }
482 }
483 
484 void STK_Interface::addEntityToFaceBlock(stk::mesh::Entity entity,stk::mesh::Part * faceblock)
485 {
486  std::vector<stk::mesh::Part*> faceblockV;
487  faceblockV.push_back(faceblock);
488 
489  bulkData_->change_entity_parts(entity,faceblockV);
490 }
491 void STK_Interface::addEntitiesToFaceBlock(std::vector<stk::mesh::Entity> entities,stk::mesh::Part * faceblock)
492 {
493  if (entities.size() > 0) {
494  std::vector<stk::mesh::Part*> faceblockV;
495  faceblockV.push_back(faceblock);
496 
497  bulkData_->change_entity_parts(entities,faceblockV);
498  }
499 }
500 
501 void STK_Interface::addElement(const Teuchos::RCP<ElementDescriptor> & ed,stk::mesh::Part * block)
502 {
503  std::vector<stk::mesh::Part*> blockVec;
504  blockVec.push_back(block);
505 
506  stk::mesh::EntityRank elementRank = getElementRank();
507  stk::mesh::EntityRank nodeRank = getNodeRank();
508  stk::mesh::Entity element = bulkData_->declare_entity(elementRank,ed->getGID(),blockVec);
509 
510  // build relations that give the mesh structure
511  const std::vector<stk::mesh::EntityId> & nodes = ed->getNodes();
512  for(std::size_t i=0;i<nodes.size();++i) {
513  // add element->node relation
514  stk::mesh::Entity node = bulkData_->get_entity(nodeRank,nodes[i]);
515  TEUCHOS_ASSERT(bulkData_->is_valid(node));
516  bulkData_->declare_relation(element,node,i);
517  }
518 
519  ProcIdData * procId = stk::mesh::field_data(*processorIdField_,element);
520  procId[0] = Teuchos::as<ProcIdData>(procRank_);
521 }
522 
523 
525 {
526  // loop over elements
527  stk::mesh::EntityRank edgeRank = getEdgeRank();
528  std::vector<stk::mesh::Entity> localElmts;
529  getMyElements(localElmts);
530  std::vector<stk::mesh::Entity>::const_iterator itr;
531  for(itr=localElmts.begin();itr!=localElmts.end();++itr) {
532  stk::mesh::Entity element = (*itr);
533  stk::mesh::EntityId gid = bulkData_->identifier(element);
534  std::vector<stk::mesh::EntityId> subcellIds;
535  getSubcellIndices(edgeRank,gid,subcellIds);
536 
537  for(std::size_t i=0;i<subcellIds.size();++i) {
538  stk::mesh::Entity edge = bulkData_->get_entity(edgeRank,subcellIds[i]);
539  stk::mesh::Entity const* relations = bulkData_->begin_nodes(edge);
540 
541  double * node_coord_1 = stk::mesh::field_data(*coordinatesField_,relations[0]);
542  double * node_coord_2 = stk::mesh::field_data(*coordinatesField_,relations[1]);
543 
544  // set coordinate vector
545  double * edgeCoords = stk::mesh::field_data(*edgesField_,edge);
546  for(std::size_t j=0;j<getDimension();++j)
547  edgeCoords[j] = (node_coord_1[j]+node_coord_2[j])/2.0;
548  }
549  }
550 }
551 
553 {
554  // loop over elements
555  stk::mesh::EntityRank faceRank = getFaceRank();
556  std::vector<stk::mesh::Entity> localElmts;
557  getMyElements(localElmts);
558  std::vector<stk::mesh::Entity>::const_iterator itr;
559  for(itr=localElmts.begin();itr!=localElmts.end();++itr) {
560  stk::mesh::Entity element = (*itr);
561  stk::mesh::EntityId gid = elementGlobalId(element);
562  std::vector<stk::mesh::EntityId> subcellIds;
563  getSubcellIndices(faceRank,gid,subcellIds);
564 
565  for(std::size_t i=0;i<subcellIds.size();++i) {
566  stk::mesh::Entity face = bulkData_->get_entity(faceRank,subcellIds[i]);
567  stk::mesh::Entity const* relations = bulkData_->begin_nodes(face);
568  const size_t num_relations = bulkData_->num_nodes(face);
569 
570  // set coordinate vector
571  double * faceCoords = stk::mesh::field_data(*facesField_,face);
572  for(std::size_t j=0;j<getDimension();++j){
573  faceCoords[j] = 0.0;
574  for(std::size_t k=0;k<num_relations;++k)
575  faceCoords[j] += stk::mesh::field_data(*coordinatesField_,relations[k])[j];
576  faceCoords[j] /= double(num_relations);
577  }
578  }
579  }
580 }
581 
582 stk::mesh::Entity STK_Interface::findConnectivityById(stk::mesh::Entity src, stk::mesh::EntityRank tgt_rank, unsigned rel_id) const
583 {
584  const size_t num_rels = bulkData_->num_connectivity(src, tgt_rank);
585  stk::mesh::Entity const* relations = bulkData_->begin(src, tgt_rank);
586  stk::mesh::ConnectivityOrdinal const* ordinals = bulkData_->begin_ordinals(src, tgt_rank);
587  for (size_t i = 0; i < num_rels; ++i) {
588  if (ordinals[i] == static_cast<stk::mesh::ConnectivityOrdinal>(rel_id)) {
589  return relations[i];
590  }
591  }
592 
593  return stk::mesh::Entity();
594 }
595 
597 //
598 // writeToExodus()
599 //
601 void
603 writeToExodus(const std::string& filename,
604  const bool append)
605 {
606  setupExodusFile(filename,append);
607  writeToExodus(0.0);
608 } // end of writeToExodus()
609 
611 //
612 // setupExodusFile()
613 //
615 void
617 setupExodusFile(const std::string& filename,
618  const bool append,
619  const bool append_after_restart_time,
620  const double restart_time)
621 {
622  std::vector<Ioss::Property> ioss_properties;
623  setupExodusFile(filename,
624  ioss_properties,
625  append,
626  append_after_restart_time,
627  restart_time);
628 }
629 
630 void
632 setupExodusFile(const std::string& filename,
633  const std::vector<Ioss::Property>& ioss_properties,
634  const bool append,
635  const bool append_after_restart_time,
636  const double restart_time)
637 {
638  using std::runtime_error;
639  using stk::io::StkMeshIoBroker;
640  using stk::mesh::FieldVector;
641  using stk::ParallelMachine;
642  using Teuchos::rcp;
643  PANZER_FUNC_TIME_MONITOR("STK_Interface::setupExodusFile(filename)");
644 #ifdef PANZER_HAVE_IOSS
646 
647  ParallelMachine comm = *mpiComm_->getRawMpiComm();
648  meshData_ = rcp(new StkMeshIoBroker(comm));
649  meshData_->set_bulk_data(Teuchos::get_shared_ptr(bulkData_));
650  Ioss::PropertyManager props;
651  props.add(Ioss::Property("LOWER_CASE_VARIABLE_NAMES", "FALSE"));
652  for ( const auto& p : ioss_properties ) {
653  props.add(p);
654  }
655  if (append) {
656  if (append_after_restart_time) {
657  meshIndex_ = meshData_->create_output_mesh(filename, stk::io::APPEND_RESULTS,
658  props, restart_time);
659  }
660  else // Append results to the end of the file
661  meshIndex_ = meshData_->create_output_mesh(filename, stk::io::APPEND_RESULTS, props);
662  }
663  else
664  meshIndex_ = meshData_->create_output_mesh(filename, stk::io::WRITE_RESULTS, props);
665  const FieldVector& fields = metaData_->get_fields();
666  for (size_t i(0); i < fields.size(); ++i) {
667  // Do NOT add MESH type stk fields to exodus io, but do add everything
668  // else. This allows us to avoid having to catch a throw for
669  // re-registering coordinates, sidesets, etc... Note that some
670  // fields like LOAD_BAL don't always have a role assigned, so for
671  // roles that point to null, we need to register them as well.
672  auto role = stk::io::get_field_role(*fields[i]);
673  if (role != nullptr) {
674  if (*role != Ioss::Field::MESH)
675  meshData_->add_field(meshIndex_, *fields[i]);
676  } else {
677  meshData_->add_field(meshIndex_, *fields[i]);
678  }
679  }
680 
681  // convert the set to a vector
682  std::vector<std::string> deduped_info_records(informationRecords_.begin(),informationRecords_.end());
683  meshData_->add_info_records(meshIndex_, deduped_info_records);
684 #else
685  TEUCHOS_ASSERT(false)
686 #endif
687 } // end of setupExodusFile()
688 
690 //
691 // writeToExodus()
692 //
694 void
697  double timestep)
698 {
699  using std::cout;
700  using std::endl;
701  using Teuchos::FancyOStream;
702  using Teuchos::rcpFromRef;
703  PANZER_FUNC_TIME_MONITOR("STK_Interface::writeToExodus(timestep)");
704 #ifdef PANZER_HAVE_IOSS
705  if (not meshData_.is_null())
706  {
707  currentStateTime_ = timestep;
708  globalToExodus(GlobalVariable::ADD);
709  meshData_->begin_output_step(meshIndex_, currentStateTime_);
710  meshData_->write_defined_output_fields(meshIndex_);
711  globalToExodus(GlobalVariable::WRITE);
712  meshData_->end_output_step(meshIndex_);
713  }
714  else // if (meshData_.is_null())
715  {
716  FancyOStream out(rcpFromRef(cout));
717  out.setOutputToRootOnly(0);
718  out << "WARNING: Exodus I/O has been disabled or not setup properly; "
719  << "not writing to Exodus." << endl;
720  } // end if (meshData_.is_null()) or not
721 #else
722  TEUCHOS_ASSERT(false);
723 #endif
724 } // end of writeToExodus()
725 
727 //
728 // globalToExodus()
729 //
731 void
732 STK_Interface::
733 globalToExodus(
734  const GlobalVariable& flag)
735 {
736  using std::invalid_argument;
737  using std::string;
738  using Teuchos::Array;
739 
740  // Loop over all the global variables to be added to the Exodus output file.
741  // For each global variable, we determine the data type, and then add or
742  // write it accordingly, depending on the value of flag.
743  for (auto i = globalData_.begin(); i != globalData_.end(); ++i)
744  {
745  const string& name = globalData_.name(i);
746 
747  // Integers.
748  if (globalData_.isType<int>(name))
749  {
750  const auto& value = globalData_.get<int>(name);
751  if (flag == GlobalVariable::ADD)
752  {
753  try
754  {
755  meshData_->add_global(meshIndex_, name, value,
756  stk::util::ParameterType::INTEGER);
757  }
758  catch (...)
759  {
760  return;
761  }
762  }
763  else // if (flag == GlobalVariable::WRITE)
764  meshData_->write_global(meshIndex_, name, value,
765  stk::util::ParameterType::INTEGER);
766  }
767 
768  // Doubles.
769  else if (globalData_.isType<double>(name))
770  {
771  const auto& value = globalData_.get<double>(name);
772  if (flag == GlobalVariable::ADD)
773  {
774  try
775  {
776  meshData_->add_global(meshIndex_, name, value,
777  stk::util::ParameterType::DOUBLE);
778  }
779  catch (...)
780  {
781  return;
782  }
783  }
784  else // if (flag == GlobalVariable::WRITE)
785  meshData_->write_global(meshIndex_, name, value,
786  stk::util::ParameterType::DOUBLE);
787  }
788 
789  // Vectors of integers.
790  else if (globalData_.isType<Array<int>>(name))
791  {
792  const auto& value = globalData_.get<Array<int>>(name).toVector();
793  if (flag == GlobalVariable::ADD)
794  {
795  try
796  {
797  meshData_->add_global(meshIndex_, name, value,
798  stk::util::ParameterType::INTEGERVECTOR);
799  }
800  catch (...)
801  {
802  return;
803  }
804  }
805  else // if (flag == GlobalVariable::WRITE)
806  meshData_->write_global(meshIndex_, name, value,
807  stk::util::ParameterType::INTEGERVECTOR);
808  }
809 
810  // Vectors of doubles.
811  else if (globalData_.isType<Array<double>>(name))
812  {
813  const auto& value = globalData_.get<Array<double>>(name).toVector();
814  if (flag == GlobalVariable::ADD)
815  {
816  try
817  {
818  meshData_->add_global(meshIndex_, name, value,
819  stk::util::ParameterType::DOUBLEVECTOR);
820  }
821  catch (...)
822  {
823  return;
824  }
825  }
826  else // if (flag == GlobalVariable::WRITE)
827  meshData_->write_global(meshIndex_, name, value,
828  stk::util::ParameterType::DOUBLEVECTOR);
829  }
830 
831  // If the data type is something else, throw an exception.
832  else
833  TEUCHOS_TEST_FOR_EXCEPTION(true, invalid_argument,
834  "STK_Interface::globalToExodus(): The global variable to be added " \
835  "to the Exodus output file is of an invalid type. Valid types are " \
836  "int and double, along with std::vectors of those types.")
837  } // end loop over globalData_
838 } // end of globalToExodus()
839 
841 //
842 // addGlobalToExodus()
843 //
845 void
848  const std::string& key,
849  const int& value)
850 {
851  globalData_.set(key, value);
852 } // end of addGlobalToExodus()
853 
855 //
856 // addGlobalToExodus()
857 //
859 void
862  const std::string& key,
863  const double& value)
864 {
865  globalData_.set(key, value);
866 } // end of addGlobalToExodus()
867 
869 //
870 // addGlobalToExodus()
871 //
873 void
876  const std::string& key,
877  const std::vector<int>& value)
878 {
879  using Teuchos::Array;
880  globalData_.set(key, Array<int>(value));
881 } // end of addGlobalToExodus()
882 
884 //
885 // addGlobalToExodus()
886 //
888 void
891  const std::string& key,
892  const std::vector<double>& value)
893 {
894  using Teuchos::Array;
895  globalData_.set(key, Array<double>(value));
896 } // end of addGlobalToExodus()
897 
899 {
900  #ifdef PANZER_HAVE_IOSS
901  return true;
902  #else
903  return false;
904  #endif
905 }
906 
907 void STK_Interface::getElementsSharingNode(stk::mesh::EntityId nodeId,std::vector<stk::mesh::Entity> & elements) const
908 {
909  stk::mesh::EntityRank nodeRank = getNodeRank();
910 
911  // get all relations for node
912  stk::mesh::Entity node = bulkData_->get_entity(nodeRank,nodeId);
913  const size_t numElements = bulkData_->num_elements(node);
914  stk::mesh::Entity const* relations = bulkData_->begin_elements(node);
915 
916  // extract elements sharing nodes
917  elements.insert(elements.end(), relations, relations + numElements);
918 }
919 
920 void STK_Interface::getOwnedElementsSharingNode(stk::mesh::Entity node,std::vector<stk::mesh::Entity> & elements,
921  std::vector<int> & relIds) const
922 {
923  // get all relations for node
924  const size_t numElements = bulkData_->num_elements(node);
925  stk::mesh::Entity const* relations = bulkData_->begin_elements(node);
926  stk::mesh::ConnectivityOrdinal const* rel_ids = bulkData_->begin_element_ordinals(node);
927 
928  // extract elements sharing nodes
929  for (size_t i = 0; i < numElements; ++i) {
930  stk::mesh::Entity element = relations[i];
931 
932  // if owned by this processor
933  if(bulkData_->parallel_owner_rank(element) == static_cast<int>(procRank_)) {
934  elements.push_back(element);
935  relIds.push_back(rel_ids[i]);
936  }
937  }
938 }
939 
940 void STK_Interface::getOwnedElementsSharingNode(stk::mesh::EntityId nodeId,std::vector<stk::mesh::Entity> & elements,
941  std::vector<int> & relIds, unsigned int matchType) const
942 {
943  stk::mesh::EntityRank rank;
944  if(matchType == 0)
945  rank = getNodeRank();
946  else if(matchType == 1)
947  rank = getEdgeRank();
948  else if(matchType == 2)
949  rank = getFaceRank();
950  else
951  TEUCHOS_ASSERT(false);
952 
953  stk::mesh::Entity node = bulkData_->get_entity(rank,nodeId);
954 
955  getOwnedElementsSharingNode(node,elements,relIds);
956 }
957 
958 void STK_Interface::getElementsSharingNodes(const std::vector<stk::mesh::EntityId> nodeIds,std::vector<stk::mesh::Entity> & elements) const
959 {
960  std::vector<stk::mesh::Entity> current;
961 
962  getElementsSharingNode(nodeIds[0],current); // fill it with elements touching first node
963  std::sort(current.begin(),current.end()); // sort for intersection on the pointer
964 
965  // find intersection with remaining nodes
966  for(std::size_t n=1;n<nodeIds.size();++n) {
967  // get elements associated with next node
968  std::vector<stk::mesh::Entity> nextNode;
969  getElementsSharingNode(nodeIds[n],nextNode); // fill it with elements touching first node
970  std::sort(nextNode.begin(),nextNode.end()); // sort for intersection on the pointer ID
971 
972  // intersect next node elements with current element list
973  std::vector<stk::mesh::Entity> intersection(std::min(nextNode.size(),current.size()));
974  std::vector<stk::mesh::Entity>::const_iterator endItr
975  = std::set_intersection(current.begin(),current.end(),
976  nextNode.begin(),nextNode.end(),
977  intersection.begin());
978  std::size_t newLength = endItr-intersection.begin();
979  intersection.resize(newLength);
980 
981  // store intersection
982  current.clear();
983  current = intersection;
984  }
985 
986  // return the elements computed
987  elements = current;
988 }
989 
990 void STK_Interface::getNodeIdsForElement(stk::mesh::Entity element,std::vector<stk::mesh::EntityId> & nodeIds) const
991 {
992  stk::mesh::Entity const* nodeRel = getBulkData()->begin_nodes(element);
993  const size_t numNodes = getBulkData()->num_nodes(element);
994 
995  nodeIds.reserve(numNodes);
996  for(size_t i = 0; i < numNodes; ++i) {
997  nodeIds.push_back(elementGlobalId(nodeRel[i]));
998  }
999 }
1000 
1002 {
1003  entityCounts_.clear();
1004  stk::mesh::comm_mesh_counts(*bulkData_,entityCounts_);
1005 }
1006 
1008 {
1009  // developed to mirror "comm_mesh_counts" in stk_mesh/base/Comm.cpp
1010 
1011  const auto entityRankCount = metaData_->entity_rank_count();
1012  const size_t commCount = 10; // entityRankCount
1013 
1014  TEUCHOS_ASSERT(entityRankCount<10);
1015 
1016  // stk::ParallelMachine mach = bulkData_->parallel();
1017  stk::ParallelMachine mach = *mpiComm_->getRawMpiComm();
1018 
1019  std::vector<stk::mesh::EntityId> local(commCount,0);
1020 
1021  // determine maximum ID for this processor for each entity type
1022  stk::mesh::Selector ownedPart = metaData_->locally_owned_part();
1023  for(stk::mesh::EntityRank i=stk::topology::NODE_RANK;
1024  i < static_cast<stk::mesh::EntityRank>(entityRankCount); ++i) {
1025  std::vector<stk::mesh::Entity> entities;
1026 
1027  stk::mesh::get_selected_entities(ownedPart,bulkData_->buckets(i),entities);
1028 
1029  // determine maximum ID for this processor
1030  std::vector<stk::mesh::Entity>::const_iterator itr;
1031  for(itr=entities.begin();itr!=entities.end();++itr) {
1032  stk::mesh::EntityId id = bulkData_->identifier(*itr);
1033  if(id>local[i])
1034  local[i] = id;
1035  }
1036  }
1037 
1038  // get largest IDs across processors
1039  stk::all_reduce(mach,stk::ReduceMax<10>(&local[0]));
1040  maxEntityId_.assign(local.begin(),local.begin()+entityRankCount+1);
1041 }
1042 
1043 std::size_t STK_Interface::getEntityCounts(unsigned entityRank) const
1044 {
1045  TEUCHOS_TEST_FOR_EXCEPTION(entityRank>=entityCounts_.size(),std::logic_error,
1046  "STK_Interface::getEntityCounts: Entity counts do not include rank: " << entityRank);
1047 
1048  return entityCounts_[entityRank];
1049 }
1050 
1051 stk::mesh::EntityId STK_Interface::getMaxEntityId(unsigned entityRank) const
1052 {
1053  TEUCHOS_TEST_FOR_EXCEPTION(entityRank>=maxEntityId_.size(),std::logic_error,
1054  "STK_Interface::getMaxEntityId: Max entity ids do not include rank: " << entityRank);
1055 
1056  return maxEntityId_[entityRank];
1057 }
1058 
1060 {
1061  stk::mesh::PartVector emptyPartVector;
1062  stk::mesh::create_adjacent_entities(*bulkData_,emptyPartVector);
1063 
1066 
1067  addEdges();
1068  if (dimension_ > 2)
1069  addFaces();
1070 }
1071 
1072 const double * STK_Interface::getNodeCoordinates(stk::mesh::EntityId nodeId) const
1073 {
1074  stk::mesh::Entity node = bulkData_->get_entity(getNodeRank(),nodeId);
1075  return stk::mesh::field_data(*coordinatesField_,node);
1076 }
1077 
1078 const double * STK_Interface::getNodeCoordinates(stk::mesh::Entity node) const
1079 {
1080  return stk::mesh::field_data(*coordinatesField_,node);
1081 }
1082 
1083 void STK_Interface::getSubcellIndices(unsigned entityRank,stk::mesh::EntityId elementId,
1084  std::vector<stk::mesh::EntityId> & subcellIds) const
1085 {
1086  stk::mesh::EntityRank elementRank = getElementRank();
1087  stk::mesh::Entity cell = bulkData_->get_entity(elementRank,elementId);
1088 
1089  TEUCHOS_TEST_FOR_EXCEPTION(!bulkData_->is_valid(cell),std::logic_error,
1090  "STK_Interface::getSubcellIndices: could not find element requested (GID = " << elementId << ")");
1091 
1092  const size_t numSubcells = bulkData_->num_connectivity(cell, static_cast<stk::mesh::EntityRank>(entityRank));
1093  stk::mesh::Entity const* subcells = bulkData_->begin(cell, static_cast<stk::mesh::EntityRank>(entityRank));
1094  subcellIds.clear();
1095  subcellIds.resize(numSubcells,0);
1096 
1097  // loop over relations and fill subcell vector
1098  for(size_t i = 0; i < numSubcells; ++i) {
1099  stk::mesh::Entity subcell = subcells[i];
1100  subcellIds[i] = bulkData_->identifier(subcell);
1101  }
1102 }
1103 
1104 void STK_Interface::getMyElements(std::vector<stk::mesh::Entity> & elements) const
1105 {
1106  // setup local ownership
1107  stk::mesh::Selector ownedPart = metaData_->locally_owned_part();
1108 
1109  // grab elements
1110  stk::mesh::EntityRank elementRank = getElementRank();
1111  stk::mesh::get_selected_entities(ownedPart,bulkData_->buckets(elementRank),elements);
1112 }
1113 
1114 void STK_Interface::getMyElements(const std::string & blockID,std::vector<stk::mesh::Entity> & elements) const
1115 {
1116  stk::mesh::Part * elementBlock = getElementBlockPart(blockID);
1117 
1118  TEUCHOS_TEST_FOR_EXCEPTION(elementBlock==0,std::logic_error,"Could not find element block \"" << blockID << "\"");
1119 
1120  // setup local ownership
1121  // stk::mesh::Selector block = *elementBlock;
1122  stk::mesh::Selector ownedBlock = metaData_->locally_owned_part() & (*elementBlock);
1123 
1124  // grab elements
1125  stk::mesh::EntityRank elementRank = getElementRank();
1126  stk::mesh::get_selected_entities(ownedBlock,bulkData_->buckets(elementRank),elements);
1127 }
1128 
1129 void STK_Interface::getNeighborElements(std::vector<stk::mesh::Entity> & elements) const
1130 {
1131  // setup local ownership
1132  stk::mesh::Selector neighborBlock = (!metaData_->locally_owned_part());
1133 
1134  // grab elements
1135  stk::mesh::EntityRank elementRank = getElementRank();
1136  stk::mesh::get_selected_entities(neighborBlock,bulkData_->buckets(elementRank),elements);
1137 }
1138 
1139 void STK_Interface::getNeighborElements(const std::string & blockID,std::vector<stk::mesh::Entity> & elements) const
1140 {
1141  stk::mesh::Part * elementBlock = getElementBlockPart(blockID);
1142 
1143  TEUCHOS_TEST_FOR_EXCEPTION(elementBlock==0,std::logic_error,"Could not find element block \"" << blockID << "\"");
1144 
1145  // setup local ownership
1146  stk::mesh::Selector neighborBlock = (!metaData_->locally_owned_part()) & (*elementBlock);
1147 
1148  // grab elements
1149  stk::mesh::EntityRank elementRank = getElementRank();
1150  stk::mesh::get_selected_entities(neighborBlock,bulkData_->buckets(elementRank),elements);
1151 }
1152 
1153 void STK_Interface::getMyEdges(std::vector<stk::mesh::Entity> & edges) const
1154 {
1155  // setup local ownership
1156  stk::mesh::Selector ownedPart = metaData_->locally_owned_part();
1157 
1158  // grab elements
1159  stk::mesh::get_selected_entities(ownedPart,bulkData_->buckets(getEdgeRank()),edges);
1160 }
1161 
1162 void STK_Interface::getMyEdges(const std::string & edgeBlockName,std::vector<stk::mesh::Entity> & edges) const
1163 {
1164  stk::mesh::Part * edgeBlockPart = getEdgeBlock(edgeBlockName);
1165  TEUCHOS_TEST_FOR_EXCEPTION(edgeBlockPart==0,std::logic_error,
1166  "Unknown edge block \"" << edgeBlockName << "\"");
1167 
1168  stk::mesh::Selector edge_block = *edgeBlockPart;
1169  stk::mesh::Selector owned_block = metaData_->locally_owned_part() & edge_block;
1170 
1171  // grab elements
1172  stk::mesh::get_selected_entities(owned_block,bulkData_->buckets(getEdgeRank()),edges);
1173 }
1174 
1175 void STK_Interface::getMyEdges(const std::string & edgeBlockName,const std::string & blockName,std::vector<stk::mesh::Entity> & edges) const
1176 {
1177  stk::mesh::Part * edgeBlockPart = getEdgeBlock(edgeBlockName);
1178  stk::mesh::Part * elmtPart = getElementBlockPart(blockName);
1180  "Unknown edge block \"" << edgeBlockName << "\"");
1182  "Unknown element block \"" << blockName << "\"");
1183 
1184  stk::mesh::Selector edge_block = *edgeBlockPart;
1185  stk::mesh::Selector element_block = *elmtPart;
1186  stk::mesh::Selector owned_block = metaData_->locally_owned_part() & element_block & edge_block;
1187 
1188  // grab elements
1189  stk::mesh::get_selected_entities(owned_block,bulkData_->buckets(getEdgeRank()),edges);
1190 }
1191 
1192 void STK_Interface::getAllEdges(const std::string & edgeBlockName,std::vector<stk::mesh::Entity> & edges) const
1193 {
1194  stk::mesh::Part * edgeBlockPart = getEdgeBlock(edgeBlockName);
1195  TEUCHOS_TEST_FOR_EXCEPTION(edgeBlockPart==0,std::logic_error,
1196  "Unknown edge block \"" << edgeBlockName << "\"");
1197 
1198  stk::mesh::Selector edge_block = *edgeBlockPart;
1199 
1200  // grab elements
1201  stk::mesh::get_selected_entities(edge_block,bulkData_->buckets(getEdgeRank()),edges);
1202 }
1203 
1204 void STK_Interface::getAllEdges(const std::string & edgeBlockName,const std::string & blockName,std::vector<stk::mesh::Entity> & edges) const
1205 {
1206  stk::mesh::Part * edgeBlockPart = getEdgeBlock(edgeBlockName);
1207  stk::mesh::Part * elmtPart = getElementBlockPart(blockName);
1209  "Unknown edge block \"" << edgeBlockName << "\"");
1211  "Unknown element block \"" << blockName << "\"");
1212 
1213  stk::mesh::Selector edge_block = *edgeBlockPart;
1214  stk::mesh::Selector element_block = *elmtPart;
1215  stk::mesh::Selector element_edge_block = element_block & edge_block;
1216 
1217  // grab elements
1218  stk::mesh::get_selected_entities(element_edge_block,bulkData_->buckets(getEdgeRank()),edges);
1219 }
1220 
1221 void STK_Interface::getMyFaces(std::vector<stk::mesh::Entity> & faces) const
1222 {
1223  // setup local ownership
1224  stk::mesh::Selector ownedPart = metaData_->locally_owned_part();
1225 
1226  // grab elements
1227  stk::mesh::EntityRank faceRank = getFaceRank();
1228  stk::mesh::get_selected_entities(ownedPart,bulkData_->buckets(faceRank),faces);
1229 }
1230 
1231 void STK_Interface::getMyFaces(const std::string & faceBlockName,std::vector<stk::mesh::Entity> & faces) const
1232 {
1233  stk::mesh::Part * faceBlockPart = getFaceBlock(faceBlockName);
1234  TEUCHOS_TEST_FOR_EXCEPTION(faceBlockPart==0,std::logic_error,
1235  "Unknown face block \"" << faceBlockName << "\"");
1236 
1237  stk::mesh::Selector face_block = *faceBlockPart;
1238  stk::mesh::Selector owned_block = metaData_->locally_owned_part() & face_block;
1239 
1240  // grab elements
1241  stk::mesh::get_selected_entities(owned_block,bulkData_->buckets(getFaceRank()),faces);
1242 }
1243 
1244 void STK_Interface::getMyFaces(const std::string & faceBlockName,const std::string & blockName,std::vector<stk::mesh::Entity> & faces) const
1245 {
1246  stk::mesh::Part * faceBlockPart = getFaceBlock(faceBlockName);
1247  stk::mesh::Part * elmtPart = getElementBlockPart(blockName);
1249  "Unknown face block \"" << faceBlockName << "\"");
1251  "Unknown element block \"" << blockName << "\"");
1252 
1253  stk::mesh::Selector face_block = *faceBlockPart;
1254  stk::mesh::Selector element_block = *elmtPart;
1255  stk::mesh::Selector owned_block = metaData_->locally_owned_part() & element_block & face_block;
1256 
1257  // grab elements
1258  stk::mesh::get_selected_entities(owned_block,bulkData_->buckets(getFaceRank()),faces);
1259 }
1260 
1261 void STK_Interface::getAllFaces(const std::string & faceBlockName,std::vector<stk::mesh::Entity> & faces) const
1262 {
1263  stk::mesh::Part * faceBlockPart = getFaceBlock(faceBlockName);
1264  TEUCHOS_TEST_FOR_EXCEPTION(faceBlockPart==0,std::logic_error,
1265  "Unknown face block \"" << faceBlockName << "\"");
1266 
1267  stk::mesh::Selector face_block = *faceBlockPart;
1268 
1269  // grab elements
1270  stk::mesh::get_selected_entities(face_block,bulkData_->buckets(getFaceRank()),faces);
1271 }
1272 
1273 void STK_Interface::getAllFaces(const std::string & faceBlockName,const std::string & blockName,std::vector<stk::mesh::Entity> & faces) const
1274 {
1275  stk::mesh::Part * faceBlockPart = getFaceBlock(faceBlockName);
1276  stk::mesh::Part * elmtPart = getElementBlockPart(blockName);
1278  "Unknown face block \"" << faceBlockName << "\"");
1280  "Unknown element block \"" << blockName << "\"");
1281 
1282  stk::mesh::Selector face_block = *faceBlockPart;
1283  stk::mesh::Selector element_block = *elmtPart;
1284  stk::mesh::Selector element_face_block = element_block & face_block;
1285 
1286  // grab elements
1287  stk::mesh::get_selected_entities(element_face_block,bulkData_->buckets(getFaceRank()),faces);
1288 }
1289 
1290 void STK_Interface::getMySides(const std::string & sideName,std::vector<stk::mesh::Entity> & sides) const
1291 {
1292  stk::mesh::Part * sidePart = getSideset(sideName);
1293  TEUCHOS_TEST_FOR_EXCEPTION(sidePart==0,std::logic_error,
1294  "Unknown side set \"" << sideName << "\"");
1295 
1296  stk::mesh::Selector side = *sidePart;
1297  stk::mesh::Selector ownedBlock = metaData_->locally_owned_part() & side;
1298 
1299  // grab elements
1300  stk::mesh::get_selected_entities(ownedBlock,bulkData_->buckets(getSideRank()),sides);
1301 }
1302 
1303 void STK_Interface::getMySides(const std::string & sideName,const std::string & blockName,std::vector<stk::mesh::Entity> & sides) const
1304 {
1305  stk::mesh::Part * sidePart = getSideset(sideName);
1306  stk::mesh::Part * elmtPart = getElementBlockPart(blockName);
1308  "Unknown side set \"" << sideName << "\"");
1310  "Unknown element block \"" << blockName << "\"");
1311 
1312  stk::mesh::Selector side = *sidePart;
1313  stk::mesh::Selector block = *elmtPart;
1314  stk::mesh::Selector ownedBlock = metaData_->locally_owned_part() & block & side;
1315 
1316  // grab elements
1317  stk::mesh::get_selected_entities(ownedBlock,bulkData_->buckets(getSideRank()),sides);
1318 }
1319 
1320 void STK_Interface::getAllSides(const std::string & sideName,std::vector<stk::mesh::Entity> & sides) const
1321 {
1322  stk::mesh::Part * sidePart = getSideset(sideName);
1323  TEUCHOS_TEST_FOR_EXCEPTION(sidePart==0,std::logic_error,
1324  "Unknown side set \"" << sideName << "\"");
1325 
1326  stk::mesh::Selector side = *sidePart;
1327 
1328  // grab elements
1329  stk::mesh::get_selected_entities(side,bulkData_->buckets(getSideRank()),sides);
1330 }
1331 
1332 void STK_Interface::getAllSides(const std::string & sideName,const std::string & blockName,std::vector<stk::mesh::Entity> & sides) const
1333 {
1334  stk::mesh::Part * sidePart = getSideset(sideName);
1335  stk::mesh::Part * elmtPart = getElementBlockPart(blockName);
1337  "Unknown side set \"" << sideName << "\"");
1339  "Unknown element block \"" << blockName << "\"");
1340 
1341  stk::mesh::Selector side = *sidePart;
1342  stk::mesh::Selector block = *elmtPart;
1343  stk::mesh::Selector sideBlock = block & side;
1344 
1345  // grab elements
1346  stk::mesh::get_selected_entities(sideBlock,bulkData_->buckets(getSideRank()),sides);
1347 }
1348 
1349 void STK_Interface::getMyNodes(const std::string & nodesetName,const std::string & blockName,std::vector<stk::mesh::Entity> & nodes) const
1350 {
1351  stk::mesh::Part * nodePart = getNodeset(nodesetName);
1352  stk::mesh::Part * elmtPart = getElementBlockPart(blockName);
1354  "Unknown node set \"" << nodesetName << "\"");
1356  "Unknown element block \"" << blockName << "\"");
1357 
1358  stk::mesh::Selector nodeset = *nodePart;
1359  stk::mesh::Selector block = *elmtPart;
1360  stk::mesh::Selector ownedBlock = metaData_->locally_owned_part() & block & nodeset;
1361 
1362  // grab elements
1363  stk::mesh::get_selected_entities(ownedBlock,bulkData_->buckets(getNodeRank()),nodes);
1364 }
1365 
1366 void STK_Interface::getElementBlockNames(std::vector<std::string> & names) const
1367 {
1368  // TEUCHOS_ASSERT(initialized_); // all blocks must have been added
1369 
1370  names.clear();
1371 
1372  // fill vector with automagically ordered string values
1373  std::map<std::string, stk::mesh::Part*>::const_iterator blkItr; // Element blocks
1374  for(blkItr=elementBlocks_.begin();blkItr!=elementBlocks_.end();++blkItr)
1375  names.push_back(blkItr->first);
1376 }
1377 
1378 void STK_Interface::getSidesetNames(std::vector<std::string> & names) const
1379 {
1380  // TEUCHOS_ASSERT(initialized_); // all blocks must have been added
1381 
1382  names.clear();
1383 
1384  // fill vector with automagically ordered string values
1385  std::map<std::string, stk::mesh::Part*>::const_iterator sideItr; // Side sets
1386  for(sideItr=sidesets_.begin();sideItr!=sidesets_.end();++sideItr)
1387  names.push_back(sideItr->first);
1388 }
1389 
1390 void STK_Interface::getNodesetNames(std::vector<std::string> & names) const
1391 {
1392  names.clear();
1393 
1394  // fill vector with automagically ordered string values
1395  std::map<std::string, stk::mesh::Part*>::const_iterator nodeItr; // Node sets
1396  for(nodeItr=nodesets_.begin();nodeItr!=nodesets_.end();++nodeItr)
1397  names.push_back(nodeItr->first);
1398 }
1399 
1400 void STK_Interface::getEdgeBlockNames(std::vector<std::string> & names) const
1401 {
1402  names.clear();
1403 
1404  // fill vector with automagically ordered string values
1405  std::map<std::string, stk::mesh::Part*>::const_iterator edgeBlockItr; // Edge blocks
1406  for(edgeBlockItr=edgeBlocks_.begin();edgeBlockItr!=edgeBlocks_.end();++edgeBlockItr)
1407  names.push_back(edgeBlockItr->first);
1408 }
1409 
1410 void STK_Interface::getFaceBlockNames(std::vector<std::string> & names) const
1411 {
1412  names.clear();
1413 
1414  // fill vector with automagically ordered string values
1415  std::map<std::string, stk::mesh::Part*>::const_iterator faceBlockItr; // Face blocks
1416  for(faceBlockItr=faceBlocks_.begin();faceBlockItr!=faceBlocks_.end();++faceBlockItr)
1417  names.push_back(faceBlockItr->first);
1418 }
1419 
1420 std::size_t STK_Interface::elementLocalId(stk::mesh::Entity elmt) const
1421 {
1422  return elementLocalId(bulkData_->identifier(elmt));
1423  // const std::size_t * fieldCoords = stk::mesh::field_data(*localIdField_,*elmt);
1424  // return fieldCoords[0];
1425 }
1426 
1427 std::size_t STK_Interface::elementLocalId(stk::mesh::EntityId gid) const
1428 {
1429  // stk::mesh::EntityRank elementRank = getElementRank();
1430  // stk::mesh::Entity elmt = bulkData_->get_entity(elementRank,gid);
1431  // TEUCHOS_ASSERT(elmt->owner_rank()==procRank_);
1432  // return elementLocalId(elmt);
1433  std::unordered_map<stk::mesh::EntityId,std::size_t>::const_iterator itr = localIDHash_.find(gid);
1434  TEUCHOS_ASSERT(itr!=localIDHash_.end());
1435  return itr->second;
1436 }
1437 
1438 bool STK_Interface::isEdgeLocal(stk::mesh::Entity edge) const
1439 {
1440  return isEdgeLocal(bulkData_->identifier(edge));
1441 }
1442 
1443 bool STK_Interface::isEdgeLocal(stk::mesh::EntityId gid) const
1444 {
1445  std::unordered_map<stk::mesh::EntityId,std::size_t>::const_iterator itr = localEdgeIDHash_.find(gid);
1446  if (itr==localEdgeIDHash_.end()) {
1447  return false;
1448  }
1449  return true;
1450 }
1451 
1452 std::size_t STK_Interface::edgeLocalId(stk::mesh::Entity edge) const
1453 {
1454  return edgeLocalId(bulkData_->identifier(edge));
1455 }
1456 
1457 std::size_t STK_Interface::edgeLocalId(stk::mesh::EntityId gid) const
1458 {
1459  std::unordered_map<stk::mesh::EntityId,std::size_t>::const_iterator itr = localEdgeIDHash_.find(gid);
1460  TEUCHOS_ASSERT(itr!=localEdgeIDHash_.end());
1461  return itr->second;
1462 }
1463 
1464 bool STK_Interface::isFaceLocal(stk::mesh::Entity face) const
1465 {
1466  return isFaceLocal(bulkData_->identifier(face));
1467 }
1468 
1469 bool STK_Interface::isFaceLocal(stk::mesh::EntityId gid) const
1470 {
1471  std::unordered_map<stk::mesh::EntityId,std::size_t>::const_iterator itr = localFaceIDHash_.find(gid);
1472  if (itr==localFaceIDHash_.end()) {
1473  return false;
1474  }
1475  return true;
1476 }
1477 
1478 std::size_t STK_Interface::faceLocalId(stk::mesh::Entity face) const
1479 {
1480  return faceLocalId(bulkData_->identifier(face));
1481 }
1482 
1483 std::size_t STK_Interface::faceLocalId(stk::mesh::EntityId gid) const
1484 {
1485  std::unordered_map<stk::mesh::EntityId,std::size_t>::const_iterator itr = localFaceIDHash_.find(gid);
1486  TEUCHOS_ASSERT(itr!=localFaceIDHash_.end());
1487  return itr->second;
1488 }
1489 
1490 
1491 std::string STK_Interface::containingBlockId(stk::mesh::Entity elmt) const
1492 {
1493  for(const auto & eb_pair : elementBlocks_)
1494  if(bulkData_->bucket(elmt).member(*(eb_pair.second)))
1495  return eb_pair.first;
1496  return "";
1497 }
1498 
1499 stk::mesh::Field<double> * STK_Interface::getSolutionField(const std::string & fieldName,
1500  const std::string & blockId) const
1501 {
1502  // look up field in map
1503  std::map<std::pair<std::string,std::string>, SolutionFieldType*>::const_iterator
1504  iter = fieldNameToSolution_.find(std::make_pair(fieldName,blockId));
1505 
1506  // check to make sure field was actually found
1507  TEUCHOS_TEST_FOR_EXCEPTION(iter==fieldNameToSolution_.end(),std::runtime_error,
1508  "Solution field name \"" << fieldName << "\" in block ID \"" << blockId << "\" was not found");
1509 
1510  return iter->second;
1511 }
1512 
1513 stk::mesh::Field<double> * STK_Interface::getCellField(const std::string & fieldName,
1514  const std::string & blockId) const
1515 {
1516  // look up field in map
1517  std::map<std::pair<std::string,std::string>, SolutionFieldType*>::const_iterator
1518  iter = fieldNameToCellField_.find(std::make_pair(fieldName,blockId));
1519 
1520  // check to make sure field was actually found
1521  TEUCHOS_TEST_FOR_EXCEPTION(iter==fieldNameToCellField_.end(),std::runtime_error,
1522  "Cell field named \"" << fieldName << "\" in block ID \"" << blockId << "\" was not found");
1523 
1524  return iter->second;
1525 }
1526 
1527 stk::mesh::Field<double> * STK_Interface::getEdgeField(const std::string & fieldName,
1528  const std::string & blockId) const
1529 {
1530  // look up field in map
1531  std::map<std::pair<std::string,std::string>, SolutionFieldType*>::const_iterator
1532  iter = fieldNameToEdgeField_.find(std::make_pair(fieldName,blockId));
1533 
1534  // check to make sure field was actually found
1535  TEUCHOS_TEST_FOR_EXCEPTION(iter==fieldNameToEdgeField_.end(),std::runtime_error,
1536  "Edge field named \"" << fieldName << "\" in block ID \"" << blockId << "\" was not found");
1537 
1538  return iter->second;
1539 }
1540 
1541 stk::mesh::Field<double> * STK_Interface::getFaceField(const std::string & fieldName,
1542  const std::string & blockId) const
1543 {
1544  // look up field in map
1545  std::map<std::pair<std::string,std::string>, SolutionFieldType*>::const_iterator
1546  iter = fieldNameToFaceField_.find(std::make_pair(fieldName,blockId));
1547 
1548  // check to make sure field was actually found
1549  TEUCHOS_TEST_FOR_EXCEPTION(iter==fieldNameToFaceField_.end(),std::runtime_error,
1550  "Face field named \"" << fieldName << "\" in block ID \"" << blockId << "\" was not found");
1551 
1552  return iter->second;
1553 }
1554 
1556 {
1557  using Teuchos::RCP;
1558  using Teuchos::rcp;
1559 
1560  if(orderedElementVector_==Teuchos::null) {
1561  // safe because essentially this is a call to modify a mutable object
1562  const_cast<STK_Interface*>(this)->buildLocalElementIDs();
1563  }
1564 
1566 }
1567 
1568 void STK_Interface::addElementBlock(const std::string & name,const CellTopologyData * ctData)
1569 {
1571 
1572  stk::mesh::Part * block = metaData_->get_part(name);
1573  if(block==0) {
1574  block = &metaData_->declare_part_with_topology(name, stk::mesh::get_topology(shards::CellTopology(ctData), dimension_));
1575  }
1576 
1577  // construct cell topology object for this block
1579  = Teuchos::rcp(new shards::CellTopology(ctData));
1580 
1581  // add element block part and cell topology
1582  elementBlocks_.insert(std::make_pair(name,block));
1583  elementBlockCT_.insert(std::make_pair(name,ct));
1584 }
1585 
1587 {
1588  using Teuchos::RCP;
1589  using Teuchos::rcp;
1590 
1591  if(orderedEdgeVector_==Teuchos::null) {
1592  // safe because essentially this is a call to modify a mutable object
1593  const_cast<STK_Interface*>(this)->buildLocalEdgeIDs();
1594  }
1595 
1596  return orderedEdgeVector_.getConst();
1597 }
1598 
1599 void STK_Interface::addEdgeBlock(const std::string & elemBlockName,
1600  const std::string & edgeBlockName,
1601  const stk::topology & topology)
1602 {
1604 
1605  stk::mesh::Part * edge_block = metaData_->get_part(edgeBlockName);
1606  if(edge_block==0) {
1607  edge_block = &metaData_->declare_part_with_topology(edgeBlockName, topology);
1608  }
1609 
1610  /* There is only one edge block for each edge topology, so declare it
1611  * as a subset of the element block even if it wasn't just created.
1612  */
1613  stk::mesh::Part * elem_block = metaData_->get_part(elemBlockName);
1614  metaData_->declare_part_subset(*elem_block, *edge_block);
1615 
1616  // add edge block part
1617  edgeBlocks_.insert(std::make_pair(edgeBlockName,edge_block));
1618 }
1619 
1620 void STK_Interface::addEdgeBlock(const std::string & elemBlockName,
1621  const std::string & edgeBlockName,
1622  const CellTopologyData * ctData)
1623 {
1625 
1626  addEdgeBlock(elemBlockName,
1627  edgeBlockName,
1628  stk::mesh::get_topology(shards::CellTopology(ctData), dimension_));
1629 }
1630 
1632 {
1633  using Teuchos::RCP;
1634  using Teuchos::rcp;
1635 
1636  if(orderedFaceVector_==Teuchos::null) {
1637  // safe because essentially this is a call to modify a mutable object
1638  const_cast<STK_Interface*>(this)->buildLocalFaceIDs();
1639  }
1640 
1641  return orderedFaceVector_.getConst();
1642 }
1643 
1644 void STK_Interface::addFaceBlock(const std::string & elemBlockName,
1645  const std::string & faceBlockName,
1646  const stk::topology & topology)
1647 {
1649 
1650  stk::mesh::Part * face_block = metaData_->get_part(faceBlockName);
1651  if(face_block==0) {
1652  face_block = &metaData_->declare_part_with_topology(faceBlockName, topology);
1653  }
1654 
1655  /* There is only one face block for each edge topology, so declare it
1656  * as a subset of the element block even if it wasn't just created.
1657  */
1658  stk::mesh::Part * elem_block = metaData_->get_part(elemBlockName);
1659  metaData_->declare_part_subset(*elem_block, *face_block);
1660 
1661  // add face block part
1662  faceBlocks_.insert(std::make_pair(faceBlockName,face_block));
1663 }
1664 
1665 void STK_Interface::addFaceBlock(const std::string & elemBlockName,
1666  const std::string & faceBlockName,
1667  const CellTopologyData * ctData)
1668 {
1670 
1671  addFaceBlock(elemBlockName,
1672  faceBlockName,
1673  stk::mesh::get_topology(shards::CellTopology(ctData), dimension_));
1674 }
1675 
1677 {
1678  dimension_ = metaData_->spatial_dimension();
1679 
1680  // declare coordinates and node parts
1681  coordinatesField_ = &metaData_->declare_field<double>(stk::topology::NODE_RANK, coordsString);
1682  edgesField_ = &metaData_->declare_field<double>(stk::topology::EDGE_RANK, edgesString);
1683  if (dimension_ > 2)
1684  facesField_ = &metaData_->declare_field<double>(stk::topology::FACE_RANK, facesString);
1685  processorIdField_ = &metaData_->declare_field<ProcIdData>(stk::topology::ELEMENT_RANK, "PROC_ID");
1686  loadBalField_ = &metaData_->declare_field<double>(stk::topology::ELEMENT_RANK, "LOAD_BAL");
1687 
1688  // stk::mesh::put_field( *coordinatesField_ , getNodeRank() , metaData_->universal_part() );
1689 
1690  nodesPart_ = &metaData_->declare_part(nodesString,getNodeRank());
1691  nodesPartVec_.push_back(nodesPart_);
1692  edgesPart_ = &metaData_->declare_part(edgesString,getEdgeRank());
1693  edgesPartVec_.push_back(edgesPart_);
1694  if (dimension_ > 2) {
1695  facesPart_ = &metaData_->declare_part(facesString,getFaceRank());
1696  facesPartVec_.push_back(facesPart_);
1697  }
1698 }
1699 
1701 {
1702  currentLocalId_ = 0;
1703 
1704  orderedElementVector_ = Teuchos::null; // forces rebuild of ordered lists
1705 
1706  // might be better (faster) to do this by buckets
1707  std::vector<stk::mesh::Entity> elements;
1708  getMyElements(elements);
1709 
1710  for(std::size_t index=0;index<elements.size();++index) {
1711  stk::mesh::Entity element = elements[index];
1712 
1713  // set processor rank
1714  ProcIdData * procId = stk::mesh::field_data(*processorIdField_,element);
1715  procId[0] = Teuchos::as<ProcIdData>(procRank_);
1716 
1717  localIDHash_[bulkData_->identifier(element)] = currentLocalId_;
1718 
1719  currentLocalId_++;
1720  }
1721 
1722  // copy elements into the ordered element vector
1723  orderedElementVector_ = Teuchos::rcp(new std::vector<stk::mesh::Entity>(elements));
1724 
1725  elements.clear();
1726  getNeighborElements(elements);
1727 
1728  for(std::size_t index=0;index<elements.size();++index) {
1729  stk::mesh::Entity element = elements[index];
1730 
1731  // set processor rank
1732  ProcIdData * procId = stk::mesh::field_data(*processorIdField_,element);
1733  procId[0] = Teuchos::as<ProcIdData>(procRank_);
1734 
1735  localIDHash_[bulkData_->identifier(element)] = currentLocalId_;
1736 
1737  currentLocalId_++;
1738  }
1739 
1740  orderedElementVector_->insert(orderedElementVector_->end(),elements.begin(),elements.end());
1741 }
1742 
1744 {
1745  std::vector<std::string> names;
1746  getElementBlockNames(names);
1747 
1748  for(std::size_t b=0;b<names.size();b++) {
1749  // find user specified block weight, otherwise use 1.0
1750  std::map<std::string,double>::const_iterator bw_itr = blockWeights_.find(names[b]);
1751  double blockWeight = (bw_itr!=blockWeights_.end()) ? bw_itr->second : 1.0;
1752 
1753  std::vector<stk::mesh::Entity> elements;
1754  getMyElements(names[b],elements);
1755 
1756  for(std::size_t index=0;index<elements.size();++index) {
1757  // set local element ID
1758  double * loadBal = stk::mesh::field_data(*loadBalField_,elements[index]);
1759  loadBal[0] = blockWeight;
1760  }
1761  }
1762 }
1763 
1765 {
1766  currentLocalId_ = 0;
1767 
1768  orderedEdgeVector_ = Teuchos::null; // forces rebuild of ordered lists
1769 
1770  // might be better (faster) to do this by buckets
1771  std::vector<stk::mesh::Entity> edges;
1772  getMyEdges(edges);
1773 
1774  for(std::size_t index=0;index<edges.size();++index) {
1775  stk::mesh::Entity edge = edges[index];
1776  localEdgeIDHash_[bulkData_->identifier(edge)] = currentLocalId_;
1777  currentLocalId_++;
1778  }
1779 
1780  // copy edges into the ordered edge vector
1781  orderedEdgeVector_ = Teuchos::rcp(new std::vector<stk::mesh::Entity>(edges));
1782 }
1783 
1785 {
1786  currentLocalId_ = 0;
1787 
1788  orderedFaceVector_ = Teuchos::null; // forces rebuild of ordered lists
1789 
1790  // might be better (faster) to do this by buckets
1791  std::vector<stk::mesh::Entity> faces;
1792  getMyFaces(faces);
1793 
1794  for(std::size_t index=0;index<faces.size();++index) {
1795  stk::mesh::Entity face = faces[index];
1796  localFaceIDHash_[bulkData_->identifier(face)] = currentLocalId_;
1797  currentLocalId_++;
1798  }
1799 
1800  // copy faces into the ordered face vector
1801  orderedFaceVector_ = Teuchos::rcp(new std::vector<stk::mesh::Entity>(faces));
1802 }
1803 
1804 bool
1805 STK_Interface::isMeshCoordField(const std::string & eBlock,
1806  const std::string & fieldName,
1807  int & axis) const
1808 {
1809  std::map<std::string,std::vector<std::string> >::const_iterator blkItr = meshCoordFields_.find(eBlock);
1810  if(blkItr==meshCoordFields_.end()) {
1811  return false;
1812  }
1813 
1814  axis = 0;
1815  for(axis=0;axis<Teuchos::as<int>(blkItr->second.size());axis++) {
1816  if(blkItr->second[axis]==fieldName)
1817  break; // found axis, break
1818  }
1819 
1820  if(axis>=Teuchos::as<int>(blkItr->second.size()))
1821  return false;
1822 
1823  return true;
1824 }
1825 
1826 std::pair<Teuchos::RCP<std::vector<std::pair<std::size_t,std::size_t> > >, Teuchos::RCP<std::vector<unsigned int> > >
1828 {
1830  Teuchos::RCP<std::vector<unsigned int > > type_vec = rcp(new std::vector<unsigned int>);
1831  const std::vector<Teuchos::RCP<const PeriodicBC_MatcherBase> > & matchers = getPeriodicBCVector();
1832  const bool & useBBoxSearch = useBoundingBoxSearch();
1833  std::vector<std::vector<std::string> > matchedSides(3); // (coord,edge,face)
1834 
1835  // build up the vectors by looping over the matched pair
1836  for(std::size_t m=0;m<matchers.size();m++){
1837  unsigned int type;
1838  if(matchers[m]->getType() == "coord")
1839  type = 0;
1840  else if(matchers[m]->getType() == "edge")
1841  type = 1;
1842  else if(matchers[m]->getType() == "face")
1843  type = 2;
1844  else
1845  TEUCHOS_ASSERT(false);
1846 #ifdef PANZER_HAVE_STKSEARCH
1847 
1848  if (useBBoxSearch) {
1849  vec = matchers[m]->getMatchedPair(*this,matchedSides[type],vec);
1850  } else {
1851  vec = matchers[m]->getMatchedPair(*this,vec);
1852  }
1853 #else
1854  TEUCHOS_TEST_FOR_EXCEPTION(useBBoxSearch,std::logic_error,
1855  "panzer::STK_Interface::getPeriodicNodePairing(): Requested bounding box search, but "
1856  "did not compile with STK_SEARCH enabled.");
1857  vec = matchers[m]->getMatchedPair(*this,vec);
1858 #endif
1859  type_vec->insert(type_vec->begin(),vec->size()-type_vec->size(),type);
1860  matchedSides[type].push_back(matchers[m]->getLeftSidesetName());
1861  }
1862 
1863  return std::make_pair(vec,type_vec);
1864 }
1865 
1866 bool STK_Interface::validBlockId(const std::string & blockId) const
1867 {
1868  std::map<std::string, stk::mesh::Part*>::const_iterator blkItr = elementBlocks_.find(blockId);
1869 
1870  return blkItr!=elementBlocks_.end();
1871 }
1872 
1873 void STK_Interface::print(std::ostream & os) const
1874 {
1875  std::vector<std::string> blockNames, sidesetNames, nodesetNames;
1876 
1877  getElementBlockNames(blockNames);
1878  getSidesetNames(sidesetNames);
1879  getNodesetNames(nodesetNames);
1880 
1881  os << "STK Mesh data:\n";
1882  os << " Spatial dim = " << getDimension() << "\n";
1883  if(getDimension()==2)
1884  os << " Entity counts (Nodes, Edges, Cells) = ( "
1885  << getEntityCounts(getNodeRank()) << ", "
1886  << getEntityCounts(getEdgeRank()) << ", "
1887  << getEntityCounts(getElementRank()) << " )\n";
1888  else if(getDimension()==3)
1889  os << " Entity counts (Nodes, Edges, Faces, Cells) = ( "
1890  << getEntityCounts(getNodeRank()) << ", "
1891  << getEntityCounts(getEdgeRank()) << ", "
1892  << getEntityCounts(getSideRank()) << ", "
1893  << getEntityCounts(getElementRank()) << " )\n";
1894  else
1895  os << " Entity counts (Nodes, Cells) = ( "
1896  << getEntityCounts(getNodeRank()) << ", "
1897  << getEntityCounts(getElementRank()) << " )\n";
1898 
1899  os << " Element blocks = ";
1900  for(std::size_t i=0;i<blockNames.size();i++)
1901  os << "\"" << blockNames[i] << "\" ";
1902  os << "\n";
1903  os << " Sidesets = ";
1904  for(std::size_t i=0;i<sidesetNames.size();i++)
1905  os << "\"" << sidesetNames[i] << "\" ";
1906  os << "\n";
1907  os << " Nodesets = ";
1908  for(std::size_t i=0;i<nodesetNames.size();i++)
1909  os << "\"" << nodesetNames[i] << "\" ";
1910  os << std::endl;
1911 
1912  // print out periodic boundary conditions
1913  const std::vector<Teuchos::RCP<const PeriodicBC_MatcherBase> > & bcVector
1914  = getPeriodicBCVector();
1915  if(bcVector.size()!=0) {
1916  os << " Periodic BCs:\n";
1917  for(std::size_t i=0;i<bcVector.size();i++)
1918  os << " " << bcVector[i]->getString() << "\n";
1919  os << std::endl;
1920  }
1921 }
1922 
1923 void STK_Interface::printMetaData(std::ostream & os) const
1924 {
1925  std::vector<std::string> blockNames, sidesetNames, nodesetNames;
1926 
1927  getElementBlockNames(blockNames);
1928  getSidesetNames(sidesetNames);
1929  getNodesetNames(nodesetNames);
1930 
1931  os << "STK Meta data:\n";
1932  os << " Element blocks = ";
1933  for(std::size_t i=0;i<blockNames.size();i++)
1934  os << "\"" << blockNames[i] << "\" ";
1935  os << "\n";
1936  os << " Sidesets = ";
1937  for(std::size_t i=0;i<sidesetNames.size();i++)
1938  os << "\"" << sidesetNames[i] << "\" ";
1939  os << "\n";
1940  os << " Nodesets = ";
1941  for(std::size_t i=0;i<nodesetNames.size();i++)
1942  os << "\"" << nodesetNames[i] << "\" ";
1943  os << std::endl;
1944 
1945  // print out periodic boundary conditions
1946  const std::vector<Teuchos::RCP<const PeriodicBC_MatcherBase> > & bcVector
1947  = getPeriodicBCVector();
1948  if(bcVector.size()!=0) {
1949  os << " Periodic BCs:\n";
1950  for(std::size_t i=0;i<bcVector.size();i++)
1951  os << " " << bcVector[i]->getString() << "\n";
1952  os << std::endl;
1953  }
1954 
1955  // print all available fields in meta data
1956  os << " Fields = ";
1957  const stk::mesh::FieldVector & fv = metaData_->get_fields();
1958  for(std::size_t i=0;i<fv.size();i++)
1959  os << "\"" << fv[i]->name() << "\" ";
1960  os << std::endl;
1961 }
1962 
1964 {
1965  std::map<std::string, Teuchos::RCP<shards::CellTopology> >::const_iterator itr;
1966  itr = elementBlockCT_.find(eBlock);
1967 
1968  if(itr==elementBlockCT_.end()) {
1969  std::stringstream ss;
1970  printMetaData(ss);
1971  TEUCHOS_TEST_FOR_EXCEPTION(itr==elementBlockCT_.end(),std::logic_error,
1972  "STK_Interface::getCellTopology: No such element block \"" +eBlock +"\" available.\n\n"
1973  << "STK Meta Data follows: \n" << ss.str());
1974  }
1975 
1976  return itr->second;
1977 }
1978 
1980 {
1981  MPI_Comm newComm;
1982  const int err = MPI_Comm_dup (parallelMach, &newComm);
1983  TEUCHOS_TEST_FOR_EXCEPTION(err != MPI_SUCCESS, std::runtime_error,
1984  "panzer::STK_Interface: MPI_Comm_dup failed with error \""
1985  << Teuchos::mpiErrorCodeToString (err) << "\".");
1986 
1987  return Teuchos::rcp(new Teuchos::MpiComm<int>(Teuchos::opaqueWrapper (newComm,MPI_Comm_free)));
1988 }
1989 
1991 {
1992  TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "Rebalance not currently supported");
1993 #if 0
1994  // make sure weights have been set (a local operation)
1996 
1997  stk::mesh::Selector selector(getMetaData()->universal_part());
1998  stk::mesh::Selector owned_selector(getMetaData()->locally_owned_part());
1999 
2000  Teuchos::FancyOStream out(Teuchos::rcpFromRef(std::cout));
2001  out.setOutputToRootOnly(0);
2002  out << "Load balance before: " << stk::rebalance::check_balance(*getBulkData(), loadBalField_, getElementRank(), &selector) << std::endl;
2003 
2004  // perform reblance
2005  Teuchos::ParameterList graph;
2006  if(params.begin()!=params.end())
2007  graph.sublist(stk::rebalance::Zoltan::default_parameters_name()) = params;
2008  stk::rebalance::Zoltan zoltan_partition(*mpiComm_->getRawMpiComm(), getDimension(), graph);
2009  stk::rebalance::rebalance(*getBulkData(), owned_selector, &getCoordinatesField(), loadBalField_, zoltan_partition);
2010 
2011  out << "Load balance after: " << stk::rebalance::check_balance(*getBulkData(), loadBalField_, getElementRank(), &selector) << std::endl;
2012 
2013  currentLocalId_ = 0;
2014  orderedElementVector_ = Teuchos::null; // forces rebuild of ordered lists
2015 #endif
2016 }
2017 
2020 {
2021  TEUCHOS_ASSERT(this->isInitialized());
2022  return mpiComm_;
2023 }
2024 
2025 void STK_Interface::refineMesh(const int numberOfLevels, const bool deleteParentElements) {
2026 #ifdef PANZER_HAVE_PERCEPT
2027  TEUCHOS_TEST_FOR_EXCEPTION(numberOfLevels < 1,std::runtime_error,
2028  "ERROR: Number of levels for uniform refinement must be greater than 0");
2029  TEUCHOS_ASSERT(nonnull(refinedMesh_));
2030  TEUCHOS_ASSERT(nonnull(breakPattern_));
2031 
2032  refinedMesh_->setCoordinatesField();
2033 
2034  percept::UniformRefiner breaker(*refinedMesh_,*breakPattern_);
2035  breaker.setRemoveOldElements(deleteParentElements);
2036 
2037  for (int i=0; i < numberOfLevels; ++i)
2038  breaker.doBreak();
2039 
2040 #else
2041  TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
2042  "ERROR: Uniform refinement requested. This requires the Percept package to be enabled in Trilinos!");
2043 #endif
2044 }
2045 
2046 
2047 } // end namespace panzer_stk
Teuchos::RCP< ElementDescriptor > buildElementDescriptor(stk::mesh::EntityId elmtId, std::vector< stk::mesh::EntityId > &nodes)
Teuchos::RCP< Teuchos::MpiComm< int > > getSafeCommunicator(stk::ParallelMachine parallelMach) const
void getSidesetNames(std::vector< std::string > &name) const
RCP< const T > getConst() const
std::pair< Teuchos::RCP< std::vector< std::pair< std::size_t, std::size_t > > >, Teuchos::RCP< std::vector< unsigned int > > > getPeriodicNodePairing() const
const bool & useBoundingBoxSearch() const
Teuchos::RCP< std::vector< stk::mesh::Entity > > orderedEdgeVector_
void addNodeset(const std::string &name)
Teuchos::RCP< stk::mesh::BulkData > bulkData_
void getFaceBlockNames(std::vector< std::string > &names) const
void print(std::ostream &os) const
void getMyEdges(std::vector< stk::mesh::Entity > &edges) const
Teuchos::RCP< const std::vector< stk::mesh::Entity > > getElementsOrderedByLID() const
std::vector< stk::mesh::Part * > facesPartVec_
std::map< std::pair< std::string, std::string >, SolutionFieldType * > fieldNameToSolution_
void addEntityToNodeset(stk::mesh::Entity entity, stk::mesh::Part *nodeset)
void addGlobalToExodus(const std::string &key, const int &value)
Add an int global variable to the information to be written to the Exodus output file.
void getElementBlockNames(std::vector< std::string > &names) const
void getSubcellIndices(unsigned entityRank, stk::mesh::EntityId elementId, std::vector< stk::mesh::EntityId > &subcellIds) const
void getElementsSharingNodes(const std::vector< stk::mesh::EntityId > nodeId, std::vector< stk::mesh::Entity > &elements) const
get a set of elements sharing multiple nodes
stk::mesh::Field< double > SolutionFieldType
stk::mesh::Part * getElementBlockPart(const std::string &name) const
get the block part
std::vector< stk::mesh::Part * > edgesPartVec_
bool isFaceLocal(stk::mesh::Entity face) const
std::map< std::string, double > blockWeights_
Teuchos::RCP< const std::vector< stk::mesh::Entity > > getEdgesOrderedByLID() const
basic_FancyOStream< char > FancyOStream
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
std::size_t getEntityCounts(unsigned entityRank) const
get the global counts for the entity of specified rank
void printMetaData(std::ostream &os) const
void addEntityToSideset(stk::mesh::Entity entity, stk::mesh::Part *sideset)
std::map< std::string, stk::mesh::Part * > faceBlocks_
void addSolutionField(const std::string &fieldName, const std::string &blockId)
std::map< std::string, Teuchos::RCP< shards::CellTopology > > elementBlockCT_
void addEntityToFaceBlock(stk::mesh::Entity entity, stk::mesh::Part *faceblock)
stk::mesh::EntityId getMaxEntityId(unsigned entityRank) const
get max entity ID of type entityRank
std::map< std::pair< std::string, std::string >, SolutionFieldType * > fieldNameToFaceField_
std::map< std::string, stk::mesh::Part * > sidesets_
std::vector< std::size_t > entityCounts_
bool validBlockId(const std::string &blockId) const
stk::mesh::Part * getNodeset(const std::string &name) const
void getEdgeBlockNames(std::vector< std::string > &names) const
stk::mesh::Part * getFaceBlock(const std::string &name) const
get the block part
void addInformationRecords(const std::vector< std::string > &info_records)
void endModification(const bool find_and_set_shared_nodes_in_stk=true)
void getAllFaces(const std::string &faceBlockName, std::vector< stk::mesh::Entity > &faces) const
stk::mesh::Field< double > * getSolutionField(const std::string &fieldName, const std::string &blockId) const
void addEdgeBlock(const std::string &elemBlockName, const std::string &edgeBlockName, const stk::topology &topology)
const double * getNodeCoordinates(stk::mesh::EntityId nodeId) const
stk::mesh::Part * getSideset(const std::string &name) const
static const std::string nodesString
void instantiateBulkData(stk::ParallelMachine parallelMach)
std::set< std::string > informationRecords_
void getMySides(const std::string &sideName, std::vector< stk::mesh::Entity > &sides) const
stk::mesh::Field< double > * getEdgeField(const std::string &fieldName, const std::string &blockId) const
std::size_t elementLocalId(stk::mesh::Entity elmt) const
unsigned getDimension() const
get the dimension
void addElement(const Teuchos::RCP< ElementDescriptor > &ed, stk::mesh::Part *block)
std::map< std::string, std::vector< std::string > > meshDispFields_
void setupExodusFile(const std::string &filename, const bool append=false, const bool append_after_restart_time=false, const double restart_time=0.0)
Set up an output Exodus file for writing results.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
stk::mesh::EntityRank getSideRank() const
void getAllEdges(const std::string &edgeBlockName, std::vector< stk::mesh::Entity > &edges) const
void initialize(stk::ParallelMachine parallelMach, bool setupIO=true, const bool buildRefinementSupport=false)
static const std::string coordsString
Teuchos::RCP< stk::mesh::BulkData > getBulkData() const
std::map< std::string, stk::mesh::Part * > edgeBlocks_
stk::mesh::EntityId elementGlobalId(std::size_t lid) const
std::map< std::string, stk::mesh::Part * > elementBlocks_
std::vector< stk::mesh::Part * > nodesPartVec_
static const std::string edgeBlockString
static const std::string edgesString
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
std::string containingBlockId(stk::mesh::Entity elmt) const
stk::mesh::EntityRank getFaceRank() const
std::size_t edgeLocalId(stk::mesh::Entity elmt) const
void getOwnedElementsSharingNode(stk::mesh::Entity node, std::vector< stk::mesh::Entity > &elements, std::vector< int > &relIds) const
void addNode(stk::mesh::EntityId gid, const std::vector< double > &coord)
void addEntitiesToEdgeBlock(std::vector< stk::mesh::Entity > entities, stk::mesh::Part *edgeblock)
void buildSubcells()
force the mesh to build subcells: edges and faces
Teuchos::RCP< Teuchos::MpiComm< int > > mpiComm_
Teuchos::RCP< stk::mesh::MetaData > metaData_
Teuchos::RCP< stk::mesh::MetaData > getMetaData() const
Teuchos::RCP< std::vector< stk::mesh::Entity > > orderedElementVector_
bool isInitialized() const
Has initialize been called on this mesh object?
TransListIter iter
void writeToExodus(const std::string &filename, const bool append=false)
Write this mesh and associated fields to the given output file.
void getMyNodes(const std::string &sideName, const std::string &blockName, std::vector< stk::mesh::Entity > &nodes) const
bool nonnull(const boost::shared_ptr< T > &p)
void addEdgeField(const std::string &fieldName, const std::string &blockId)
void addMeshCoordFields(const std::string &blockId, const std::vector< std::string > &coordField, const std::string &dispPrefix)
stk::mesh::Entity findConnectivityById(stk::mesh::Entity src, stk::mesh::EntityRank tgt_rank, unsigned rel_id) const
bool isMeshCoordField(const std::string &eBlock, const std::string &fieldName, int &axis) const
void getAllSides(const std::string &sideName, std::vector< stk::mesh::Entity > &sides) const
void addSideset(const std::string &name, const CellTopologyData *ctData)
static const std::string faceBlockString
std::unordered_map< stk::mesh::EntityId, std::size_t > localFaceIDHash_
void addEntityToEdgeBlock(stk::mesh::Entity entity, stk::mesh::Part *edgeblock)
std::map< std::pair< std::string, std::string >, SolutionFieldType * > fieldNameToEdgeField_
stk::mesh::Part * getEdgeBlock(const std::string &name) const
get the block part
std::unordered_map< stk::mesh::EntityId, std::size_t > localEdgeIDHash_
PHX::MDField< ScalarT, panzer::Cell, panzer::BASIS > field
A field to which we&#39;ll contribute, or in which we&#39;ll store, the result of computing this integral...
void rebalance(const Teuchos::ParameterList &params)
std::map< std::string, std::vector< std::string > > meshCoordFields_
stk::mesh::EntityRank getEdgeRank() const
static const std::string facesString
void addEntitiesToFaceBlock(std::vector< stk::mesh::Entity > entities, stk::mesh::Part *faceblock)
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
get the comm associated with this mesh
void initializeFieldsInSTK(const std::map< std::pair< std::string, std::string >, SolutionFieldType * > &nameToField, bool setupIO)
const std::vector< Teuchos::RCP< const PeriodicBC_MatcherBase > > & getPeriodicBCVector() const
void refineMesh(const int numberOfLevels, const bool deleteParentElements)
stk::mesh::Field< double > * getFaceField(const std::string &fieldName, const std::string &blockId) const
std::size_t faceLocalId(stk::mesh::Entity elmt) const
void addFaceBlock(const std::string &elemBlockName, const std::string &faceBlockName, const stk::topology &topology)
Teuchos::RCP< std::vector< stk::mesh::Entity > > orderedFaceVector_
std::unordered_map< stk::mesh::EntityId, std::size_t > localIDHash_
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
std::vector< stk::mesh::EntityId > maxEntityId_
void getElementsSharingNode(stk::mesh::EntityId nodeId, std::vector< stk::mesh::Entity > &elements) const
get a set of elements sharing a single node
void addFaceField(const std::string &fieldName, const std::string &blockId)
void getMyElements(std::vector< stk::mesh::Entity > &elements) const
#define TEUCHOS_ASSERT(assertion_test)
stk::mesh::EntityRank getNodeRank() const
void getMyFaces(std::vector< stk::mesh::Entity > &faces) const
void addCellField(const std::string &fieldName, const std::string &blockId)
void getNodeIdsForElement(stk::mesh::Entity element, std::vector< stk::mesh::EntityId > &nodeIds) const
get a list of node ids for nodes connected to an element
Teuchos::RCP< const std::vector< stk::mesh::Entity > > getFacesOrderedByLID() const
stk::mesh::EntityRank getElementRank() const
void addElementBlock(const std::string &name, const CellTopologyData *ctData)
stk::mesh::Field< double > * getCellField(const std::string &fieldName, const std::string &blockId) const
const VectorFieldType & getCoordinatesField() const
bool isEdgeLocal(stk::mesh::Entity edge) const
void getNeighborElements(std::vector< stk::mesh::Entity > &elements) const
void getNodesetNames(std::vector< std::string > &name) const
Teuchos::RCP< const shards::CellTopology > getCellTopology(const std::string &eBlock) const
std::map< std::pair< std::string, std::string >, SolutionFieldType * > fieldNameToCellField_
std::map< std::string, stk::mesh::Part * > nodesets_
bool is_null() const