Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_FieldAggPattern.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 
14 
15 using Teuchos::RCP;
16 using Teuchos::rcp;
17 
18 namespace panzer {
19 
21 {
22 }
23 
25  const Teuchos::RCP<const FieldPattern> & geomAggPattern)
26 {
27  buildPattern(patterns,geomAggPattern);
28 }
29 
31 {
32  return geomAggPattern_;
33 }
34 
35 void FieldAggPattern::buildPattern(const std::vector<std::tuple<int,panzer::FieldType,Teuchos::RCP<const FieldPattern> > > & patterns,
36  const Teuchos::RCP<const FieldPattern> & geomAggPattern)
37 {
38  TEUCHOS_ASSERT(patterns.size()>0);
39 
40  // build geometric information
41  if(geomAggPattern==Teuchos::null) {
42  std::vector<std::pair<FieldType,FPPtr>> patternVec;
43 
44  // convert map into vector
45  auto itr = patterns.cbegin();
46  for(;itr!=patterns.cend();++itr)
47  patternVec.push_back(std::make_pair(std::get<1>(*itr),std::get<2>(*itr)));
48 
49  // build geometric aggregate field pattern
50  geomAggPattern_ = rcp(new GeometricAggFieldPattern(patternVec));
51  }
52  else
53  geomAggPattern_ = geomAggPattern;
54 
55  patterns_ = patterns;
56 
57  buildFieldIdToPatternIdx(); // builds look up from fieldId to index into patterns_ vector
58  buildFieldIdsVector(); // meat of matter: build field pattern information
59  buildFieldPatternData(); // this handles the "getSubcell*" information
60 }
61 
63 {
64  FPPtr geomPattern = getGeometricAggFieldPattern();
65  TEUCHOS_TEST_FOR_EXCEPTION(geomPattern==Teuchos::null,std::logic_error,
66  "Geometric field pattern not yet set, call buildPatterns first");
67 
68  return geomPattern->getDimension();
69 }
70 
71 shards::CellTopology FieldAggPattern::getCellTopology() const
72 {
73  FPPtr geomPattern = getGeometricAggFieldPattern();
74  TEUCHOS_TEST_FOR_EXCEPTION(geomPattern==Teuchos::null,std::logic_error,
75  "Geometric field pattern not yet set, call buildPatterns first");
76 
77  return geomPattern->getCellTopology();
78 }
79 
80 int FieldAggPattern::getSubcellCount(int dimension) const
81 {
82  return patternData_[dimension].size();
83 }
84 
85 const std::vector<int> & FieldAggPattern::getSubcellIndices(int dimension, int subcell) const
86 {
87  return patternData_[dimension][subcell];
88 }
89 
90 void FieldAggPattern::getSubcellClosureIndices(int, int, std::vector<int> &) const
91 {
92  TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
93  "FieldAggPattern::getSubcellClosureIndices should not be called");
94 }
95 
96 void FieldAggPattern::print(std::ostream & os) const
97 {
99 
100  os << "FieldPattern: FieldAggPattern" << std::endl;
101  os << "FieldPattern: |numFields| = " << numFields_.size() << std::endl;
102  os << "FieldPattern: numFields = [ ";
103  int total=0;
104  for(std::size_t i=0;i<numFields_.size();i++) {
105  os << numFields_[i] << " ";
106  total += numFields_[i];
107  }
108  os << "]" << std::endl;
109  os << "FieldPattern: |fieldIds| = " << fieldIds_.size() << " (" << total << ")" << std::endl;
110  os << "FieldPattern: fieldIds = [ ";
111  for(std::size_t i=0;i<fieldIds_.size();i++)
112  os << fieldIds_[i] << " ";
113  os << "]" << std::endl;
114  os << "FieldPattern: local offsets\n";
115 
116  std::map<int,int>::const_iterator itr;
117  for(itr=fieldIdToPatternIdx_.begin();itr!=fieldIdToPatternIdx_.end();++itr) {
118  int fieldId = itr->first;
119  const std::vector<int> & offsets = localOffsets(fieldId);
120  os << "FieldPattern: field " << itr->first << " = [ ";
121  for(std::size_t i=0;i<offsets.size();i++)
122  os << offsets[i] << " ";
123  os << "]" << std::endl;
124  }
125 }
126 
128 {
129  std::map<int,int>::const_iterator idxIter = fieldIdToPatternIdx_.find(fieldId);
130  TEUCHOS_TEST_FOR_EXCEPTION(idxIter==fieldIdToPatternIdx_.end(),std::logic_error,
131  "FieldID = " << fieldId << " not defined in this pattern");
132 
133  return std::get<2>(patterns_[idxIter->second]);
134 }
135 
137 {
138  std::map<int,int>::const_iterator idxIter = fieldIdToPatternIdx_.find(fieldId);
139  TEUCHOS_TEST_FOR_EXCEPTION(idxIter==fieldIdToPatternIdx_.end(),std::logic_error,
140  "FieldID = " << fieldId << " not defined in this pattern");
141 
142  return std::get<1>(patterns_[idxIter->second]);
143 }
144 
146 {
147  // convert map into vector
148  int index = 0;
149  auto itr = patterns_.cbegin();
150  for(;itr!=patterns_.cend();++itr,++index)
151  fieldIdToPatternIdx_[std::get<0>(*itr)] = index;
152 }
153 
155 {
156  FPPtr geomAggPattern = getGeometricAggFieldPattern();
157 
158  // numFields_: stores number of fields per geometric ID
159  // fieldIds_: stores field IDs for each entry field indicated by numFields_
160  numFields_.resize(geomAggPattern->numberIds(),0);
161  fieldIds_.clear();
162 
163  // build numFields_ and fieldIds_ vectors
164 
165  // Merge the field patterns for multiple fields for each dimension
166  // and subcell. We do all the CG first, then all DG. This allows us
167  // to use one offset for mapping DOFs to subcells later on.
170 }
171 
173 {
174  auto geomAggPattern = getGeometricAggFieldPattern();
175 
176  // For DG, all DOFs are added to the internal cell
177  const int cellDim = this->getDimension();
178  const int numDimensions = getDimension()+1;
179 
180  for(int dim=0;dim<numDimensions;dim++) {
181  int numSubcell = geomAggPattern->getSubcellCount(dim);
182  for(int subcell=0;subcell<numSubcell;subcell++) {
183 
184  // Get the geometric index to add the DOF indices to. CG adds to
185  // the subcell we are iterating over, (dim,subcel), while DG
186  // adds to the internal cell (cellDim,0)
187  const std::vector<int> * geomIndices = nullptr;
188  if (fieldType == FieldType::CG)
189  geomIndices = &(getGeometricAggFieldPattern()->getSubcellIndices(dim,subcell));
190  else
191  geomIndices = &(getGeometricAggFieldPattern()->getSubcellIndices(cellDim,0));
192 
193  if (geomIndices->size() > 0) {
194  const int geomIndex = (*geomIndices)[0];
195 
196  auto itr = patterns_.cbegin();
197  for(;itr!=patterns_.cend();++itr) {
198  // Only merge in if pattern matches the FieldType.
199  if (std::get<1>(*itr) == fieldType) {
200  const std::size_t fieldSize = std::get<2>(*itr)->getSubcellIndices(dim,subcell).size();
201 
202  // add field ID if there are enough in current pattern
203  for (std::size_t i=0;i<fieldSize;++i)
204  fieldIds_.push_back(std::get<0>(*itr));
205  numFields_[geomIndex]+=fieldSize;
206  }
207  }
208  TEUCHOS_ASSERT(numFields_[geomIndex]>=0);
209  }
210 
211  }
212  }
213 
214 }
215 
217 {
218  int dimension = getDimension();
219  FPPtr geomIdsPattern = getGeometricAggFieldPattern();
220 
221  // build patternData_ vector for implementation of the FieldPattern
222  // functions (indicies will index into fieldIds_)
223  patternData_.resize(dimension+1);
224  int nextIndex = 0;
225  for(int d=0;d<dimension+1;d++) {
226  int numSubcell = geomIdsPattern->getSubcellCount(d);
227  patternData_[d].resize(numSubcell);
228 
229  // loop through sub cells
230  for(int sc=0;sc<numSubcell;sc++) {
231  // a single geometric entity is assigned to field pattern
232  // geomIds size should be either 0 or 1.
233  const std::vector<int> & geomIds = geomIdsPattern->getSubcellIndices(d,sc);
234  TEUCHOS_ASSERT(geomIds.size()<=1);
235  if (geomIds.size() > 0) {
236  const int geomId = geomIds[0];
237  const int numFields = numFields_[geomId];
238  for(int k=0;k<numFields;k++,nextIndex++)
239  patternData_[d][sc].push_back(nextIndex);
240  }
241  }
242  }
243 }
244 
245 const std::vector<int> & FieldAggPattern::localOffsets(int fieldId) const
246 {
247  // lazy evaluation
248  std::map<int,std::vector<int> >::const_iterator itr = fieldOffsets_.find(fieldId);
249  if(itr!=fieldOffsets_.end())
250  return itr->second;
251 
252  std::vector<int> & offsets = fieldOffsets_[fieldId];
253  localOffsets_build(fieldId,offsets);
254  return offsets;
255 }
256 
257 const PHX::View<const int*> FieldAggPattern::localOffsetsKokkos(int fieldId) const
258 {
259  // lazy evaluation
260  std::map<int,PHX::View<int*> >::const_iterator itr = fieldOffsetsKokkos_.find(fieldId);
261  if(itr!=fieldOffsetsKokkos_.end())
262  return itr->second;
263 
264  const auto hostOffsetsStdVector = this->localOffsets(fieldId);
265  PHX::View<int*> offsets("panzer::FieldAggPattern::localOffsetsKokkos",hostOffsetsStdVector.size());
266  auto hostOffsets = Kokkos::create_mirror_view(offsets);
267  for (size_t i=0; i < hostOffsetsStdVector.size(); ++i)
268  hostOffsets(i) = hostOffsetsStdVector[i];
269  Kokkos::deep_copy(offsets,hostOffsets);
270  fieldOffsetsKokkos_[fieldId] = offsets;
271  return offsets;
272 }
273 
275 {
276  if(a[0] < b[0]) return true;
277  if(a[0] > b[0]) return false;
278 
279  // a[0]==b[0]
280  if(a[1] < b[1]) return true;
281  if(a[1] > b[1]) return false;
282 
283  // a[1]==b[1] && a[0]==b[0]
284  if(a[2] < b[2]) return true;
285  if(a[2] > b[2]) return false;
286 
287  // a[2]==b[2] && a[1]==b[1] && a[0]==b[0]
288  return false; // these are equal to, but not less than!
289 }
290 
291 //const std::vector<int> &
292 const std::pair<std::vector<int>,std::vector<int> > &
293 FieldAggPattern::localOffsets_closure(int fieldId,int subcellDim,int subcellId) const
294 {
295  // lazy evaluation
296  typedef std::map<Teuchos::Tuple<int,3>, std::pair<std::vector<int>,std::vector<int> >,LessThan> OffsetMap;
297 
298  Teuchos::Tuple<int,3> subcellTuple = Teuchos::tuple<int>(fieldId,subcellDim,subcellId);
299 
300  OffsetMap::const_iterator itr
301  = fieldSubcellOffsets_closure_.find(subcellTuple);
302  if(itr!=fieldSubcellOffsets_closure_.end()) {
303  return itr->second;
304  }
305 
306  TEUCHOS_TEST_FOR_EXCEPTION(subcellDim >= getDimension(),std::logic_error,
307  "FieldAggPattern::localOffsets_closure precondition subcellDim<getDimension() failed");
308  TEUCHOS_TEST_FOR_EXCEPTION(subcellId < 0,std::logic_error,
309  "FieldAggPattern::localOffsets_closure precondition subcellId>=0 failed");
310  TEUCHOS_TEST_FOR_EXCEPTION(subcellId>=getSubcellCount(subcellDim),std::logic_error,
311  "FieldAggPattern::localOffsets_closure precondition subcellId<getSubcellCount(subcellDim) failed");
312 
313  // build vector for sub cell closure indices
315  const std::vector<int> & fieldOffsets = localOffsets(fieldId);
316 
317  // get offsets into field offsets for the closure indices (from field pattern)
318  std::vector<int> closureOffsets;
319  FPPtr fieldPattern = getFieldPattern(fieldId);
320  fieldPattern->getSubcellClosureIndices(subcellDim,subcellId,closureOffsets);
321 
322  // build closure indices into the correct location in lazy evaluation map.
323  std::pair<std::vector<int>,std::vector<int> > & indicesPair
324  = fieldSubcellOffsets_closure_[subcellTuple];
325 
326  std::vector<int> & closureIndices = indicesPair.first;
327  for(std::size_t i=0;i<closureOffsets.size();i++)
328  closureIndices.push_back(fieldOffsets[closureOffsets[i]]);
329 
330  std::vector<int> & basisIndices = indicesPair.second;
331  basisIndices.assign(closureOffsets.begin(),closureOffsets.end());
332 
333  TEUCHOS_ASSERT(fieldSubcellOffsets_closure_[subcellTuple].first.size()==closureIndices.size());
334  return fieldSubcellOffsets_closure_[subcellTuple];
335 }
336 
337 void FieldAggPattern::localOffsets_build(int fieldId,std::vector<int> & offsets) const
338 {
339  // This function makes the assumption that if there are multiple indices
340  // shared by a subcell then the GeometricAggFieldPattern reflects this.
341  // This is a fine assumption on edges and faces because the symmetries require
342  // extra information about ordering. However, on nodes and "volumes" the
343  // assumption appears to be stupid. For consistency we will make it.
344  //
345  // This code needs to be tested with a basis that has multple IDs at
346  // a node or "volume" sub cell.
347 
348  FPPtr fieldPattern = getFieldPattern(fieldId);
349  FieldType fieldType = getFieldType(fieldId);
350 
351  offsets.clear();
352  offsets.resize(fieldPattern->numberIds(),-111111); // fill with negative number for testing
353 
354  // this will offsets for all IDs associated with the field
355  // but using a geometric ordering
356  std::vector<int> fieldIdsGeomOrder;
357  for(std::size_t i=0;i<fieldIds_.size();++i) {
358  if(fieldIds_[i]==fieldId)
359  fieldIdsGeomOrder.push_back(i);
360  }
361 
362  // Check that number of DOFs line up
363  TEUCHOS_ASSERT((int) fieldIdsGeomOrder.size()==fieldPattern->numberIds());
364 
365  // Build geometric ordering for this pattern: will index into fieldIdsGeomOrder
366  GeometricAggFieldPattern geomPattern(fieldType,fieldPattern);
367  int cnt = 0;
368  for(int dim=0;dim<geomPattern.getDimension()+1;dim++) {
369  for(int sc=0;sc<geomPattern.getSubcellCount(dim);sc++) {
370  const std::vector<int> & fIndices = fieldPattern->getSubcellIndices(dim,sc);
371 
372  for(std::size_t i=0;i<fIndices.size();i++)
373  offsets[fIndices[i]] = fieldIdsGeomOrder[cnt++];
374  }
375  }
376 
377  // check for failure/bug
378  for(std::size_t i=0;i<offsets.size();i++) {
379  TEUCHOS_ASSERT(offsets[i]>=0);
380  }
381 }
382 
383 }
const std::pair< std::vector< int >, std::vector< int > > & localOffsets_closure(int fieldId, int subcellDim, int subcellId) const
std::map< int, std::vector< int > > fieldOffsets_
Stores the Field offsets for the fieldId key. Note that the key is the fieldId, not the index into th...
std::map< Teuchos::Tuple< int, 3 >, std::pair< std::vector< int >, std::vector< int > >, LessThan > fieldSubcellOffsets_closure_
virtual Teuchos::RCP< const FieldPattern > getFieldPattern(int fieldId) const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual Teuchos::RCP< const FieldPattern > getGeometricAggFieldPattern() const
std::map< int, int > fieldIdToPatternIdx_
virtual int getSubcellCount(int dimension) const
std::vector< std::vector< std::vector< int > > > patternData_
FieldType
The type of discretization to use for a field pattern.
virtual FieldType getFieldType(int fieldId) const
virtual int getDimension() const
Teuchos::RCP< const FieldPattern > geomAggPattern_
int numFields
virtual void getSubcellClosureIndices(int, int, std::vector< int > &) const
virtual void buildPattern(const std::vector< std::tuple< int, panzer::FieldType, Teuchos::RCP< const FieldPattern > > > &patterns, const Teuchos::RCP< const FieldPattern > &geomAggPattern=Teuchos::null)
PHX::View< const int * > offsets
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void localOffsets_build(int fieldId, std::vector< int > &offsets) const
Continuous Galerkin Formulation.
std::map< int, PHX::View< int * > > fieldOffsetsKokkos_
Stores the Field offsets for the fieldId key. Note that the key is the fieldId, not the index into th...
virtual void print(std::ostream &os) const
virtual void print(std::ostream &os) const
Print this pattern.
std::vector< std::tuple< int, panzer::FieldType, Teuchos::RCP< const FieldPattern > > > patterns_
bool operator()(const Teuchos::Tuple< int, 3 > &a, const Teuchos::Tuple< int, 3 > &b) const
const PHX::View< const int * > localOffsetsKokkos(int fieldId) const
virtual const std::vector< int > & getSubcellIndices(int dimension, int subcell) const
#define TEUCHOS_ASSERT(assertion_test)
virtual shards::CellTopology getCellTopology() const
void mergeFieldPatterns(const FieldType &fieldType)
const std::vector< int > & localOffsets(int fieldId) const