SundanceInhomogeneousDOFMapHN.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 "SundanceInhomogeneousDOFMapHN.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 
00057 static Time& mixedHNDOFCtorTimer()
00058 {
00059   static RCP<Time> rtn 
00060     = TimeMonitor::getNewTimer("mixed hanging-node DOF map init");
00061   return *rtn;
00062 }
00063 static Time& maxDOFBuildTimer() 
00064 {
00065   static RCP<Time> rtn 
00066     = TimeMonitor::getNewTimer("max-cell dof table init"); 
00067   return *rtn;
00068 }
00069 
00070 InhomogeneousDOFMapHN::InhomogeneousDOFMapHN(const Mesh& mesh,
00071   const Array<RCP<BasisDOFTopologyBase> >& basis,
00072   const Array<Map<Set<int>, CellFilter> >& funcSetToDomainMap,
00073   int setupVerb)
00074  : HNDoFMapBase(mesh, basis.size(), setupVerb),
00075    DOFMapBase(mesh, setupVerb),
00076     dim_(mesh.spatialDim()),
00077     dofs_(mesh.spatialDim()+1),
00078     funcDefined_(mesh.spatialDim()+1),
00079     maximalDofs_(),
00080     haveMaximalDofs_(false),
00081     localNodePtrs_(),
00082     maxSubdomains_(),
00083     allFuncs_(),
00084     elemFuncSets_(),
00085     hasCellHanging_(),
00086     isElementHanging_(mesh.spatialDim()+1),
00087     HN_To_globalFacetsLID_(),
00088     HN_To_globalFacetsDim_(),
00089     HN_To_coeffs_(),
00090     maxCellLIDwithHN_to_TrafoMatrix_(),
00091     matrixStore_(),
00092     nNodesPerCell_(),
00093     cellHasAnyDOFs_(dim_+1),
00094     numFacets_(mesh.spatialDim()+1),
00095     originalFacetOrientation_(2),
00096     hasBeenAssigned_(mesh.spatialDim()+1),
00097     structure_(),
00098     nFuncs_()
00099 {
00100   TimeMonitor timer(mixedHNDOFCtorTimer());
00101   Tabs tab;
00102 
00103   SUNDANCE_MSG1(setupVerb, tab << "building mixed inhomogeneous hanging node DOF map");
00104 
00105   int nMaxCell = mesh.numCells(dim_);
00106 
00107 // ---------- DEAL WITH INHOMOGENITY ---------------
00108 // we only consider the maxcell filters, if considering only this results in error then it is the users fault ;-)
00109 
00110   for (Map<Set<int>, CellFilter>::const_iterator
00111          i=funcSetToDomainMap[dim_].begin(); i!=funcSetToDomainMap[dim_].end(); i++)
00112   {
00113     allFuncs_.merge(i->first);
00114     elemFuncSetsDomain_.append(i->first);
00115       maxSubdomains_.append(i->second);
00116   }
00117 
00118   nrAllFuncs_ = allFuncs_.size();
00119   Array<Set<int> > maxCellToFuncSetMap(mesh.numCells(dim_));
00120   Array<Array<int> > cellLIDs(maxSubdomains_.size());
00121   funcDomains_.resize(nrAllFuncs_);
00122 
00123   SUNDANCE_MSG1(setupVerb, tab << " getting the cell set for each cell ");
00124   for (int r=0; r<maxSubdomains_.size(); r++)
00125   {
00126     int d = maxSubdomains_[r].dimension(mesh);
00127     CellSet cells = maxSubdomains_[r].getCells(mesh);
00128     SUNDANCE_MSG2(setupVerb, " dim:" << d << " , domain " << maxSubdomains_[r] << " has functions "
00129       << elemFuncSetsDomain_[r]);
00130 
00131     for (CellIterator c=cells.begin(); c!=cells.end(); c++)
00132     {
00133       int cellLID = *c;
00134       cellLIDs[r].append(cellLID);
00135     }
00136     if (cellLIDs[r].size()==0) continue;
00137 
00138     // for each filter add to the cell the function (merge)
00139     for (int c=0; c<cellLIDs[r].size(); c++)
00140     {
00141       maxCellToFuncSetMap[cellLIDs[r][c]].merge(elemFuncSetsDomain_[r]);
00142     }
00143     // add for each function the cell filter where it is defined
00144     Array<Array<int> > elemFuncs = tuple(elemFuncSetsDomain_[r].elements());
00145     for (int i=0; i<elemFuncs[0].size(); i++)
00146     {
00147       funcDomains_[elemFuncs[0][i]] = funcDomains_[elemFuncs[0][i]] + maxSubdomains_[r];
00148     }
00149   }
00150 
00151   elemFuncSets_.resize(0);
00152   maxCellFuncSetsIndex_.resize(nMaxCell);
00153   Map<Set<int>, int> fsToFSIndexMap;
00154 
00155   SUNDANCE_MSG1(setupVerb, tab << " For each cell get the correct function combination ");
00156   /** for each cell store the index in the set array */
00157   for (int n=0; n<nMaxCell; n++)
00158   {
00159     const Set<int>& f = maxCellToFuncSetMap[n];
00160     if (f.size()==0) continue;
00161     int funcComboIndex;
00162     if (!fsToFSIndexMap.containsKey(f))
00163     {
00164       funcComboIndex = elemFuncSets_.size();
00165       fsToFSIndexMap.put(f, funcComboIndex);
00166       SUNDANCE_MSG2(setupVerb, " New combination found : " << f );
00167       elemFuncSets_.append(f);
00168       funcSetCellCount_.append(1);
00169     }
00170     else
00171     {
00172       funcComboIndex = fsToFSIndexMap.get(f);
00173       funcSetCellCount_[funcComboIndex]++;
00174     }
00175     SUNDANCE_MSG2(setupVerb, " CellLID: "<< n << " combiIndex:" << funcComboIndex << " , function set: "<< f );
00176     maxCellFuncSetsIndex_[n] = funcComboIndex;
00177   }
00178   SUNDANCE_MSG1(setupVerb, tab << " END deal with inhomogeneity variables ");
00179 // ---------- END DEAL WITH INHOMOGENITY ---------------
00180 
00181   Sundance::Map<OrderedHandle<BasisDOFTopologyBase>, int> basisToChunkMap;
00182   Array<RCP<BasisDOFTopologyBase> > chunkBases;
00183   Array<Array<int> > chunkFuncs;
00184   
00185   int chunk = 0;
00186   int nBasis = basis.size();
00187   basis_.resize(nBasis);
00188 
00189   nPoints_ = mesh.numCells(0);
00190   // this must be satisfied
00191   //TEUCHOS_TEST_FOR_EXCEPTION( nrAllFuncs_ != nBasis , std::runtime_error,
00192   //   " nrAllFuncs_ != nBasis , nrAllFuncs_=" <<  nrAllFuncs_ << " , nBasis = " << nBasis );
00193   if ( nrAllFuncs_ < nBasis) nrAllFuncs_ = nBasis;
00194 
00195   for (int i=0; i<nBasis; i++)
00196   {
00197     OrderedHandle<BasisDOFTopologyBase> bh = basis[i];
00198     if (!basisToChunkMap.containsKey(bh))
00199     {
00200       chunkBases.append(basis[i]);
00201       basisToChunkMap.put(bh, chunk);
00202       chunkFuncs.append(tuple(i));
00203       basis_[chunk] = rcp_dynamic_cast<BasisFamilyBase>(basis[i]);
00204       chunk++;
00205     }
00206     else
00207     {
00208       int b = basisToChunkMap.get(bh);
00209       chunkFuncs[b].append(i);
00210     }
00211   }
00212   basis_.resize(chunk);
00213 
00214   // initialize the matrix store
00215   matrixStore_.init(chunk);
00216 
00217   Tabs tab1;
00218   SUNDANCE_MSG1(setupVerb, tab1 << "basis to chunk map = " << basisToChunkMap);
00219 
00220   structure_ = rcp(new MapStructure(basis.size(), chunkBases, chunkFuncs));
00221 
00222   nFuncs_.resize(chunkBases.size());
00223   for (int i=0; i<nFuncs_.size(); i++) 
00224     nFuncs_[i] = chunkFuncs[i].size();
00225 
00226   allocate(mesh);
00227 
00228   initMap();
00229 
00230   buildMaximalDofTable();
00231 
00232   SUNDANCE_MSG1(setupVerb, tab << "done building mixed HN DOF map");
00233 
00234 }
00235 
00236 
00237 void InhomogeneousDOFMapHN::allocate(const Mesh& mesh)
00238 {
00239   Tabs tab;
00240 
00241   /* gather functions into chunks sharing identical basis functions */
00242   SUNDANCE_MSG1(setupVerb(),tab << "InhomogeneousDOFMapHN::allocate() grouping like basis functions");
00243 
00244   /* now that we know the number of basis chunks, allocate arrays */
00245   localNodePtrs_.resize(nBasisChunks());
00246   nNodesPerCell_.resize(nBasisChunks());
00247   nDofsPerCell_.resize(nBasisChunks());
00248   maximalDofs_.resize(mesh.numCells(dim_));
00249   totalNNodesPerCell_.resize(nBasisChunks());
00250 
00251   for (int b=0; b<nBasisChunks(); b++)
00252   {
00253     localNodePtrs_[b].resize(mesh.spatialDim()+1);
00254     nNodesPerCell_[b].resize(mesh.spatialDim()+1);
00255     nDofsPerCell_[b].resize(mesh.spatialDim()+1);
00256     totalNNodesPerCell_[b].resize(mesh.spatialDim()+1);
00257   }
00258 
00259   /* compute node counts for each cell dimension and each basis type */
00260   SUNDANCE_MSG1(setupVerb(),tab << "working out DOF map node counts");
00261   
00262   numFacets_.resize(dim_+1);
00263   isElementHanging_.resize(dim_+1);
00264   hasCellHanging_.resize(mesh.numCells(dim_),false);
00265 
00266   /* allocate the maximal dof array */
00267   for (int i = 0 ; i < mesh.numCells(dim_) ; i++){
00268     maximalDofs_[i].resize(nrAllFuncs_);
00269   }
00270 
00271 
00272   for (int d=0; d<=dim_; d++)
00273   {
00274     Tabs tab1;
00275     SUNDANCE_MSG1(setupVerb(),tab << "allocating maps for cell dim=" << d);
00276     /* record the number of facets for each cell type so we're
00277      * not making a bunch of mesh calls */
00278     numFacets_[d].resize(d);
00279 
00280     for (int fd=0; fd<d; fd++) numFacets_[d][fd]=mesh.numFacets(d, 0, fd);
00281     SUNDANCE_MSG1(setupVerb(),tab1 << "num facets for dimension " << d << " is "
00282       << numFacets_[d]);
00283 
00284     cellHasAnyDOFs_[d] = false;
00285 
00286     int numCells = mesh.numCells(d);
00287     hasBeenAssigned_[d].resize(numCells);
00288     dofs_[d].resize(numCells);
00289     funcDefined_[d].resize(nrAllFuncs_);
00290 
00291     // set the arrays which show which element is hanging or cell has hanging DoFs
00292     isElementHanging_[d].resize(numCells,false);
00293     for (int c=0; c<numCells; c++) { isElementHanging_[d][c] = false; }
00294     if (d == dim_){
00295       for (int c=0; c<numCells; c++) { hasCellHanging_[c] = false; }
00296     }
00297 
00298     /* allocate the DOFs array for this dimension */
00299     for (int i = 0 ; i < numCells ; i++){
00300       dofs_[d][i].resize(nrAllFuncs_);
00301     }
00302     for (int f = 0 ; f < nrAllFuncs_ ; f++){
00303     funcDefined_[d][f].resize( numCells , 0 );
00304     }
00305 
00306     for (int b=0; b<nBasisChunks(); b++)
00307     {
00308       Tabs tab2;
00309       SUNDANCE_MSG2(setupVerb(),tab1 << "basis chunk=" << b);
00310       SUNDANCE_MSG2(setupVerb(),tab2 << "basis=" << basis(b)->description());
00311       int nNodes = basis(b).ptr()->nReferenceDOFsWithFacets(mesh.cellType(dim_), mesh.cellType(d));
00312       SUNDANCE_MSG2(setupVerb(),tab2 << "nNodes per cell=" << nNodes);
00313       if (nNodes == 0)
00314       {
00315         nNodesPerCell_[b][d] = 0;
00316         nDofsPerCell_[b][d] = 0;
00317       }
00318       else
00319       {
00320         /* look up the node pointer for this cell and for all of its
00321          * facets */
00322         basis(b).ptr()->getReferenceDOFs(mesh.cellType(dim_),
00323           mesh.cellType(d),  localNodePtrs_[b][d]);
00324               
00325         SUNDANCE_MSG3(setupVerb(),tab2 << "node ptrs are "
00326           << localNodePtrs_[b][d]);
00327               
00328         /* with the node pointers in hand, we can work out the number
00329          * of nodes per cell in this dimension for this basis */
00330         if (localNodePtrs_[b][d][d].size() > 0) 
00331         {
00332           nNodesPerCell_[b][d] = localNodePtrs_[b][d][d][0].size();
00333           if (nNodesPerCell_[b][d] > 0) cellHasAnyDOFs_[d] = true;
00334         }
00335         else
00336         {
00337           nNodesPerCell_[b][d] = 0;
00338         }
00339         nDofsPerCell_[b][d] = nNodesPerCell_[b][d];
00340       }
00341 
00342       /* if the cell is of intermediate dimension and it has DOFs, we
00343        * need to assign GIDs for the cells of this dimension. Otherwise,
00344        * we can skip intermediate GID assignment, saving some parallel
00345        * communication */
00346       if (nDofsPerCell_[b][d] > 0 && d > 0 && d < mesh.spatialDim())
00347       {
00348         Mesh& tmpMesh = const_cast<Mesh&>(mesh);
00349         tmpMesh.assignIntermediateCellGIDs(d);
00350       }
00351       SUNDANCE_MSG3(setupVerb(),tab2 << "num nodes is "  << nNodesPerCell_[b][d]);
00352 
00353       totalNNodesPerCell_[b][d] = nNodesPerCell_[b][d];
00354       for (int dd=0; dd<d; dd++)
00355       {
00356         totalNNodesPerCell_[b][d]
00357           += numFacets_[d][dd]*nNodesPerCell_[b][dd];
00358       }
00359       SUNDANCE_MSG3(setupVerb(),tab2 << "totalNNodesPerCell_[b][d] " << totalNNodesPerCell_[b][d]);
00360     }
00361 
00362     /* allocate the array of original facet orientations */
00363     if (d > 0 && d < dim_) 
00364     {
00365       originalFacetOrientation_[d-1].resize(numCells);
00366     }
00367 
00368   } // end from dimension loop
00369 
00370   SUNDANCE_MSG1(setupVerb(),tab << "done allocating DOF map");
00371 }
00372 
00373 void InhomogeneousDOFMapHN::initMap()
00374 {
00375   Tabs tab;
00376   SUNDANCE_MSG1(setupVerb(),tab << "InhomogeneousDOFMapHN::initMap() initializing DOF map");
00377   /* start the DOF count at zero. */
00378   int nextDOF = 0;
00379 
00380   /* Space in which to keep a list of remote cells needed by each processor
00381    * for each dimension. The first index is dimension, the second proc, the
00382    * third cell number. */
00383   Array<Array<Array<int> > > remoteCells(mesh().spatialDim()+1);
00384   Array<int> functionValid(nrAllFuncs_);
00385 
00386   for (int d=0; d<remoteCells.size(); d++) 
00387     remoteCells[d].resize(mesh().comm().getNProc());
00388 
00389   int nrMaxCell = mesh().numCells(dim_);
00390 
00391   // first we set the "funcDefined_" variable which shows at each element which function
00392   // is defined and which is not
00393   SUNDANCE_MSG1(setupVerb(),tab << " starting detetecting which cell has which functions");
00394   for (int cellLID = 0; cellLID < nrMaxCell ; cellLID++)
00395   {
00396     Tabs tab2;
00397     for (int nrf=0; nrf < nrAllFuncs_ ; nrf++) functionValid[nrf] = 0;
00398 
00399     const Set<int>& functs = elemFuncSets_[maxCellFuncSetsIndex_[cellLID]];
00400 
00401     SUNDANCE_MSG1(setupVerb() , tab2 << " maxCell LID:" << cellLID << " has functions:" << functs);
00402     // here we store on this maxCell which functions are defined
00403     for (int nrf=0; nrf < nrAllFuncs_ ; nrf++) {
00404          if (functs.contains(nrf)){
00405            functionValid[nrf] = 1;
00406            funcDefined_[dim_][nrf][cellLID] = 1;
00407            SUNDANCE_MSG1(setupVerb() , tab2 << " functionID:" << nrf << " added to function set" );
00408          } else {
00409            //funcDefined_[dim_][nrf][cellLID] = 0;
00410            SUNDANCE_MSG1(setupVerb() , tab2 << " functionID:" << nrf << " is not defined on this cell" );
00411          }
00412     }
00413 
00414     // mark all the facets that they have also the functions which the maxcell has
00415     for (int d=0; d<dim_; d++)
00416     {
00417         int nf = numFacets_[dim_][d];
00418         Array<int> facetLID(nf);
00419         Array<int> facetOrientations(nf);
00420         // look up the LIDs of the facets
00421         mesh().getFacetArray(dim_, cellLID, d,  facetLID, facetOrientations);
00422 
00423         // for each facet, process its DOFs
00424         for (int f=0; f<nf; f++)
00425         {
00426           for (int nrf=0; nrf < nrAllFuncs_ ; nrf++){
00427            SUNDANCE_MSG1(setupVerb() , tab2 << " dim:" << d << " facetLID:" << facetLID[f]
00428                              << " functionID:" << nrf << " is defined:" << functionValid[nrf]);
00429             if (functionValid[nrf] == 1) {
00430               funcDefined_[d][nrf][facetLID[f]] = 1;
00431             } else {
00432               //funcDefined_[d][nrf][facetLID[f]] = 0;
00433             }
00434           }
00435         }
00436     }
00437   } // end of cell iteration
00438   
00439 
00440   /* we run trough each cell and for each element we test which functions have DOFs */
00441   for (int cellLID = 0; cellLID < nrMaxCell ; cellLID++)
00442   {
00443     int owner;
00444     if (cellHasAnyDOFs_[dim_])
00445     {
00446       /* if the maximal cell is owned by another processor,
00447        * put it in the list of cells for which we need to request 
00448        * DOF information from another processor */
00449       if (isRemote(dim_, cellLID, owner))
00450       {
00451       // cells can not be hanging
00452         int cellGID = mesh().mapLIDToGID(dim_, cellLID);
00453         SUNDANCE_MSG4(setupVerb(),"proc=" << comm().getRank()
00454           << " thinks d-" << dim_ 
00455           << " cell GID=" << cellGID
00456           << " is owned remotely by p=" 
00457           << owner);
00458         remoteCells[dim_][owner].append(cellGID); 
00459       }
00460       else /* the cell is locally owned, so we can 
00461             * set its DOF numbers now */
00462       {
00463         for (int nrf=0; nrf < nrAllFuncs_ ; nrf++)
00464         {
00465           // assign DoFs in the interior of the cell
00466           // we try to assign DoFs to all functions i nthis cell
00467           setDOFs(nrf, dim_, cellLID, nextDOF);
00468         }
00469       }
00470     }
00471 
00472     /* Now assign any DOFs associated with the facets. */
00473     for (int d=0; d<dim_; d++)
00474     {
00475       if (cellHasAnyDOFs_[d])
00476       {
00477         int nf = numFacets_[dim_][d];
00478         Array<int> facetLID(nf);
00479         Array<int> facetOrientations(nf);
00480         // look up the LIDs of the facets
00481 
00482         mesh().getFacetArray(dim_, cellLID, d,  facetLID, facetOrientations);
00483 
00484         // for each facet, process its DOFs
00485         for (int f=0; f<nf; f++)
00486         {
00487           // if the facet's DOFs have been assigned already, we're done
00488           if (!hasBeenAssigned(d, facetLID[f]))
00489           {
00490             markAsAssigned(d, facetLID[f]);
00491             // the facet may be owned by another processor, if the facet is hanging element then not
00492             if ( isRemote(d, facetLID[f], owner) && (!mesh().isElementHangingNode(d,facetLID[f])))
00493             {
00494               int facetGID 
00495                 = mesh().mapLIDToGID(d, facetLID[f]);
00496               SUNDANCE_MSG4(setupVerb(),"proc=" << comm().getRank()
00497                 << " thinks d-" << d 
00498                 << " cell GID=" << facetGID
00499                 << " is owned remotely by p=" << owner);
00500               remoteCells[d][owner].append(facetGID);
00501             }
00502             else // we can assign a DOF locally
00503             {
00504               // assign DOF
00505               for (int nrf=0; nrf < nrAllFuncs_ ; nrf++)
00506               {
00507                 // we try assign DoFs for all functions
00508                 setDOFs( nrf , d, facetLID[f], nextDOF);
00509               }
00510               // record the orientation wrt the maximal cell
00511               if (d > 0) 
00512               {
00513                 originalFacetOrientation_[d-1][facetLID[f]] 
00514                   = facetOrientations[f];
00515               }
00516             }
00517           } // end from the hasbeedAssigned
00518         }
00519       }
00520     }
00521   }
00522 
00523   /* Done with first pass, in which we have assigned DOFs for all
00524    * local processors. We now have to share DOF information between
00525    * processors */
00526 
00527   int numLocalDOFs = nextDOF;
00528   if (mesh().comm().getNProc() > 1)
00529   {
00530     for (int d=0; d<=dim_; d++)
00531     {
00532       if (cellHasAnyDOFs_[d])
00533       {
00534         computeOffsets(d, numLocalDOFs);
00535         shareDOFs(d, remoteCells[d]);
00536       }
00537     }
00538   }
00539   else
00540   {
00541     setLowestLocalDOF(0);
00542     setNumLocalDOFs(numLocalDOFs);
00543     setTotalNumDOFs(numLocalDOFs);
00544   }
00545   SUNDANCE_MSG1(setupVerb(),tab << "done initializing DOF map , numLocalDOFs:" << numLocalDOFs);
00546 }
00547 
00548 
00549 void InhomogeneousDOFMapHN::setDOFs(int funcID, int cellDim, int cellLID,
00550   int& nextDOF, bool isRemote)
00551 {
00552   int basisChunk = chunkForFuncID(funcID);
00553   int nDofs = nDofsPerCell_[basisChunk][cellDim];
00554   if (nDofs==0) return;
00555 
00556   Tabs tab;
00557   SUNDANCE_MSG4(setupVerb(),tab << "setting DOFs for " << cellDim
00558     << "-cell " << cellLID <<  " , basisChunk:" << basisChunk <<" , nDofs:" <<nDofs << " , nextDOF:" << nextDOF
00559     << " , def:" << funcDefined_[cellDim][funcID][cellLID]);
00560 
00561   // this means the function is not defined on this element
00562   // so just resize the vector to zero
00563   if (funcDefined_[cellDim][funcID][cellLID] <= 0){
00564     SUNDANCE_MSG4(setupVerb(),tab << "No DOFs defined on dim:" << cellDim << "-cell " << cellLID << " funcID:" << funcID);
00565     dofs_[cellDim][cellLID][funcID].resize(0);
00566     return;
00567   }
00568 
00569   // resize the dofs_ to the number of DoFs of this function on this element
00570   dofs_[cellDim][cellLID][funcID].resize(nDofs,-1);
00571   int* ptr = getInitialDOFPtrForCell(cellDim, cellLID, funcID );
00572 
00573   // display the size of that part of the dofs_ array
00574   //SUNDANCE_MSG1(setupVerb(), " dofs_[cellDim][cellLID][funcID].size(): " << dofs_[cellDim][cellLID][funcID].size() );
00575 
00576   if (isRemote)
00577   {
00578   // for remote nodes where one function does not exist we'll get -1, in this case do nothing and exit
00579   if ( nextDOF < 0 ) return;
00580 
00581   if (mesh().isElementHangingNode(cellDim, cellLID)){
00582     isElementHanging_[cellDim][cellLID] = true;
00583     for (int i=0; i<nDofs; i++) {//hanging cell, no global DoF
00584       ptr[i] = -1;
00585     }
00586   }
00587   else
00588   {  // not hanging cell
00589     for (int i=0; i<nDofs; i++, nextDOF++){
00590       ptr[i] = nextDOF;
00591       addGhostIndex(nextDOF);
00592     }
00593   }
00594   }
00595   else
00596   {
00597   if (mesh().isElementHangingNode(cellDim, cellLID)){
00598     isElementHanging_[cellDim][cellLID] = true;
00599     for (int i=0; i<nDofs; i++) {//hanging cell, no global DoF
00600       //SUNDANCE_MSG1(setupVerb()," cellDim:" << cellDim << ",cellLID:" << cellLID << ",basisChunk:" << basisChunk << "  ELEM HANGING");
00601       ptr[i] = -1;
00602     }
00603   }
00604   else
00605   {  // not hanging DoF
00606     for (int i=0; i<nDofs; i++,nextDOF++) {
00607       //SUNDANCE_MSG1(setupVerb()," cellDim:" << cellDim << ",cellLID:" << cellLID << ",basisChunk:" << basisChunk << "  dof:" << nextDOF);
00608       //SUNDANCE_MSG1(setupVerb()," ptr[i]:" << ptr[i] );
00609       ptr[i] = nextDOF;
00610     }
00611   }
00612   }
00613 }
00614 
00615 
00616 
00617 void InhomogeneousDOFMapHN::shareDOFs(int cellDim,
00618   const Array<Array<int> >& outgoingCellRequests)
00619 {
00620 
00621   int np = mesh().comm().getNProc();
00622   int rank = mesh().comm().getRank();
00623 
00624   Array<Array<int> > incomingCellRequests;
00625   Array<Array<int> > outgoingDOFs(np);
00626   Array<Array<int> > incomingDOFs;
00627 
00628   SUNDANCE_MSG2(setupVerb(),
00629     "InhomogeneousDOFMapHN::shareDOFs , p=" << mesh().comm().getRank()
00630     << "synchronizing DOFs for cells of dimension " << cellDim);
00631   SUNDANCE_MSG2(setupVerb(),
00632     "p=" << mesh().comm().getRank()
00633     << " sending cell reqs d=" << cellDim << " GID=" << outgoingCellRequests);
00634 
00635   // share the cell requests
00636   MPIContainerComm<int>::allToAll(outgoingCellRequests, 
00637     incomingCellRequests,
00638     mesh().comm());
00639   
00640   // we send the following information in response:
00641    // (1) The first DOF for each chunk for the requested cell
00642    // (2) The orientation if the cell is an edge or face
00643 
00644   int blockSize = 0;
00645   bool sendOrientation = false;
00646   for (int b=0; b<nBasisChunks(); b++)
00647   {
00648   // here we have to sum up all the functions which are defined
00649   int nDofs = nDofsPerCell_[b][cellDim];
00650   // per chunck we have to transmit all the functions DoFs (some might not exist)
00651   if (nDofs > 0) blockSize = blockSize + nFuncs(b);
00652   if (nDofs > 1 && cellDim > 0 && cellDim < dim_) sendOrientation = true;
00653   }
00654   blockSize += sendOrientation;
00655 
00656   SUNDANCE_MSG2(setupVerb(),
00657     "p=" << rank
00658     << "recvd DOF requests for cells of dimension " << cellDim
00659     << " GID=" << incomingCellRequests);
00660 
00661   // get orientations and DOF numbers for the first node of every cell that's been
00662   //  requested by someone else
00663   for (int p=0; p<np; p++)
00664   {
00665     if (p==rank) continue;
00666     const Array<int>& requestsFromProc = incomingCellRequests[p];
00667     int nReq = requestsFromProc.size();
00668 
00669     SUNDANCE_MSG4(setupVerb(),"p=" << mesh().comm().getRank()
00670       << " recv'd from proc=" << p
00671       << " reqs for DOFs for cells " 
00672       << requestsFromProc);
00673 
00674     outgoingDOFs[p].resize(nReq * blockSize);
00675 
00676     for (int c=0; c<nReq; c++)
00677     {
00678       int GID = requestsFromProc[c];
00679       SUNDANCE_MSG3(setupVerb(),
00680         "p=" << rank
00681         << " processing cell with d=" << cellDim 
00682         << " GID=" << GID << " nReq=" << nReq << " , blockSize=" << blockSize);
00683       int LID = mesh().mapGIDToLID(cellDim, GID);
00684       SUNDANCE_MSG3(setupVerb(),
00685         "p=" << rank
00686         << " LID=" << LID << " dofs=" << dofs_[cellDim][LID]);
00687       int blockOffset = 0;
00688       for (int b=0; b<nBasisChunks(); b++)
00689       {
00690         if (nDofsPerCell_[b][cellDim] <= 0) continue;
00691         for (int funcI = 0 ; funcI < nFuncs(b) ; funcI++){
00692           // get the first function ID from this chunk
00693           int funcID = getfuncID( b , funcI );
00694       //assign value only if the function is defined, -1 otherwise
00695           //SUNDANCE_MSG3(setupVerb(), "Getting DoF for b="<<b<<", funcI="<< funcI <<
00696           //    ", funcID=" << funcID << " is defined:" << funcDefined_[cellDim][funcID][LID]);
00697       if (funcDefined_[cellDim][funcID][LID] > 0){
00698         outgoingDOFs[p][blockSize*c+blockOffset]
00699                         = getInitialDOFForCell(cellDim, LID, funcID );
00700       } else {
00701         outgoingDOFs[p][blockSize*c+blockOffset] = -1;
00702       }
00703             // increase the blockoffset
00704       blockOffset++;
00705         }
00706       }
00707       // add the orientation
00708       if (sendOrientation)
00709       {
00710         outgoingDOFs[p][blockSize*(c+1) - 1] 
00711           = originalFacetOrientation_[cellDim-1][LID];
00712       }
00713       SUNDANCE_MSG3(setupVerb(),
00714         "p=" << rank
00715         << " done processing cell with GID=" << GID);
00716     }
00717   }
00718  
00719 
00720   SUNDANCE_MSG2(setupVerb(),
00721     "p=" << mesh().comm().getRank()
00722     << "answering DOF requests for cells of dimension " << cellDim);
00723 
00724   // share the DOF numbers
00725   MPIContainerComm<int>::allToAll(outgoingDOFs,
00726     incomingDOFs,
00727     mesh().comm());
00728 
00729   SUNDANCE_MSG2(setupVerb(),
00730     "p=" << mesh().comm().getRank()
00731     << "communicated DOF answers for cells of dimension " << cellDim );
00732 
00733   SUNDANCE_MSG2(setupVerb(), "My rank:" << mesh().comm().getRank() << ",  nr. Proc:" << mesh().comm().getNProc());
00734   
00735   // now assign the DOFs from the other procs
00736   for (int p=0; p<mesh().comm().getNProc(); p++)
00737   {
00738   SUNDANCE_MSG3(setupVerb(), "Test p="<<p);
00739     if (p==mesh().comm().getRank()) continue;
00740 
00741     const Array<int>& dofsFromProc = incomingDOFs[p];
00742     int numCells = dofsFromProc.size()/blockSize;
00743 
00744     //
00745   //SUNDANCE_MSG3(setupVerb(), "Setting from p="<<p<<", GID="<< outgoingCellRequests[p]);
00746   //SUNDANCE_MSG3(setupVerb(), "received from p="<<p<<", dofsFromProc="<< dofsFromProc);
00747 
00748     for (int c=0; c<numCells; c++)
00749     {
00750       int cellGID = outgoingCellRequests[p][c];
00751       int cellLID = mesh().mapGIDToLID(cellDim, cellGID);
00752       int blockOffset = 0;
00753       for (int b=0; b<nBasisChunks(); b++)
00754       {
00755         if (nDofsPerCell_[b][cellDim] == 0) continue;
00756         for (int funcI = 0 ; funcI < nFuncs(b) ; funcI++){
00757           // get the first function ID from this chunk
00758           int funcID = getfuncID( b , funcI );
00759           int dof = dofsFromProc[blockSize*c+blockOffset];
00760           // set the recieved DoF
00761           SUNDANCE_MSG3(setupVerb(), "Set DoF b="<<b<<", funcI="<< funcI <<
00762               ", funcID=" << funcID << " is defined:" << funcDefined_[cellDim][funcID][cellLID] <<
00763                " dof=" << dof );
00764           setDOFs(funcID, cellDim, cellLID, dof, true);
00765           blockOffset++;
00766         }
00767       }
00768       if (sendOrientation) 
00769       {
00770         originalFacetOrientation_[cellDim-1][cellLID] 
00771           = dofsFromProc[blockSize*(c+1)-1];
00772       }
00773     }
00774   }
00775 }
00776 
00777 
00778 RCP<const MapStructure> InhomogeneousDOFMapHN
00779 ::getDOFsForCellBatch(int cellDim,
00780   const Array<int>& cellLID,
00781   const Set<int>& requestedFuncSet,
00782   Array<Array<int> >& dofs,
00783   Array<int>& nNodes,
00784   int verbosity) const 
00785 {
00786   TimeMonitor timer(batchedDofLookupTimer());
00787 
00788   Tabs tab;
00789   //verbosity = 6;
00790   SUNDANCE_MSG2(verbosity,
00791     tab << "getDOFsForCellBatch(): cellDim=" << cellDim
00792     << " cellLID=" << cellLID);
00793 
00794 
00795   int nCells = cellLID.size();
00796   // the requested function elements
00797   Array<int> funcs = requestedFuncSet.elements();
00798   int nrReqFuncs = funcs.size();
00799   SUNDANCE_MSG2(verbosity, tab << "nrReqFuncs=" << nrReqFuncs << " functions requested:" << requestedFuncSet);
00800 
00801   dofs.resize(nBasisChunks());
00802   nNodes.resize(nBasisChunks());
00803 
00804   // here we specify which DoF to return at function places where
00805   // these values might be input for "ghostView_" object
00806   // as a dummy value this will be used, this dummy value should always exist
00807   // now we take first DoF which is local on the processor
00808   int DoFs_Non =  lowestLocalDOF()+1; //-1;
00809 
00810   if (cellDim == dim_)
00811   {
00812     Tabs tab1;
00813 
00814     SUNDANCE_MSG4(verbosity,tab1 << "getting dofs for maximal cells : " << cellLID );
00815 
00816     for (int b = 0 ; b < nBasisChunks() ; b++)
00817     {
00818       // set the value and resize the dof array
00819       nNodes[b] = totalNNodesPerCell_[ b ][cellDim];
00820       // resize the array with, and put dummy DoFs in the array
00821       dofs[b].resize( nNodes[b]* nFuncs(b) * nCells );
00822       for (int tmpI = 0; tmpI < nNodes[b]* nFuncs(b) * nCells ; tmpI++)
00823         dofs[b][tmpI] = DoFs_Non;
00824     }
00825 
00826     for (int b = 0; b < nBasisChunks() ; b++)
00827     {
00828      for (int funcI = 0; funcI < nFuncs(b) ; funcI++)
00829      {
00830       //int b = chunkForFuncID(nfc);
00831       //int func = indexForFuncID(nfc);
00832       int funcID = getfuncID(b , funcI );
00833 
00834       int nrFunc = nFuncs(b);
00835       int dofsPerCell = nNodes[b];
00836       Array<int>& chunkDofs = dofs[b];
00837       // for each cell just copy the DoFs of this function
00838       for (int c=0; c<nCells; c++)
00839       {
00840       // if the function is not defined then skip this cell
00841         if (funcDefined_[cellDim][funcID][cellLID[c]] <= 0) {
00842             SUNDANCE_MSG3(verbosity,tab << " Skip this cell since function is not defined on this cell:" << cellLID[c]);
00843           continue;
00844         }
00845 
00846         for (int i=0; i<dofsPerCell; i++)
00847         {
00848           // copy the values from the "maximalDofs_" into the target array
00849           //SUNDANCE_MSG3(verbosity,tab1 << "i:" << i << " , fi:" << fi << ", funcs[fi]:" << funcs[fi]);
00850           chunkDofs[c*dofsPerCell*nrFunc + dofsPerCell*funcI + i]
00851             = maximalDofs_[cellLID[c]][funcID][i];
00852         }
00853       }
00854       SUNDANCE_MSG3(verbosity,tab1 << "dofs for chunk-" << b << " , funcI:" << funcI << " :" << chunkDofs);
00855      }// end function index in chunk
00856     }
00857   }
00858   else
00859   {
00860     Tabs tab1;
00861     SUNDANCE_MSG3(verbosity,tab1 << "getting dofs for non-maximal cells");
00862   
00863     static Array<Array<int> > facetLID(3);
00864     static Array<Array<int> > facetOrientations(3);
00865     static Array<int> numFacets(3);
00866 
00867     for (int d=0; d<cellDim; d++) 
00868     {
00869       numFacets[d] = mesh().numFacets(cellDim, cellLID[0], d);
00870       mesh().getFacetLIDs(cellDim, cellLID, d, facetLID[d], 
00871         facetOrientations[d]);
00872     }
00873 
00874   // set the value and resize the dof array
00875     for (int b = 0 ; b < nBasisChunks() ; b++)
00876     {
00877       nNodes[b] = totalNNodesPerCell_[b][cellDim];
00878       // resize the array with, and put dummy DoFs in the array
00879       dofs[b].resize( nNodes[b]* nFuncs(b) * nCells , -1);
00880       for (int tmpI = 0; tmpI < nNodes[b]* nFuncs(b) * nCells ; tmpI++)
00881         dofs[b][tmpI] = DoFs_Non;
00882     }
00883 
00884     // for each function that has been requested
00885     for (int b = 0; b < nBasisChunks() ; b++)
00886     {
00887      for (int funcI = 0; funcI < nFuncs(b) ; funcI++)
00888      {
00889       //int b = chunkForFuncID(nfc);
00890       //int func = indexForFuncID(nfc);
00891       int funcID = getfuncID(b , funcI );
00892       int nrFunc = nFuncs(b); //mapFunctions[b_r].size();
00893       int dofsPerCell = nrFunc*nNodes[b];
00894           
00895       Array<int>& toPtr = dofs[b];
00896 
00897       for (int c=0; c<nCells; c++)
00898       {
00899         Tabs tab2;
00900         SUNDANCE_MSG3(verbosity,tab2 << "cell=" << c << "    ,cellLID[c]:" << cellLID[c]);
00901         int offset = dofsPerCell*c;
00902 
00903       // if the function is not defined then skip this cell
00904         if (funcDefined_[cellDim][funcID][cellLID[c]] <= 0) {
00905             SUNDANCE_MSG3(verbosity,tab2 << " Skip this cell since function is not defined on this cell:" << cellLID[c]);
00906           continue;
00907         }
00908 
00909         // first get the DOFs for the nodes associated with
00910         // the cell's interior
00911         // nothing to do here for hanging DoFs, since no facet integration should occur with hanging DoF
00912         SUNDANCE_MSG3(verbosity,tab2 << "doing interior nodes");
00913         int nInteriorNodes = nNodesPerCell_[b][cellDim];
00914         if (nInteriorNodes > 0)
00915         {
00916           if (cellDim==0 || nInteriorNodes <= 1) // orientation-independent
00917           {
00918             for (int n=0; n<nInteriorNodes; n++)
00919             {
00920                 int ptr = localNodePtrs_[b][cellDim][cellDim][0][n];
00921                 toPtr[offset + funcI*nNodes[b] + ptr]
00922                   = dofs_[cellDim][cellLID[c]][funcID][n];
00923             }
00924           }
00925           else
00926           {
00927             int sign = originalFacetOrientation_[cellDim-1][cellLID[c]];
00928             int nInteriorNodes = localNodePtrs_[b][cellDim][cellDim][0].size();
00929 
00930             for (int m=0; m<nInteriorNodes; m++)
00931             {
00932                int n = m;
00933                if (sign<0) n = nInteriorNodes-1-m;
00934                int ptr = localNodePtrs_[b][cellDim][cellDim][0][m];
00935                toPtr[offset + funcI*nNodes[b] + ptr]
00936                  = dofs_[cellDim][cellLID[c]][funcID][n];
00937             }
00938           }
00939         } // end if interior nodes > 0
00940 
00941         // now do the facetsnInteriorNodes
00942         for (int d=0; d<cellDim; d++)
00943         {
00944           Tabs tab2;
00945           SUNDANCE_MSG3(verbosity,tab2 << "facet dim=" << d);
00946           if (nNodesPerCell_[b][d] == 0) continue;
00947           for (int f=0; f<numFacets[d]; f++)
00948           {
00949             Tabs tab3;
00950             int facetID = facetLID[d][c*numFacets[d]+f];
00951             SUNDANCE_MSG3(verbosity,tab2 << "f=" << f << " facetLID=" << facetID);
00952             if (localNodePtrs_[b][cellDim].size()==0) continue;
00953             int nFacetNodes = localNodePtrs_[b][cellDim][d][f].size();
00954             int* toPtr1 = &( dofs[b][dofsPerCell*c]);
00955             const int* nodePtr = &(localNodePtrs_[b][cellDim][d][f][0]);
00956 
00957             // hanging DoF can occure here only in 3D for 2D surf)
00958             if (d == 0 || nFacetNodes <= 1) // orientation-independent
00959             {
00960                 for (int n=0; n<nFacetNodes; n++)
00961                 {
00962                   int ptr = nodePtr[n];
00963                   toPtr1[funcI*nNodes[b] + ptr] = dofs_[d][facetID][funcID][n];
00964 
00965                   // if this is negative , then we have to correct it
00966                   if (toPtr1[funcI*nNodes[b] + ptr] < 0 )
00967                   {
00968                     int fIndex = 1 , tmp1 = 1;
00969                     // get any cell which has this element
00970                     int maxCell = mesh().maxCofacetLID( cellDim , cellLID[c] , 0 , fIndex);
00971                       Array<int> facetsLIDs;
00972                       mesh().returnParentFacets( maxCell , d , facetsLIDs , tmp1 );
00973                       // return the parent facet at the same index
00974                       //SUNDANCE_MSG3(verbosity,tab2 << "f=" << f << " facetLID=" << facetID << " replaced by facetsLIDs[fIndex]:" << facetsLIDs[fIndex]);
00975                       toPtr1[funcI*nNodes[b] + ptr] = dofs_[d][facetsLIDs[fIndex]][funcID][n];
00976                    }
00977                 }
00978               }
00979               else // orientation-dependent
00980               {
00981                 int facetOrientation = facetOrientations[d][c*numFacets[d]+f]
00982                   * originalFacetOrientation_[d-1][facetID];
00983                 for (int m=0; m<nFacetNodes; m++)
00984                 {
00985                   int n = m;
00986                   if (facetOrientation<0) n = nFacetNodes-1-m;
00987                   int ptr = nodePtr[n];
00988                   toPtr1[funcI*nNodes[b] + ptr] = dofs_[d][facetID][funcID][n];
00989 
00990                   // if this is negative , then we have to correct it
00991                   if (toPtr1[funcI*nNodes[b]+ptr] < 0)
00992                   {
00993                     int fIndex = 1 , tmp1 = 1;
00994                     // get any cell which has this element
00995                     int maxCell = mesh().maxCofacetLID( cellDim , cellLID[c] , 0 , fIndex);
00996                       Array<int> facetsLIDs;
00997                       mesh().returnParentFacets( maxCell , d , facetsLIDs , tmp1 );
00998                       // return the parent facet at the same index
00999                       //SUNDANCE_MSG3(verbosity,tab2 << "f=" << f << " facetLID=" << facetID << " replaced by facetsLIDs[fIndex]:" << facetsLIDs[fIndex]);
01000                       toPtr1[funcI*nNodes[b] + ptr] = dofs_[d][facetsLIDs[fIndex]][funcID][n];
01001                    }
01002                 }
01003               } // orientation dependent branch
01004           } // end loop over facets
01005         } // end loop of the facets of the facet
01006       } // end loop over cells
01007       SUNDANCE_MSG3(verbosity,tab1 << "dofs for chunk-" << b << " , dofs[b]:" << dofs[b]);
01008      } // end loop over functions in chunk
01009     } // end loop over chunks
01010   } // else branch from the facet case
01011   //*/
01012 
01013   return structure_;
01014   // return the structure which was created at the beginning
01015   //return rtn;
01016 }    
01017 
01018 void InhomogeneousDOFMapHN::buildMaximalDofTable()
01019 {
01020   TimeMonitor timer(maxDOFBuildTimer());
01021   Tabs tab;
01022   int cellDim = dim_;
01023   int nCells = mesh().numCells(dim_);
01024 
01025   SUNDANCE_MSG1(setupVerb(),tab << "building dofs for maximal cells");
01026 
01027   Array<Array<int> > facetLID(3);
01028   Array<Array<int> > facetOrientations(3);
01029   Array<int> numFacets(3);
01030 
01031   Array<int> cellLID(nCells);
01032 
01033   // set up the array of the cell LIDs,
01034   for (int c=0; c<nCells; c++) cellLID[c]=c;
01035   
01036   // get the facets and the number of facets
01037   for (int d=0; d<cellDim; d++) 
01038   {
01039     numFacets[d] = mesh().numFacets(cellDim, cellLID[0], d);
01040     mesh().getFacetLIDs(cellDim, cellLID, d, 
01041       facetLID[d], facetOrientations[d]);
01042   }
01043 
01044   Array<int> nInteriorNodes(nBasisChunks());
01045   Array<int> nNodes(nBasisChunks());
01046   for (int b = 0; b<nBasisChunks(); b++)
01047   {
01048   // localNodePtrs_[basisChunk][cellDim][facetDim][facetNumber][nodeNumber]
01049     if (localNodePtrs_[b][cellDim].size() != 0)
01050     {
01051       nInteriorNodes[b] = localNodePtrs_[b][cellDim][cellDim][0].size();
01052     }
01053     else 
01054     {
01055       nInteriorNodes[b] = 0;
01056     }
01057     nNodes[b] = totalNNodesPerCell_[b][cellDim];
01058   }
01059 
01060 //--------------------- Loop over all cells -------------------------
01061 
01062   // List of global DoFs for each basis chunk and function nr
01063   Array<Array<int> > globalDoFs_Cell(nrAllFuncs_);
01064   // trafo matrix for each basis chunk
01065   Array<Array<double> > trafoMatrix(nBasisChunks());
01066   // the row in the traf matrix
01067   Array<int>    localDoFs;
01068   Array<int>    parentFacetDim;
01069   Array<int>    parentFacetIndex;
01070   Array<int>    parentFacetNode;
01071   Array<int>    retFacets;
01072   Array<double> coefs;
01073   int           maxCellLID;
01074 
01075 
01076   for (int c=0; c<nCells; c++)
01077   {
01078   maxCellLID = cellLID[c];
01079 
01080   // first for each cell we should find out is it has hanging elements
01081   // it is enough if we check the points if they are hanging
01082   for (int jj = 0 ; jj < numFacets[0] ; jj++){
01083     if (mesh().isElementHangingNode(0,facetLID[0][ c*numFacets[0] + jj])){
01084         //    if order > 0, but only for that basis ... (not as a cell)
01085         //       but even if we mark for this as a hanging it is OK
01086         hasCellHanging_[cellLID[c]] = true;
01087         break;
01088       }
01089   }
01090 
01091     Tabs tab1;
01092     SUNDANCE_MSG3(setupVerb(),tab1 << "working on cell=" << c
01093       << " LID=" << cellLID[c]);
01094     // first get the DOFs for the nodes associated with
01095     // the cell's interior
01096 
01097 
01098     SUNDANCE_MSG3(setupVerb(),tab1 << "doing interior nodes");
01099     for (int b = 0; b < nBasisChunks() ; b++)
01100     {
01101 
01102      SUNDANCE_MSG3(setupVerb(),tab1 << "basis chunk=" << b);
01103 
01104      // loop over each function in this chunk
01105      for (int func = 0; func < nFuncs(b) ; func++)
01106      {
01107       //int b = chunkForFuncID(nfc);
01108       //int func = indexForFuncID(nfc);
01109       int nfc = getfuncID(b , func );
01110 
01111       // Initialization for cells with hanging nodes we need to create
01112       if (hasCellHanging_[cellLID[c]]){
01113         // ----------- NH -------------
01114       if (func == 0){
01115         // do this only once for a chunk
01116         trafoMatrix[b].resize(nNodes[b]*nNodes[b], 0.0);
01117         for (int jj = 0; jj < nNodes[b]*nNodes[b] ; jj++) trafoMatrix[b][jj] = 0.0;
01118       }
01119 
01120         globalDoFs_Cell[nfc].resize(nNodes[b]);
01121         for (int kk = 0 ; kk < nNodes[b] ; kk++ ){
01122             globalDoFs_Cell[nfc][kk] = -1;
01123         }
01124       }
01125 
01126 
01127       // if on the maxcell the this function is not defined then skip this
01128       if (funcDefined_[dim_][nfc][maxCellLID] <= 0 ){
01129           SUNDANCE_MSG3(setupVerb(),tab1 << " function " << nfc << " , on this maxCell not defined: " << maxCellLID );
01130           maximalDofs_[maxCellLID][nfc].resize(0);
01131         continue;
01132       }
01133       else
01134       {   // in this case we resize the
01135           SUNDANCE_MSG3(setupVerb(),tab1 << " function " << nfc << " , is defined on maxCell : " << maxCellLID << " resize to:" << nNodes[b]);
01136         maximalDofs_[maxCellLID][nfc].resize(nNodes[b]);
01137       }
01138 
01139       if (nInteriorNodes[b]>0)
01140       {
01141       SUNDANCE_MSG3(setupVerb(),tab1<< "nInteriorNodes = " <<nInteriorNodes[b]);
01142         int* toPtr = &(maximalDofs_[maxCellLID][nfc][0]);
01143           for (int n=0; n<nInteriorNodes[b]; n++)
01144           {
01145           // copy all the interior nodes to the maximal Cell DOF map
01146           int ptr = localNodePtrs_[b][cellDim][cellDim][0][n];
01147 
01148             if (hasCellHanging_[cellLID[c]])
01149             {
01150               SUNDANCE_MSG1(setupVerb(), tab1 << "Cell has HDoF cellLID[c]=" << cellLID[c] );
01151               int dof_tmp = dofs_[cellDim][maxCellLID][nfc][n];
01152                 // dof_tmp can not be negative since it is inside the cell and can not be hanging
01153               //SUNDANCE_MSG1(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , globalDoFs_Cell[nfc][n]:"<<globalDoFs_Cell[nfc][n]<<" dof=" << dof_tmp);
01154               globalDoFs_Cell[nfc][ptr] = dof_tmp;
01155               //SUNDANCE_MSG1(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr <<" dof=" << dof_tmp);
01156                 if (func == 0){
01157                   trafoMatrix[b][nNodes[b]*ptr + ptr] = 1.0;
01158                 }
01159             }
01160             // internal nodes can not be hanging
01161             toPtr[ptr] = dofs_[cellDim][maxCellLID][nfc][n];
01162             //SUNDANCE_MSG1(setupVerb(), tab1 << " dof=" << dofs_[cellDim][maxCellLID][nfc][n];);
01163           }
01164       }
01165      } // end function in chunk
01166     }// end chunk
01167       
01168     SUNDANCE_MSG3(setupVerb(),tab1 << "doing facet nodes");
01169     // now get the DOFs for the nodes on the facets
01170     for (int d=0; d<cellDim; d++)
01171     {
01172       Tabs tab2;
01173       SUNDANCE_MSG3(setupVerb(),tab2 << "facet dim=" << d);
01174 
01175       for (int f=0; f<numFacets[d]; f++)
01176       {
01177         Tabs tab3;
01178         int facetID = facetLID[d][c*numFacets[d]+f];
01179         SUNDANCE_MSG3(setupVerb(),tab2 << "f=" << f << " facetLID=" << facetID);
01180 
01181         for (int b = 0; b < nBasisChunks() ; b++)
01182         {
01183          for (int func = 0; func < nFuncs(b) ; func++)
01184          {
01185           //int b = chunkForFuncID(nfc);
01186           //int func = indexForFuncID(nfc);
01187         int nfc = getfuncID(b , func );
01188 
01189           // if on the maxcell the this function is not defined then skip this
01190           if (funcDefined_[dim_][nfc][maxCellLID] <= 0 ){
01191               SUNDANCE_MSG3(setupVerb(),tab2 << " function= " << nfc << " , on this maxCell not defined: " << maxCellLID );
01192               continue;
01193           }
01194           else
01195           {
01196               SUNDANCE_MSG3(setupVerb(),tab2 << " function= " << nfc << " , is defined on maxcell: " << maxCellLID );
01197           }
01198           Tabs tab4;
01199           SUNDANCE_MSG3(setupVerb(),tab4 << "basis chunk=" << b);
01200           SUNDANCE_MSG3(setupVerb(),tab4 << "function index in  chunk=" << func);
01201           SUNDANCE_MSG3(setupVerb(),tab4 << "num nodes per cell=" << nNodesPerCell_[b][d]);
01202           if (nDofsPerCell_[b][d]==0) continue;
01203           int nFacetNodes = 0;
01204           if (localNodePtrs_[b][cellDim].size()!=0)
01205             nFacetNodes = localNodePtrs_[b][cellDim][d][f].size();
01206           if (nFacetNodes == 0) continue;
01207 
01208           SUNDANCE_MSG3(setupVerb(),tab4 << "dof table size=" << maximalDofs_[maxCellLID][nfc].size());
01209           // = maximalDofs_[LID][funcID][DoFIndex];
01210           int* toPtr = &(maximalDofs_[maxCellLID][nfc][0]);
01211           // localNodePtrs_[basisChunk][cellDim][facetDim][facetNumber][nodeNumber]
01212           const int* nodePtr = &(localNodePtrs_[b][cellDim][d][f][0]);
01213 
01214             Tabs tab5;
01215             SUNDANCE_MSG3(setupVerb(),tab5 << "func=" << func);
01216             if (d == 0 || nFacetNodes <= 1) // orientation-independent
01217             {
01218               Tabs tab6;
01219               for (int n=0; n<nFacetNodes; n++)
01220               {
01221               //SUNDANCE_MSG3(setupVerb(),tab5 << "n=" << n);
01222                 int ptr = nodePtr[n];
01223                 //SUNDANCE_MSG3(setupVerb(),tab6 << "ptr=" << ptr);
01224                 // = maximalDofs_[LID][funcID][DoFIndex];
01225               // = dofs_[cellDim][cellLID][funcID][node]
01226                 if (hasCellHanging_[cellLID[c]]){
01227                   int parentCellLID = 0;
01228                   int dof_tmp = dofs_[d][facetID][nfc][n];
01229                   //SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , d="<<d<<", f="<<f<<", n="<<n<<", dof=" << dof_tmp);
01230                     if (dof_tmp < 0){
01231                       Array<int> constFacetLID;
01232                       Array<int> constFacetDim;
01233                        // get the collaborating global DoFs, add the coefficients to the row of the trafo matrix (if func == 0)
01234                         basis_[b]->getConstrainsForHNDoF(
01235                           mesh().indexInParent(cellLID[c]), cellDim ,
01236                           mesh().maxChildren(), d , f , n,
01237                           localDoFs, parentFacetDim,
01238                           parentFacetIndex, parentFacetNode, coefs );
01239                         SUNDANCE_MSG3(setupVerb(), tab1 << " After  basis_[b]->getConstrainsForHNDoF:");
01240                         constFacetLID.resize(localDoFs.size());
01241                         constFacetDim.resize(localDoFs.size());
01242                         for (int indexi = 0 ; indexi < localDoFs.size() ; indexi++)
01243                         {
01244                             // localNodePtrs_[basisChunk][cellDim][facetDim][facetNumber][nodeNumber]
01245                           int ptr1 = localNodePtrs_[b][cellDim][parentFacetDim[indexi]]
01246                                       [parentFacetIndex[indexi]][parentFacetNode[indexi]];
01247                           // get the dof belonging to the parent cell
01248                           mesh().returnParentFacets(cellLID[c] , parentFacetDim[indexi], retFacets , parentCellLID );
01249                           int parFacetLID = retFacets[parentFacetIndex[indexi]];
01250                           int parFacetNode = parentFacetNode[indexi];
01251                           //SUNDANCE_MSG3(setupVerb(), tab1 << "returnParentFacets , parFacetLID=" << parFacetLID <<" parFacetNode=" << parFacetNode );
01252                           //SUNDANCE_MSG3(setupVerb(), tab1 << "returnParentFacets , retFacets=" << retFacets );
01253                           // store the facet LID and its index
01254                           constFacetDim[indexi] = parentFacetDim[indexi];
01255                           constFacetLID[indexi] = parFacetLID;
01256                           // set the DoF in the array, and add line to the
01257                           // = dofs_[cellDim][cellLID][funcID][node]
01258                           dof_tmp = dofs_[parentFacetDim[indexi]][parFacetLID][nfc][parFacetNode];
01259 
01260                           globalDoFs_Cell[nfc][ptr1] = dof_tmp;
01261 
01262                           //SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr << "ptr1=" << ptr1 <<" dof=" << dof_tmp);
01263               if (func == 0){
01264                 trafoMatrix[b][nNodes[b]*ptr + ptr1] = coefs[indexi];
01265               }
01266               //SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , DONE Fill");
01267                         }
01268                         //only for hanging points store the components
01269                         if ( (d == 0) && (func == 0)) {
01270                           HN_To_globalFacetsLID_.put( nPoints_*b + facetID , constFacetLID);
01271                           HN_To_globalFacetsDim_.put( nPoints_*b + facetID , constFacetDim);
01272                           HN_To_coeffs_.put( nPoints_*b + facetID , coefs);
01273                         }
01274                     }else {
01275                        // just put the DoF in the list , and in the matrix add one row (unit) (if func == 0)
01276                       SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr <<" dof=" << dof_tmp);
01277                         //SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , trafoMatrix[b].size()" <<
01278                           //  trafoMatrix[b].size() << ", nNodes[b]:" << nNodes[b]);
01279                         //SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , globalDoFs_Cell[nfc].size():" <<
01280                           //  globalDoFs_Cell[nfc].size() << ", globalDoFs_Cell[nfc].size():" << globalDoFs_Cell[nfc].size());
01281                       globalDoFs_Cell[nfc][ptr] = dof_tmp;
01282                         if (func == 0){
01283                           trafoMatrix[b][nNodes[b]*ptr + ptr] = 1.0;
01284                         }
01285                     }
01286                 } else {
01287                   // = dofs_[cellDim][cellLID][funcID][node]
01288                   toPtr[ptr] = dofs_[d][facetID][nfc][n];
01289                   //SUNDANCE_MSG3(setupVerb(), tab1 << " dof=" << dofs_[d][facetID][nfc][n] );
01290                 }
01291               }
01292             }
01293             else // orientation-dependent
01294             {
01295               int facetOrientation = facetOrientations[d][c*numFacets[d]+f]
01296                 * originalFacetOrientation_[d-1][facetID];
01297               for (int m=0; m<nFacetNodes; m++)
01298               {
01299                 int n = m;
01300                 if (facetOrientation<0) n = nFacetNodes-1-m; // this means we have to take the DoFs in reverse order
01301                 int ptr = nodePtr[m];
01302                 // = maximalDofs_[LID][funcID][DoFIndex];
01303               // = dofs_[cellDim][cellLID][funcID][node]
01304 
01305                 if (hasCellHanging_[cellLID[c]])
01306                 {
01307                   int parentCellLID = 0;
01308                   int dof_tmp = dofs_[d][facetID][nfc][n];
01309                   SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , d="<<d<<", f="<<f<<", n="<<n<<", dof=" << dof_tmp);
01310                     if (dof_tmp < 0){
01311                       Array<int> constFacetLID;
01312                       Array<int> constFacetDim;
01313                        // get the collaborating global DoFs, add the coefficients to the row of the trafo matrix (if func == 0)
01314                         basis_[b]->getConstrainsForHNDoF(
01315                           mesh().indexInParent(cellLID[c]), cellDim ,
01316                           mesh().maxChildren(), d , f , n,
01317                           localDoFs, parentFacetDim,
01318                           parentFacetIndex, parentFacetNode, coefs );
01319                         SUNDANCE_MSG3(setupVerb(), tab1 << " After  basis_[b]->getConstrainsForHNDoF:");
01320                         constFacetLID.resize(localDoFs.size());
01321                         constFacetDim.resize(localDoFs.size());
01322                         for (int indexi = 0 ; indexi < localDoFs.size() ; indexi++)
01323                         {
01324                             // localNodePtrs_[basisChunk][cellDim][facetDim][facetNumber][nodeNumber]
01325                           int ptr1 = localNodePtrs_[b][cellDim][parentFacetDim[indexi]]
01326                                       [parentFacetIndex[indexi]][parentFacetNode[indexi]];
01327                           // get the dof belonging to the parent cell
01328                           mesh().returnParentFacets(cellLID[c] , parentFacetDim[indexi], retFacets , parentCellLID );
01329                           int parFacetLID = retFacets[parentFacetIndex[indexi]];
01330                           int parFacetNode = parentFacetNode[indexi];
01331                           //SUNDANCE_MSG3(setupVerb(), tab1 << "returnParentFacets , parFacetLID=" << parFacetLID <<" parFacetNode=" << parFacetNode );
01332                           //SUNDANCE_MSG3(setupVerb(), tab1 << "returnParentFacets , retFacets=" << retFacets );
01333                           // store the facet LID and its index
01334                           constFacetDim[indexi] = parentFacetDim[indexi];
01335                           constFacetLID[indexi] = parFacetLID;
01336                           // set the DoF in the array, and add line to the
01337                             // = dofs_[cellDim][cellLID][funcID][node]
01338                             dof_tmp = dofs_[parentFacetDim[indexi]][parFacetLID][nfc][parFacetNode];
01339 
01340                           globalDoFs_Cell[nfc][ptr1] = dof_tmp;
01341 
01342                           //SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr1 <<" dof=" << dof_tmp);
01343               if (func == 0){
01344                 trafoMatrix[b][nNodes[b]*ptr + ptr1] = coefs[indexi];
01345               }
01346                         }
01347                         //only for hanging points store the components
01348                         if ( (d == 0) && (func == 0)) {
01349                           HN_To_globalFacetsLID_.put( nPoints_*b + facetID , constFacetLID);
01350                           HN_To_globalFacetsDim_.put( nPoints_*b + facetID , constFacetDim);
01351                           HN_To_coeffs_.put( nPoints_*b + facetID , coefs);
01352                         }
01353                     }else{
01354                        // just put the DoF in the list , and in the matrix add one row (unit) (if func == 0)
01355                         //returnInsertionPosition( globalDoFs_Cell[nfc] , dof_tmp , insertPos);
01356                       //SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr <<" dof=" << dof_tmp);
01357                       globalDoFs_Cell[nfc][ptr] = dof_tmp;
01358                         if (func == 0){
01359                           trafoMatrix[b][nNodes[b]*ptr + ptr] = 1.0;
01360                         }
01361                     }
01362                 } else {
01363                     // = dofs_[cellDim][cellLID][funcID][node]
01364                     toPtr[ptr] = dofs_[d][facetID][nfc][n];
01365                   //SUNDANCE_MSG3(setupVerb(), tab1 << " dof=" << dofs_[d][facetID][nfc][n] );
01366                 }
01367               }
01368             } // end orientation dependent
01369          } //end functions in chunk
01370         } //end chunks
01371       } // facetInd
01372     } // facetDim
01373 
01374     //in case of cells with hanging node write the collected information to the maximalDofs_ and store the trafo matrix
01375     if (hasCellHanging_[cellLID[c]]){
01376     // store tranfo Matrix
01377       Array<int> matrixIndexes(nBasisChunks());
01378       for (int b=0; b<nBasisChunks(); b++){
01379         matrixIndexes[b] = matrixStore_.addMatrix( b , trafoMatrix[b] );
01380       }
01381     maxCellLIDwithHN_to_TrafoMatrix_.put( cellLID[c] , matrixIndexes );
01382 
01383       for (int b=0; b<nBasisChunks(); b++)
01384     {
01385         // display trafo matrix per basis chunk
01386         SUNDANCE_MSG3(setupVerb(), "trafoMatrix[b]=" << trafoMatrix[b]);
01387       for (int func=0; func<nFuncs(b); func++)
01388       {
01389         int funcID = getfuncID(b , func );
01390         // if the function is not defined then just skip to the next one
01391         if (funcDefined_[dim_][funcID][maxCellLID] <= 0 ) continue;
01392         // display global DoFs for this basis chunk and this function inside the chunk
01393         SUNDANCE_MSG1(setupVerb(), "funcID=" << funcID << "globalDoFs_Cell[funcID]=" << globalDoFs_Cell[funcID]);
01394         for (int jj=0 ; jj < nNodes[b] ; jj++){
01395           // store global DoFs for this cell
01396           maximalDofs_[maxCellLID][funcID][jj] = globalDoFs_Cell[funcID][jj];
01397         }
01398       }
01399     }
01400     }
01401   } // -------------- cell iteration -------------
01402   haveMaximalDofs_ = true;
01403 
01404   SUNDANCE_MSG1(setupVerb(),tab << "done building dofs for maximal cells");
01405 }
01406 
01407 
01408 void InhomogeneousDOFMapHN::getTrafoMatrixForCell(
01409       int cellLID,
01410       int funcID,
01411       int& trafoMatrixSize,
01412       bool& doTransform,
01413       Array<double>& transfMatrix ) const {
01414 
01415   trafoMatrixSize = 0;
01416 
01417   if (maxCellLIDwithHN_to_TrafoMatrix_.containsKey(cellLID))
01418   {
01419     // return the transformation matrix from the Map
01420     const Array<int> &matrixIndexes = maxCellLIDwithHN_to_TrafoMatrix_.get( cellLID );
01421     matrixStore_.getMatrix( chunkForFuncID(funcID) , matrixIndexes[chunkForFuncID(funcID)] , transfMatrix );
01422     //transfMatrix = (maxCellLIDwithHN_to_TrafoMatrix_.get( cellLID ))[chunkForFuncID(funcID)]; // this should return a valid array
01423     // KL added cast to double to avoid compilation problems on windows
01424     trafoMatrixSize = sqrt((double) transfMatrix.size());
01425     SUNDANCE_MSG1(setupVerb(), "getTrafoMatrixForCell() cellLID:" << cellLID << ",funcID:" <<
01426         funcID << ",chunkForFuncID(funcID):" << chunkForFuncID(funcID) <<
01427         " , indexForFuncID(funcID)" << indexForFuncID(funcID) << ", trafoMatrixSize:" << trafoMatrixSize);
01428     SUNDANCE_MSG1(setupVerb(), "getTrafoMatrixForCell() Matrix:" << std::endl << transfMatrix );
01429     doTransform = true;
01430   }
01431   else  // no transformation needed, return false
01432   {
01433     doTransform = false;
01434   }
01435 }
01436 
01437 void InhomogeneousDOFMapHN::getTrafoMatrixForFacet(
01438     int cellDim,
01439     int cellLID,
01440     int facetIndex,
01441     int funcID,
01442     int& trafoMatrixSize,
01443     bool& doTransform,
01444     Array<double>& transfMatrix ) const {
01445 
01446   int fIndex;
01447   int maxCellLID;
01448   // here we ask for cofacet 0 , assuming that these are anyhow boundary facets
01449   SUNDANCE_MSG2(setupVerb() , "NodalDOFMapHN::getTrafoMatrixForFacet() cellDim :" << cellDim << ", cellLID:" << cellLID
01450        << ",chunkForFuncID(funcID):" << chunkForFuncID(funcID) << " , indexForFuncID(funcID)" << indexForFuncID(funcID) );
01451   maxCellLID = mesh().maxCofacetLID( cellDim, cellLID, 0 , fIndex);
01452   SUNDANCE_MSG2(setupVerb() , "NodalDOFMapHN::getTrafoMatrixForFacet() testing :" << maxCellLID);
01453 
01454   if (maxCellLIDwithHN_to_TrafoMatrix_.containsKey(maxCellLID))
01455   {
01456     const Array<int> &matrixIndexes = maxCellLIDwithHN_to_TrafoMatrix_.get( maxCellLID );
01457     matrixStore_.getMatrix( chunkForFuncID(funcID) , matrixIndexes[chunkForFuncID(funcID)] , transfMatrix );
01458     doTransform = true;
01459   }
01460   else  // no transformation needed, return false
01461   {
01462     doTransform = false;
01463   }
01464 }
01465 
01466 /** Function for nodal plotting */
01467 void InhomogeneousDOFMapHN::getDOFsForHNCell(
01468     int cellDim,
01469     int cellLID,
01470       int funcID,
01471       Array<int>& dofs ,
01472       Array<double>& coefs ) const {
01473 
01474   // here we can make the asumption that there is only one node at this element
01475   // and that the element is a point (since this is called only for at the plotting)
01476 
01477   // treat the cells only of dimension zero
01478   if (  (cellDim == 0) && ( HN_To_globalFacetsLID_.containsKey(nPoints_*chunkForFuncID(funcID) + cellLID)) )
01479   {
01480     Array<int> facetLIDs;
01481     Array<int> facetDim;
01482     SUNDANCE_MSG1(setupVerb(), "getDOFsForHNCell() cellDim:"<<cellDim<<" cellLID:"<<
01483         cellLID<<"funcID:" << funcID <<",chunkForFuncID(funcID)" << chunkForFuncID(funcID));
01484     facetLIDs = HN_To_globalFacetsLID_.get( nPoints_*chunkForFuncID(funcID) + cellLID );
01485     facetDim = HN_To_globalFacetsDim_.get( nPoints_*chunkForFuncID(funcID) + cellLID );
01486     dofs.resize(facetLIDs.size());
01487     int b = chunkForFuncID(funcID);
01488     int func = indexForFuncID(funcID);
01489     // return the DoFs belonging to the points and function which collaborate to the hanging node
01490     for (int ind = 0 ; ind < facetLIDs.size() ; ind++){
01491       // dofs_[cellDim][chunk][(cellLID*nFunc + func)*nNode + node]
01492       dofs[ind] = dofs_[facetDim[ind]][facetLIDs[ind]][funcID][0]; // node = 0
01493     }
01494     // get the coefficients
01495     coefs = HN_To_coeffs_.get( nPoints_*chunkForFuncID(funcID) + cellLID );
01496     SUNDANCE_MSG1(setupVerb(),  "b=" << b);
01497     SUNDANCE_MSG1(setupVerb(),  "func=" << func);
01498     SUNDANCE_MSG1(setupVerb(),  "funcID=" << funcID);
01499     SUNDANCE_MSG1(setupVerb(),  "facetLIDs=" << facetLIDs);
01500     SUNDANCE_MSG1(setupVerb(),  "facetDim = " << facetDim);
01501     SUNDANCE_MSG1(setupVerb(),  "dofs=" << dofs);
01502     SUNDANCE_MSG1(setupVerb(),  "coefs = " << coefs);
01503   }
01504 }
01505 
01506 RCP<const Set<int> >
01507 InhomogeneousDOFMapHN::allowedFuncsOnCellBatch(int cellDim,
01508   const Array<int>& cellLID) const
01509 {
01510   Set<int> rtn;
01511 
01512   if (cellDim != dim_)
01513   {
01514   SUNDANCE_MSG3(setupVerb(),  "InhomogeneousDOFMapHN::allowedFuncsOnCellBatch cellDim = " << cellDim);
01515     for (int c=0; c<cellLID.size(); c++)
01516     {
01517       // for each maxcofacet make a merge of the functions
01518       int numMaxCoFs = mesh().numMaxCofacets( cellDim, cellLID[c] ) , tmp , maxCoFacet;
01519     SUNDANCE_MSG3(setupVerb(),  "Get all the maxCoFacets , numMaxCoFs = " << numMaxCoFs);
01520     Set<int> rtn_tmp;
01521       for (int i = 0 ; i < numMaxCoFs ; i++){
01522         maxCoFacet = mesh().maxCofacetLID( cellDim, cellLID[c] , i, tmp );
01523         SUNDANCE_MSG3(setupVerb(),  " maxCoFacet = " << maxCoFacet << " ComboIndex:" << maxCellFuncSetsIndex_[maxCoFacet]);
01524         SUNDANCE_MSG3(setupVerb(),  " function set = " << elemFuncSets_[maxCellFuncSetsIndex_[maxCoFacet]] );
01525         rtn_tmp.merge( elemFuncSets_[maxCellFuncSetsIndex_[maxCoFacet]] );
01526       }
01527       // make intersect
01528       if (c == 0){
01529         rtn = rtn_tmp;
01530       }
01531       else {
01532         rtn = rtn.intersection(rtn_tmp);
01533       }
01534     } // end loop over cells
01535   }
01536   else
01537   {
01538     rtn = elemFuncSets_[maxCellFuncSetsIndex_[cellLID[0]]];
01539   SUNDANCE_MSG3(setupVerb(),  "InhomogeneousDOFMapHN::allowedFuncsOnCellBatch cellDim = " << cellDim);
01540     for (int c=1; c<cellLID.size(); c++)
01541     {
01542         SUNDANCE_MSG3(setupVerb(),  " maxCoFacet merge set of cell:" << cellLID[c] << " , " << elemFuncSets_[maxCellFuncSetsIndex_[cellLID[c]]]);
01543       rtn = rtn.intersection(elemFuncSets_[maxCellFuncSetsIndex_[cellLID[c]]]);
01544     } // end loop over cells
01545   }
01546 
01547   return rcp(new Set<int>(rtn));
01548 }
01549 
01550 void InhomogeneousDOFMapHN::computeOffsets(int dim, int localCount)
01551 {
01552   if (setupVerb() > 2)
01553   {
01554     comm().synchronize();
01555     comm().synchronize();
01556     comm().synchronize();
01557     comm().synchronize();
01558   }
01559   SUNDANCE_MSG2(setupVerb(),
01560     "p=" << mesh().comm().getRank()
01561     << " sharing offsets for DOF numbering for dim=" << dim);
01562 
01563   SUNDANCE_MSG2(setupVerb(),
01564     "p=" << mesh().comm().getRank()
01565     << " I have " << localCount << " cells");
01566 
01567   Array<int> dofOffsets;
01568   int totalDOFCount;
01569   MPIContainerComm<int>::accumulate(localCount, dofOffsets, totalDOFCount,
01570     mesh().comm());
01571   int myOffset = dofOffsets[mesh().comm().getRank()];
01572 
01573   SUNDANCE_MSG2(setupVerb(),
01574     "p=" << mesh().comm().getRank()
01575     << " back from MPI accumulate , myOffset=" << myOffset);
01576 
01577   if (setupVerb() > 2)
01578   {
01579     comm().synchronize();
01580     comm().synchronize();
01581     comm().synchronize();
01582     comm().synchronize();
01583   }
01584 
01585   for (int cellNr=0 ; cellNr < dofs_[dim].size() ; cellNr++)
01586   {
01587     for (int funcID=0 ; funcID < dofs_[dim][cellNr].size() ;  funcID++)
01588     {
01589       if (funcDefined_[dim][funcID][cellNr] > 0){
01590          SUNDANCE_MSG2(setupVerb(), " cellNr = " << cellNr << " , funcID=" << funcID );
01591        for (int nrDoF=0 ; nrDoF < dofs_[dim][cellNr][funcID].size() ;  nrDoF++)
01592          {
01593           // increment only when this is not marked as hanging
01594           if (dofs_[dim][cellNr][funcID][nrDoF] >= 0) {
01595              dofs_[dim][cellNr][funcID][nrDoF] += myOffset;
01596           }
01597          }
01598       }
01599     }
01600   }
01601 
01602   setLowestLocalDOF(myOffset);
01603   setNumLocalDOFs(localCount);
01604   setTotalNumDOFs(totalDOFCount);
01605 
01606   SUNDANCE_MSG2(setupVerb(),
01607     "p=" << mesh().comm().getRank() 
01608     << " done sharing offsets for DOF numbering for dim=" << dim);
01609   if (setupVerb() > 2)
01610   {
01611     comm().synchronize();
01612     comm().synchronize();
01613     comm().synchronize();
01614     comm().synchronize();
01615   }
01616 
01617 }                           
01618 
01619 
01620 void InhomogeneousDOFMapHN::print(std::ostream& os) const
01621 {
01622   // todo: implement this
01623   /*
01624   Tabs tab0;
01625   std::cout << tab0 << "dof map: " << std::endl;
01626   for (int d=0; d<=dim_; d++)
01627   {
01628     Tabs tab1;
01629     std::cout << tab1 << d << "-cells: " << std::endl;
01630     for (int n=0; n<mesh().numCells(d); n++)
01631     {
01632       Tabs tab2;
01633       std::cout << tab2 << "d=" << d << " cell=" << n << std::endl;
01634       RCP<const Set<int> > funcs = allowedFuncsOnCellBatch(d, tuple(n));
01635       for (Set<int>::const_iterator f=funcs->begin(); f!=funcs->end(); f++)
01636       {
01637         Tabs tab3;
01638         Array<int> dofs;
01639         getDOFsForCell(d, n, *f, dofs);
01640         std::cout << tab3 << " f=" << *f << " dofs=" << dofs << std::endl;
01641       }
01642     }
01643   }*/
01644 }

Site Contact