Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_STK_PeriodicBC_Matcher.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 
12 
13 #include <stk_mesh/base/GetEntities.hpp>
14 #include <stk_mesh/base/GetBuckets.hpp>
15 #include <stk_mesh/base/FieldBase.hpp>
16 
17 #include "Panzer_NodeType.hpp"
18 #include "Tpetra_Map.hpp"
19 #include "Tpetra_Import.hpp"
20 #include "Tpetra_Vector.hpp"
21 
22 #include "Teuchos_FancyOStream.hpp"
23 
24 namespace panzer_stk {
25 
26 namespace periodic_helpers {
27 
29 getGlobalPairing(const std::vector<std::size_t> & locallyRequiredIds,
30  const std::vector<std::pair<std::size_t,std::size_t> > & locallyMatchedIds,
31  const STK_Interface & mesh,bool failure)
32 {
33  using LO = panzer::LocalOrdinal;
34  using GO = panzer::GlobalOrdinal;
36  using Map = Tpetra::Map<LO,GO,NODE>;
37  using Importer = Tpetra::Import<LO,GO,NODE>;
38 
39  auto comm = mesh.getComm();
40 
41  // this is needed to prevent hanging: it is unfortunately expensive
42  // need a better way!
43  int myVal = failure ? 1 : 0;
44  int sumVal = 0;
45  Teuchos::reduceAll<int,int>(*comm,Teuchos::REDUCE_SUM,1,&myVal,&sumVal);
46  TEUCHOS_ASSERT(sumVal==0);
47 
48  std::vector<GO> requiredInts(locallyRequiredIds.size());
49  for(std::size_t i=0;i<requiredInts.size();i++)
50  requiredInts[i] = locallyRequiredIds[i];
51 
52  std::vector<GO> providedInts(locallyMatchedIds.size());
53  for(std::size_t i=0;i<locallyMatchedIds.size();i++)
54  providedInts[i] = locallyMatchedIds[i].first;
55 
56  // maps and communciation all set up
58  Teuchos::RCP<Map> requiredMap = Teuchos::rcp(new Map(computeInternally,Teuchos::ArrayView<const GO>(requiredInts),0,comm));
59  Teuchos::RCP<Map> providedMap = Teuchos::rcp(new Map(computeInternally,Teuchos::ArrayView<const GO>(providedInts),0,comm));
60  Importer importer(providedMap,requiredMap);
61 
62  // this is what to distribute
63  Tpetra::Vector<GO,LO,GO,NODE> providedVector(providedMap);
64  {
65  auto pvHost = providedVector.getLocalViewHost(Tpetra::Access::OverwriteAll);
66  for(std::size_t i=0;i<locallyMatchedIds.size();i++)
67  pvHost(i,0) = locallyMatchedIds[i].second;
68  }
69 
70  Tpetra::Vector<GO,LO,GO,NODE> requiredVector(requiredMap);
71  requiredVector.doImport(providedVector,importer,Tpetra::INSERT);
72 
73 
75  = Teuchos::rcp(new std::vector<std::pair<std::size_t,std::size_t> >(requiredInts.size()));
76 
77  auto rvHost = requiredVector.getLocalViewHost(Tpetra::Access::ReadOnly);
78  for(std::size_t i=0;i<result->size();i++) {
79  (*result)[i].first = requiredInts[i];
80  (*result)[i].second = rvHost(i,0);
81  }
82  return result;
83 }
84 
85 
86 
92  const std::string & sideName, const std::string type_)
93 {
96 
97  // grab nodes owned by requested side
99  std::stringstream ss;
100  ss << "Can't find part=\"" << sideName << "\"" << std::endl;
101  stk::mesh::Part * side = metaData->get_part(sideName,ss.str().c_str());
102  stk::mesh::Selector mySides = *side & (metaData->locally_owned_part() | metaData->globally_shared_part());
103 
104  stk::mesh::EntityRank rank;
105  panzer::GlobalOrdinal offset = 0; // offset to avoid giving nodes, edges, faces the same sideId
106  if(type_ == "coord"){
107  rank = mesh.getNodeRank();
108  } else if(type_ == "edge"){
109  rank = mesh.getEdgeRank();
110  offset = mesh.getMaxEntityId(mesh.getNodeRank());
111  } else if(type_ == "face"){
112  rank = mesh.getFaceRank();
113  offset = mesh.getMaxEntityId(mesh.getNodeRank())+mesh.getMaxEntityId(mesh.getEdgeRank());
114  } else {
115  ss << "Can't do BCs of type " << type_ << std::endl;
116  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error, ss.str())
117  }
118 
119  std::vector<stk::mesh::Bucket*> const& nodeBuckets =
120  bulkData->get_buckets(rank, mySides);
121 
122  // build id vector
124  std::size_t nodeCount = 0;
125  for(std::size_t b=0;b<nodeBuckets.size();b++)
126  nodeCount += nodeBuckets[b]->size();
127 
129  = Teuchos::rcp(new std::vector<std::size_t>(nodeCount));
130 
131  // loop over node buckets
132  for(std::size_t b=0,index=0;b<nodeBuckets.size();b++) {
133  stk::mesh::Bucket & bucket = *nodeBuckets[b];
134 
135  for(std::size_t n=0;n<bucket.size();n++,index++)
136  (*sideIds)[index] = bulkData->identifier(bucket[n]) + offset;
137  }
138 
139  return sideIds;
140 }
141 
142 std::pair<Teuchos::RCP<std::vector<std::size_t> >,
145  const std::string & sideName, const std::string type_)
146 {
147  unsigned physicalDim = mesh.getDimension();
148 
151 
152  // grab nodes owned by requested side
154  std::stringstream ss;
155  ss << "Can't find part=\"" << sideName << "\"" << std::endl;
156  stk::mesh::Part * side = metaData->get_part(sideName,ss.str().c_str());
157  stk::mesh::Selector mySides = (*side) & metaData->locally_owned_part();
158 
159  stk::mesh::EntityRank rank;
161  stk::mesh::EntityId offset = 0;
162  if(type_ == "coord"){
163  rank = mesh.getNodeRank();
164  field = & mesh.getCoordinatesField();
165  } else if(type_ == "edge"){
166  rank = mesh.getEdgeRank();
167  field = & mesh.getEdgesField();
168  offset = mesh.getMaxEntityId(mesh.getNodeRank());
169  } else if(type_ == "face"){
170  rank = mesh.getFaceRank();
171  field = & mesh.getFacesField();
172  offset = mesh.getMaxEntityId(mesh.getNodeRank())+mesh.getMaxEntityId(mesh.getEdgeRank());
173  } else {
174  ss << "Can't do BCs of type " << type_ << std::endl;
175  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error, ss.str())
176  }
177 
178  std::vector<stk::mesh::Bucket*> const& nodeBuckets =
179  bulkData->get_buckets(rank, mySides);
180 
181  // build id vector
183  std::size_t nodeCount = 0;
184  for(std::size_t b=0;b<nodeBuckets.size();b++)
185  nodeCount += nodeBuckets[b]->size();
186 
188  = Teuchos::rcp(new std::vector<std::size_t>(nodeCount));
190  = Teuchos::rcp(new std::vector<Teuchos::Tuple<double,3> >(nodeCount));
191 
192  // loop over node buckets
193  for(std::size_t b=0,index=0;b<nodeBuckets.size();b++) {
194  stk::mesh::Bucket & bucket = *nodeBuckets[b];
195  double const* array = stk::mesh::field_data(*field, bucket);
196 
197  for(std::size_t n=0;n<bucket.size();n++,index++) {
198  (*sideIds)[index] = bulkData->identifier(bucket[n]) + offset;
199  Teuchos::Tuple<double,3> & coord = (*sideCoords)[index];
200 
201  // copy coordinates into multi vector
202  for(std::size_t d=0;d<physicalDim;d++)
203  coord[d] = array[physicalDim*n + d];
204 
205  // need to ensure that higher dimensions are properly zeroed
206  // required for 1D periodic boundary conditions
207  for(std::size_t d=physicalDim;d<3;d++)
208  coord[d] = 0;
209  }
210  }
211 
212  return std::make_pair(sideIds,sideCoords);
213 }
214 
215 std::pair<Teuchos::RCP<std::vector<std::size_t> >,
218  const std::string & sideName, const std::string type_)
219 {
220  using Teuchos::RCP;
221  using Teuchos::rcp;
222  using LO = panzer::LocalOrdinal;
223  using GO = panzer::GlobalOrdinal;
225  using Map = Tpetra::Map<LO,GO,NODE>;
226  using Importer = Tpetra::Import<LO,GO,NODE>;
227 
228  // Epetra_MpiComm Comm(mesh.getBulkData()->parallel());
229  auto comm = mesh.getComm();
230 
231  unsigned physicalDim = mesh.getDimension();
232 
233  // grab local IDs and coordinates on this side
234  // and build local epetra vector
236 
237  std::pair<Teuchos::RCP<std::vector<std::size_t> >,
239  getLocalSideIdsAndCoords(mesh,sideName,type_);
240 
241  std::vector<std::size_t> & local_side_ids = *sidePair.first;
242  std::vector<Teuchos::Tuple<double,3> > & local_side_coords = *sidePair.second;
243  std::size_t nodeCount = local_side_ids.size();
244 
245  // build local Tpetra objects
247  RCP<Map> idMap_ = rcp(new Map(computeInternally,nodeCount,0,comm));
248  RCP<Tpetra::Vector<GO,LO,GO,NODE>> localIdVec_ = rcp(new Tpetra::Vector<GO,LO,GO,NODE>(idMap_));
249  RCP<Tpetra::MultiVector<double,LO,GO,NODE>> localCoordVec_ = rcp(new Tpetra::MultiVector<double,LO,GO,NODE>(idMap_,physicalDim));
250 
251  // copy local Ids and coords into Tpetra vectors
252  {
253  auto lidHost = localIdVec_->getLocalViewHost(Tpetra::Access::OverwriteAll);
254  auto lcoordHost = localCoordVec_->getLocalViewHost(Tpetra::Access::OverwriteAll);
255  for(std::size_t n=0;n<local_side_ids.size();n++) {
256  std::size_t nodeId = local_side_ids[n];
257  Teuchos::Tuple<double,3> & coords = local_side_coords[n];
258 
259  lidHost(n,0) = static_cast<GO>(nodeId);
260  for(unsigned d=0;d<physicalDim;d++)
261  lcoordHost(n,d) = coords[d];
262  }
263  }
264 
265  // fully distribute epetra vector across all processors
266  // (these are "distributed" or "dist" objects)
268 
269  std::size_t dist_nodeCount = idMap_->getGlobalNumElements();
270 
271  // build global Tpetra objects
272  RCP<Map> distMap_ = rcp(new Map(dist_nodeCount,0,comm,Tpetra::LocallyReplicated));
273  RCP<Tpetra::Vector<GO,LO,GO,NODE>> distIdVec_ = rcp(new Tpetra::Vector<GO,LO,GO,NODE>(distMap_));
274  RCP<Tpetra::MultiVector<double,LO,GO,NODE>> distCoordVec_ = rcp(new Tpetra::MultiVector<double,LO,GO,NODE>(distMap_,physicalDim));
275 
276  // export to the localVec object from the "vector" object
277  Importer importer_(idMap_,distMap_);
278  distIdVec_->doImport(*localIdVec_,importer_,Tpetra::INSERT);
279  distCoordVec_->doImport(*localCoordVec_,importer_,Tpetra::INSERT);
280 
281  // convert back to generic stl vector objects
283 
285  = Teuchos::rcp(new std::vector<std::size_t>(dist_nodeCount));
287  = Teuchos::rcp(new std::vector<Teuchos::Tuple<double,3> >(dist_nodeCount));
288 
289  // copy local Ids from Tpetra vector
290  const auto didHost = distIdVec_->getLocalViewHost(Tpetra::Access::ReadOnly);
291  const auto dcoordHost = distCoordVec_->getLocalViewHost(Tpetra::Access::ReadOnly);
292  for(std::size_t n=0;n<dist_side_ids->size();++n) {
293  (*dist_side_ids)[n] = didHost(n,0);
294 
295  Teuchos::Tuple<double,3> & coords = (*dist_side_coords)[n];
296  for(unsigned d=0;d<physicalDim;++d) {
297  coords[d] = dcoordHost(n,d);
298  }
299  // ensure that higher dimensions are zero
300  for(unsigned d=physicalDim;d<3;++d)
301  coords[d] = 0;
302  }
303 
304  return std::make_pair(dist_side_ids,dist_side_coords);
305 }
306 
307 } // end periodic_helpers
308 
309 } // end panzer_stk
stk::mesh::Field< double > VectorFieldType
Teuchos::RCP< std::vector< std::size_t > > getLocalSideIds(const STK_Interface &mesh, const std::string &sideName, const std::string type_)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
stk::mesh::EntityId getMaxEntityId(unsigned entityRank) const
get max entity ID of type entityRank
std::pair< Teuchos::RCP< std::vector< std::size_t > >, Teuchos::RCP< std::vector< Teuchos::Tuple< double, 3 > > > > getLocalSideIdsAndCoords(const STK_Interface &mesh, const std::string &sideName, const std::string type_)
PHX::MDField< ScalarT, panzer::Cell, panzer::IP > result
A field that will be used to build up the result of the integral we&#39;re performing.
unsigned getDimension() const
get the dimension
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< stk::mesh::BulkData > getBulkData() const
stk::mesh::EntityRank getFaceRank() const
Teuchos::RCP< stk::mesh::MetaData > getMetaData() const
const VectorFieldType & getEdgesField() const
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...
stk::mesh::EntityRank getEdgeRank() const
Teuchos::RCP< std::vector< std::pair< std::size_t, std::size_t > > > getGlobalPairing(const std::vector< std::size_t > &locallyRequiredIds, const std::vector< std::pair< std::size_t, std::size_t > > &locallyMatchedIds, const STK_Interface &mesh, bool failure)
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
get the comm associated with this mesh
const VectorFieldType & getFacesField() const
#define TEUCHOS_ASSERT(assertion_test)
stk::mesh::EntityRank getNodeRank() const
Tpetra::KokkosCompat::KokkosDeviceWrapperNode< PHX::Device > TpetraNodeType
std::pair< Teuchos::RCP< std::vector< std::size_t > >, Teuchos::RCP< std::vector< Teuchos::Tuple< double, 3 > > > > getSideIdsAndCoords(const STK_Interface &mesh, const std::string &sideName, const std::string type_)
const VectorFieldType & getCoordinatesField() const