SundanceMixedDOFMap.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                              Sundance
00005 //                 Copyright (2005) Sandia Corporation
00006 // 
00007 // Copyright (year first published) Sandia Corporation.  Under the terms 
00008 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 
00009 // retains certain rights in this software.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //                                                                                 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA                                                                                
00025 // Questions? Contact Kevin Long (krlong@sandia.gov), 
00026 // Sandia National Laboratories, Livermore, California, USA
00027 // 
00028 // ************************************************************************
00029 /* @HEADER@ */
00030 
00031 #include "SundanceMixedDOFMap.hpp"
00032 #include "SundanceBasisDOFTopologyBase.hpp"
00033 #include "SundanceCellFilter.hpp"
00034 #include "SundanceMaximalCellFilter.hpp"
00035 #include "Teuchos_MPIContainerComm.hpp"
00036 #include "SundanceOut.hpp"
00037 #include "SundanceTabs.hpp"
00038 #include "Teuchos_Time.hpp"
00039 #include "Teuchos_TimeMonitor.hpp"
00040 
00041 
00042 using namespace Sundance;
00043 using namespace Teuchos;
00044 
00045 
00046 static Time& mixedDOFCtorTimer() 
00047 {
00048   static RCP<Time> rtn 
00049     = TimeMonitor::getNewTimer("mixed DOF map init"); 
00050   return *rtn;
00051 }
00052 static Time& maxDOFBuildTimer() 
00053 {
00054   static RCP<Time> rtn 
00055     = TimeMonitor::getNewTimer("max-cell dof table init"); 
00056   return *rtn;
00057 }
00058 
00059 MixedDOFMap::MixedDOFMap(const Mesh& mesh, 
00060   const Array<RCP<BasisDOFTopologyBase> >& basis,
00061   const CellFilter& maxCells,
00062   int setupVerb)
00063   : SpatiallyHomogeneousDOFMapBase(mesh, basis.size(), setupVerb), 
00064     maxCells_(maxCells),
00065     dim_(mesh.spatialDim()),
00066     dofs_(mesh.spatialDim()+1),
00067     maximalDofs_(),
00068     haveMaximalDofs_(false),
00069     localNodePtrs_(),
00070     nNodesPerCell_(),
00071     totalNNodesPerCell_(),
00072     cellHasAnyDOFs_(dim_+1),
00073     numFacets_(mesh.spatialDim()+1),
00074     originalFacetOrientation_(2),
00075     hasBeenAssigned_(mesh.spatialDim()+1),
00076     structure_(),
00077     nFuncs_()
00078 {
00079   TimeMonitor timer(mixedDOFCtorTimer());
00080   Tabs tab;
00081   SUNDANCE_MSG1(setupVerb, tab << "building mixed DOF map");
00082 
00083   Sundance::Map<OrderedHandle<BasisDOFTopologyBase>, int> basisToChunkMap;
00084   Array<RCP<BasisDOFTopologyBase> > chunkBases;
00085   Array<Array<int> > chunkFuncs;
00086   
00087   int chunk = 0;
00088   int nBasis = basis.size();
00089   for (int i=0; i<nBasis; i++)
00090   {
00091     OrderedHandle<BasisDOFTopologyBase> bh = basis[i];
00092     if (!basisToChunkMap.containsKey(bh))
00093     {
00094       chunkBases.append(basis[i]);
00095       basisToChunkMap.put(bh, chunk);
00096       chunkFuncs.append(tuple(i));
00097       chunk++;
00098     }
00099     else
00100     {
00101       int b = basisToChunkMap.get(bh);
00102       chunkFuncs[b].append(i);
00103     }
00104   }
00105 
00106   Tabs tab1;
00107   SUNDANCE_MSG2(setupVerb, tab1 << "basis to chunk map = " << basisToChunkMap);
00108 
00109 
00110   structure_ = rcp(new MapStructure(basis.size(), chunkBases, chunkFuncs));
00111 
00112   nFuncs_.resize(chunkBases.size());
00113   for (int i=0; i<nFuncs_.size(); i++) 
00114     nFuncs_[i] = chunkFuncs[i].size();
00115 
00116   allocate(mesh);
00117 
00118   initMap();
00119 
00120   buildMaximalDofTable();
00121 
00122   /* do a sanity check */
00123   checkTable();
00124 
00125   SUNDANCE_MSG1(setupVerb, tab << "done building mixed DOF map");
00126 }
00127 
00128 
00129 void MixedDOFMap::allocate(const Mesh& mesh)
00130 {
00131   Tabs tab;
00132 
00133   /* gather functions into chunks sharing identical basis functions */
00134   SUNDANCE_MSG1(setupVerb(), tab << "grouping like basis functions");
00135   
00136 
00137   /* now that we know the number of basis chunks, allocate arrays */
00138   localNodePtrs_.resize(nBasisChunks());
00139   nNodesPerCell_.resize(nBasisChunks());
00140   totalNNodesPerCell_.resize(nBasisChunks());
00141   nDofsPerCell_.resize(nBasisChunks());
00142   totalNDofsPerCell_.resize(nBasisChunks());
00143   maximalDofs_.resize(nBasisChunks());
00144 
00145   for (int b=0; b<nBasisChunks(); b++)
00146   {
00147     localNodePtrs_[b].resize(mesh.spatialDim()+1);
00148     nNodesPerCell_[b].resize(mesh.spatialDim()+1);
00149     totalNNodesPerCell_[b].resize(mesh.spatialDim()+1);
00150     nDofsPerCell_[b].resize(mesh.spatialDim()+1);
00151     totalNDofsPerCell_[b].resize(mesh.spatialDim()+1);
00152   }
00153   
00154 
00155   /* compute node counts for each cell dimension and each basis type */
00156   SUNDANCE_MSG1(setupVerb(), tab << "working out DOF map node counts");
00157   
00158   numFacets_.resize(dim_+1);
00159 
00160   for (int d=0; d<=dim_; d++)
00161   {
00162     Tabs tab1;
00163     SUNDANCE_MSG2(setupVerb(), tab << "allocating maps for cell dim=" << d);
00164     /* record the number of facets for each cell type so we're
00165      * not making a bunch of mesh calls */
00166     numFacets_[d].resize(d);
00167     for (int fd=0; fd<d; fd++) numFacets_[d][fd]=mesh.numFacets(d, 0, fd);
00168     SUNDANCE_MSG3(setupVerb(), tab1 << "num facets for dimension " << d << " is " 
00169       << numFacets_[d]);
00170 
00171     cellHasAnyDOFs_[d] = false;
00172     dofs_[d].resize(nBasisChunks());
00173 
00174     int numCells = mesh.numCells(d);
00175     hasBeenAssigned_[d].resize(numCells);
00176 
00177     for (int b=0; b<nBasisChunks(); b++)
00178     {
00179       Tabs tab2;
00180       SUNDANCE_MSG2(setupVerb(), tab1 << "basis chunk=" << b);
00181       SUNDANCE_MSG2(setupVerb(), tab2 << "basis=" << basis(b)->description());
00182       int nNodes = basis(b).ptr()->nReferenceDOFsWithFacets(mesh.cellType(dim_), mesh.cellType(d));
00183       SUNDANCE_MSG2(setupVerb(), tab2 << "nNodes per cell=" << nNodes);
00184       if (nNodes == 0)
00185       {
00186         nNodesPerCell_[b][d] = 0;
00187         nDofsPerCell_[b][d] = 0;
00188       }
00189       else
00190       {
00191         /* look up the node pointer for this cell and for all of its
00192          * facets */
00193         basis(b).ptr()->getReferenceDOFs(mesh.cellType(dim_),
00194           mesh.cellType(d), 
00195           localNodePtrs_[b][d]);
00196               
00197               
00198         SUNDANCE_MSG3(setupVerb(), tab2 << "node ptrs are " 
00199           << localNodePtrs_[b][d]);
00200               
00201         /* with the node pointers in hand, we can work out the number
00202          * of nodes per cell in this dimension for this basis */
00203         if (localNodePtrs_[b][d][d].size() > 0) 
00204         {
00205           nNodesPerCell_[b][d] = localNodePtrs_[b][d][d][0].size();
00206           if (nNodesPerCell_[b][d] > 0) cellHasAnyDOFs_[d] = true;
00207         }
00208         else
00209         {
00210           nNodesPerCell_[b][d] = 0;
00211         }
00212         nDofsPerCell_[b][d] = nNodesPerCell_[b][d] * nFuncs(b);
00213       }
00214 
00215       /* if the cell is of intermediate dimension and it has DOFs, we
00216        * need to assign GIDs for the cells of this dimension. Otherwise,
00217        * we can skip intermediate GID assignment, saving some parallel
00218        * communication */
00219       if (nDofsPerCell_[b][d] > 0 && d > 0 && d < mesh.spatialDim())
00220       {
00221         Mesh& tmpMesh = const_cast<Mesh&>(mesh);
00222         tmpMesh.assignIntermediateCellGIDs(d);
00223       }
00224           
00225       SUNDANCE_MSG3(setupVerb(), tab2 << 
00226         "num nodes is " 
00227         << nNodesPerCell_[b][d]);
00228 
00229       totalNNodesPerCell_[b][d] = nNodesPerCell_[b][d];
00230       for (int dd=0; dd<d; dd++) 
00231       {
00232         totalNNodesPerCell_[b][d] 
00233           += numFacets_[d][dd]*nNodesPerCell_[b][dd];
00234       }
00235       totalNDofsPerCell_[b][d] = totalNNodesPerCell_[b][d] * nFuncs(b);
00236       SUNDANCE_MSG3(setupVerb(), tab2 << "totalNDofsPerCell " << totalNDofsPerCell_[b][d]);
00237 
00238       if (nNodes > 0)
00239       {
00240         /* allocate the DOFs array for this dimension */
00241         dofs_[d][b].resize(nDofsPerCell_[b][d] * numCells);
00242               
00243         /* set all DOFs to a marker value */
00244         int nDof = dofs_[d][b].size();
00245         Array<int>& dofs = dofs_[d][b];
00246         int marker = uninitializedVal();
00247         for (int i=0; i<nDof; i++) 
00248         {
00249           dofs[i] = marker;
00250         }
00251       }
00252       /* allocate the maximal dof array */
00253       if (d==dim_)
00254       {
00255         maximalDofs_[b].resize(totalNDofsPerCell_[b][d]*numCells);
00256       }
00257     }
00258 
00259     /* allocate the array of original facet orientations */
00260     if (d > 0 && d < dim_) 
00261     {
00262       originalFacetOrientation_[d-1].resize(numCells);
00263     }
00264       
00265   }
00266   SUNDANCE_MSG1(setupVerb(), tab << "done allocating DOF map");
00267 }
00268 
00269 void MixedDOFMap::initMap()
00270 {
00271   Tabs tab;
00272   SUNDANCE_MSG1(setupVerb(), tab << "initializing DOF map");
00273   /* start the DOF count at zero. */
00274   int nextDOF = 0;
00275 
00276   /* Space in which to keep a list of remote cells needed by each processor
00277    * for each dimension. The first index is dimension, the second proc, the
00278    * third cell number. */
00279   Array<Array<Array<int> > > remoteCells(mesh().spatialDim()+1);
00280 
00281   for (int d=0; d<remoteCells.size(); d++) 
00282     remoteCells[d].resize(mesh().comm().getNProc());
00283   
00284   /* Loop over maximal cells in the order specified by the cell iterator.
00285    * This might be reordered relative to the mesh. 
00286    *
00287    * At each maximal cell, we'll run through the facets and 
00288    * assign DOFs. That will take somewhat more work, but gives much 
00289    * better cache locality for the matrix because all the DOFs for
00290    * each maximal element and its facets are grouped together. */
00291   
00292   CellSet cells = maxCells_.getCells(mesh());
00293   CellIterator iter;
00294   for (iter=cells.begin(); iter != cells.end(); iter++)
00295   {
00296     /* first assign any DOFs associated with the maximal cell */
00297     int cellLID = *iter;
00298     int owner;
00299       
00300     if (cellHasAnyDOFs_[dim_])
00301     {
00302       /* if the maximal cell is owned by another processor,
00303        * put it in the list of cells for which we need to request 
00304        * DOF information from another processor */
00305       if (isRemote(dim_, cellLID, owner))
00306       {
00307         int cellGID = mesh().mapLIDToGID(dim_, cellLID);
00308         SUNDANCE_MSG4(setupVerb(), "proc=" << comm().getRank() 
00309           << " thinks d-" << dim_ 
00310           << " cell GID=" << cellGID
00311           << " is owned remotely by p=" 
00312           << owner);
00313         remoteCells[dim_][owner].append(cellGID); 
00314       }
00315       else /* the cell is locally owned, so we can 
00316             * set its DOF numbers now */
00317       {
00318         for (int b=0; b<nBasisChunks(); b++)
00319         {
00320           setDOFs(b, dim_, cellLID, nextDOF);
00321         }
00322       }
00323     }
00324 
00325     /* Now assign any DOFs associated with the facets. */
00326     for (int d=0; d<dim_; d++)
00327     {
00328       if (cellHasAnyDOFs_[d])
00329       {
00330         int nf = numFacets_[dim_][d];
00331         Array<int> facetLID(nf);
00332         Array<int> facetOrientations(nf);
00333         /* look up the LIDs of the facets */
00334         mesh().getFacetArray(dim_, cellLID, d, 
00335           facetLID, facetOrientations);
00336         /* for each facet, process its DOFs */
00337         for (int f=0; f<nf; f++)
00338         {
00339           /* if the facet's DOFs have been assigned already,
00340            * we're done */
00341           if (!hasBeenAssigned(d, facetLID[f]))
00342           {
00343             markAsAssigned(d, facetLID[f]);
00344             /* the facet may be owned by another processor */
00345             if (isRemote(d, facetLID[f], owner))
00346             {
00347               int facetGID 
00348                 = mesh().mapLIDToGID(d, facetLID[f]);
00349               SUNDANCE_MSG4(setupVerb(), "proc=" << comm().getRank() 
00350                 << " thinks d-" << d 
00351                 << " cell GID=" << facetGID
00352                 << " is owned remotely by p=" << owner);
00353               remoteCells[d][owner].append(facetGID);
00354             }
00355             else /* we can assign a DOF locally */
00356             {
00357               /* assign DOF */
00358               for (int b=0; b<nBasisChunks(); b++)
00359               {
00360                 setDOFs(b, d, facetLID[f], nextDOF);
00361               }
00362               /* record the orientation wrt the maximal cell */
00363               if (d > 0) 
00364               {
00365                 originalFacetOrientation_[d-1][facetLID[f]] 
00366                   = facetOrientations[f];
00367               }
00368             }
00369           }
00370         }
00371       }
00372     }
00373   }
00374     
00375 
00376   /* Done with first pass, in which we have assigned DOFs for all
00377    * local processors. We now have to share DOF information between
00378    * processors */
00379 
00380   int numLocalDOFs = nextDOF;
00381   if (mesh().comm().getNProc() > 1)
00382   {
00383     for (int d=0; d<=dim_; d++)
00384     {
00385       if (cellHasAnyDOFs_[d])
00386       {
00387         computeOffsets(d, numLocalDOFs);
00388         shareDOFs(d, remoteCells[d]);
00389       }
00390     }
00391   }
00392   else
00393   {
00394     setLowestLocalDOF(0);
00395     setNumLocalDOFs(numLocalDOFs);
00396     setTotalNumDOFs(numLocalDOFs);
00397   }
00398   SUNDANCE_MSG1(setupVerb(), tab << "done initializing DOF map");
00399 }
00400 
00401 void MixedDOFMap::shareDOFs(int cellDim,
00402   const Array<Array<int> >& outgoingCellRequests)
00403 {
00404   int np = mesh().comm().getNProc();
00405   int rank = mesh().comm().getRank();
00406 
00407   Array<Array<int> > incomingCellRequests;
00408   Array<Array<int> > outgoingDOFs(np);
00409   Array<Array<int> > incomingDOFs;
00410 
00411   SUNDANCE_MSG2(setupVerb(),  
00412     "p=" << mesh().comm().getRank()
00413     << "synchronizing DOFs for cells of dimension " << cellDim);
00414   SUNDANCE_MSG2(setupVerb(),  
00415     "p=" << mesh().comm().getRank()
00416     << " sending cell reqs d=" << cellDim << " GID=" << outgoingCellRequests);
00417 
00418   /* share the cell requests */
00419   MPIContainerComm<int>::allToAll(outgoingCellRequests, 
00420     incomingCellRequests,
00421     mesh().comm());
00422   
00423   /* we send the following information in response:
00424    * (1) The first DOF for each chunk for the requested cell
00425    * (2) The orientation if the cell is an edge or face 
00426    */
00427   int blockSize = 0;
00428   bool sendOrientation = false;
00429   for (int b=0; b<nBasisChunks(); b++)
00430   {
00431     int nDofs = nDofsPerCell_[b][cellDim];
00432     if (nDofs > 0) blockSize++;
00433     if (nDofs > 1 && cellDim > 0 && cellDim < dim_) sendOrientation = true;
00434   }
00435   blockSize += sendOrientation;
00436 
00437   SUNDANCE_MSG2(setupVerb(),  
00438     "p=" << rank
00439     << "recvd DOF requests for cells of dimension " << cellDim
00440     << " GID=" << incomingCellRequests);
00441 
00442   /* get orientations and DOF numbers for the first node of every cell that's been 
00443    * requested by someone else */
00444   for (int p=0; p<np; p++)
00445   {
00446     if (p==rank) continue;
00447     const Array<int>& requestsFromProc = incomingCellRequests[p];
00448     int nReq = requestsFromProc.size();
00449 
00450     SUNDANCE_MSG4(setupVerb(), "p=" << mesh().comm().getRank() 
00451       << " recv'd from proc=" << p
00452       << " reqs for DOFs for cells " 
00453       << requestsFromProc);
00454 
00455     outgoingDOFs[p].resize(nReq * blockSize);
00456 
00457     for (int c=0; c<nReq; c++)
00458     {
00459       int GID = requestsFromProc[c];
00460       SUNDANCE_MSG3(setupVerb(),  
00461         "p=" << rank
00462         << " processing cell with d=" << cellDim 
00463         << " GID=" << GID);
00464       int LID = mesh().mapGIDToLID(cellDim, GID);
00465       SUNDANCE_MSG3(setupVerb(),  
00466         "p=" << rank
00467         << " LID=" << LID << " dofs=" << dofs_[cellDim]);
00468       int blockOffset = 0;
00469       for (int b=0; b<nBasisChunks(); b++)
00470       {
00471         if (nDofsPerCell_[b][cellDim] == 0) continue;
00472         outgoingDOFs[p][blockSize*c+blockOffset] 
00473           = getInitialDOFForCell(cellDim, LID, b);
00474         blockOffset++;
00475       }
00476       if (sendOrientation)
00477       {
00478         outgoingDOFs[p][blockSize*(c+1) - 1] 
00479           = originalFacetOrientation_[cellDim-1][LID];
00480       }
00481       SUNDANCE_MSG3(setupVerb(),  
00482         "p=" << rank
00483         << " done processing cell with GID=" << GID);
00484     }
00485   }
00486  
00487 
00488   SUNDANCE_MSG2(setupVerb(),  
00489     "p=" << mesh().comm().getRank()
00490     << "answering DOF requests for cells of dimension " << cellDim);
00491 
00492   /* share the DOF numbers */
00493   MPIContainerComm<int>::allToAll(outgoingDOFs,
00494     incomingDOFs,
00495     mesh().comm());
00496 
00497   SUNDANCE_MSG2(setupVerb(),  
00498     "p=" << mesh().comm().getRank()
00499     << "communicated DOF answers for cells of dimension " << cellDim);
00500 
00501   
00502   /* now assign the DOFs from the other procs */
00503 
00504   for (int p=0; p<mesh().comm().getNProc(); p++)
00505   {
00506     if (p==mesh().comm().getRank()) continue;
00507     const Array<int>& dofsFromProc = incomingDOFs[p];
00508     int numCells = dofsFromProc.size()/blockSize;
00509     for (int c=0; c<numCells; c++)
00510     {
00511       int cellGID = outgoingCellRequests[p][c];
00512       int cellLID = mesh().mapGIDToLID(cellDim, cellGID);
00513       int blockOffset = 0;
00514       for (int b=0; b<nBasisChunks(); b++)
00515       {
00516         if (nDofsPerCell_[b][cellDim] == 0) continue;
00517         int dof = dofsFromProc[blockSize*c+blockOffset];
00518         setDOFs(b, cellDim, cellLID, dof, true);
00519         blockOffset++;
00520       }
00521       if (sendOrientation) 
00522       {
00523         originalFacetOrientation_[cellDim-1][cellLID] 
00524           = dofsFromProc[blockSize*(c+1)-1];
00525       }
00526     }
00527   }
00528   
00529 }
00530 
00531 
00532 
00533 void MixedDOFMap::setDOFs(int basisChunk, int cellDim, int cellLID, 
00534   int& nextDOF, bool isRemote)
00535 {
00536   Tabs tab;
00537   SUNDANCE_MSG3(setupVerb(), tab << "setting DOFs for " << cellDim 
00538     << "-cell " << cellLID);
00539   int nDofs = nDofsPerCell_[basisChunk][cellDim];
00540   if (nDofs==0) return;
00541 
00542   int* ptr = getInitialDOFPtrForCell(cellDim, cellLID, basisChunk);
00543   
00544   if (isRemote)
00545   {
00546     for (int i=0; i<nDofs; i++, nextDOF++) 
00547     {
00548       ptr[i] = nextDOF;;
00549       addGhostIndex(nextDOF);
00550     }
00551   }
00552   else
00553   {
00554     for (int i=0; i<nDofs; i++,nextDOF++) 
00555     {
00556       ptr[i] = nextDOF;
00557     }
00558   }
00559 }
00560 
00561 
00562 
00563 RCP<const MapStructure> MixedDOFMap
00564 ::getDOFsForCellBatch(int cellDim,
00565   const Array<int>& cellLID,
00566   const Set<int>& requestedFuncSet,
00567   Array<Array<int> >& dofs,
00568   Array<int>& nNodes,
00569   int verbosity) const 
00570 {
00571   TimeMonitor timer(batchedDofLookupTimer());
00572 
00573   Tabs tab;
00574   SUNDANCE_MSG3(verbosity, 
00575     tab << "getDOFsForCellBatch(): cellDim=" << cellDim
00576     << " cellLID=" << cellLID);
00577 
00578   dofs.resize(nBasisChunks());
00579   nNodes.resize(nBasisChunks());
00580 
00581   int nCells = cellLID.size();
00582 
00583   if (cellDim == dim_)
00584   {
00585     Tabs tab1;
00586 
00587     if (!haveMaximalDofs_) 
00588     {
00589       buildMaximalDofTable();
00590     }
00591 
00592     SUNDANCE_MSG4(verbosity, tab1 << "getting dofs for maximal cells");
00593 
00594     for (int b=0; b<nBasisChunks(); b++)
00595     {
00596       nNodes[b] = totalNNodesPerCell_[b][cellDim];
00597       dofs[b].resize(nNodes[b]*nFuncs(b)*nCells);
00598       int dofsPerCell = nFuncs(b)*nNodes[b];
00599       Array<int>& chunkDofs = dofs[b];
00600       for (int c=0; c<nCells; c++)
00601       {
00602         for (int i=0; i<dofsPerCell; i++)
00603         {
00604           chunkDofs[c*dofsPerCell + i] 
00605             = maximalDofs_[b][cellLID[c]*dofsPerCell+i];
00606         }
00607       }
00608     }
00609   }
00610   else
00611   {
00612     Tabs tab1;
00613     SUNDANCE_MSG4(verbosity, tab1 << "getting dofs for non-maximal cells");
00614   
00615     static Array<Array<int> > facetLID(3);
00616     static Array<Array<int> > facetOrientations(3);
00617     static Array<int> numFacets(3);
00618 
00619     for (int d=0; d<cellDim; d++) 
00620     {
00621       numFacets[d] = mesh().numFacets(cellDim, cellLID[0], d);
00622       mesh().getFacetLIDs(cellDim, cellLID, d, facetLID[d], 
00623         facetOrientations[d]);
00624     }
00625 
00626     for (int b=0; b<nBasisChunks(); b++)
00627     {
00628       nNodes[b] = totalNNodesPerCell_[b][cellDim];
00629       dofs[b].resize(nNodes[b]*nFuncs(b)*nCells);
00630       int dofsPerCell = nFuncs(b)*nNodes[b];
00631           
00632       Array<int>& toPtr = dofs[b];
00633       int nf = nFuncs(b);
00634 
00635       for (int c=0; c<nCells; c++)
00636       {
00637         Tabs tab2;
00638         SUNDANCE_MSG4(verbosity, tab2 << "cell=" << c);
00639         int offset = dofsPerCell*c;
00640 
00641         /* first get the DOFs for the nodes associated with 
00642          * the cell's interior */
00643         SUNDANCE_MSG4(verbosity, tab2 << "doing interior nodes");
00644         int nInteriorNodes = nNodesPerCell_[b][cellDim];
00645         //              int nInteriorNodes = localNodePtrs_[b][cellDim][cellDim][0].size();
00646         if (nInteriorNodes > 0)
00647         {
00648           if (cellDim==0 || nInteriorNodes <= 1) /* orientation-independent */
00649           {
00650             // const int* fromPtr 
00651             //                        = getInitialDOFPtrForCell(cellDim, cellLID[c], b);
00652 
00653             for (int func=0; func<nf; func++)
00654             {
00655               for (int n=0; n<nInteriorNodes; n++)
00656               {
00657                 int ptr = localNodePtrs_[b][cellDim][cellDim][0][n];
00658                 toPtr[offset + func*nNodes[b] + ptr] 
00659                   = dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00660                 //                                = fromPtr[func*nNodes[b] + n];
00661               }
00662             }
00663           }
00664           else
00665           {
00666             int sign = originalFacetOrientation_[cellDim-1][cellLID[c]];
00667             int nInteriorNodes = localNodePtrs_[b][cellDim][cellDim][0].size();
00668             //     const int* fromPtr 
00669             //                        = getInitialDOFPtrForCell(cellDim, cellLID[c], b);
00670                  
00671             for (int func=0; func<nf; func++)
00672             {
00673               for (int m=0; m<nInteriorNodes; m++)
00674               {
00675                 int n = m;
00676                 if (sign<0) n = nInteriorNodes-1-m;
00677                 int ptr = localNodePtrs_[b][cellDim][cellDim][0][m];
00678                 toPtr[offset + func*nNodes[b] + ptr]  = dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00679                 //    = fromPtr[func*nNodes[b] + n];
00680               }
00681             }
00682           }
00683         }
00684 
00685         /* now do the facets */
00686         for (int d=0; d<cellDim; d++)
00687         {
00688           Tabs tab2;
00689           SUNDANCE_MSG4(verbosity, tab2 << "facet dim=" << d);
00690           if (nNodesPerCell_[b][d] == 0) continue;
00691           for (int f=0; f<numFacets[d]; f++)
00692           {
00693             Tabs tab3;
00694             int facetID = facetLID[d][c*numFacets[d]+f];
00695             SUNDANCE_MSG4(verbosity, tab2 << "f=" << f << " facetLID=" << facetID);
00696             if (localNodePtrs_[b][cellDim].size()==0) continue;
00697             int nFacetNodes = localNodePtrs_[b][cellDim][d][f].size();
00698             //const int* fromPtr = getInitialDOFPtrForCell(d, facetID, b);
00699             int* toPtr1 = &(dofs[b][dofsPerCell*c]);
00700             const int* nodePtr = &(localNodePtrs_[b][cellDim][d][f][0]);
00701             for (int func=0; func<nf; func++)
00702             {
00703               if (d == 0 || nFacetNodes <= 1) /* orientation-independent */
00704               {
00705                 for (int n=0; n<nFacetNodes; n++)
00706                 {
00707                   int ptr = nodePtr[n];
00708                   toPtr1[func*nNodes[b] + ptr] //= fromPtr[func*nNodes[b] + n];
00709                     = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00710                 }
00711               }
00712               else /* orientation-dependent */
00713               {
00714                 int facetOrientation = facetOrientations[d][c*numFacets[d]+f]
00715                   * originalFacetOrientation_[d-1][facetID];
00716                 for (int m=0; m<nFacetNodes; m++)
00717                 {
00718                   int n = m;
00719                   if (facetOrientation<0) n = nFacetNodes-1-m;
00720                   int ptr = nodePtr[n];
00721                   toPtr1[func*nNodes[b]+ptr] 
00722                     = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00723                   //                                    = fromPtr[func*nNodes[b]+n];
00724                 }
00725               }
00726             }
00727           }
00728         }
00729       }
00730     }
00731   }
00732   return structure_;
00733 }    
00734 
00735 void MixedDOFMap::buildMaximalDofTable() const
00736 {
00737   TimeMonitor timer(maxDOFBuildTimer());
00738   Tabs tab;
00739   int cellDim = dim_;
00740   int nCells = mesh().numCells(dim_);
00741 
00742   SUNDANCE_MSG2(setupVerb(), tab << "building dofs for maximal cells");
00743 
00744   Array<Array<int> > facetLID(3);
00745   Array<Array<int> > facetOrientations(3);
00746   Array<int> numFacets(3);
00747 
00748   Array<int> cellLID(nCells);
00749 
00750   for (int c=0; c<nCells; c++) cellLID[c]=c;
00751   
00752   for (int d=0; d<cellDim; d++) 
00753   {
00754     numFacets[d] = mesh().numFacets(cellDim, cellLID[0], d);
00755     mesh().getFacetLIDs(cellDim, cellLID, d, 
00756       facetLID[d], facetOrientations[d]);
00757   }
00758 
00759   Array<int> nInteriorNodes(nBasisChunks());
00760   Array<int> nNodes(nBasisChunks());
00761   for (int b = 0; b<nBasisChunks(); b++)
00762   {
00763     if (localNodePtrs_[b][cellDim].size() != 0)
00764     {
00765       nInteriorNodes[b] = localNodePtrs_[b][cellDim][cellDim][0].size();
00766     }
00767     else 
00768     {
00769       nInteriorNodes[b] = 0;
00770     }
00771     nNodes[b] = totalNNodesPerCell_[b][cellDim];
00772   }
00773 
00774   for (int c=0; c<nCells; c++)
00775   {
00776     Tabs tab1;
00777     SUNDANCE_MSG4(setupVerb(), tab1 << "working on cell=" << c 
00778       << " LID=" << cellLID[c]);
00779     /* first get the DOFs for the nodes associated with 
00780      * the cell's interior */
00781     SUNDANCE_MSG4(setupVerb(), tab1 << "doing interior nodes");
00782     for (int b=0; b<nBasisChunks(); b++)
00783     {
00784       SUNDANCE_MSG4(setupVerb(), tab1 << "basis chunk=" << b); 
00785       if (nInteriorNodes[b]>0)
00786       {
00787         SUNDANCE_MSG4(setupVerb(), tab1<< "nInteriorNodes = " <<nInteriorNodes[b]);
00788         //const int* fromPtr = getInitialDOFPtrForCell(dim_, cellLID[c], b);
00789         int* toPtr = &(maximalDofs_[b][nNodes[b]*nFuncs(b)*cellLID[c]]);
00790         int nf = nFuncs(b);
00791         for (int func=0; func<nf; func++)
00792         {
00793           for (int n=0; n<nInteriorNodes[b]; n++)
00794           {
00795                       
00796             int ptr = localNodePtrs_[b][cellDim][cellDim][0][n];
00797             toPtr[func*nNodes[b] + ptr] = //fromPtr[func*nNodes[b] + n];
00798               dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00799           }
00800         }
00801       }
00802     }
00803       
00804     SUNDANCE_MSG4(setupVerb(), tab1 << "doing facet nodes");
00805     /* now get the DOFs for the nodes on the facets */
00806     for (int d=0; d<cellDim; d++)
00807     {
00808       Tabs tab2;
00809       SUNDANCE_MSG4(setupVerb(), tab2 << "facet dim=" << d);
00810 
00811       for (int f=0; f<numFacets[d]; f++)
00812       {
00813         Tabs tab3;
00814         int facetID = facetLID[d][c*numFacets[d]+f];
00815         SUNDANCE_MSG4(setupVerb(), tab2 << "f=" << f << " facetLID=" << facetID);
00816 
00817         for (int b=0; b<nBasisChunks(); b++)
00818         {
00819           Tabs tab4;
00820           SUNDANCE_MSG4(setupVerb(), tab4 << "basis chunk=" << b); 
00821           SUNDANCE_MSG4(setupVerb(), tab4 << "num nodes per cell=" << nNodesPerCell_[b][d]); 
00822           int nf = nFuncs(b);
00823           if (nDofsPerCell_[b][d]==0) continue;
00824           int nFacetNodes = 0;
00825           if (localNodePtrs_[b][cellDim].size()!=0)
00826             nFacetNodes = localNodePtrs_[b][cellDim][d][f].size();
00827           if (nFacetNodes == 0) continue;
00828           //  const int* fromPtr = getInitialDOFPtrForCell(d, facetID, b);
00829           SUNDANCE_MSG4(setupVerb(), tab4 << "dof table size=" << maximalDofs_[b].size()); 
00830           int* toPtr = &(maximalDofs_[b][nNodes[b]*nFuncs(b)*cellLID[c]]);
00831           const int* nodePtr = &(localNodePtrs_[b][cellDim][d][f][0]);
00832           for (int func=0; func<nf; func++)
00833           {
00834             Tabs tab5;
00835             SUNDANCE_MSG4(setupVerb(), tab5 << "func=" << func); 
00836             if (d == 0 || nFacetNodes <= 1) /* orientation-independent */
00837             {
00838               Tabs tab6;
00839               for (int n=0; n<nFacetNodes; n++)
00840               {
00841                 SUNDANCE_MSG4(setupVerb(), tab5 << "n=" << n); 
00842                 int ptr = nodePtr[n];
00843                 SUNDANCE_MSG4(setupVerb(), tab6 << "ptr=" << ptr); 
00844 
00845                 toPtr[func*nNodes[b] + ptr] 
00846                   = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00847                 //= fromPtr[func*nNodes[b] + n];
00848               }
00849             }
00850             else /* orientation-dependent */
00851             {
00852               int facetOrientation = facetOrientations[d][c*numFacets[d]+f]
00853                 * originalFacetOrientation_[d-1][facetID];
00854               for (int m=0; m<nFacetNodes; m++)
00855               {
00856                 int n = m;
00857                 if (facetOrientation<0) n = nFacetNodes-1-m;
00858                 int ptr = nodePtr[m];
00859                 toPtr[func*nNodes[b]+ptr] 
00860                   = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00861                 //= fromPtr[func*nNodes[b]+n];
00862               }
00863             }
00864           }
00865         }
00866       }
00867     }
00868   }
00869 
00870   haveMaximalDofs_ = true;
00871 
00872   SUNDANCE_MSG2(setupVerb(), tab << "done building dofs for maximal cells");
00873 }
00874 
00875 
00876 
00877 
00878 
00879 void MixedDOFMap::computeOffsets(int dim, int localCount)
00880 {
00881   if (setupVerb() > 2)
00882   {
00883     comm().synchronize();
00884     comm().synchronize();
00885     comm().synchronize();
00886     comm().synchronize();
00887   }
00888   SUNDANCE_MSG2(setupVerb(), 
00889     "p=" << mesh().comm().getRank()
00890     << " sharing offsets for DOF numbering for dim=" << dim);
00891 
00892   SUNDANCE_MSG2(setupVerb(), 
00893     "p=" << mesh().comm().getRank()
00894     << " I have " << localCount << " cells");
00895 
00896   Array<int> dofOffsets;
00897   int totalDOFCount;
00898   MPIContainerComm<int>::accumulate(localCount, dofOffsets, totalDOFCount,
00899     mesh().comm());
00900   int myOffset = dofOffsets[mesh().comm().getRank()];
00901 
00902   SUNDANCE_MSG2(setupVerb(), 
00903     "p=" << mesh().comm().getRank()
00904     << " back from MPI accumulate");
00905 
00906   if (setupVerb() > 2)
00907   {
00908     comm().synchronize();
00909     comm().synchronize();
00910     comm().synchronize();
00911     comm().synchronize();
00912   }
00913 
00914   for (int chunk=0; chunk<dofs_[dim].size(); chunk++)
00915   {
00916     for (int n=0; n<dofs_[dim][chunk].size(); n++)
00917     {
00918       if (dofs_[dim][chunk][n] >= 0) dofs_[dim][chunk][n] += myOffset;
00919     }
00920   }
00921 
00922   setLowestLocalDOF(myOffset);
00923   setNumLocalDOFs(localCount);
00924   setTotalNumDOFs(totalDOFCount);
00925 
00926   SUNDANCE_MSG2(setupVerb(), 
00927     "p=" << mesh().comm().getRank() 
00928     << " done sharing offsets for DOF numbering for dim=" << dim);
00929   if (setupVerb() > 2)
00930   {
00931     comm().synchronize();
00932     comm().synchronize();
00933     comm().synchronize();
00934     comm().synchronize();
00935   }
00936 
00937 }                           
00938 
00939 
00940 
00941 void MixedDOFMap::checkTable() const 
00942 {
00943   int bad = 0;
00944   for (int d=0; d<dofs_.size(); d++)
00945   {
00946     for (int chunk=0; chunk<dofs_[d].size(); chunk++)
00947     {
00948       const Array<int>& dofs = dofs_[d][chunk];
00949       for (int n=0; n<dofs.size(); n++)
00950       {
00951         if (dofs[n] < 0) bad = 1;
00952       }
00953     }
00954   }
00955   
00956   int anyBad = bad;
00957   comm().allReduce((void*) &bad, (void*) &anyBad, 1, 
00958     MPIComm::INT, MPIComm::SUM);
00959   TEST_FOR_EXCEPTION(anyBad > 0, RuntimeError, "invalid DOF map");
00960 }

Site Contact