SundanceHomogeneousDOFMap.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 #include "SundanceHomogeneousDOFMap.hpp"
00043 #include "SundanceCellFilter.hpp"
00044 #include "SundanceMaximalCellFilter.hpp"
00045 #include "PlayaMPIContainerComm.hpp"
00046 #include "SundanceOut.hpp"
00047 #include "PlayaTabs.hpp"
00048 #include "Teuchos_Time.hpp"
00049 #include "Teuchos_TimeMonitor.hpp"
00050 
00051 using namespace Sundance;
00052 using namespace Teuchos;
00053 using Playa::MPIComm;
00054 using Playa::MPIContainerComm;
00055 
00056 
00057 static Time& dofLookupTimer() 
00058 {
00059   static RCP<Time> rtn 
00060     = TimeMonitor::getNewTimer("unbatched dof lookup"); 
00061   return *rtn;
00062 }
00063 
00064 static Time& dofBatchLookupTimer() 
00065 {
00066   static RCP<Time> rtn 
00067     = TimeMonitor::getNewTimer("batched dof lookup"); 
00068   return *rtn;
00069 }
00070 
00071 HomogeneousDOFMap::HomogeneousDOFMap(const Mesh& mesh, 
00072   const BasisFamily& basis,
00073   int numFuncs, 
00074   int setupVerb)
00075   : DOFMapBase(mesh, setupVerb), 
00076     dim_(mesh.spatialDim()),
00077     dofs_(mesh.spatialDim()+1),
00078     maximalDofs_(),
00079     haveMaximalDofs_(false),
00080     localNodePtrs_(mesh.spatialDim()+1),
00081     nNodesPerCell_(mesh.spatialDim()+1),
00082     totalNNodesPerCell_(mesh.spatialDim()+1, 0),
00083     numFacets_(mesh.spatialDim()+1),
00084     originalFacetOrientation_(2),
00085     basisIsContinuous_(false)
00086 {
00087   verbosity() = DOFMapBase::classVerbosity();
00088   
00089   CellFilter maximalCells = new MaximalCellFilter();
00090   cellSets().append(maximalCells.getCells(mesh));
00091   cellDimOnCellSets().append(mesh.spatialDim());
00092 
00093   allocate(mesh, basis, numFuncs);
00094   initMap();
00095 }
00096 
00097 
00098 HomogeneousDOFMap::HomogeneousDOFMap(const Mesh& mesh, 
00099                                      const BasisFamily& basis,
00100                                      const Array<CellFilter>& subregions,
00101                                      int numFuncs)
00102   : DOFMapBase(mesh), 
00103     dim_(mesh.spatialDim()),
00104     dofs_(mesh.spatialDim()+1),
00105     maximalDofs_(),
00106     haveMaximalDofs_(false),
00107     localNodePtrs_(mesh.spatialDim()+1),
00108     nNodesPerCell_(mesh.spatialDim()+1),
00109     totalNNodesPerCell_(mesh.spatialDim()+1, 0),
00110     numFacets_(mesh.spatialDim()+1),
00111     originalFacetOrientation_(2),
00112     basisIsContinuous_(false)
00113 {
00114   verbosity() = DOFMapBase::classVerbosity();
00115   
00116   for (int r=0; r<subregions.size(); r++)
00117     {
00118       cellSets().append(subregions[r].getCells(mesh));
00119       cellDimOnCellSets().append(subregions[r].dimension(mesh));
00120     }
00121 
00122   allocate(mesh, basis, numFuncs);
00123   initMap();
00124 }
00125 
00126 
00127 void HomogeneousDOFMap::allocate(const Mesh& mesh, 
00128                                  const BasisFamily& basis,
00129                                  int numFuncs)
00130 {
00131   Tabs tab;
00132   SUNDANCE_MSG1(setupVerb(), tab << "allocating DOF map for nFuncs=" << numFuncs);
00133   Array<int> fid(numFuncs);
00134   for (int f=0; f<numFuncs; f++) fid[f] = f;
00135   funcIDOnCellSets().append(fid);
00136 
00137 
00138   
00139   for (int d=0; d<=dim_; d++)
00140     {
00141       Tabs tab1;
00142       SUNDANCE_MSG2(setupVerb(), tab1 << "allocating d=" << d);
00143       /* record the number of facets for each cell type so we're
00144        * not making a bunch of mesh calls */
00145       numFacets_[d].resize(d);
00146       for (int fd=0; fd<d; fd++) numFacets_[d][fd]=mesh.numFacets(d, 0, fd);
00147       SUNDANCE_MSG3(setupVerb(), tab1 << "num facets for dimension " << d << " is " 
00148                          << numFacets_[d]);
00149           
00150       /* look up the node pointer for this cell and for all of its
00151        * facets */
00152       basis.ptr()->getLocalDOFs(mesh.cellType(d), localNodePtrs_[d]);
00153 
00154 
00155       SUNDANCE_MSG3(setupVerb(), tab1 << "node ptrs for dimension " << d << " are " 
00156                          << localNodePtrs_[d]);
00157 
00158       /* with the node pointers in hand, we can work out the number
00159        * of nodes per cell in this dimension */
00160       if (localNodePtrs_[d][d].size() > 0) 
00161         {
00162           nNodesPerCell_[d] = localNodePtrs_[d][d][0].size();
00163         }
00164       else
00165         {
00166           nNodesPerCell_[d] = 0;
00167         }
00168       SUNDANCE_MSG3(setupVerb(), tab1 << 
00169                          "num nodes for dimension " << d << " is " 
00170                          << nNodesPerCell_[d]);
00171 
00172       totalNNodesPerCell_[d] = nNodesPerCell_[d];
00173       for (int dd=0; dd<d; dd++) 
00174         {
00175           totalNNodesPerCell_[d] += numFacets_[d][dd]*nNodesPerCell_[dd];
00176         }
00177 
00178       /* we know from the mesh the number of cells in this dimension */
00179       if (nNodesPerCell_[d] > 0)
00180         {
00181           dofs_[d].resize(mesh.numCells(d));
00182         }
00183       else
00184         {
00185           dofs_[d].resize(0);
00186         }
00187 
00188       if (d > 0 && d < dim_) originalFacetOrientation_[d-1].resize(mesh.numCells(d));
00189 
00190       /* If any nodes are associated with the facets, then we know we have
00191        * a continuous basis function */
00192       if (d < dim_ && nNodesPerCell_[d] > 0) basisIsContinuous_ = true;
00193 
00194 
00195       /* now that we know the number of nodes per cell for this dimension,
00196        * we can allocate space for the DOFs in this dimension */
00197       int numCells = dofs_[d].size();
00198       for (int c=0; c<numCells; c++)
00199         {
00200           dofs_[d][c].resize(funcIDList().size() * nNodesPerCell_[d]);
00201           /* set everything to uninitializedVal() */
00202           for (int i=0; i<dofs_[d][c].size(); i++) 
00203             {
00204               dofs_[d][c][i] = uninitializedVal();
00205             }
00206         }
00207     }
00208   SUNDANCE_MSG1(setupVerb(), tab << "done allocating DOF map");
00209 }
00210 
00211 void HomogeneousDOFMap::initMap()
00212 {
00213   Tabs tab;
00214   SUNDANCE_MSG1(setupVerb(), tab << "initializing DOF map");
00215   /* start the DOF count at zero. */
00216   int nextDOF = 0;
00217 
00218   /* Space in which to keep a list of remote cells needed by each processor
00219    * for each dimension. The first index is dimension, the second proc, the
00220    * third cell number. */
00221   Array<Array<Array<int> > > remoteCells(mesh().spatialDim()+1,
00222                                          mesh().comm().getNProc());
00223   
00224   for (int r=0; r<numCellSets(); r++)
00225     {
00226       /* Loop over maximal cells in the order specified by the cell iterator.
00227        * This might be reordered relative to the mesh. 
00228        *
00229        * At each maximal cell, we'll run through the facets and 
00230        * assign DOFs. That will take somewhat more work, but gives much 
00231        * better cache locality for the matrix because all the DOFs for
00232        * each maximal element and its facets are grouped together. */
00233 
00234       CellSet cells = cellSet(r);
00235       CellIterator iter;
00236       for (iter=cells.begin(); iter != cells.end(); iter++)
00237         {
00238           /* first assign any DOFs associated with the maximal cell */
00239           int cellLID = *iter;
00240           int owner;
00241       
00242           if (nNodesPerCell_[dim_] > 0)
00243             {
00244               /* if the maximal cell is owned by another processor,
00245                * put it in the list of cells for which we need to request 
00246                * DOF information from another processor */
00247               if (isRemote(dim_, cellLID, owner))
00248                 {
00249                   int dummy=0;
00250                   int cellGID = mesh().mapLIDToGID(dim_, cellLID);
00251                   remoteCells[dim_][owner].append(cellGID); 
00252                   setDOFs(dim_, cellLID, dummy);
00253                 }
00254               else /* the cell is locally owned, so we can 
00255                     * set its DOF numbers now */
00256                 {
00257                   setDOFs(dim_, cellLID, nextDOF);
00258                 }
00259             }
00260 
00261           /* Now assign any DOFs associated with the facets. */
00262           /* We can skip this step if the basis is discontinuous at element
00263            * boundaries, because the facets will own no nodes */
00264           if (basisIsContinuous_)
00265             {
00266               for (int d=0; d<dim_; d++)
00267                 {
00268                   if (nNodesPerCell_[d] > 0)
00269                     {
00270                       int nf = numFacets_[dim_][d];
00271                       Array<int> facetLID(nf);
00272                       Array<int> facetOrientations(nf);
00273                       /* look up the LIDs of the facets */
00274                       mesh().getFacetArray(dim_, cellLID, d, 
00275                                            facetLID, facetOrientations);
00276                       /* for each facet, process its DOFs */
00277                       for (int f=0; f<nf; f++)
00278                         {
00279                           /* if the facet's DOFs have been assigned already,
00280                            * we're done */
00281                           if (!hasBeenAssigned(d, facetLID[f]))
00282                             {
00283                               /* the facet may be owned by another processor */
00284                               if (isRemote(d, facetLID[f], owner))
00285                                 {
00286                                   int dummy=0;
00287                                   int facetGID = mesh().mapLIDToGID(d, facetLID[f]);
00288                                   remoteCells[d][owner].append(facetGID);
00289                                   setDOFs(d, facetLID[f], dummy);
00290                                 }
00291                               else /* we can assign a DOF locally */
00292                                 {
00293                                   /* assign DOF */
00294                                   setDOFs(d, facetLID[f], nextDOF);
00295                                   /* record the orientation wrt the maximal cell */
00296                                   if (d > 0) 
00297                                     {
00298                                       originalFacetOrientation_[d-1][facetLID[f]] 
00299                                         = facetOrientations[f];
00300                                     }
00301                                 }
00302                             }
00303                         }
00304                     }
00305                 }
00306             }
00307         }
00308     }
00309   /* Done with first pass, in which we have assigned DOFs for all
00310    * local processors. We now have to share DOF information between
00311    * processors */
00312 
00313   if (mesh().comm().getNProc() > 1)
00314     {
00315       for (int d=0; d<=dim_; d++)
00316         {
00317           if (nNodesPerCell_[d] > 0)
00318             {
00319               computeOffsets(d, nextDOF);
00320               shareDOFs(d, remoteCells[d]);
00321             }
00322         }
00323     }
00324   else
00325     {
00326       setLowestLocalDOF(0);
00327       setNumLocalDOFs(nextDOF);
00328       setTotalNumDOFs(nextDOF);
00329     }
00330   SUNDANCE_MSG1(setupVerb(), tab << "done initializing DOF map");
00331 }
00332 
00333 void HomogeneousDOFMap::shareDOFs(int cellDim,
00334                                   const Array<Array<int> >& outgoingCellRequests)
00335 {
00336   int np = mesh().comm().getNProc();
00337   int rank = mesh().comm().getRank();
00338 
00339   if (np == 1) return;
00340 
00341   TEUCHOS_TEST_FOR_EXCEPTION(np != outgoingCellRequests.size(), std::runtime_error,
00342                      "incorrect size of outgoingCellRequests array. Size is "
00343                      << outgoingCellRequests.size() << ", should be np=" << np);
00344 
00345 
00346 
00347   Array<Array<int> > incomingCellRequests;
00348   Array<Array<int> > outgoingDOFs(np);
00349   Array<Array<int> > incomingDOFs;
00350 
00351   SUNDANCE_MSG2(setupVerb(),  
00352                "p=" << mesh().comm().getRank()
00353                << "synchronizing DOFs for cells of dimension " << cellDim);
00354   SUNDANCE_MSG2(setupVerb(),  
00355                "p=" << mesh().comm().getRank()
00356                << " sending cell reqs d=" << cellDim << " GID=" << outgoingCellRequests);
00357 
00358   /* share the cell requests */
00359   MPIContainerComm<int>::allToAll(outgoingCellRequests, 
00360                                   incomingCellRequests,
00361                                   mesh().comm());
00362 
00363   
00364 
00365   SUNDANCE_MSG2(setupVerb(),  
00366                "p=" << rank
00367                << "recvd DOF requests for cells of dimension " << cellDim
00368                << " GID=" << incomingCellRequests);
00369 
00370   /* get orientations and DOF numbers for the first node of every cell that's been 
00371    * requested by someone else */
00372   for (int p=0; p<np; p++)
00373     {
00374       if (p==rank) continue;
00375       const Array<int>& requestsFromProc = incomingCellRequests[p];
00376       int nReq = requestsFromProc.size();
00377       int blockSize = 1;
00378       if (cellDim > 0 && cellDim < dim_)
00379         {
00380           outgoingDOFs[p].resize(2 * nReq);
00381           blockSize = 2;
00382         }
00383       else
00384         {
00385           outgoingDOFs[p].resize(nReq);
00386         }
00387       SUNDANCE_MSG3(setupVerb(),  
00388                    "p=" << mesh().comm().getRank() << " recv'd from proc=" << p
00389                    << " reqs for DOFs for cells " << requestsFromProc);
00390       for (int c=0; c<nReq; c++)
00391         {
00392           int GID = requestsFromProc[c];
00393           SUNDANCE_MSG3(setupVerb(),  
00394                        "p=" << rank
00395                        << " processing cell with d=" << cellDim 
00396                        << " GID=" << GID);
00397           int LID = mesh().mapGIDToLID(cellDim, GID);
00398           SUNDANCE_MSG3(setupVerb(),  
00399                        "p=" << rank
00400                        << " LID=" << LID << " dofs=" << dofs_[cellDim]);
00401           outgoingDOFs[p][blockSize*c] = dofs_[cellDim][LID][0];
00402           if (cellDim > 0 && cellDim < dim_) 
00403             {
00404               outgoingDOFs[p][blockSize*c+1] = originalFacetOrientation_[cellDim-1][LID];
00405             }
00406           SUNDANCE_MSG3(setupVerb(),  
00407                        "p=" << rank
00408                        << " done processing cell with GID=" << GID);
00409         }
00410     }
00411  
00412   
00413 
00414   SUNDANCE_MSG2(setupVerb(),  
00415                "p=" << mesh().comm().getRank()
00416                << "answering DOF requests for cells of dimension " << cellDim);
00417 
00418   /* share the DOF numbers */
00419   MPIContainerComm<int>::allToAll(outgoingDOFs,
00420                                   incomingDOFs,
00421                                   mesh().comm());
00422 
00423   SUNDANCE_MSG2(setupVerb(),  
00424                "p=" << mesh().comm().getRank()
00425                << "communicated DOF answers for cells of dimension " << cellDim);
00426 
00427   
00428   /* now assign the DOFs from the other procs */
00429   for (int p=0; p<mesh().comm().getNProc(); p++)
00430     {
00431       if (p==mesh().comm().getRank()) continue;
00432       const Array<int>& dofsFromProc = incomingDOFs[p];
00433       int blockSize = 1;
00434       if (cellDim > 0 && cellDim < dim_)
00435         {
00436           blockSize = 2;
00437         }
00438 
00439       for (int c=0; c<dofsFromProc.size()/blockSize; c++)
00440         {
00441           int cellGID = outgoingCellRequests[p][c];
00442           int cellLID = mesh().mapGIDToLID(cellDim, cellGID);
00443           int dof = dofsFromProc[blockSize*c];
00444           setDOFs(cellDim, cellLID, dof, true);
00445           if (cellDim > 0 && cellDim < dim_) 
00446             {
00447               originalFacetOrientation_[cellDim-1][cellLID] = dofsFromProc[blockSize*c+1];
00448             }
00449         }
00450     }
00451   
00452 }
00453 
00454 
00455 
00456 void HomogeneousDOFMap::setDOFs(int cellDim, int cellLID, 
00457                                 int& nextDOF,
00458                                 bool isRemote)
00459 {
00460   Tabs tab;
00461   SUNDANCE_MSG3(setupVerb(), tab << "setting DOFs for " << cellDim << "-cell " << cellLID);
00462   Array<int>& cellDOFs = dofs_[cellDim][cellLID];
00463   
00464   int nn = nNodesPerCell_[cellDim];
00465   int nf = funcIDList().size();
00466 
00467   for (int i=0; i<nn; i++)
00468     {
00469       for (int f=0; f<nf; f++)
00470         {
00471           int k = nextDOF++;
00472           cellDOFs[funcIDList()[f] + nf*i] = k;
00473           if (isRemote) addGhostIndex(k);
00474         }
00475     }
00476 }
00477 
00478 
00479 
00480 void HomogeneousDOFMap::getDOFsForCellBatch(int cellDim, 
00481                                             const Array<int>& cellLID,
00482                                             Array<int>& dofs,
00483                                             int& nNodes) const 
00484 {
00485   TimeMonitor timer(dofBatchLookupTimer());
00486 
00487   Tabs tab;
00488   SUNDANCE_MSG3(setupVerb(), 
00489                tab << "getDOFsForCellBatch(): cellDim=" << cellDim
00490                << " cellLID=" << cellLID);
00491 
00492   if (cellLID.size()==0) return;
00493 
00494   if (cellDim == dim_)
00495     {
00496       if (!haveMaximalDofs_) 
00497         {
00498           buildMaximalDofTable();
00499         }
00500 
00501       SUNDANCE_MSG4(setupVerb(), tab << "getting dofs for maximal cells");
00502 
00503       nNodes = totalNNodesPerCell_[cellDim];
00504       int nCells = cellLID.size();
00505       int nTotalCells = mesh().numCells(cellDim);
00506       int nf = funcIDList().size();
00507       dofs.resize(totalNNodesPerCell_[cellDim] * cellLID.size() * nf);
00508       
00509       for (int c=0; c<cellLID.size(); c++)
00510         {
00511           Tabs tab1;
00512           SUNDANCE_MSG4(setupVerb(), tab1 << "cell=" << c);
00513           for (int fid=0; fid<nf; fid++)
00514             {
00515               Tabs tab2;
00516               SUNDANCE_MSG4(setupVerb(), tab2 << "f= " << fid);
00517               for (int n=0; n<nNodes; n++) 
00518                 {
00519                   Tabs tab3;
00520                   dofs[(fid*nCells + c)*nNodes + n] 
00521                     = maximalDofs_[(fid*nTotalCells + cellLID[c])*nNodes + n];
00522                   SUNDANCE_MSG4(setupVerb(), tab3 << "n=" << n << " dof=" 
00523                                         << dofs[(fid*nCells + c)*nNodes + n]);
00524                 }
00525               
00526             }
00527         }
00528     }
00529   else
00530     {
00531       int nf = funcIDList().size();
00532       int nCells = cellLID.size();
00533       dofs.resize(totalNNodesPerCell_[cellDim] * cellLID.size() * nf);
00534 
00535       Tabs tab1;
00536       SUNDANCE_MSG4(setupVerb(), tab1 << "getting dofs for non-maximal cells");
00537   
00538       static Array<Array<int> > facetLID(3);
00539       static Array<Array<int> > facetOrientations(3);
00540       static Array<int> numFacets(3);
00541 
00542       for (int d=0; d<cellDim; d++) 
00543         {
00544           numFacets[d] = mesh().numFacets(cellDim, cellLID[0], d);
00545           mesh().getFacetLIDs(cellDim, cellLID, d, facetLID[d], 
00546                               facetOrientations[d]);
00547         }
00548 
00549   
00550       int nInteriorNodes = localNodePtrs_[cellDim][cellDim][0].size();
00551   
00552       nNodes = totalNNodesPerCell_[cellDim];
00553       
00554       for (int c=0; c<cellLID.size(); c++)
00555         {
00556           Tabs tab2;
00557           SUNDANCE_MSG4(setupVerb(), tab2 << "cell=" << c);
00558           SUNDANCE_MSG4(setupVerb(), tab2 << "doing interior nodes");
00559 
00560           /* first get the DOFs for the nodes associated with 
00561            * the cell's interior */
00562           if (cellDim==0 || nInteriorNodes <= 1) /* orientation-independent */
00563             {
00564               for (int m=0; m<nInteriorNodes; m++)
00565                 {
00566                   Tabs tab3;
00567                   int ptr = localNodePtrs_[cellDim][cellDim][0][m];
00568                   for (int f=0; f<nf; f++)
00569                     {
00570                       dofs[(f*nCells + c)*nNodes+ptr] 
00571                         = dofs_[cellDim][cellLID[c]][f + nf*m];
00572                       SUNDANCE_MSG4(setupVerb(), tab3 << "n=" << m << " f=" << f 
00573                                             << " dof=" 
00574                                             <<  dofs[(f*nCells + c)*nNodes+ptr]);
00575                     }
00576                 }
00577             }
00578           else
00579             {
00580               int sign = originalFacetOrientation_[cellDim-1][cellLID[c]];
00581               for (int m=0; m<nInteriorNodes; m++)
00582                 {
00583                   int n = m;
00584                   if (sign < 0) n = nInteriorNodes - 1 - m;
00585                   Tabs tab3;
00586                   int ptr = localNodePtrs_[cellDim][cellDim][0][m];
00587                   for (int f=0; f<nf; f++)
00588                     {
00589                       dofs[(f*nCells + c)*nNodes+ptr] 
00590                         = dofs_[cellDim][cellLID[c]][f + nf*n];
00591                       SUNDANCE_MSG4(setupVerb(), tab3 << "n=" << m << " f=" << f 
00592                                             << " dof=" 
00593                                             <<  dofs[(f*nCells + c)*nNodes+ptr]);
00594                     }
00595                 }
00596             }
00597 
00598           SUNDANCE_MSG4(setupVerb(), tab1 << "doing facet nodes");
00599           /* now get the DOFs for the nodes on the facets */
00600           for (int d=0; d<cellDim; d++)
00601             {
00602               Tabs tab3;
00603               SUNDANCE_MSG4(setupVerb(), tab3 << "d= " << d);
00604               for (int f=0; f<numFacets[d]; f++)
00605                 {
00606                   Tabs tab4;
00607                   int facetID = facetLID[d][c*numFacets[d]+f];
00608                   
00609                   SUNDANCE_MSG4(setupVerb(), tab4 << "f= " << f << " facetLID = " << facetID);
00610                   int nFacetNodes = localNodePtrs_[cellDim][d][f].size();
00611                   if (d==0 || nFacetNodes <= 1) /* orientation-independent */
00612                     {
00613                       Tabs tab5;
00614                       for (int n=0; n<nFacetNodes; n++)
00615                         {
00616                           SUNDANCE_MSG3(setupVerb(), 
00617                                        tab5 << "n=" << n);
00618                           int ptr = localNodePtrs_[cellDim][d][f][n];
00619                           SUNDANCE_MSG3(setupVerb(), 
00620                                        tab5 << "local ptr=" << ptr);
00621                           for (int funcID=0; funcID<nf; funcID++)
00622                             {
00623                               SUNDANCE_MSG3(setupVerb(), 
00624                                            tab5 << "found dof=" 
00625                                            << dofs_[d][facetID][funcID + nf*n]);
00626                               dofs[(funcID*nCells + c)*nNodes+ptr] 
00627                                 = dofs_[d][facetID][funcID + nf*n];
00628                             }
00629                         }
00630                     }
00631                   else /* orientation-dependent */
00632                     {
00633                       Tabs tab5;
00634                       int facetOrientation 
00635                         = facetOrientations[d][c*numFacets[d]+f] 
00636                         * originalFacetOrientation_[d-1][facetID];
00637                       for (int m=0; m<nFacetNodes; m++)
00638                         {
00639                           int n = m;
00640                           if (facetOrientation<0) n = nFacetNodes-1-m;
00641                           SUNDANCE_MSG3(setupVerb(), 
00642                                        tab5 << "n=" << n);
00643                           int ptr = localNodePtrs_[cellDim][d][f][m];
00644                           SUNDANCE_MSG3(setupVerb(), 
00645                                        tab5 << "local ptr=" << ptr);
00646                           for (int funcID=0; funcID<nf; funcID++)
00647                             {
00648                               SUNDANCE_MSG3(setupVerb(), 
00649                                            tab5 << "found dof=" 
00650                                            << dofs_[d][facetID][funcID + nf*n]);
00651                               dofs[(funcID*nCells + c)*nNodes+ptr] 
00652                                 = dofs_[d][facetID][funcID + nf*n];
00653                             }
00654                         }
00655                     }
00656                 }
00657             }
00658         }
00659     }
00660 }    
00661 
00662 void HomogeneousDOFMap::buildMaximalDofTable() const
00663 {
00664   Tabs tab;
00665   int cellDim = dim_;
00666   int nf = funcIDList().size();
00667   int nCells = mesh().numCells(dim_);
00668 
00669   SUNDANCE_MSG2(setupVerb(), tab << "building dofs for maximal cells");
00670 
00671   SUNDANCE_MSG3(setupVerb(), tab << "nf=" << nf
00672                << " total nNodes=" << totalNNodesPerCell_[cellDim]);
00673   
00674   static Array<Array<int> > facetLID(3);
00675   static Array<Array<int> > facetOrientations(3);
00676   static Array<int> numFacets(3);
00677 
00678   Array<int> cellLID(nCells);
00679 
00680   for (int c=0; c<cellLID.size(); c++) cellLID[c]=c;
00681   
00682   for (int d=0; d<cellDim; d++) 
00683     {
00684       numFacets[d] = mesh().numFacets(cellDim, cellLID[0], d);
00685       mesh().getFacetLIDs(cellDim, cellLID, d, facetLID[d], facetOrientations[d]);
00686     }
00687 
00688   
00689   int nInteriorNodes = localNodePtrs_[cellDim][cellDim][0].size();
00690   
00691 
00692   int nNodes = totalNNodesPerCell_[cellDim];
00693 
00694   maximalDofs_.resize(nCells*nf*nNodes);
00695 
00696   for (int c=0; c<nCells; c++)
00697     {
00698       Tabs tab1;
00699       SUNDANCE_MSG4(setupVerb(), tab1 << "working on cell=" << c << " LID=" << cellLID[c]);
00700       /* first get the DOFs for the nodes associated with 
00701        * the cell's interior */
00702       SUNDANCE_MSG4(setupVerb(), tab1 << "doing interior nodes");
00703       for (int n=0; n<nInteriorNodes; n++)
00704         {
00705           int ptr = localNodePtrs_[cellDim][cellDim][0][n];
00706           for (int f=0; f<nf; f++)
00707             {
00708               maximalDofs_[(f*nCells + c)*nNodes+ptr] 
00709                 = dofs_[cellDim][c][f + nf*n];
00710             }
00711         }
00712       
00713       SUNDANCE_MSG4(setupVerb(), tab1 << "doing facet nodes");
00714       /* now get the DOFs for the nodes on the facets */
00715       for (int d=0; d<cellDim; d++)
00716         {
00717           Tabs tab2;
00718           SUNDANCE_MSG4(setupVerb(), tab2 << "facet dim=" << d);
00719           for (int f=0; f<numFacets[d]; f++)
00720             {
00721               Tabs tab3;
00722               int facetID = facetLID[d][c*numFacets[d]+f];
00723               SUNDANCE_MSG4(setupVerb(), tab2 << "f=" << f << " facetLID=" << facetID);
00724               int nFacetNodes = localNodePtrs_[cellDim][d][f].size();
00725               if (d == 0 || nFacetNodes <= 1) /* orientation-independent */
00726                 {
00727                   for (int n=0; n<nFacetNodes; n++)
00728                     {
00729                       Tabs tab4;
00730                       SUNDANCE_MSG3(setupVerb(), 
00731                                    tab4 << "n=" << n);
00732                       int ptr = localNodePtrs_[cellDim][d][f][n];
00733                       for (int funcID=0; funcID<nf; funcID++)
00734                         {
00735                           SUNDANCE_MSG3(setupVerb(), 
00736                                        tab4 << "found dof=" 
00737                                        << dofs_[d][facetID][funcID + nf*n])
00738                             maximalDofs_[(funcID*nCells + c)*nNodes+ptr] 
00739                             = dofs_[d][facetID][funcID + nf*n];
00740                         }
00741                     }
00742                 }
00743               else /* orientation-dependent */
00744                 {
00745                   Tabs tab4;
00746                   int facetOrientation = facetOrientations[d][c*numFacets[d]+f]
00747                     * originalFacetOrientation_[d-1][facetID];
00748                   for (int m=0; m<nFacetNodes; m++)
00749                     {
00750                       Tabs tab4;
00751                       int n = m;
00752                       if (facetOrientation<0) n = nFacetNodes-1-m;
00753                       SUNDANCE_MSG3(setupVerb(), 
00754                                    tab4 << "n=" << n);
00755                       int ptr = localNodePtrs_[cellDim][d][f][m];
00756                       for (int funcID=0; funcID<nf; funcID++)
00757                         {
00758                           SUNDANCE_MSG3(setupVerb(), 
00759                                        tab4 << "found dof=" 
00760                                        << dofs_[d][facetID][funcID + nf*n])
00761                             maximalDofs_[(funcID*nCells + c)*nNodes+ptr] 
00762                             = dofs_[d][facetID][funcID + nf*n];
00763                         }
00764                     }
00765                 }
00766             }
00767         }
00768     }
00769   haveMaximalDofs_ = true;
00770 }
00771 
00772 
00773 
00774 
00775 
00776 void HomogeneousDOFMap::computeOffsets(int dim, int localCount)
00777 {
00778   if (verbosity() > 2)
00779     {
00780       comm().synchronize();
00781       comm().synchronize();
00782       comm().synchronize();
00783       comm().synchronize();
00784     }
00785   SUNDANCE_MSG2(setupVerb(), 
00786                "p=" << mesh().comm().getRank()
00787                << " sharing offsets for DOF numbering for dim=" << dim);
00788 
00789   SUNDANCE_MSG2(setupVerb(), 
00790                "p=" << mesh().comm().getRank()
00791                << " I have " << localCount << " cells");
00792 
00793   Array<int> dofOffsets;
00794   int totalDOFCount;
00795   MPIContainerComm<int>::accumulate(localCount, dofOffsets, totalDOFCount,
00796                                     mesh().comm());
00797   int myOffset = dofOffsets[mesh().comm().getRank()];
00798 
00799   SUNDANCE_MSG2(setupVerb(), 
00800                "p=" << mesh().comm().getRank()
00801                << " back from MPI accumulate");
00802 
00803   if (verbosity() > 2)
00804     {
00805       comm().synchronize();
00806       comm().synchronize();
00807       comm().synchronize();
00808       comm().synchronize();
00809     }
00810 
00811   for (int c=0; c<dofs_[dim].size(); c++)
00812     {
00813       if (hasBeenAssigned(dim, c))
00814         {
00815           for (int n=0; n<dofs_[dim][c].size(); n++) 
00816             {
00817               dofs_[dim][c][n] += myOffset;
00818             }
00819         }
00820     }
00821 
00822   setLowestLocalDOF(myOffset);
00823   setNumLocalDOFs(localCount);
00824   setTotalNumDOFs(totalDOFCount);
00825 
00826   SUNDANCE_MSG2(setupVerb(), 
00827                "p=" << mesh().comm().getRank() 
00828                << " done sharing offsets for DOF numbering for dim=" << dim);
00829   if (verbosity() > 2)
00830     {
00831       comm().synchronize();
00832       comm().synchronize();
00833       comm().synchronize();
00834       comm().synchronize();
00835     }
00836 
00837 }                           
00838 
00839 
00840 
00841 void HomogeneousDOFMap::print(std::ostream& os) const
00842 {
00843   int myRank = mesh().comm().getRank();
00844 
00845   Tabs tabs;
00846 
00847   os << "DOFS = " << dofs_ << std::endl;
00848 
00849   for (int p=0; p<mesh().comm().getNProc(); p++)
00850     {
00851       mesh().comm().synchronize();
00852       mesh().comm().synchronize();
00853       if (p == myRank)
00854         {
00855           os << tabs << 
00856             "========= DOFMap on proc p=" << p << " =============" << std::endl;
00857           for (int d=dim_; d>=0; d--)
00858             {
00859               Tabs tabs1;
00860               os << tabs1 << "dimension = " << d << std::endl;
00861               for (int c=0; c<mesh().numCells(d); c++)
00862                 {
00863                   Tabs tabs2;
00864                   os << tabs2 << "Cell LID=" << c << " GID=" 
00865                      << mesh().mapLIDToGID(d, c) << std::endl;
00866                   for (int f=0; f<funcIDList().size(); f++)
00867                     {
00868                       Tabs tabs3;
00869                       Array<int> dofs;
00870                       getDOFsForCell(d, c, funcIDList()[f], dofs);
00871                       os << tabs3 << "f=" << funcIDList()[f] << " " 
00872                          << dofs << std::endl;
00873                       if (false)
00874                         {
00875                           os << tabs3 << "{";
00876                           for (int i=0; i<dofs.size(); i++)
00877                             {
00878                               if (i != 0) os << ", ";
00879                               if (isLocalDOF(dofs[i])) os << "L";
00880                               else os << "R";
00881                             }
00882                           os << "}" << std::endl;
00883                         }
00884                     }
00885                 }
00886             }
00887         }
00888       mesh().comm().synchronize();
00889       mesh().comm().synchronize();
00890     }
00891 }
00892 
00893 

Site Contact