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