1 // @HEADER
2 // ************************************************************************
3 //
4 //               Rapid Optimization Library (ROL) Package
5 //                 Copyright (2014) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact lead developers:
38 //              Drew Kouri   (dpkouri@sandia.gov) and
39 //              Denis Ridzal (dridzal@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
44 /*! \file  dofmanager.hpp
45     \brief Given a mesh with connectivity information, sets up data
46            structures for the indexing of the global degrees of
47            freedom (Dofs).
48 */
49 
50 #ifndef DOFMANAGER_HPP
51 #define DOFMANAGER_HPP
52 
53 #include "Teuchos_ParameterList.hpp"
54 #include "Intrepid_FieldContainer.hpp"
55 #include "Intrepid_Basis.hpp"
56 #include "meshmanager.hpp"
57 
58 template <class Real>
59 class DofManager {
60 
61 private:
62   using GO = typename Tpetra::Map<>::global_ordinal_type;
63 
64   ROL::Ptr<MeshManager<Real> > meshManager_;
65   std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real> > > > intrepidBasis_;
66 
67   GO numCells_;         // number of mesh cells
68   GO numNodes_;         // number of mesh nodes
69   GO numEdges_;         // number of mesh edges
70 
71   ROL::Ptr<Intrepid::FieldContainer<GO> > meshCellToNodeMap_;
72   ROL::Ptr<Intrepid::FieldContainer<GO> > meshCellToEdgeMap_;
73 
74   // Local dof information.
75   int numBases_;                                  // number of bases (fields)
76   int numLocalNodes_;                             // number of nodes in the basic cell topology
77   int numLocalEdges_;                             // number of edges in the basic cell topology
78   int numLocalFaces_;                             // number of faces in the basic cell topology
79   int numLocalNodeDofs_;                          // number of local (single-cell) node dofs for all bases
80   int numLocalEdgeDofs_;                          // number of local (single-cell) edge dofs for all bases
81   int numLocalFaceDofs_;                          // number of local (single-cell) face dofs for all bases
82   int numLocalDofs_;                              // total number of local (single-cell) face dofs for all bases
83   std::vector<int> numDofsPerNode_;               // number of dofs per node in a cell (assumed constant), per basis
84   std::vector<int> numDofsPerEdge_;               // number of dofs per edge in a cell (assumed constant), per basis
85   std::vector<int> numDofsPerFace_;               // number of dofs per face in a cell (assumed constant), per basis
86   std::vector<std::vector<int> > fieldPattern_;   // local indexing of fields into the array [0,1,...,numLocalDofs-1];
87                                                   // contains [number of bases] index vectors, where each index vector
88                                                   // is of size [basis cardinality]
89   // Global dof information.
90   GO numNodeDofs_;  // number of global node dofs
91   GO numEdgeDofs_;  // number of global edge dofs
92   GO numFaceDofs_;  // number of global face dofs
93   GO numDofs_;      // total number of global dofs
94 
95   ROL::Ptr<Intrepid::FieldContainer<GO> > nodeDofs_;  // global node dofs, of size [numNodes_ x numLocalNodeDofs_]
96   ROL::Ptr<Intrepid::FieldContainer<GO> > edgeDofs_;  // global edge dofs, of size [numEdges_ x numLocalEdgeDofs_]
97   ROL::Ptr<Intrepid::FieldContainer<GO> > faceDofs_;  // global face dofs, of size [numFaces_ x numLocalFaceDofs_]
98   ROL::Ptr<Intrepid::FieldContainer<GO> > cellDofs_;  // global cell dofs, of size [numCells_ x numLocalDofs_];
99                                                            // ordered by subcell (node, then edge, then face) and basis index
100 
101   std::vector<ROL::Ptr<Intrepid::FieldContainer<GO> > > fieldDofs_;  // global cell dofs, indexed by field/basis, of size [numCells_ x basis cardinality];
102                                                                           // ordered by subcell (node, then edge, then face)
103 
104 public:
105 
DofManager(ROL::Ptr<MeshManager<Real>> & meshManager,std::vector<ROL::Ptr<Intrepid::Basis<Real,Intrepid::FieldContainer<Real>>>> & intrepidBasis)106   DofManager(ROL::Ptr<MeshManager<Real> >                                                    &meshManager,
107              std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real> > > > &intrepidBasis) {
108 
109     meshManager_ = meshManager;
110     intrepidBasis_ = intrepidBasis;
111     numCells_ = meshManager_->getNumCells();
112     numNodes_ = meshManager_->getNumNodes();
113     numEdges_ = meshManager_->getNumEdges();
114 
115     // Mesh data structures.
116     meshCellToNodeMap_ = meshManager_->getCellToNodeMap();
117     meshCellToEdgeMap_ = meshManager_->getCellToEdgeMap();
118 
119     // Local degree-of-freedom footprint.
120     numBases_ = static_cast<int>(intrepidBasis_.size());
121     numDofsPerNode_.resize(numBases_, 0);
122     numDofsPerEdge_.resize(numBases_, 0);
123     numDofsPerFace_.resize(numBases_, 0);
124     numLocalDofs_ = 0;
125     for (int i=0; i<numBases_; ++i) {
126       std::vector<std::vector<int> > dofTags = (intrepidBasis_[i])->getAllDofTags();
127       for (int j=0; j<(intrepidBasis_[i])->getCardinality(); j++) {
128         if (dofTags[j][0] == 0) {
129           numDofsPerNode_[i] = dofTags[j][3];
130         }
131         else if (dofTags[j][0] == 1) {
132           numDofsPerEdge_[i] = dofTags[j][3];
133         }
134         else if (dofTags[j][0] == 2) {
135           numDofsPerFace_[i] = dofTags[j][3];
136         }
137       }
138       numLocalDofs_ += (intrepidBasis_[i])->getCardinality();
139     }
140     numLocalNodeDofs_ = 0;
141     numLocalEdgeDofs_ = 0;
142     numLocalFaceDofs_ = 0;
143     for (int i=0; i<numBases_; ++i) {
144       numLocalNodeDofs_ += numDofsPerNode_[i];
145       numLocalEdgeDofs_ += numDofsPerEdge_[i];
146       numLocalFaceDofs_ += numDofsPerFace_[i];
147     }
148     numLocalNodes_ = static_cast<int>( (intrepidBasis_[0])->getBaseCellTopology().getVertexCount() );
149     numLocalEdges_ = static_cast<int>( (intrepidBasis_[0])->getBaseCellTopology().getEdgeCount() );
150     numLocalFaces_ = 1;
151     computeFieldPattern();
152 
153     // Global data structures.
154     computeDofArrays();
155     computeCellDofs();
156     computeFieldDofs();
157   }
158 
159 
getNodeDofs() const160   ROL::Ptr<Intrepid::FieldContainer<GO> > getNodeDofs() const {
161     return nodeDofs_;
162   }
163 
164 
getEdgeDofs() const165   ROL::Ptr<Intrepid::FieldContainer<GO> > getEdgeDofs() const {
166     return edgeDofs_;
167   }
168 
169 
getFaceDofs() const170   ROL::Ptr<Intrepid::FieldContainer<GO> > getFaceDofs() const {
171     return faceDofs_;
172   }
173 
174 
getCellDofs() const175   ROL::Ptr<Intrepid::FieldContainer<GO> > getCellDofs() const {
176     return cellDofs_;
177   }
178 
179 
getFieldDofs() const180   std::vector<ROL::Ptr<Intrepid::FieldContainer<GO> > > getFieldDofs() const {
181     return fieldDofs_;
182   }
183 
184 
getFieldDofs(const int & fieldNumber) const185   ROL::Ptr<Intrepid::FieldContainer<GO> > getFieldDofs(const int & fieldNumber) const {
186     return fieldDofs_[fieldNumber];
187   }
188 
189 
getNumNodeDofs() const190   GO getNumNodeDofs() const {
191     return numNodeDofs_;
192   }
193 
194 
getNumEdgeDofs() const195   GO getNumEdgeDofs() const {
196     return numEdgeDofs_;
197   }
198 
199 
getNumFaceDofs() const200   GO getNumFaceDofs() const {
201     return numFaceDofs_;
202   }
203 
204 
getNumDofs() const205   GO getNumDofs() const {
206     return numDofs_;
207   }
208 
209 
getNumFields() const210   int getNumFields() const {
211     return numBases_;
212   }
213 
214 
getLocalFieldSize() const215   int getLocalFieldSize() const {
216     return numLocalDofs_;
217   }
218 
219 
getLocalFieldSize(const int & fieldNumber) const220   int getLocalFieldSize(const int & fieldNumber) const {
221     return (intrepidBasis_[fieldNumber])->getCardinality();
222   }
223 
224 
getFieldPattern() const225   std::vector<std::vector<int> > getFieldPattern() const {
226     return fieldPattern_;
227   }
228 
229 
getFieldPattern(const int & fieldNumber) const230   std::vector<int> getFieldPattern(const int & fieldNumber) const {
231     return fieldPattern_[fieldNumber];
232   }
233 
234 
235 private:
236 
computeDofArrays()237   void computeDofArrays() {
238 
239     nodeDofs_ = ROL::makePtr<Intrepid::FieldContainer<GO>>(numNodes_, numLocalNodeDofs_);
240     edgeDofs_ = ROL::makePtr<Intrepid::FieldContainer<GO>>(numEdges_, numLocalEdgeDofs_);
241     faceDofs_ = ROL::makePtr<Intrepid::FieldContainer<GO>>(numCells_, numLocalFaceDofs_);
242 
243     Intrepid::FieldContainer<GO> &nodeDofs = *nodeDofs_;
244     Intrepid::FieldContainer<GO> &edgeDofs = *edgeDofs_;
245     Intrepid::FieldContainer<GO> &faceDofs = *faceDofs_;
246 
247     int dofCt = -1;
248 
249     //
250     // This is the independent node id --> edge id --> cell id ordering.
251     // For example, for a Q2-Q2-Q1 basis (Taylor-Hood), we would have:
252     //
253     //     Q2   Q2   Q1
254     //     --------------
255     // n1  1    1    1
256     // n2  1    1    1
257     // ...
258     // e1  1    1    0
259     // e2  1    1    0
260     // ...
261     // c1  1    1    0
262     // c2  1    1    0
263     // ...
264     //
265 
266     // count node dofs
267     for (GO i=0; i<numNodes_; ++i) {
268       int locNodeCt = -1;
269       for (int j=0; j<numBases_; ++j) {
270         for (int k=0; k<numDofsPerNode_[j]; ++k) {
271           nodeDofs(i, ++locNodeCt) = ++dofCt;
272         }
273       }
274     }
275     numNodeDofs_ = dofCt+1;
276 
277     // count edge dofs
278     for (GO i=0; i<numEdges_; ++i) {
279       int locEdgeCt = -1;
280       for (int j=0; j<numBases_; ++j) {
281         for (int k=0; k<numDofsPerEdge_[j]; ++k) {
282           edgeDofs(i, ++locEdgeCt) = ++dofCt;
283         }
284       }
285     }
286     numEdgeDofs_ = dofCt+1-numNodeDofs_;
287 
288     // count face dofs
289     for (GO i=0; i<numCells_; ++i) {
290       int locFaceCt = -1;
291       for (int j=0; j<numBases_; ++j) {
292         for (int k=0; k<numDofsPerFace_[j]; ++k) {
293           faceDofs(i, ++locFaceCt) = ++dofCt;
294         }
295       }
296     }
297     numFaceDofs_ = dofCt+1-numNodeDofs_-numEdgeDofs_;
298 
299     numDofs_ = numNodeDofs_+numEdgeDofs_+numFaceDofs_;
300 
301   } // computeDofArrays
302 
303 
computeCellDofs()304   void computeCellDofs() {
305 
306     cellDofs_ = ROL::makePtr<Intrepid::FieldContainer<GO>>(numCells_, numLocalDofs_);
307 
308     // Grab object references, for easier indexing.
309     Intrepid::FieldContainer<GO> &cdofs = *cellDofs_;
310     Intrepid::FieldContainer<GO> &nodeDofs = *nodeDofs_;
311     Intrepid::FieldContainer<GO> &edgeDofs = *edgeDofs_;
312     Intrepid::FieldContainer<GO> &faceDofs = *faceDofs_;
313     Intrepid::FieldContainer<GO> &ctn = *meshCellToNodeMap_;
314     Intrepid::FieldContainer<GO> &cte = *meshCellToEdgeMap_;
315 
316     for (GO i=0; i<numCells_; ++i) {
317       int ct = -1;
318       for (int j=0; j<numLocalNodes_; ++j) {
319         for (int k=0; k<numLocalNodeDofs_; ++k) {
320           cdofs(i,++ct) = nodeDofs(ctn(i,j), k);
321         }
322       }
323       for (int j=0; j<numLocalEdges_; ++j) {
324         for (int k=0; k<numLocalEdgeDofs_; ++k) {
325           cdofs(i,++ct) = edgeDofs(cte(i,j), k);
326         }
327       }
328       for (int j=0; j<numLocalFaces_; ++j) {
329         for (int k=0; k<numLocalFaceDofs_; ++k) {
330           cdofs(i,++ct) = faceDofs(i, k);
331         }
332       }
333     }
334   } // computeCellDofs
335 
336 
computeFieldPattern()337   void computeFieldPattern() {
338 
339     fieldPattern_.resize(numBases_);
340 
341     int dofCt = -1;
342 
343     // count node dofs
344     for (int i=0; i<numLocalNodes_; ++i) {
345       for (int j=0; j<numBases_; ++j) {
346         for (int k=0; k<numDofsPerNode_[j]; ++k) {
347           fieldPattern_[j].push_back(++dofCt);
348         }
349       }
350     }
351 
352     // count edge dofs
353     for (int i=0; i<numLocalEdges_; ++i) {
354       for (int j=0; j<numBases_; ++j) {
355         for (int k=0; k<numDofsPerEdge_[j]; ++k) {
356           fieldPattern_[j].push_back(++dofCt);
357         }
358       }
359     }
360 
361     // count face dofs
362     for (int i=0; i<numLocalFaces_; ++i) {
363       for (int j=0; j<numBases_; ++j) {
364         for (int k=0; k<numDofsPerFace_[j]; ++k) {
365           fieldPattern_[j].push_back(++dofCt);
366         }
367       }
368     }
369 
370   } // computeFieldPattern
371 
372 
computeFieldDofs()373   void computeFieldDofs() {
374 
375     fieldDofs_.resize(numBases_);
376 
377     Intrepid::FieldContainer<GO> &cdofs = *cellDofs_;
378 
379     for (int fieldNum=0; fieldNum<numBases_; ++fieldNum) {
380       int basisCard = intrepidBasis_[fieldNum]->getCardinality();
381       fieldDofs_[fieldNum] = ROL::makePtr<Intrepid::FieldContainer<GO>>(numCells_, basisCard);
382       Intrepid::FieldContainer<GO> &fdofs = *(fieldDofs_[fieldNum]);
383       for (GO i=0; i<numCells_; ++i) {
384         for (int j=0; j<basisCard; ++j) {
385           fdofs(i,j) = cdofs(i, fieldPattern_[fieldNum][j]);
386         }
387       }
388     }
389   } // computeFieldDofs
390 
391 }; // DofManager
392 
393 #endif
394