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