Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_STKConnManager_impl.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Panzer: A partial differential equation assembly
5 // engine for strongly coupled complex multiphysics systems
6 // Copyright (2011) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Roger P. Pawlowski (rppawlo@sandia.gov) and
39 // Eric C. Cyr (eccyr@sandia.gov)
40 // ***********************************************************************
41 // @HEADER
42 
44 
45 #include <vector>
46 
47 // Teuchos includes
48 #include "Teuchos_RCP.hpp"
49 
50 #include "Kokkos_DynRankView.hpp"
51 
56 
57 #include "Teuchos_FancyOStream.hpp"
58 
59 namespace panzer_stk {
60 
61 using Teuchos::RCP;
62 using Teuchos::rcp;
63 
64 // Object describing how to sort a vector of elements using
65 // local ID as the key
67 public:
69 
70  // Compares two stk mesh entities based on local ID
71  bool operator() (stk::mesh::Entity a,stk::mesh::Entity b)
72  { return mesh_->elementLocalId(a) < mesh_->elementLocalId(b);}
73 
74 private:
76 };
77 
78 template <typename GO>
80  : stkMeshDB_(stkMeshDB), ownedElementCount_(0)
81 {
82 }
83 
84 template <typename GO>
88 {
89  return Teuchos::rcp(new STKConnManager<GO>(stkMeshDB_));
90 }
91 
92 template <typename GO>
94 {
95  elements_ = Teuchos::null;
96 
97  elementBlocks_.clear();
98  elmtLidToConn_.clear();
99  connSize_.clear();
100  elmtToAssociatedElmts_.clear();
101 }
102 
103 template <typename GO>
105 {
106  clearLocalElementMapping(); // forget the past
107 
108  // build element block information
110  elements_ = Teuchos::rcp(new std::vector<stk::mesh::Entity>);
111 
112  // defines ordering of blocks
113  std::vector<std::string> blockIds;
114  stkMeshDB_->getElementBlockNames(blockIds);
115 
116  std::size_t blockIndex=0;
117  for(std::vector<std::string>::const_iterator idItr=blockIds.begin();
118  idItr!=blockIds.end();++idItr,++blockIndex) {
119  std::string blockId = *idItr;
120 
121  // grab elements on this block
122  std::vector<stk::mesh::Entity> blockElmts;
123  stkMeshDB_->getMyElements(blockId,blockElmts);
124 
125  // concatenate them into element LID lookup table
126  elements_->insert(elements_->end(),blockElmts.begin(),blockElmts.end());
127 
128  // build block to LID map
129  elementBlocks_[blockId] = Teuchos::rcp(new std::vector<LocalOrdinal>);
130  for(std::size_t i=0;i<blockElmts.size();i++)
131  elementBlocks_[blockId]->push_back(stkMeshDB_->elementLocalId(blockElmts[i]));
132  }
133 
134  ownedElementCount_ = elements_->size();
135 
136  blockIndex=0;
137  for(std::vector<std::string>::const_iterator idItr=blockIds.begin();
138  idItr!=blockIds.end();++idItr,++blockIndex) {
139  std::string blockId = *idItr;
140 
141  // grab elements on this block
142  std::vector<stk::mesh::Entity> blockElmts;
143  stkMeshDB_->getNeighborElements(blockId,blockElmts);
144 
145  // concatenate them into element LID lookup table
146  elements_->insert(elements_->end(),blockElmts.begin(),blockElmts.end());
147 
148  // build block to LID map
149  neighborElementBlocks_[blockId] = Teuchos::rcp(new std::vector<LocalOrdinal>);
150  for(std::size_t i=0;i<blockElmts.size();i++)
151  neighborElementBlocks_[blockId]->push_back(stkMeshDB_->elementLocalId(blockElmts[i]));
152  }
153 
154  // this expensive operation gurantees ordering of local IDs
155  std::sort(elements_->begin(),elements_->end(),LocalIdCompare(stkMeshDB_));
156 
157  // allocate space for element LID to Connectivty map
158  // connectivity size
159  elmtLidToConn_.clear();
160  elmtLidToConn_.resize(elements_->size(),0);
161 
162  connSize_.clear();
163  connSize_.resize(elements_->size(),0);
164 }
165 
166 template <typename GO>
168  LocalOrdinal & nodeIdCnt, LocalOrdinal & edgeIdCnt,
169  LocalOrdinal & faceIdCnt, LocalOrdinal & cellIdCnt,
170  GlobalOrdinal & nodeOffset, GlobalOrdinal & edgeOffset,
171  GlobalOrdinal & faceOffset, GlobalOrdinal & cellOffset) const
172 {
173  // get the global counts for all the nodes, faces, edges and cells
174  GlobalOrdinal maxNodeId = stkMeshDB_->getMaxEntityId(stkMeshDB_->getNodeRank());
175  GlobalOrdinal maxEdgeId = stkMeshDB_->getMaxEntityId(stkMeshDB_->getEdgeRank());
176  GlobalOrdinal maxFaceId = stkMeshDB_->getMaxEntityId(stkMeshDB_->getFaceRank());
177 
178  // compute ID counts for each sub cell type
179  int patternDim = fp.getDimension();
180  switch(patternDim) {
181  case 3:
182  faceIdCnt = fp.getSubcellIndices(2,0).size();
183  // Intentional fall-through.
184  case 2:
185  edgeIdCnt = fp.getSubcellIndices(1,0).size();
186  // Intentional fall-through.
187  case 1:
188  nodeIdCnt = fp.getSubcellIndices(0,0).size();
189  cellIdCnt = fp.getSubcellIndices(patternDim,0).size();
190  break;
191  case 0:
192  default:
193  TEUCHOS_ASSERT(false);
194  };
195 
196  // compute offsets for each sub cell type
197  nodeOffset = 0;
198  edgeOffset = nodeOffset+(maxNodeId+1)*nodeIdCnt;
199  faceOffset = edgeOffset+(maxEdgeId+1)*edgeIdCnt;
200  cellOffset = faceOffset+(maxFaceId+1)*faceIdCnt;
201 
202  // sanity check
203  TEUCHOS_ASSERT(nodeOffset <= edgeOffset
204  && edgeOffset <= faceOffset
205  && faceOffset <= cellOffset);
206 }
207 
208 template <typename GO>
210  stk::mesh::Entity element,unsigned subcellRank,LocalOrdinal idCnt,GlobalOrdinal offset)
211 {
212  if(idCnt<=0)
213  return 0 ;
214 
215  // loop over all relations of specified type
216  LocalOrdinal numIds = 0;
217  stk::mesh::BulkData& bulkData = *stkMeshDB_->getBulkData();
218  const stk::mesh::EntityRank rank = static_cast<stk::mesh::EntityRank>(subcellRank);
219  const size_t num_rels = bulkData.num_connectivity(element, rank);
220  stk::mesh::Entity const* relations = bulkData.begin(element, rank);
221  for(std::size_t sc=0; sc<num_rels; ++sc) {
222  stk::mesh::Entity subcell = relations[sc];
223 
224  // add connectivities: adjust for STK indexing craziness
225  for(LocalOrdinal i=0;i<idCnt;i++)
226  connectivity_.push_back(offset+idCnt*(bulkData.identifier(subcell)-1)+i);
227 
228  numIds += idCnt;
229  }
230  return numIds;
231 }
232 
233 template <typename GO>
235  unsigned subcellRank,unsigned subcellId,GlobalOrdinal newId,
236  GlobalOrdinal offset)
237 {
238  LocalOrdinal elmtLID = stkMeshDB_->elementLocalId(element);
239  GlobalOrdinal * conn = this->getConnectivity(elmtLID);
240  const std::vector<int> & subCellIndices = fp.getSubcellIndices(subcellRank,subcellId);
241 
242  // add connectivities: adjust for STK indexing craziness
243  for(std::size_t i=0;i<subCellIndices.size();i++) {
244  conn[subCellIndices[i]] = offset+subCellIndices.size()*(newId-1)+i;
245  }
246 }
247 
248 template <typename GO>
250 {
251 #ifdef HAVE_EXTRA_TIMERS
252  using Teuchos::TimeMonitor;
253  RCP<Teuchos::TimeMonitor> tM = rcp(new TimeMonitor(*TimeMonitor::getNewTimer(std::string("panzer_stk::STKConnManager::buildConnectivity"))));
254 #endif
255 
256  stk::mesh::BulkData& bulkData = *stkMeshDB_->getBulkData();
257 
258  // get element info from STK_Interface
259  // object and build a local element mapping.
260  buildLocalElementMapping();
261 
262  // Build sub cell ID counts and offsets
263  // ID counts = How many IDs belong on each subcell (number of mesh DOF used)
264  // Offset = What is starting index for subcell ID type?
265  // Global numbering goes like [node ids, edge ids, face ids, cell ids]
266  LocalOrdinal nodeIdCnt=0, edgeIdCnt=0, faceIdCnt=0, cellIdCnt=0;
267  GlobalOrdinal nodeOffset=0, edgeOffset=0, faceOffset=0, cellOffset=0;
268  buildOffsetsAndIdCounts(fp, nodeIdCnt, edgeIdCnt, faceIdCnt, cellIdCnt,
269  nodeOffset, edgeOffset, faceOffset, cellOffset);
270 
271  // std::cout << "node: count = " << nodeIdCnt << ", offset = " << nodeOffset << std::endl;
272  // std::cout << "edge: count = " << edgeIdCnt << ", offset = " << edgeOffset << std::endl;
273  // std::cout << "face: count = " << faceIdCnt << ", offset = " << faceOffset << std::endl;
274  // std::cout << "cell: count = " << cellIdCnt << ", offset = " << cellOffset << std::endl;
275 
276  // loop over elements and build global connectivity
277  for(std::size_t elmtLid=0;elmtLid!=elements_->size();++elmtLid) {
278  GlobalOrdinal numIds = 0;
279  stk::mesh::Entity element = (*elements_)[elmtLid];
280 
281  // get index into connectivity array
282  elmtLidToConn_[elmtLid] = connectivity_.size();
283 
284  // add connecviities for sub cells
285  numIds += addSubcellConnectivities(element,stkMeshDB_->getNodeRank(),nodeIdCnt,nodeOffset);
286  numIds += addSubcellConnectivities(element,stkMeshDB_->getEdgeRank(),edgeIdCnt,edgeOffset);
287  numIds += addSubcellConnectivities(element,stkMeshDB_->getFaceRank(),faceIdCnt,faceOffset);
288 
289  // add connectivity for parent cells
290  if(cellIdCnt>0) {
291  // add connectivities: adjust for STK indexing craziness
292  for(LocalOrdinal i=0;i<cellIdCnt;i++)
293  connectivity_.push_back(cellOffset+cellIdCnt*(bulkData.identifier(element)-1));
294 
295  numIds += cellIdCnt;
296  }
297 
298  connSize_[elmtLid] = numIds;
299  }
300 
301  applyPeriodicBCs( fp, nodeOffset, edgeOffset, faceOffset, cellOffset);
302 
303  // This method does not modify connectivity_. But it should be called here
304  // because the data it initializes should be available at the same time as
305  // connectivity_.
306  if (hasAssociatedNeighbors())
307  applyInterfaceConditions();
308 }
309 
310 template <typename GO>
312 {
313  // walk through the element blocks and figure out which this ID belongs to
314  stk::mesh::Entity element = (*elements_)[localElmtId];
315 
316  return stkMeshDB_->containingBlockId(element);
317 }
318 
319 template <typename GO>
321  GlobalOrdinal faceOffset, GlobalOrdinal /* cellOffset */)
322 {
323  using Teuchos::RCP;
324  using Teuchos::rcp;
325 
326 #ifdef HAVE_EXTRA_TIMERS
327  using Teuchos::TimeMonitor;
328  RCP<Teuchos::TimeMonitor> tM = rcp(new TimeMonitor(*TimeMonitor::getNewTimer(std::string("panzer_stk::STKConnManager::applyPeriodicBCs"))));
329 #endif
330 
331  std::pair<Teuchos::RCP<std::vector<std::pair<std::size_t,std::size_t> > >, Teuchos::RCP<std::vector<unsigned int> > > matchedValues
332  = stkMeshDB_->getPeriodicNodePairing();
333 
335  = matchedValues.first;
337  = matchedValues.second;
338 
339  // no matchedNodes means nothing to do!
340  if(matchedNodes==Teuchos::null) return;
341 
342  for(std::size_t m=0;m<matchedNodes->size();m++) {
343  stk::mesh::EntityId oldNodeId = (*matchedNodes)[m].first;
344  std::size_t newNodeId = (*matchedNodes)[m].second;
345 
346  std::vector<stk::mesh::Entity> elements;
347  std::vector<int> localIds;
348 
349  GlobalOrdinal offset0 = 0; // to make numbering consistent with that in PeriodicBC_Matcher
350  GlobalOrdinal offset1 = 0; // offset for dof indexing
351  if((*matchTypes)[m] == 0)
352  offset1 = nodeOffset-offset0;
353  else if((*matchTypes)[m] == 1){
354  offset0 = stkMeshDB_->getMaxEntityId(stkMeshDB_->getNodeRank());
355  offset1 = edgeOffset-offset0;
356  } else if((*matchTypes)[m] == 2){
357  offset0 = stkMeshDB_->getMaxEntityId(stkMeshDB_->getNodeRank())+stkMeshDB_->getMaxEntityId(stkMeshDB_->getEdgeRank());
358  offset1 = faceOffset-offset0;
359  } else
360  TEUCHOS_ASSERT(false);
361 
362  // get relevent elements and node IDs
363  stkMeshDB_->getOwnedElementsSharingNode(oldNodeId-offset0,elements,localIds,(*matchTypes)[m]);
364 
365  // modify global numbering already built for each element
366  for(std::size_t e=0;e<elements.size();e++){
367  modifySubcellConnectivities(fp,elements[e],(*matchTypes)[m],localIds[e],newNodeId,offset1);
368  }
369 
370  }
371 }
372 
375 template <typename GO>
376 void STKConnManager<GO>::getDofCoords(const std::string & blockId,
377  const panzer::Intrepid2FieldPattern & coordProvider,
378  std::vector<std::size_t> & localCellIds,
379  Kokkos::DynRankView<double,PHX::Device> & points) const
380 {
381  int dim = coordProvider.getDimension();
382  int numIds = coordProvider.numberIds();
383 
384  // grab element vertices
385  Kokkos::DynRankView<double,PHX::Device> vertices;
386  workset_utils::getIdsAndVertices(*stkMeshDB_,blockId,localCellIds,vertices);
387 
388  // setup output array
389  points = Kokkos::DynRankView<double,PHX::Device>("points",localCellIds.size(),numIds,dim);
390  coordProvider.getInterpolatoryCoordinates(vertices,points);
391 }
392 
393 template <typename GO>
395 {
396  return ! sidesetsToAssociate_.empty();
397 }
398 
399 template <typename GO>
400 void STKConnManager<GO>::associateElementsInSideset(const std::string sideset_id)
401 {
402  sidesetsToAssociate_.push_back(sideset_id);
403  sidesetYieldedAssociations_.push_back(false);
404 }
405 
406 inline std::size_t
407 getElementIdx(const std::vector<stk::mesh::Entity>& elements,
408  stk::mesh::Entity const e)
409 {
410  return static_cast<std::size_t>(
411  std::distance(elements.begin(), std::find(elements.begin(), elements.end(), e)));
412 }
413 
414 template <typename GO>
416 {
417  stk::mesh::BulkData& bulkData = *stkMeshDB_->getBulkData();
418  elmtToAssociatedElmts_.resize(elements_->size());
419  for (std::size_t i = 0; i < sidesetsToAssociate_.size(); ++i) {
420  std::vector<stk::mesh::Entity> sides;
421  stkMeshDB_->getAllSides(sidesetsToAssociate_[i], sides);
422  sidesetYieldedAssociations_[i] = ! sides.empty();
423  for (std::vector<stk::mesh::Entity>::const_iterator si = sides.begin();
424  si != sides.end(); ++si) {
425  stk::mesh::Entity side = *si;
426  const size_t num_elements = bulkData.num_elements(side);
427  stk::mesh::Entity const* elements = bulkData.begin_elements(side);
428  if (num_elements != 2) {
429  // If relations.size() != 2 for one side in the sideset, then it's true
430  // for all, including the first.
431  TEUCHOS_ASSERT(si == sides.begin());
432  sidesetYieldedAssociations_[i] = false;
433  break;
434  }
435  const std::size_t ea_id = getElementIdx(*elements_, elements[0]),
436  eb_id = getElementIdx(*elements_, elements[1]);
437  elmtToAssociatedElmts_[ea_id].push_back(eb_id);
438  elmtToAssociatedElmts_[eb_id].push_back(ea_id);
439  }
440  }
441 }
442 
443 template <typename GO>
444 std::vector<std::string> STKConnManager<GO>::
446 {
447  std::vector<std::string> sidesets;
448  for (std::size_t i = 0; i < sidesetYieldedAssociations_.size(); ++i) {
449  int sya, my_sya = sidesetYieldedAssociations_[i] ? 1 : 0;
450  Teuchos::reduceAll(comm, Teuchos::REDUCE_MAX, 1, &my_sya, &sya);
451  if (sya == 0)
452  sidesets.push_back(sidesetsToAssociate_[i]);
453  }
454  return sidesets;
455 }
456 
457 template <typename GO>
458 const std::vector<typename STKConnManager<GO>::LocalOrdinal>&
460 {
461  return elmtToAssociatedElmts_[el];
462 }
463 
464 }
virtual int getDimension() const =0
panzer::ConnManager< int, GO >::GlobalOrdinal GlobalOrdinal
void associateElementsInSideset(const std::string sideset_id)
virtual Teuchos::RCP< panzer::ConnManagerBase< int > > noConnectivityClone() const
void getIdsAndVertices(const panzer_stk::STK_Interface &mesh, std::string blockId, std::vector< std::size_t > &localIds, ArrayT &vertices)
virtual void buildConnectivity(const panzer::FieldPattern &fp)
STKConnManager(const Teuchos::RCP< const STK_Interface > &stkMeshDB)
virtual bool hasAssociatedNeighbors() const
virtual const std::vector< LocalOrdinal > & getAssociatedNeighbors(const LocalOrdinal &el) const
LocalIdCompare(const RCP< const STK_Interface > &mesh)
virtual void getDofCoords(const std::string &blockId, const panzer::Intrepid2FieldPattern &coordProvider, std::vector< std::size_t > &localCellIds, Kokkos::DynRankView< double, PHX::Device > &points) const
virtual int numberIds() const
panzer::ConnManager< int, GO >::LocalOrdinal LocalOrdinal
LocalOrdinal addSubcellConnectivities(stk::mesh::Entity element, unsigned subcellRank, LocalOrdinal idCnt, GlobalOrdinal offset)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void modifySubcellConnectivities(const panzer::FieldPattern &fp, stk::mesh::Entity element, unsigned subcellRank, unsigned subcellId, GlobalOrdinal newId, GlobalOrdinal offset)
std::vector< std::string > checkAssociateElementsInSidesets(const Teuchos::Comm< int > &comm) const
TEUCHOS_DEPRECATED void reduceAll(const Comm< Ordinal > &comm, const EReductionType reductType, const Packet &send, Packet *globalReduct)
void applyPeriodicBCs(const panzer::FieldPattern &fp, GlobalOrdinal nodeOffset, GlobalOrdinal edgeOffset, GlobalOrdinal faceOffset, GlobalOrdinal cellOffset)
virtual std::string getBlockId(LocalOrdinal localElmtId) const
void buildOffsetsAndIdCounts(const panzer::FieldPattern &fp, LocalOrdinal &nodeIdCnt, LocalOrdinal &edgeIdCnt, LocalOrdinal &faceIdCnt, LocalOrdinal &cellIdCnt, GlobalOrdinal &nodeOffset, GlobalOrdinal &edgeOffset, GlobalOrdinal &faceOffset, GlobalOrdinal &cellOffset) const
RCP< const STK_Interface > mesh_
void getInterpolatoryCoordinates(Kokkos::DynRankView< double, PHX::Device > &coords) const
bool operator()(stk::mesh::Entity a, stk::mesh::Entity b)
virtual const std::vector< int > & getSubcellIndices(int dim, int cellIndex) const =0
#define TEUCHOS_ASSERT(assertion_test)
std::size_t getElementIdx(const std::vector< stk::mesh::Entity > &elements, stk::mesh::Entity const e)