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 //
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 <stk_mesh/base/GetEntities.hpp>
46 #include <stk_mesh/base/GetBuckets.hpp>
47 #include <stk_mesh/base/FieldBase.hpp>
48 
49 #include "Epetra_Vector.h"
50 #include "Epetra_MultiVector.h"
51 #include "Epetra_IntVector.h"
52 #include "Epetra_MpiComm.h"
53 #include "Epetra_Map.h"
54 #include "Epetra_LocalMap.h"
55 #include "Epetra_Import.h"
56 
57 #include "Teuchos_FancyOStream.hpp"
58 
59 namespace panzer_stk {
60 
61 namespace periodic_helpers {
62 
64 getGlobalPairing(const std::vector<std::size_t> & locallyRequiredIds,
65  const std::vector<std::pair<std::size_t,std::size_t> > & locallyMatchedIds,
66  const STK_Interface & mesh,bool failure)
67 {
68  Epetra_MpiComm Comm(mesh.getBulkData()->parallel());
69 
70  // this is needed to prevent hanging: it is unfortunately expensive
71  // need a better way!
72  int myVal = failure ? 1 : 0;
73  int sumVal = 0;
74  Comm.SumAll(&myVal,&sumVal,1);
75  TEUCHOS_ASSERT(sumVal==0);
76 
77  std::vector<int> requiredInts(locallyRequiredIds.size());
78  for(std::size_t i=0;i<requiredInts.size();i++)
79  requiredInts[i] = locallyRequiredIds[i];
80 
81  std::vector<int> providedInts(locallyMatchedIds.size());
82  for(std::size_t i=0;i<locallyMatchedIds.size();i++)
83  providedInts[i] = locallyMatchedIds[i].first;
84 
85  // maps and communciation all set up
86  int* requiredIntsPtr = NULL;
87  if (requiredInts.size() > 0)
88  requiredIntsPtr = &requiredInts[0];
89  int* providedIntsPtr = NULL;
90  if (providedInts.size() > 0)
91  providedIntsPtr = &providedInts[0];
92  Epetra_Map requiredMap(-1,requiredInts.size(),requiredIntsPtr,0,Comm);
93  Epetra_Map providedMap(-1,providedInts.size(),providedIntsPtr,0,Comm);
94  Epetra_Import importer(requiredMap,providedMap);
95 
96  // this is what to distribute
97  Epetra_IntVector providedVector(providedMap);
98  for(std::size_t i=0;i<locallyMatchedIds.size();i++)
99  providedVector[i] = locallyMatchedIds[i].second;
100 
101  // vector to fill
102  Epetra_IntVector requiredVector(requiredMap);
103  TEUCHOS_ASSERT(requiredVector.Import(providedVector,importer,Insert)==0);
104  int * myMappedIds = requiredVector.Values();
105 
107  = Teuchos::rcp(new std::vector<std::pair<std::size_t,std::size_t> >(requiredInts.size()));
108  for(std::size_t i=0;i<result->size();i++) {
109  (*result)[i].first = requiredInts[i];
110  (*result)[i].second = myMappedIds[i];
111  }
112 
113  return result;
114 }
115 
116 
117 
123  const std::string & sideName, const std::string type_)
124 {
127 
128  // grab nodes owned by requested side
130  std::stringstream ss;
131  ss << "Can't find part=\"" << sideName << "\"" << std::endl;
132  stk::mesh::Part * side = metaData->get_part(sideName,ss.str().c_str());
133  stk::mesh::Selector mySides = *side & (metaData->locally_owned_part() | metaData->globally_shared_part());
134 
135  stk::mesh::EntityRank rank;
136  unsigned int offset = 0; // offset to avoid giving nodes, edges, faces the same sideId
137  if(type_ == "coord"){
138  rank = mesh.getNodeRank();
139  } else if(type_ == "edge"){
140  rank = mesh.getEdgeRank();
141  offset = mesh.getMaxEntityId(mesh.getNodeRank());
142  } else if(type_ == "face"){
143  rank = mesh.getFaceRank();
144  offset = mesh.getMaxEntityId(mesh.getNodeRank())+mesh.getMaxEntityId(mesh.getEdgeRank());
145  } else {
146  ss << "Can't do BCs of type " << type_ << std::endl;
147  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error, ss.str())
148  }
149 
150  std::vector<stk::mesh::Bucket*> const& nodeBuckets =
151  bulkData->get_buckets(rank, mySides);
152 
153  // build id vector
155  std::size_t nodeCount = 0;
156  for(std::size_t b=0;b<nodeBuckets.size();b++)
157  nodeCount += nodeBuckets[b]->size();
158 
160  = Teuchos::rcp(new std::vector<std::size_t>(nodeCount));
161 
162  // loop over node buckets
163  for(std::size_t b=0,index=0;b<nodeBuckets.size();b++) {
164  stk::mesh::Bucket & bucket = *nodeBuckets[b];
165 
166  for(std::size_t n=0;n<bucket.size();n++,index++)
167  (*sideIds)[index] = bulkData->identifier(bucket[n]) + offset;
168  }
169 
170  return sideIds;
171 }
172 
173 std::pair<Teuchos::RCP<std::vector<std::size_t> >,
176  const std::string & sideName, const std::string type_)
177 {
178  unsigned physicalDim = mesh.getDimension();
179 
182 
183  // grab nodes owned by requested side
185  std::stringstream ss;
186  ss << "Can't find part=\"" << sideName << "\"" << std::endl;
187  stk::mesh::Part * side = metaData->get_part(sideName,ss.str().c_str());
188  stk::mesh::Selector mySides = (*side) & metaData->locally_owned_part();
189 
190  stk::mesh::EntityRank rank;
192  unsigned int offset = 0;
193  if(type_ == "coord"){
194  rank = mesh.getNodeRank();
195  field = & mesh.getCoordinatesField();
196  } else if(type_ == "edge"){
197  rank = mesh.getEdgeRank();
198  field = & mesh.getEdgesField();
199  offset = mesh.getMaxEntityId(mesh.getNodeRank());
200  } else if(type_ == "face"){
201  rank = mesh.getFaceRank();
202  field = & mesh.getFacesField();
203  offset = mesh.getMaxEntityId(mesh.getNodeRank())+mesh.getMaxEntityId(mesh.getEdgeRank());
204  } else {
205  ss << "Can't do BCs of type " << type_ << std::endl;
206  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error, ss.str())
207  }
208 
209  std::vector<stk::mesh::Bucket*> const& nodeBuckets =
210  bulkData->get_buckets(rank, mySides);
211 
212  // build id vector
214  std::size_t nodeCount = 0;
215  for(std::size_t b=0;b<nodeBuckets.size();b++)
216  nodeCount += nodeBuckets[b]->size();
217 
219  = Teuchos::rcp(new std::vector<std::size_t>(nodeCount));
221  = Teuchos::rcp(new std::vector<Teuchos::Tuple<double,3> >(nodeCount));
222 
223  // loop over node buckets
224  for(std::size_t b=0,index=0;b<nodeBuckets.size();b++) {
225  stk::mesh::Bucket & bucket = *nodeBuckets[b];
226  double const* array = stk::mesh::field_data(*field, bucket);
227 
228  for(std::size_t n=0;n<bucket.size();n++,index++) {
229  (*sideIds)[index] = bulkData->identifier(bucket[n]) + offset;
230  Teuchos::Tuple<double,3> & coord = (*sideCoords)[index];
231 
232  // copy coordinates into multi vector
233  for(std::size_t d=0;d<physicalDim;d++)
234  coord[d] = array[physicalDim*n + d];
235 
236  // need to ensure that higher dimensions are properly zeroed
237  // required for 1D periodic boundary conditions
238  for(std::size_t d=physicalDim;d<3;d++)
239  coord[d] = 0;
240  }
241  }
242 
243  return std::make_pair(sideIds,sideCoords);
244 }
245 
246 std::pair<Teuchos::RCP<std::vector<std::size_t> >,
249  const std::string & sideName, const std::string type_)
250 {
251  Epetra_MpiComm Comm(mesh.getBulkData()->parallel());
252 
253  unsigned physicalDim = mesh.getDimension();
254 
255  // grab local IDs and coordinates on this side
256  // and build local epetra vector
258 
259  std::pair<Teuchos::RCP<std::vector<std::size_t> >,
261  getLocalSideIdsAndCoords(mesh,sideName,type_);
262 
263  std::vector<std::size_t> & local_side_ids = *sidePair.first;
264  std::vector<Teuchos::Tuple<double,3> > & local_side_coords = *sidePair.second;
265  int nodeCount = local_side_ids.size();
266 
267  // build local Epetra objects
268  Epetra_Map idMap(-1,nodeCount,0,Comm);
270  Teuchos::RCP<Epetra_MultiVector> localCoordVec = Teuchos::rcp(new Epetra_MultiVector(idMap,physicalDim));
271 
272  // copy local Ids into Epetra vector
273  for(std::size_t n=0;n<local_side_ids.size();n++) {
274  std::size_t nodeId = local_side_ids[n];
275  Teuchos::Tuple<double,3> & coords = local_side_coords[n];
276 
277  (*localIdVec)[n] = nodeId;
278  for(unsigned d=0;d<physicalDim;d++)
279  (*(*localCoordVec)(d))[n] = coords[d];
280  }
281 
282  // fully distribute epetra vector across all processors
283  // (these are "distributed" or "dist" objects)
285 
286  int dist_nodeCount = idMap.NumGlobalElements();
287 
288  // build global epetra objects
289  Epetra_LocalMap distMap(dist_nodeCount,0,Comm);
291  Teuchos::RCP<Epetra_MultiVector> distCoordVec = Teuchos::rcp(new Epetra_MultiVector(distMap,physicalDim));
292 
293  // export to the localVec object from the "vector" object
294  Epetra_Import importer(distMap,idMap);
295  TEUCHOS_ASSERT(distIdVec->Import(*localIdVec,importer,Insert)==0);
296  TEUCHOS_ASSERT(distCoordVec->Import(*localCoordVec,importer,Insert)==0);
297 
298  // convert back to generic stl vector objects
300 
302  = Teuchos::rcp(new std::vector<std::size_t>(dist_nodeCount));
304  = Teuchos::rcp(new std::vector<Teuchos::Tuple<double,3> >(dist_nodeCount));
305 
306  // copy local Ids into Epetra vector
307  for(std::size_t n=0;n<dist_side_ids->size();n++) {
308  (*dist_side_ids)[n] = (*distIdVec)[n];
309 
310  Teuchos::Tuple<double,3> & coords = (*dist_side_coords)[n];
311  for(unsigned d=0;d<physicalDim;d++)
312  coords[d] = (*(*distCoordVec)(d))[n];
313 
314  // ensure that higher dimensions are zero
315  for(unsigned d=physicalDim;d<3;d++)
316  coords[d] = 0;
317  }
318 
319  return std::make_pair(dist_side_ids,dist_side_coords);
320 }
321 
322 } // end periodic_helpers
323 
324 } // end panzer_stk
int NumGlobalElements() const
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
int * Values() const
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)
int SumAll(double *PartialSums, double *GlobalSums, int Count) const
stk::mesh::Field< double, stk::mesh::Cartesian > VectorFieldType
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)
const VectorFieldType & getFacesField() const
#define TEUCHOS_ASSERT(assertion_test)
stk::mesh::EntityRank getNodeRank() const
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