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

Site Contact