Panzer Version of the Day
Loading...
Searching...
No Matches
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
15using Teuchos::RCP;
16using Teuchos::rcp;
17
18namespace panzer {
19
23
24FieldAggPattern::FieldAggPattern(std::vector<std::tuple<int,panzer::FieldType,Teuchos::RCP<const FieldPattern> > > & patterns,
25 const Teuchos::RCP<const FieldPattern> & geomAggPattern)
26{
27 buildPattern(patterns,geomAggPattern);
28}
29
30Teuchos::RCP<const FieldPattern> FieldAggPattern::getGeometricAggFieldPattern() const
31{
32 return geomAggPattern_;
33}
34
35void 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
71shards::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
80int FieldAggPattern::getSubcellCount(int dimension) const
81{
82 return patternData_[dimension].size();
83}
84
85const std::vector<int> & FieldAggPattern::getSubcellIndices(int dimension, int subcell) const
86{
87 return patternData_[dimension][subcell];
88}
89
90void 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
96void 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
127Teuchos::RCP<const FieldPattern> FieldAggPattern::getFieldPattern(int fieldId) const
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
245const 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];
254 return offsets;
255}
256
257const 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
274bool FieldAggPattern::LessThan::operator()(const Teuchos::Tuple<int,3> & a,const Teuchos::Tuple<int,3> & b) const
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> &
292const std::pair<std::vector<int>,std::vector<int> > &
293FieldAggPattern::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
337void 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}
int numFields
PHX::View< const int * > offsets
std::map< int, int > fieldIdToPatternIdx_
virtual void buildPattern(const std::vector< std::tuple< int, panzer::FieldType, Teuchos::RCP< const FieldPattern > > > &patterns, const Teuchos::RCP< const FieldPattern > &geomAggPattern=Teuchos::null)
const std::pair< std::vector< int >, std::vector< int > > & localOffsets_closure(int fieldId, int subcellDim, int subcellId) const
virtual void getSubcellClosureIndices(int, int, std::vector< int > &) const
virtual Teuchos::RCP< const FieldPattern > getFieldPattern(int fieldId) const
void mergeFieldPatterns(const FieldType &fieldType)
Teuchos::RCP< const FieldPattern > geomAggPattern_
std::map< Teuchos::Tuple< int, 3 >, std::pair< std::vector< int >, std::vector< int > >, LessThan > fieldSubcellOffsets_closure_
const std::vector< int > & localOffsets(int fieldId) const
std::vector< std::tuple< int, panzer::FieldType, Teuchos::RCP< const FieldPattern > > > patterns_
virtual const std::vector< int > & getSubcellIndices(int dimension, int subcell) const
void localOffsets_build(int fieldId, std::vector< int > &offsets) const
virtual void print(std::ostream &os) const
Print this pattern.
Teuchos::RCP< const FieldPattern > FPPtr
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...
std::vector< std::vector< std::vector< int > > > patternData_
virtual Teuchos::RCP< const FieldPattern > getGeometricAggFieldPattern() const
virtual int getSubcellCount(int dimension) const
virtual FieldType getFieldType(int fieldId) 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...
virtual shards::CellTopology getCellTopology() const
const PHX::View< const int * > localOffsetsKokkos(int fieldId) const
virtual void print(std::ostream &os) const
FieldType
The type of discretization to use for a field pattern.
@ DG
Continuous Galerkin Formulation.
bool operator()(const Teuchos::Tuple< int, 3 > &a, const Teuchos::Tuple< int, 3 > &b) const