SundanceMixedDOFMapHN.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 "SundanceMixedDOFMapHN.hpp"
00043 #include "SundanceBasisDOFTopologyBase.hpp"
00044 #include "SundanceCellFilter.hpp"
00045 #include "SundanceMaximalCellFilter.hpp"
00046 #include "PlayaMPIContainerComm.hpp"
00047 #include "SundanceOut.hpp"
00048 #include "PlayaTabs.hpp"
00049 #include "Teuchos_Time.hpp"
00050 #include "Teuchos_TimeMonitor.hpp"
00051 
00052 using namespace Sundance;
00053 using namespace Teuchos;
00054 using Playa::MPIComm;
00055 using Playa::MPIContainerComm;
00056 using Playa::MPIDataType;
00057 using Playa::MPIOp;
00058 
00059 static Time& mixedHNDOFCtorTimer()
00060 {
00061   static RCP<Time> rtn 
00062     = TimeMonitor::getNewTimer("mixed hanging-node DOF map init");
00063   return *rtn;
00064 }
00065 static Time& maxDOFBuildTimer() 
00066 {
00067   static RCP<Time> rtn 
00068     = TimeMonitor::getNewTimer("max-cell dof table init"); 
00069   return *rtn;
00070 }
00071 
00072 MixedDOFMapHN::MixedDOFMapHN(const Mesh& mesh,
00073   const Array<RCP<BasisDOFTopologyBase> >& basis,
00074   const CellFilter& maxCells,
00075   int setupVerb)
00076  : HNDoFMapBaseHomogeneous(mesh, basis.size(), setupVerb),
00077     maxCells_(maxCells),
00078     dim_(mesh.spatialDim()),
00079     dofs_(mesh.spatialDim()+1),
00080     maximalDofs_(),
00081     haveMaximalDofs_(false),
00082     localNodePtrs_(),
00083     hasCellHanging_(),
00084     isElementHanging_(mesh.spatialDim()+1),
00085     HN_To_globalFacetsLID_(),
00086     HN_To_globalFacetsDim_(),
00087     HN_To_coeffs_(),
00088     maxCellLIDwithHN_to_TrafoMatrix_(),
00089     matrixStore_(),
00090     nNodesPerCell_(),
00091     totalNNodesPerCell_(),
00092     cellHasAnyDOFs_(dim_+1),
00093     numFacets_(mesh.spatialDim()+1),
00094     originalFacetOrientation_(2),
00095     hasBeenAssigned_(mesh.spatialDim()+1),
00096     structure_(),
00097     nFuncs_()
00098 {
00099   TimeMonitor timer(mixedHNDOFCtorTimer());
00100   Tabs tab;
00101 
00102   SUNDANCE_MSG1(setupVerb, tab << "building mixed hanging node DOF map");
00103 
00104   Sundance::Map<OrderedHandle<BasisDOFTopologyBase>, int> basisToChunkMap;
00105   Array<RCP<BasisDOFTopologyBase> > chunkBases;
00106   Array<Array<int> > chunkFuncs;
00107   
00108   int chunk = 0;
00109   int nBasis = basis.size();
00110   basis_.resize(nBasis);
00111 
00112   nPoints_ = mesh.numCells(0);
00113 
00114   for (int i=0; i<nBasis; i++)
00115   {
00116     OrderedHandle<BasisDOFTopologyBase> bh = basis[i];
00117     if (!basisToChunkMap.containsKey(bh))
00118     {
00119       chunkBases.append(basis[i]);
00120       basisToChunkMap.put(bh, chunk);
00121       chunkFuncs.append(tuple(i));
00122       basis_[chunk] = rcp_dynamic_cast<BasisFamilyBase>(basis[i]);
00123       chunk++;
00124     }
00125     else
00126     {
00127       int b = basisToChunkMap.get(bh);
00128       chunkFuncs[b].append(i);
00129     }
00130   }
00131   basis_.resize(chunk);
00132 
00133   // initialize the matrix store
00134   matrixStore_.init(chunk);
00135 
00136   Tabs tab1;
00137   SUNDANCE_MSG1(setupVerb, tab1 << "basis to chunk map = " << basisToChunkMap);
00138 
00139 
00140   structure_ = rcp(new MapStructure(basis.size(), chunkBases, chunkFuncs));
00141 
00142   nFuncs_.resize(chunkBases.size());
00143   for (int i=0; i<nFuncs_.size(); i++) 
00144     nFuncs_[i] = chunkFuncs[i].size();
00145 
00146   allocate(mesh);
00147 
00148   initMap();
00149 
00150   buildMaximalDofTable();
00151 
00152   /* do a sanity check */
00153   //checkTable(); // todo: not implemented yet (would be useful in parallel case)
00154 
00155   SUNDANCE_MSG1(setupVerb, tab << "done building mixed HN DOF map");
00156 
00157 }
00158 
00159 
00160 void MixedDOFMapHN::allocate(const Mesh& mesh)
00161 {
00162   Tabs tab;
00163 
00164   /* gather functions into chunks sharing identical basis functions */
00165   SUNDANCE_MSG1(setupVerb(),tab << "grouping like basis functions");
00166 
00167   /* now that we know the number of basis chunks, allocate arrays */
00168   localNodePtrs_.resize(nBasisChunks());
00169   nNodesPerCell_.resize(nBasisChunks());
00170   totalNNodesPerCell_.resize(nBasisChunks());
00171   nDofsPerCell_.resize(nBasisChunks());
00172   totalNDofsPerCell_.resize(nBasisChunks());
00173   maximalDofs_.resize(nBasisChunks());
00174 
00175   for (int b=0; b<nBasisChunks(); b++)
00176   {
00177     localNodePtrs_[b].resize(mesh.spatialDim()+1);
00178     nNodesPerCell_[b].resize(mesh.spatialDim()+1);
00179     totalNNodesPerCell_[b].resize(mesh.spatialDim()+1);
00180     nDofsPerCell_[b].resize(mesh.spatialDim()+1);
00181     totalNDofsPerCell_[b].resize(mesh.spatialDim()+1);
00182   }
00183 
00184   /* compute node counts for each cell dimension and each basis type */
00185   SUNDANCE_MSG1(setupVerb(),tab << "working out DOF map node counts");
00186   
00187   numFacets_.resize(dim_+1);
00188   isElementHanging_.resize(dim_+1);
00189   hasCellHanging_.resize(mesh.numCells(dim_),false);
00190 
00191   for (int d=0; d<=dim_; d++)
00192   {
00193     Tabs tab1;
00194     SUNDANCE_MSG1(setupVerb(),tab << "allocating maps for cell dim=" << d);
00195     /* record the number of facets for each cell type so we're
00196      * not making a bunch of mesh calls */
00197     numFacets_[d].resize(d);
00198 
00199     for (int fd=0; fd<d; fd++) numFacets_[d][fd]=mesh.numFacets(d, 0, fd);
00200     SUNDANCE_MSG1(setupVerb(),tab1 << "num facets for dimension " << d << " is "
00201       << numFacets_[d]);
00202 
00203     cellHasAnyDOFs_[d] = false;
00204     dofs_[d].resize(nBasisChunks());
00205 
00206     int numCells = mesh.numCells(d);
00207     hasBeenAssigned_[d].resize(numCells);
00208 
00209     // set the arrays which show which element is hanging or cell has hanging DoFs
00210     isElementHanging_[d].resize(numCells,false);
00211     for (int c=0; c<numCells; c++) { isElementHanging_[d][c] = false; }
00212     if (d == dim_){
00213       for (int c=0; c<numCells; c++) { hasCellHanging_[c] = false; }
00214     }
00215 
00216     for (int b=0; b<nBasisChunks(); b++)
00217     {
00218       Tabs tab2;
00219       SUNDANCE_MSG2(setupVerb(),tab1 << "basis chunk=" << b);
00220       SUNDANCE_MSG2(setupVerb(),tab2 << "basis=" << basis(b)->description());
00221       int nNodes = basis(b).ptr()->nReferenceDOFsWithFacets(mesh.cellType(dim_), mesh.cellType(d));
00222       SUNDANCE_MSG2(setupVerb(),tab2 << "nNodes per cell=" << nNodes);
00223       if (nNodes == 0)
00224       {
00225         nNodesPerCell_[b][d] = 0;
00226         nDofsPerCell_[b][d] = 0;
00227       }
00228       else
00229       {
00230         /* look up the node pointer for this cell and for all of its
00231          * facets */
00232         basis(b).ptr()->getReferenceDOFs(mesh.cellType(dim_),
00233           mesh.cellType(d), 
00234           localNodePtrs_[b][d]);
00235               
00236               
00237         SUNDANCE_MSG3(setupVerb(),tab2 << "node ptrs are "
00238           << localNodePtrs_[b][d]);
00239               
00240         /* with the node pointers in hand, we can work out the number
00241          * of nodes per cell in this dimension for this basis */
00242         if (localNodePtrs_[b][d][d].size() > 0) 
00243         {
00244           nNodesPerCell_[b][d] = localNodePtrs_[b][d][d][0].size();
00245           if (nNodesPerCell_[b][d] > 0) cellHasAnyDOFs_[d] = true;
00246         }
00247         else
00248         {
00249           nNodesPerCell_[b][d] = 0;
00250         }
00251         nDofsPerCell_[b][d] = nNodesPerCell_[b][d] * nFuncs(b);
00252       }
00253 
00254       /* if the cell is of intermediate dimension and it has DOFs, we
00255        * need to assign GIDs for the cells of this dimension. Otherwise,
00256        * we can skip intermediate GID assignment, saving some parallel
00257        * communication */
00258       if (nDofsPerCell_[b][d] > 0 && d > 0 && d < mesh.spatialDim())
00259       {
00260         Mesh& tmpMesh = const_cast<Mesh&>(mesh);
00261         tmpMesh.assignIntermediateCellGIDs(d);
00262       }
00263           
00264       SUNDANCE_MSG3(setupVerb(),tab2 <<
00265         "num nodes is " 
00266         << nNodesPerCell_[b][d]);
00267 
00268       totalNNodesPerCell_[b][d] = nNodesPerCell_[b][d];
00269       for (int dd=0; dd<d; dd++) 
00270       {
00271         totalNNodesPerCell_[b][d] 
00272           += numFacets_[d][dd]*nNodesPerCell_[b][dd];
00273       }
00274       totalNDofsPerCell_[b][d] = totalNNodesPerCell_[b][d] * nFuncs(b);
00275       SUNDANCE_MSG3(setupVerb(),tab2 << "totalNDofsPerCell " << totalNDofsPerCell_[b][d]);
00276 
00277       if (nNodes > 0)
00278       {
00279         /* allocate the DOFs array for this dimension */
00280         dofs_[d][b].resize(nDofsPerCell_[b][d] * numCells);
00281               
00282         /* set all DOFs to a marker value */
00283         int nDof = dofs_[d][b].size();
00284         Array<int>& dofs = dofs_[d][b];
00285         int marker = uninitializedVal();
00286         for (int i=0; i<nDof; i++) 
00287         {
00288           dofs[i] = marker;
00289         }
00290       }
00291       /* allocate the maximal dof array */
00292       if (d==dim_)
00293       {
00294         maximalDofs_[b].resize(totalNDofsPerCell_[b][d]*numCells);
00295       }
00296     }
00297 
00298     /* allocate the array of original facet orientations */
00299     if (d > 0 && d < dim_) 
00300     {
00301       originalFacetOrientation_[d-1].resize(numCells);
00302     }
00303       
00304   }
00305   SUNDANCE_MSG1(setupVerb(),tab << "done allocating DOF map");
00306 }
00307 
00308 void MixedDOFMapHN::initMap()
00309 {
00310   Tabs tab;
00311   SUNDANCE_MSG1(setupVerb(),tab << "initializing DOF map");
00312   /* start the DOF count at zero. */
00313   int nextDOF = 0;
00314 
00315   /* Space in which to keep a list of remote cells needed by each processor
00316    * for each dimension. The first index is dimension, the second proc, the
00317    * third cell number. */
00318   Array<Array<Array<int> > > remoteCells(mesh().spatialDim()+1);
00319 
00320   for (int d=0; d<remoteCells.size(); d++) 
00321     remoteCells[d].resize(mesh().comm().getNProc());
00322   
00323   /* Loop over maximal cells in the order specified by the cell iterator.
00324    * This might be reordered relative to the mesh. 
00325    *
00326    * At each maximal cell, we'll run through the facets and 
00327    * assign DOFs. That will take somewhat more work, but gives much 
00328    * better cache locality for the matrix because all the DOFs for
00329    * each maximal element and its facets are grouped together. */
00330   
00331   CellSet cells = maxCells_.getCells(mesh());
00332   CellIterator iter;
00333   for (iter=cells.begin(); iter != cells.end(); iter++)
00334   {
00335     /* first assign any DOFs associated with the maximal cell */
00336     int cellLID = *iter;
00337     int owner;
00338       
00339     if (cellHasAnyDOFs_[dim_])
00340     {
00341       /* if the maximal cell is owned by another processor,
00342        * put it in the list of cells for which we need to request 
00343        * DOF information from another processor */
00344       if (isRemote(dim_, cellLID, owner))
00345       {
00346       // cells can not be hanging
00347         int cellGID = mesh().mapLIDToGID(dim_, cellLID);
00348         SUNDANCE_MSG4(setupVerb(),"proc=" << comm().getRank()
00349           << " thinks d-" << dim_ 
00350           << " cell GID=" << cellGID
00351           << " is owned remotely by p=" 
00352           << owner);
00353         remoteCells[dim_][owner].append(cellGID); 
00354       }
00355       else /* the cell is locally owned, so we can 
00356             * set its DOF numbers now */
00357       {
00358         for (int b=0; b<nBasisChunks(); b++)
00359         {
00360           setDOFs(b, dim_, cellLID, nextDOF);
00361         }
00362       }
00363     }
00364 
00365     /* Now assign any DOFs associated with the facets. */
00366     for (int d=0; d<dim_; d++)
00367     {
00368       if (cellHasAnyDOFs_[d])
00369       {
00370         int nf = numFacets_[dim_][d];
00371         Array<int> facetLID(nf);
00372         Array<int> facetOrientations(nf);
00373         // look up the LIDs of the facets
00374 
00375         mesh().getFacetArray(dim_, cellLID, d, 
00376           facetLID, facetOrientations);
00377         // for each facet, process its DOFs
00378         for (int f=0; f<nf; f++)
00379         {
00380           // if the facet's DOFs have been assigned already,
00381           // we're done
00382           if (!hasBeenAssigned(d, facetLID[f]))
00383           {
00384             markAsAssigned(d, facetLID[f]);
00385             // the facet may be owned by another processor, if the facet is hanging element then not
00386             if ( isRemote(d, facetLID[f], owner) && (!mesh().isElementHangingNode(d,facetLID[f])))
00387             {
00388               int facetGID 
00389                 = mesh().mapLIDToGID(d, facetLID[f]);
00390               SUNDANCE_MSG4(setupVerb(),"proc=" << comm().getRank()
00391                 << " thinks d-" << d 
00392                 << " cell GID=" << facetGID
00393                 << " is owned remotely by p=" << owner);
00394               remoteCells[d][owner].append(facetGID);
00395             }
00396             else // we can assign a DOF locally
00397             {
00398               // assign DOF
00399               for (int b=0; b<nBasisChunks(); b++)
00400               {
00401                 setDOFs(b, d, facetLID[f], nextDOF);
00402               }
00403               // record the orientation wrt the maximal cell
00404               if (d > 0) 
00405               {
00406                 originalFacetOrientation_[d-1][facetLID[f]] 
00407                   = facetOrientations[f];
00408               }
00409             }
00410           }
00411         }
00412       }
00413     }
00414   }
00415     
00416 
00417   /* Done with first pass, in which we have assigned DOFs for all
00418    * local processors. We now have to share DOF information between
00419    * processors */
00420 
00421   int numLocalDOFs = nextDOF;
00422   if (mesh().comm().getNProc() > 1)
00423   {
00424     for (int d=0; d<=dim_; d++)
00425     {
00426       if (cellHasAnyDOFs_[d])
00427       {
00428         computeOffsets(d, numLocalDOFs);
00429         shareDOFs(d, remoteCells[d]);
00430       }
00431     }
00432   }
00433   else
00434   {
00435     setLowestLocalDOF(0);
00436     setNumLocalDOFs(numLocalDOFs);
00437     setTotalNumDOFs(numLocalDOFs);
00438   }
00439   SUNDANCE_MSG1(setupVerb(),tab << "done initializing DOF map , numLocalDOFs:" << numLocalDOFs);
00440 }
00441 
00442 
00443 void MixedDOFMapHN::setDOFs(int basisChunk, int cellDim, int cellLID,
00444   int& nextDOF, bool isRemote)
00445 {
00446   int nDofs = nDofsPerCell_[basisChunk][cellDim];
00447   if (nDofs==0) return;
00448   Tabs tab;
00449   SUNDANCE_MSG4(setupVerb(),tab << "setting DOFs for " << cellDim
00450     << "-cell " << cellLID <<  " , basisChunk:" << basisChunk <<" , nDofs:" <<nDofs << " , nextDOF:" << nextDOF );
00451 
00452   int* ptr = getInitialDOFPtrForCell(cellDim, cellLID, basisChunk);
00453   //int setupVerb = 6;
00454 
00455   //dofs_[cellDim][basisChunk][cellLID*nDofsPerCell_[basisChunk][cellDim]]
00456   //SUNDANCE_MSG1(setupVerb," dofs_[cellDim][basisChunk].size():" << dofs_[cellDim][basisChunk].size() );
00457 
00458   if (isRemote)
00459   {
00460   if (mesh().isElementHangingNode(cellDim, cellLID)){
00461     isElementHanging_[cellDim][cellLID] = true;
00462     for (int i=0; i<nDofs; i++) {//hanging cell, no global DoF
00463       ptr[i] = -1;
00464       //addGhostIndex(nextDOF);
00465     }
00466   }
00467   else
00468   {  // not hanging cell
00469     for (int i=0; i<nDofs; i++, nextDOF++){
00470       ptr[i] = nextDOF;
00471       addGhostIndex(nextDOF);
00472     }
00473   }
00474   }
00475   else
00476   {
00477   if (mesh().isElementHangingNode(cellDim, cellLID)){
00478     isElementHanging_[cellDim][cellLID] = true;
00479     for (int i=0; i<nDofs; i++) {//hanging cell, no global DoF
00480       //SUNDANCE_MSG1(setupVerb," cellDim:" << cellDim << ",cellLID:" << cellLID << ",basisChunk:" << basisChunk << "  ELEM HANGING");
00481       //SUNDANCE_MSG1(setupVerb," cellDim:" << cellDim << ",cellLID:" << cellLID << ",basisChunk:" << basisChunk << "  dof:" << nextDOF);
00482       //SUNDANCE_MSG1(setupVerb," writing at index:" << (cellLID*nDofsPerCell_[basisChunk][cellDim]+ i) );
00483       //SUNDANCE_MSG1(setupVerb," ptr[i]:" << ptr[i] );
00484       ptr[i] = -1;
00485     }
00486   }
00487   else
00488   {  // not hanging DoF
00489     for (int i=0; i<nDofs; i++,nextDOF++) {
00490       //SUNDANCE_MSG1(setupVerb," cellDim:" << cellDim << ",cellLID:" << cellLID << ",basisChunk:" << basisChunk << "  dof:" << nextDOF);
00491       //SUNDANCE_MSG1(setupVerb," writing at index:" << (cellLID*nDofsPerCell_[basisChunk][cellDim]+ i) );
00492       //SUNDANCE_MSG1(setupVerb," ptr[i]:" << ptr[i] );
00493       ptr[i] = nextDOF;
00494     }
00495   }
00496   }
00497 }
00498 
00499 
00500 
00501 
00502 
00503 void MixedDOFMapHN::shareDOFs(int cellDim,
00504   const Array<Array<int> >& outgoingCellRequests)
00505 {
00506   int np = mesh().comm().getNProc();
00507   int rank = mesh().comm().getRank();
00508 
00509   Array<Array<int> > incomingCellRequests;
00510   Array<Array<int> > outgoingDOFs(np);
00511   Array<Array<int> > incomingDOFs;
00512 
00513   SUNDANCE_MSG2(setupVerb(),
00514     "p=" << mesh().comm().getRank()
00515     << "synchronizing DOFs for cells of dimension " << cellDim);
00516   SUNDANCE_MSG2(setupVerb(),
00517     "p=" << mesh().comm().getRank()
00518     << " sending cell reqs d=" << cellDim << " GID=" << outgoingCellRequests);
00519 
00520   /* share the cell requests */
00521   MPIContainerComm<int>::allToAll(outgoingCellRequests, 
00522     incomingCellRequests,
00523     mesh().comm());
00524   
00525   /* we send the following information in response:
00526    * (1) The first DOF for each chunk for the requested cell
00527    * (2) The orientation if the cell is an edge or face 
00528    */
00529   int blockSize = 0;
00530   bool sendOrientation = false;
00531   for (int b=0; b<nBasisChunks(); b++)
00532   {
00533     int nDofs = nDofsPerCell_[b][cellDim];
00534     if (nDofs > 0) blockSize++;
00535     if (nDofs > 1 && cellDim > 0 && cellDim < dim_) sendOrientation = true;
00536   }
00537   blockSize += sendOrientation;
00538 
00539   SUNDANCE_MSG2(setupVerb(),
00540     "p=" << rank
00541     << "recvd DOF requests for cells of dimension " << cellDim
00542     << " GID=" << incomingCellRequests);
00543 
00544   /* get orientations and DOF numbers for the first node of every cell that's been 
00545    * requested by someone else */
00546   for (int p=0; p<np; p++)
00547   {
00548     if (p==rank) continue;
00549     const Array<int>& requestsFromProc = incomingCellRequests[p];
00550     int nReq = requestsFromProc.size();
00551 
00552     SUNDANCE_MSG4(setupVerb(),"p=" << mesh().comm().getRank()
00553       << " recv'd from proc=" << p
00554       << " reqs for DOFs for cells " 
00555       << requestsFromProc);
00556 
00557     outgoingDOFs[p].resize(nReq * blockSize);
00558 
00559     for (int c=0; c<nReq; c++)
00560     {
00561       int GID = requestsFromProc[c];
00562       SUNDANCE_MSG3(setupVerb(),
00563         "p=" << rank
00564         << " processing cell with d=" << cellDim 
00565         << " GID=" << GID);
00566       int LID = mesh().mapGIDToLID(cellDim, GID);
00567       SUNDANCE_MSG3(setupVerb(),
00568         "p=" << rank
00569         << " LID=" << LID << " dofs=" << dofs_[cellDim]);
00570       int blockOffset = 0;
00571       for (int b=0; b<nBasisChunks(); b++)
00572       {
00573         if (nDofsPerCell_[b][cellDim] == 0) continue;
00574         outgoingDOFs[p][blockSize*c+blockOffset] 
00575           = getInitialDOFForCell(cellDim, LID, b);
00576         blockOffset++;
00577       }
00578       if (sendOrientation)
00579       {
00580         outgoingDOFs[p][blockSize*(c+1) - 1] 
00581           = originalFacetOrientation_[cellDim-1][LID];
00582       }
00583       SUNDANCE_MSG3(setupVerb(),
00584         "p=" << rank
00585         << " done processing cell with GID=" << GID);
00586     }
00587   }
00588  
00589 
00590   SUNDANCE_MSG2(setupVerb(),
00591     "p=" << mesh().comm().getRank()
00592     << "answering DOF requests for cells of dimension " << cellDim);
00593 
00594   /* share the DOF numbers */
00595   MPIContainerComm<int>::allToAll(outgoingDOFs,
00596     incomingDOFs,
00597     mesh().comm());
00598 
00599   SUNDANCE_MSG2(setupVerb(),
00600     "p=" << mesh().comm().getRank()
00601     << "communicated DOF answers for cells of dimension " << cellDim);
00602 
00603   
00604   /* now assign the DOFs from the other procs */
00605 
00606   for (int p=0; p<mesh().comm().getNProc(); p++)
00607   {
00608     if (p==mesh().comm().getRank()) continue;
00609     const Array<int>& dofsFromProc = incomingDOFs[p];
00610     int numCells = dofsFromProc.size()/blockSize;
00611     for (int c=0; c<numCells; c++)
00612     {
00613       int cellGID = outgoingCellRequests[p][c];
00614       int cellLID = mesh().mapGIDToLID(cellDim, cellGID);
00615       int blockOffset = 0;
00616       for (int b=0; b<nBasisChunks(); b++)
00617       {
00618         if (nDofsPerCell_[b][cellDim] == 0) continue;
00619         int dof = dofsFromProc[blockSize*c+blockOffset];
00620         setDOFs(b, cellDim, cellLID, dof, true);
00621         blockOffset++;
00622       }
00623       if (sendOrientation) 
00624       {
00625         originalFacetOrientation_[cellDim-1][cellLID] 
00626           = dofsFromProc[blockSize*(c+1)-1];
00627       }
00628     }
00629   }
00630   
00631 }
00632 
00633 
00634 RCP<const MapStructure> MixedDOFMapHN
00635 ::getDOFsForCellBatch(int cellDim,
00636   const Array<int>& cellLID,
00637   const Set<int>& requestedFuncSet,
00638   Array<Array<int> >& dofs,
00639   Array<int>& nNodes,
00640   int verbosity) const 
00641 {
00642   TimeMonitor timer(batchedDofLookupTimer());
00643 
00644   Tabs tab;
00645   //verbosity = 6; // hard code, eliminate this
00646   SUNDANCE_MSG2(verbosity,
00647     tab << "getDOFsForCellBatch(): cellDim=" << cellDim
00648     << " cellLID=" << cellLID);
00649 
00650   dofs.resize(nBasisChunks());
00651   nNodes.resize(nBasisChunks());
00652 
00653   int nCells = cellLID.size();
00654 
00655   if (cellDim == dim_)
00656   {
00657     Tabs tab1;
00658 
00659     SUNDANCE_MSG4(verbosity,tab1 << "getting dofs for maximal cells : " << cellLID );
00660 
00661     for (int b=0; b<nBasisChunks(); b++)
00662     {
00663       nNodes[b] = totalNNodesPerCell_[b][cellDim];
00664       dofs[b].resize(nNodes[b]*nFuncs(b)*nCells);
00665       int dofsPerCell = nFuncs(b)*nNodes[b];
00666       Array<int>& chunkDofs = dofs[b];
00667       // Here nothing to do for hanging DoFs
00668       // -> this should be the only place which is called with hanging nodes
00669       // -> since no facet integral with hanging DoFs should occur
00670       for (int c=0; c<nCells; c++)
00671       {
00672         for (int i=0; i<dofsPerCell; i++)
00673         {
00674           chunkDofs[c*dofsPerCell + i] 
00675             = maximalDofs_[b][cellLID[c]*dofsPerCell+i];
00676         }
00677       }
00678       SUNDANCE_MSG3(verbosity,tab1 << "dofs for chunk-" << b << " :" << chunkDofs);
00679     }
00680   }
00681   else
00682   {
00683     Tabs tab1;
00684     SUNDANCE_MSG3(verbosity,tab1 << "getting dofs for non-maximal cells");
00685   
00686     static Array<Array<int> > facetLID(3);
00687     static Array<Array<int> > facetOrientations(3);
00688     static Array<int> numFacets(3);
00689 
00690     for (int d=0; d<cellDim; d++) 
00691     {
00692       numFacets[d] = mesh().numFacets(cellDim, cellLID[0], d);
00693       mesh().getFacetLIDs(cellDim, cellLID, d, facetLID[d], 
00694         facetOrientations[d]);
00695     }
00696 
00697     for (int b=0; b<nBasisChunks(); b++)
00698     {
00699       nNodes[b] = totalNNodesPerCell_[b][cellDim];
00700       dofs[b].resize(nNodes[b]*nFuncs(b)*nCells);
00701       int dofsPerCell = nFuncs(b)*nNodes[b];
00702           
00703       Array<int>& toPtr = dofs[b];
00704       int nf = nFuncs(b);
00705 
00706       for (int c=0; c<nCells; c++)
00707       {
00708         Tabs tab2;
00709         SUNDANCE_MSG3(verbosity,tab2 << "cell=" << c << "    ,cellLID[c]:" << cellLID[c]);
00710         int offset = dofsPerCell*c;
00711 
00712         /* first get the DOFs for the nodes associated with 
00713          * the cell's interior */
00714         // nothing to do here for hanging DoFs, since no facet integration should occure with hanging DoF
00715         SUNDANCE_MSG3(verbosity,tab2 << "doing interior nodes");
00716         int nInteriorNodes = nNodesPerCell_[b][cellDim];
00717         //              int nInteriorNodes = localNodePtrs_[b][cellDim][cellDim][0].size();
00718         if (nInteriorNodes > 0)
00719         {
00720           if (cellDim==0 || nInteriorNodes <= 1) /* orientation-independent */
00721           {
00722 
00723             for (int func=0; func<nf; func++)
00724             {
00725               for (int n=0; n<nInteriorNodes; n++)
00726               {
00727                 int ptr = localNodePtrs_[b][cellDim][cellDim][0][n];
00728                 toPtr[offset + func*nNodes[b] + ptr] 
00729                   = dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00730                 //                                = fromPtr[func*nNodes[b] + n];
00731               }
00732             }
00733           }
00734           else
00735           {
00736             int sign = originalFacetOrientation_[cellDim-1][cellLID[c]];
00737             int nInteriorNodes = localNodePtrs_[b][cellDim][cellDim][0].size();
00738 
00739             for (int func=0; func<nf; func++)
00740             {
00741               for (int m=0; m<nInteriorNodes; m++)
00742               {
00743                 int n = m;
00744                 if (sign<0) n = nInteriorNodes-1-m;
00745                 int ptr = localNodePtrs_[b][cellDim][cellDim][0][m];
00746                 toPtr[offset + func*nNodes[b] + ptr]  = dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00747                 //    = fromPtr[func*nNodes[b] + n];
00748               }
00749             }
00750           }
00751         }
00752 
00753         /* now do the facets */
00754         for (int d=0; d<cellDim; d++)
00755         {
00756           Tabs tab2;
00757           SUNDANCE_MSG3(verbosity,tab2 << "facet dim=" << d);
00758           if (nNodesPerCell_[b][d] == 0) continue;
00759           for (int f=0; f<numFacets[d]; f++)
00760           {
00761             Tabs tab3;
00762             int facetID = facetLID[d][c*numFacets[d]+f];
00763             SUNDANCE_MSG3(verbosity,tab2 << "f=" << f << " facetLID=" << facetID);
00764             if (localNodePtrs_[b][cellDim].size()==0) continue;
00765             int nFacetNodes = localNodePtrs_[b][cellDim][d][f].size();
00766             //const int* fromPtr = getInitialDOFPtrForCell(d, facetID, b);
00767             int* toPtr1 = &(dofs[b][dofsPerCell*c]);
00768             const int* nodePtr = &(localNodePtrs_[b][cellDim][d][f][0]);
00769 
00770             // nothing to do here for hanging DoFs, since no facet integration should occur with hanging DoF
00771 
00772             for (int func=0; func<nf; func++)
00773             {
00774               if (d == 0 || nFacetNodes <= 1) /* orientation-independent */
00775               {
00776                 for (int n=0; n<nFacetNodes; n++)
00777                 {
00778                   int ptr = nodePtr[n];
00779                   toPtr1[func*nNodes[b] + ptr]
00780                     = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00781                   //SUNDANCE_MSG3(verbosity,tab2 << "ptr=" << ptr << " , dof= " << toPtr1[func*nNodes[b] + ptr]);
00782                   //SUNDANCE_MSG1(verbosity," read from index:" << (facetID*nDofsPerCell_[b][d]) << " , add func:" << func*nNodesPerCell_[b][d]+n );
00783                   // if this is negative , then we have to correct it
00784                   if (toPtr1[func*nNodes[b] + ptr] < 0 )
00785                      {
00786                     int fIndex = 1 , tmp1 = 1;
00787                     // get any cell which has this element
00788                     //int maxCell = mesh().maxCofacetLID( cellDim , cellLID[c] , 0 , fIndex);
00789                     // we replaced the line above with this below, due to possible bug in the 3D mesh
00790                     int maxCell = mesh().maxCofacetLID( d , facetID , 0 , fIndex);
00791                     //SUNDANCE_MSG3(verbosity,tab2 << "mesh().isElementHangingNode("<<cellDim <<","<<cellLID[c]<<")=" <<
00792                     //    mesh().isElementHangingNode( cellDim , cellLID[c]); );
00793                     //SUNDANCE_MSG3(verbosity,tab2 << "mesh().isElementHangingNode("<<d <<","<<facetID<<")=" <<
00794                     //    mesh().isElementHangingNode( d , facetID); );
00795                     //SUNDANCE_MSG3(verbosity,tab2 << " Point[" << facetID << "]=" <<  mesh().nodePosition(facetID) );
00796                       Array<int> facetsLIDs;
00797                       mesh().returnParentFacets( maxCell , d , facetsLIDs , tmp1 );
00798                       // return the parent facet at the same index
00799                       //SUNDANCE_MSG3(verbosity,tab2 << "maxCell=" << maxCell << " fIndex=" << fIndex );
00800                       //SUNDANCE_MSG3(verbosity,tab2 << "facetsLIDs[0]=" << facetsLIDs[0] << " , facetsLIDs[1]=" << facetsLIDs[1] <<
00801                       //    " , facetsLIDs[2]=" << facetsLIDs[2] << " , facetsLIDs[3]=" << facetsLIDs[3]);
00802                       //SUNDANCE_MSG3(verbosity,tab2 << "f=" << f << " facetLID=" << facetID << " replaced by facetsLIDs[fIndex]:" << facetsLIDs[fIndex]);
00803                       toPtr1[func*nNodes[b] + ptr] //= fromPtr[func*nNodes[b] + n];
00804                                           = dofs_[d][b][facetsLIDs[fIndex]*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00805                      }
00806                 }
00807               }
00808               else /* orientation-dependent */
00809               {
00810                 int facetOrientation = facetOrientations[d][c*numFacets[d]+f]
00811                   * originalFacetOrientation_[d-1][facetID];
00812                 for (int m=0; m<nFacetNodes; m++)
00813                 {
00814                   int n = m;
00815                   if (facetOrientation<0) n = nFacetNodes-1-m;
00816                   int ptr = nodePtr[n];
00817                   toPtr1[func*nNodes[b]+ptr] 
00818                     = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00819 
00820                   // if this is negative , then we have to correct it
00821                   if (toPtr1[func*nNodes[b]+ptr] < 0)
00822                      {
00823                     int fIndex = 1 , tmp1 = 1;
00824                     // get any cell which has this element
00825                     //int maxCell = mesh().maxCofacetLID( cellDim , cellLID[c] , 0 , fIndex);
00826                     // we replaced the line above with this below, due to possible bug in the 3D mesh
00827                     int maxCell = mesh().maxCofacetLID( d , facetID , 0 , fIndex);
00828                       Array<int> facetsLIDs;
00829                       mesh().returnParentFacets( maxCell , d , facetsLIDs , tmp1 );
00830                       // return the parent facet at the same index
00831                       // return the parent facet at the same index
00832                       //SUNDANCE_MSG3(verbosity,tab2 << "f=" << f << " facetLID=" << facetID << " replaced by facetsLIDs[fIndex]:" << facetsLIDs[fIndex]);
00833                       toPtr1[func*nNodes[b] + ptr] //= fromPtr[func*nNodes[b] + n];
00834                                           = dofs_[d][b][facetsLIDs[fIndex]*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00835                      }
00836                 }
00837               }
00838             }
00839           }
00840         }
00841       }
00842     }
00843 
00844   }
00845   return structure_;
00846 }    
00847 
00848 void MixedDOFMapHN::buildMaximalDofTable()
00849 {
00850   TimeMonitor timer(maxDOFBuildTimer());
00851   Tabs tab;
00852   int cellDim = dim_;
00853   int nCells = mesh().numCells(dim_);
00854 
00855   SUNDANCE_MSG1(setupVerb(),tab << "building dofs for maximal cells");
00856 
00857   Array<Array<int> > facetLID(3);
00858   Array<Array<int> > facetOrientations(3);
00859   Array<int> numFacets(3);
00860 
00861   Array<int> cellLID(nCells);
00862 
00863   for (int c=0; c<nCells; c++) cellLID[c]=c;
00864   
00865   for (int d=0; d<cellDim; d++) 
00866   {
00867     numFacets[d] = mesh().numFacets(cellDim, cellLID[0], d);
00868     mesh().getFacetLIDs(cellDim, cellLID, d, 
00869       facetLID[d], facetOrientations[d]);
00870   }
00871 
00872   Array<int> nInteriorNodes(nBasisChunks());
00873   Array<int> nNodes(nBasisChunks());
00874   for (int b = 0; b<nBasisChunks(); b++)
00875   {
00876   /* localNodePtrs_[basisChunk][cellDim][facetDim][facetNumber][nodeNumber] */
00877     if (localNodePtrs_[b][cellDim].size() != 0)
00878     {
00879       nInteriorNodes[b] = localNodePtrs_[b][cellDim][cellDim][0].size();
00880     }
00881     else 
00882     {
00883       nInteriorNodes[b] = 0;
00884     }
00885     nNodes[b] = totalNNodesPerCell_[b][cellDim];
00886   }
00887 
00888 //--------------------- Loop over all cells -------------------------
00889 
00890   // List of global DoFs for each basis chunk and function nr
00891   Array< Array<Array<int> > >globalDoFs_Cell(nBasisChunks());
00892   // trafo matrix for each basis chunk
00893   Array<Array<double> > trafoMatrix(nBasisChunks());
00894   // the row in the traf matrix
00895   Array<int>    localDoFs;
00896   Array<int>    parentFacetDim;
00897   Array<int>    parentFacetIndex;
00898   Array<int>    parentFacetNode;
00899   Array<int>    retFacets;
00900   Array<double> coefs;
00901 
00902 
00903   for (int c=0; c<nCells; c++)
00904   {
00905   // first for each cell we should find out is it has hanging elements
00906   // it is enough if we check the points if they are hanging
00907   for (int jj = 0 ; jj < numFacets[0] ; jj++){
00908     if (mesh().isElementHangingNode(0,facetLID[0][ c*numFacets[0] + jj])){
00909         //    if order > 0, but only for that basis ... (not as a cell)
00910         //       but even if we mark for this as a hanging it is OK
00911         hasCellHanging_[cellLID[c]] = true;
00912         break;
00913       }
00914   }
00915 
00916     Tabs tab1;
00917     SUNDANCE_MSG3(setupVerb(),tab1 << "working on cell=" << c
00918       << " LID=" << cellLID[c]);
00919     /* first get the DOFs for the nodes associated with 
00920      * the cell's interior */
00921     SUNDANCE_MSG3(setupVerb(),tab1 << "doing interior nodes");
00922     for (int b=0; b<nBasisChunks(); b++)
00923     {
00924       // Initialization for cells with hanging nodes we need to create
00925       if (hasCellHanging_[cellLID[c]]){
00926       // ----------- NH -------------
00927       globalDoFs_Cell[b].resize( nFuncs(b));
00928       trafoMatrix[b].resize(nNodes[b]*nNodes[b], 0.0);
00929       for (int jj = 0; jj < nNodes[b]*nNodes[b] ; jj++) trafoMatrix[b][jj] = 0.0;
00930         for (int func=0; func<nFuncs(b); func++)
00931         {
00932           globalDoFs_Cell[b][func].resize(nNodes[b]);
00933           for (int kk = 0 ; kk < nNodes[b] ; kk++ ){
00934              globalDoFs_Cell[b][func][kk] = -1;
00935           }
00936         }
00937       }
00938 
00939       SUNDANCE_MSG3(setupVerb(),tab1 << "basis chunk=" << b);
00940       if (nInteriorNodes[b]>0)
00941       {
00942       SUNDANCE_MSG3(setupVerb(),tab1<< "nInteriorNodes = " <<nInteriorNodes[b]);
00943         int* toPtr = &(maximalDofs_[b][nNodes[b]*nFuncs(b)*cellLID[c]]);
00944         int nf = nFuncs(b);
00945         for (int func=0; func<nf; func++)
00946         {
00947           for (int n=0; n<nInteriorNodes[b]; n++)
00948           {
00949             /* dof(cellLID, chunk, func, node)
00950              * = maximalDofs_[chunk][(cellLID*nFunc + func)*nNode + node]; */
00951           /* dof(cellDim, cellLID, chunk, func, node)
00952            * = dofs_[cellDim][chunk][(cellLID*nFunc + func)*nNode + node] */
00953           /* localNodePtrs_[basisChunk][cellDim][facetDim][facetNumber][nodeNumber] */
00954 
00955             int ptr = localNodePtrs_[b][cellDim][cellDim][0][n]; // ptr is the local DoF form that function (there is only one facet)
00956 
00957             if (hasCellHanging_[cellLID[c]])
00958             {
00959               SUNDANCE_MSG1(setupVerb(), tab1 << "Cell has HDoF cellLID[c]=" << cellLID[c] );
00960               int dof_tmp = dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00961                 // dof_tmp can not be negative since it is inside the cell and can not be hanging
00962               SUNDANCE_MSG1(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , globalDoFs_Cell[b][func]:"<<globalDoFs_Cell[b][func]<<" dof=" << dof_tmp);
00963               globalDoFs_Cell[b][func][ptr] = dof_tmp;
00964               SUNDANCE_MSG1(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr <<" dof=" << dof_tmp);
00965                 if (func == 0){
00966                   trafoMatrix[b][nNodes[b]*ptr + ptr] = 1.0;
00967                 }
00968             }
00969             // internal nodes can not be hanging
00970             toPtr[func*nNodes[b] + ptr] = //fromPtr[func*nNodes[b] + n];
00971                dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00972             SUNDANCE_MSG1(setupVerb(), tab1 << " dof=" << dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n]);
00973           }
00974         }
00975       }
00976     }
00977       
00978     SUNDANCE_MSG3(setupVerb(),tab1 << "doing facet nodes");
00979     /* now get the DOFs for the nodes on the facets */
00980     for (int d=0; d<cellDim; d++)
00981     {
00982       Tabs tab2;
00983       SUNDANCE_MSG3(setupVerb(),tab2 << "facet dim=" << d);
00984 
00985       for (int f=0; f<numFacets[d]; f++)
00986       {
00987         Tabs tab3;
00988         int facetID = facetLID[d][c*numFacets[d]+f];
00989         SUNDANCE_MSG3(setupVerb(),tab2 << "f=" << f << " facetLID=" << facetID);
00990 
00991         for (int b=0; b<nBasisChunks(); b++)
00992         {
00993           Tabs tab4;
00994           SUNDANCE_MSG3(setupVerb(),tab4 << "basis chunk=" << b);
00995           SUNDANCE_MSG3(setupVerb(),tab4 << "num nodes per cell=" << nNodesPerCell_[b][d]);
00996           int nf = nFuncs(b);
00997           if (nDofsPerCell_[b][d]==0) continue;
00998           int nFacetNodes = 0;
00999           if (localNodePtrs_[b][cellDim].size()!=0)
01000             nFacetNodes = localNodePtrs_[b][cellDim][d][f].size();
01001           if (nFacetNodes == 0) continue;
01002           //  const int* fromPtr = getInitialDOFPtrForCell(d, facetID, b);
01003           SUNDANCE_MSG3(setupVerb(),tab4 << "dof table size=" << maximalDofs_[b].size());
01004           /* = maximalDofs_[chunk][(cellLID*nFunc + func)*nNode + node]; */
01005           int* toPtr = &(maximalDofs_[b][nNodes[b]*nFuncs(b)*cellLID[c]]);
01006           /* localNodePtrs_[basisChunk][cellDim][facetDim][facetNumber][nodeNumber] */
01007           const int* nodePtr = &(localNodePtrs_[b][cellDim][d][f][0]);
01008 
01009           for (int func=0; func<nf; func++)
01010           {
01011             Tabs tab5;
01012             SUNDANCE_MSG3(setupVerb(),tab5 << "func=" << func);
01013             if (d == 0 || nFacetNodes <= 1) /* orientation-independent */
01014             {
01015               Tabs tab6;
01016               for (int n=0; n<nFacetNodes; n++)
01017               {
01018               SUNDANCE_MSG3(setupVerb(),tab5 << "n=" << n);
01019                 int ptr = nodePtr[n];
01020                 SUNDANCE_MSG3(setupVerb(),tab6 << "ptr=" << ptr);
01021                 /* dof(cellLID, chunk, func, node)
01022                  * = maximalDofs_[chunk][(cellLID*nFunc + func)*nNode + node]; */
01023               /* dof(cellDim, cellLID, chunk, func, node)
01024                  * = dofs_[cellDim][chunk][(cellLID*nFunc + func)*nNode + node] */
01025                 if (hasCellHanging_[cellLID[c]]){
01026                   int parentCellLID = 0;
01027                   int dof_tmp = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
01028                   SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , d="<<d<<", f="<<f<<", n="<<n<<", dof=" << dof_tmp);
01029                     if (dof_tmp < 0){
01030                       Array<int> constFacetLID;
01031                       Array<int> constFacetDim;
01032                        // get the collaborating global DoFs, add the coefficients to the row of the trafo matrix (if func == 0)
01033                         basis_[b]->getConstrainsForHNDoF(
01034                           mesh().indexInParent(cellLID[c]), cellDim ,
01035                           mesh().maxChildren(), d , f , n,
01036                           localDoFs, parentFacetDim,
01037                           parentFacetIndex, parentFacetNode, coefs );
01038                         SUNDANCE_MSG3(setupVerb(), tab1 << " After  basis_[b]->getConstrainsForHNDoF:");
01039                         constFacetLID.resize(localDoFs.size());
01040                         constFacetDim.resize(localDoFs.size());
01041                         for (int indexi = 0 ; indexi < localDoFs.size() ; indexi++)
01042                         {
01043                             // localNodePtrs_[basisChunk][cellDim][facetDim][facetNumber][nodeNumber]
01044                           int ptr1 = localNodePtrs_[b][cellDim][parentFacetDim[indexi]]
01045                                       [parentFacetIndex[indexi]][parentFacetNode[indexi]];
01046                           // get the dof belonging to the parent cell
01047                           mesh().returnParentFacets(cellLID[c] , parentFacetDim[indexi], retFacets , parentCellLID );
01048                           int parFacetLID = retFacets[parentFacetIndex[indexi]];
01049                           int parFacetNode = parentFacetNode[indexi];
01050                           SUNDANCE_MSG3(setupVerb(), tab1 << "returnParentFacets , parFacetLID=" << parFacetLID <<" parFacetNode=" << parFacetNode );
01051                           SUNDANCE_MSG3(setupVerb(), tab1 << "returnParentFacets , retFacets=" << retFacets );
01052                           // store the facet LID and its index
01053                           constFacetDim[indexi] = parentFacetDim[indexi];
01054                           constFacetLID[indexi] = parFacetLID;
01055                           // set the DoF in the array, and add line to the
01056                             dof_tmp = dofs_[parentFacetDim[indexi]][b]
01057                              [parFacetLID * nDofsPerCell_[b][parentFacetDim[indexi]]+func*nNodesPerCell_[b][parentFacetDim[indexi]]+parFacetNode];
01058 
01059                           globalDoFs_Cell[b][func][ptr1] = dof_tmp;
01060 
01061                           SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr << "ptr1=" << ptr1 <<" dof=" << dof_tmp);
01062               if (func == 0){
01063                 trafoMatrix[b][nNodes[b]*ptr + ptr1] = coefs[indexi];
01064               }
01065               SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , DONE Fill");
01066                         }
01067                         //only for hanging points store the components
01068                         if ( (d == 0) && (func == 0)) {
01069                           HN_To_globalFacetsLID_.put( nPoints_*b + facetID , constFacetLID);
01070                           HN_To_globalFacetsDim_.put( nPoints_*b + facetID , constFacetDim);
01071                           HN_To_coeffs_.put( nPoints_*b + facetID , coefs);
01072                         }
01073                     }else {
01074                        // just put the DoF in the list , and in the matrix add one row (unit) (if func == 0)
01075                       SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr <<" dof=" << dof_tmp);
01076                         //SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , trafoMatrix[b].size()" <<
01077                           //  trafoMatrix[b].size() << ", nNodes[b]:" << nNodes[b]);
01078                         //SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , globalDoFs_Cell[b].size():" <<
01079                           //  globalDoFs_Cell[b].size() << ", globalDoFs_Cell[b][func].size():" << globalDoFs_Cell[b][func].size());
01080                       globalDoFs_Cell[b][func][ptr] = dof_tmp;
01081                         if (func == 0){
01082                           trafoMatrix[b][nNodes[b]*ptr + ptr] = 1.0;
01083                         }
01084                     }
01085                 } else {
01086                   toPtr[func*nNodes[b] + ptr]
01087                         = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
01088                   SUNDANCE_MSG3(setupVerb(), tab1 << " dof=" << dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n]);
01089                 }
01090               }
01091             }
01092             else /* orientation-dependent */
01093             {
01094               int facetOrientation = facetOrientations[d][c*numFacets[d]+f]
01095                 * originalFacetOrientation_[d-1][facetID];
01096               for (int m=0; m<nFacetNodes; m++)
01097               {
01098                 int n = m;
01099                 if (facetOrientation<0) n = nFacetNodes-1-m; // this means we have to take the DoFs in reverse order
01100                 int ptr = nodePtr[m];
01101                 /* dof(cellLID, chunk, func, node)
01102                  * = maximalDofs_[chunk][(cellLID*nFunc + func)*nNode + node]; */
01103               /* dof(cellDim, cellLID, chunk, func, node)
01104                  * = dofs_[cellDim][chunk][(cellLID*nFunc + func)*nNode + node] */
01105 
01106                 if (hasCellHanging_[cellLID[c]])
01107                 {
01108                   int parentCellLID = 0;
01109                   int dof_tmp = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
01110                   SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , d="<<d<<", f="<<f<<", n="<<n<<", dof=" << dof_tmp);
01111                     if (dof_tmp < 0){
01112                       Array<int> constFacetLID;
01113                       Array<int> constFacetDim;
01114                        // get the collaborating global DoFs, add the coefficients to the row of the trafo matrix (if func == 0)
01115                         basis_[b]->getConstrainsForHNDoF(
01116                           mesh().indexInParent(cellLID[c]), cellDim ,
01117                           mesh().maxChildren(), d , f , n,
01118                           localDoFs, parentFacetDim,
01119                           parentFacetIndex, parentFacetNode, coefs );
01120                         SUNDANCE_MSG3(setupVerb(), tab1 << " After  basis_[b]->getConstrainsForHNDoF:");
01121                         constFacetLID.resize(localDoFs.size());
01122                         constFacetDim.resize(localDoFs.size());
01123                         for (int indexi = 0 ; indexi < localDoFs.size() ; indexi++)
01124                         {
01125                             // localNodePtrs_[basisChunk][cellDim][facetDim][facetNumber][nodeNumber]
01126                           int ptr1 = localNodePtrs_[b][cellDim][parentFacetDim[indexi]]
01127                                       [parentFacetIndex[indexi]][parentFacetNode[indexi]];
01128                           // get the dof belonging to the parent cell
01129                           mesh().returnParentFacets(cellLID[c] , parentFacetDim[indexi], retFacets , parentCellLID );
01130                           int parFacetLID = retFacets[parentFacetIndex[indexi]];
01131                           int parFacetNode = parentFacetNode[indexi];
01132                           SUNDANCE_MSG3(setupVerb(), tab1 << "returnParentFacets , parFacetLID=" << parFacetLID <<" parFacetNode=" << parFacetNode );
01133                           SUNDANCE_MSG3(setupVerb(), tab1 << "returnParentFacets , retFacets=" << retFacets );
01134                           // store the facet LID and its index
01135                           constFacetDim[indexi] = parentFacetDim[indexi];
01136                           constFacetLID[indexi] = parFacetLID;
01137                           // set the DoF in the array, and add line to the
01138                            dof_tmp = dofs_[parentFacetDim[indexi]][b]
01139                              [parFacetLID * nDofsPerCell_[b][parentFacetDim[indexi]]+func*nNodesPerCell_[b][parentFacetDim[indexi]]+parFacetNode];
01140 
01141                           globalDoFs_Cell[b][func][ptr1] = dof_tmp;
01142 
01143                           SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr1 <<" dof=" << dof_tmp);
01144               if (func == 0){
01145                 trafoMatrix[b][nNodes[b]*ptr + ptr1] = coefs[indexi];
01146               }
01147                         }
01148                         //only for hanging points store the components
01149                         if ( (d == 0) && (func == 0)) {
01150                           HN_To_globalFacetsLID_.put( nPoints_*b + facetID , constFacetLID);
01151                           HN_To_globalFacetsDim_.put( nPoints_*b + facetID , constFacetDim);
01152                           HN_To_coeffs_.put( nPoints_*b + facetID , coefs);
01153                         }
01154                     }else{
01155                        // just put the DoF in the list , and in the matrix add one row (unit) (if func == 0)
01156                         //returnInsertionPosition( globalDoFs_Cell[b][func] , dof_tmp , insertPos);
01157                       SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr <<" dof=" << dof_tmp);
01158                       globalDoFs_Cell[b][func][ptr] = dof_tmp;
01159                         if (func == 0){
01160                           trafoMatrix[b][nNodes[b]*ptr + ptr] = 1.0;
01161                         }
01162                     }
01163                 } else {
01164                   toPtr[func*nNodes[b]+ptr]
01165                         = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
01166                   SUNDANCE_MSG3(setupVerb(), tab1 << " dof=" << dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n]);
01167                 }
01168               }
01169             }
01170           } //func
01171         } //basischunk
01172       } // facetInd
01173     } // facetDim
01174 
01175     //in case of cells with hanging node write the collected information to the maximalDofs_ and store the trafo matrix
01176     if (hasCellHanging_[cellLID[c]]){
01177     // store tranfo Matrix
01178       Array<int> matrixIndexes(nBasisChunks());
01179       for (int b=0; b<nBasisChunks(); b++){
01180         matrixIndexes[b] = matrixStore_.addMatrix( b , trafoMatrix[b] );
01181       }
01182     maxCellLIDwithHN_to_TrafoMatrix_.put( cellLID[c] , matrixIndexes );
01183 
01184       for (int b=0; b<nBasisChunks(); b++)
01185     {
01186         // display trafo matrix per basis chunk
01187         SUNDANCE_MSG3(setupVerb(), "trafoMatrix[b]=" << trafoMatrix[b]);
01188       for (int func=0; func<nFuncs(b); func++)
01189       {
01190         // display global DoFs for this basis chunk and this function inside the chunk
01191         SUNDANCE_MSG1(setupVerb(), "globalDoFs_Cell[b][func]=" << globalDoFs_Cell[b][func]);
01192         for (int jj=0 ; jj < nNodes[b] ; jj++){
01193           // store global DoFs for this cell
01194           maximalDofs_[b][(cellLID[c]*nFuncs(b) + func)*nNodes[b] + jj] = globalDoFs_Cell[b][func][jj];
01195         }
01196       }
01197     }
01198     }
01199   } // -------------- cell iteration -------------
01200 
01201   haveMaximalDofs_ = true;
01202 
01203   SUNDANCE_MSG1(setupVerb(),tab << "done building dofs for maximal cells");
01204 }
01205 
01206 
01207 void MixedDOFMapHN::getTrafoMatrixForCell(
01208       int cellLID,
01209       int funcID,
01210       int& trafoMatrixSize,
01211       bool& doTransform,
01212       Array<double>& transfMatrix ) const {
01213 
01214   trafoMatrixSize = 0;
01215 
01216   if (maxCellLIDwithHN_to_TrafoMatrix_.containsKey(cellLID))
01217   {
01218     // return the transformation matrix from the Map
01219     const Array<int> &matrixIndexes = maxCellLIDwithHN_to_TrafoMatrix_.get( cellLID );
01220     matrixStore_.getMatrix( chunkForFuncID(funcID) , matrixIndexes[chunkForFuncID(funcID)] , transfMatrix );
01221     //transfMatrix = (maxCellLIDwithHN_to_TrafoMatrix_.get( cellLID ))[chunkForFuncID(funcID)]; // this should return a valid array
01222 
01223     // KL added cast to double to avoid compilation problems on windows
01224     trafoMatrixSize = sqrt((double) transfMatrix.size());
01225     SUNDANCE_MSG1(setupVerb(), "getTrafoMatrixForCell() cellLID:" << cellLID << ",funcID:" <<
01226         funcID << ",chunkForFuncID(funcID):" << chunkForFuncID(funcID) << ", trafoMatrixSize:" << trafoMatrixSize);
01227     //SUNDANCE_MSG1(setupVerb(), "getTrafoMatrixForCell() Matrix:" << std::endl << transfMatrix );
01228     doTransform = true;
01229   }
01230   else  // no transformation needed, return false
01231   {
01232     doTransform = false;
01233   }
01234 }
01235 
01236 void MixedDOFMapHN::getTrafoMatrixForFacet(
01237     int cellDim,
01238     int cellLID,
01239     int facetIndex,
01240     int funcID,
01241     int& trafoMatrixSize,
01242     bool& doTransform,
01243     Array<double>& transfMatrix ) const {
01244 
01245   int fIndex;
01246   int maxCellLID;
01247   // here we ask for cofacet 0 , assuming that these are anyhow boundary facets
01248   SUNDANCE_MSG2(setupVerb() , "NodalDOFMapHN::getTrafoMatrixForFacet() cellDim :" << cellDim << ", cellLID:" << cellLID);
01249   maxCellLID = mesh().maxCofacetLID( cellDim, cellLID, 0 , fIndex);
01250   SUNDANCE_MSG2(setupVerb() , "NodalDOFMapHN::getTrafoMatrixForFacet() testing :" << maxCellLID);
01251 
01252   // todo: we might pre filter cases when this is not necessary
01253 
01254   if (maxCellLIDwithHN_to_TrafoMatrix_.containsKey(maxCellLID))
01255   {
01256     const Array<int> &matrixIndexes = maxCellLIDwithHN_to_TrafoMatrix_.get( maxCellLID );
01257     matrixStore_.getMatrix( chunkForFuncID(funcID) , matrixIndexes[chunkForFuncID(funcID)] , transfMatrix );
01258     doTransform = true;
01259   }
01260   else  // no transformation needed, return false
01261   {
01262     doTransform = false;
01263   }
01264 }
01265 
01266 /** Function for nodal plotting */
01267 void MixedDOFMapHN::getDOFsForHNCell(
01268     int cellDim,
01269     int cellLID,
01270       int funcID,
01271       Array<int>& dofs ,
01272       Array<double>& coefs ) const {
01273 
01274   // here we can make the asumption that there is only one node at this element
01275   // and that the element is a point (since this is called only for at the plotting)
01276 
01277   // treat the cells only of dimension zero
01278   if (  (cellDim == 0) && ( HN_To_globalFacetsLID_.containsKey(nPoints_*chunkForFuncID(funcID) + cellLID)) )
01279   {
01280     Array<int> facetLIDs;
01281     Array<int> facetDim;
01282     SUNDANCE_MSG1(setupVerb(), "getDOFsForHNCell() cellDim:"<<cellDim<<" cellLID:"<<
01283         cellLID<<"funcID:" << funcID <<",chunkForFuncID(funcID)" << chunkForFuncID(funcID));
01284     facetLIDs = HN_To_globalFacetsLID_.get( nPoints_*chunkForFuncID(funcID) + cellLID );
01285     facetDim = HN_To_globalFacetsDim_.get( nPoints_*chunkForFuncID(funcID) + cellLID );
01286     dofs.resize(facetLIDs.size());
01287     int b = chunkForFuncID(funcID);
01288     int func = indexForFuncID(funcID);
01289     // return the DoFs belonging to the points and function which collaborate to the hanging node
01290     for (int ind = 0 ; ind < facetLIDs.size() ; ind++){
01291       // dofs_[cellDim][chunk][(cellLID*nFunc + func)*nNode + node]
01292       dofs[ind] = dofs_[facetDim[ind]][b]
01293            [facetLIDs[ind]*nDofsPerCell_[b][facetDim[ind]]+func*nNodesPerCell_[b][facetDim[ind]] + 0 ]; // node = 0
01294     }
01295     // get the coefficients
01296     coefs = HN_To_coeffs_.get( nPoints_*chunkForFuncID(funcID) + cellLID );
01297     SUNDANCE_MSG1(setupVerb(),  "b=" << b);
01298     SUNDANCE_MSG1(setupVerb(),  "func=" << func);
01299     SUNDANCE_MSG1(setupVerb(),  "facetLIDs=" << facetLIDs);
01300     SUNDANCE_MSG1(setupVerb(),  "facetDim = " << facetDim);
01301     SUNDANCE_MSG1(setupVerb(),  "dofs=" << dofs);
01302     SUNDANCE_MSG1(setupVerb(),  "coefs = " << coefs);
01303   }
01304 }
01305 
01306 
01307 void MixedDOFMapHN::computeOffsets(int dim, int localCount)
01308 {
01309   if (setupVerb() > 2)
01310   {
01311     comm().synchronize();
01312     comm().synchronize();
01313     comm().synchronize();
01314     comm().synchronize();
01315   }
01316   SUNDANCE_MSG2(setupVerb(),
01317     "p=" << mesh().comm().getRank()
01318     << " sharing offsets for DOF numbering for dim=" << dim);
01319 
01320   SUNDANCE_MSG2(setupVerb(),
01321     "p=" << mesh().comm().getRank()
01322     << " I have " << localCount << " cells");
01323 
01324   Array<int> dofOffsets;
01325   int totalDOFCount;
01326   MPIContainerComm<int>::accumulate(localCount, dofOffsets, totalDOFCount,
01327     mesh().comm());
01328   int myOffset = dofOffsets[mesh().comm().getRank()];
01329 
01330   SUNDANCE_MSG2(setupVerb(),
01331     "p=" << mesh().comm().getRank()
01332     << " back from MPI accumulate");
01333 
01334   if (setupVerb() > 2)
01335   {
01336     comm().synchronize();
01337     comm().synchronize();
01338     comm().synchronize();
01339     comm().synchronize();
01340   }
01341 
01342   for (int chunk=0; chunk<dofs_[dim].size(); chunk++)
01343   {
01344     for (int n=0; n<dofs_[dim][chunk].size(); n++)
01345     {
01346       // increment only when this is not marked as hanging
01347       if (dofs_[dim][chunk][n] >= 0) {
01348          dofs_[dim][chunk][n] += myOffset;
01349       }
01350     }
01351   }
01352 
01353   setLowestLocalDOF(myOffset);
01354   setNumLocalDOFs(localCount);
01355   setTotalNumDOFs(totalDOFCount);
01356 
01357   SUNDANCE_MSG2(setupVerb(),
01358     "p=" << mesh().comm().getRank() 
01359     << " done sharing offsets for DOF numbering for dim=" << dim);
01360   if (setupVerb() > 2)
01361   {
01362     comm().synchronize();
01363     comm().synchronize();
01364     comm().synchronize();
01365     comm().synchronize();
01366   }
01367 
01368 }                           
01369 
01370 
01371 /* not used right now */
01372 void MixedDOFMapHN::checkTable() const
01373 {
01374   int bad = 0;
01375   for (int d=0; d<dofs_.size(); d++)
01376   {
01377     for (int chunk=0; chunk<dofs_[d].size(); chunk++)
01378     {
01379       const Array<int>& dofs = dofs_[d][chunk];
01380       for (int n=0; n<dofs.size(); n++)
01381       {
01382         if (dofs[n] < 0) bad = 1;
01383       }
01384     }
01385   }
01386   
01387   int anyBad = bad;
01388   comm().allReduce((void*) &bad, (void*) &anyBad, 1, 
01389     MPIDataType::intType(), MPIOp::sumOp());
01390   TEUCHOS_TEST_FOR_EXCEPTION(anyBad > 0, std::runtime_error, "invalid DOF map");
01391 }

Site Contact