SundanceNodalDOFMapHN.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 "SundanceMap.hpp"
00043 #include "PlayaTabs.hpp"
00044 #include "SundanceOut.hpp"
00045 #include "SundanceOrderedTuple.hpp"
00046 #include "SundanceNodalDOFMapHN.hpp"
00047 #include "SundanceLagrange.hpp"
00048 #include "PlayaMPIContainerComm.hpp"
00049 #include "Teuchos_TimeMonitor.hpp"
00050 
00051 
00052 using namespace Sundance;
00053 using namespace Teuchos;
00054 using Playa::MPIComm;
00055 using Playa::MPIContainerComm;
00056 
00057 NodalDOFMapHN::NodalDOFMapHN(const Mesh& mesh,
00058   int nFuncs, 
00059   const CellFilter& maxCellFilter,
00060   int setupVerb)
00061   : HNDoFMapBaseHomogeneous(mesh, nFuncs, setupVerb),
00062     maxCellFilter_(maxCellFilter),
00063     dim_(mesh.spatialDim()),
00064     nFuncs_(nFuncs),
00065     nElems_(mesh.numCells(mesh.spatialDim())),
00066     nNodes_(mesh.numCells(0)),
00067     nNodesPerElem_(mesh.numFacets(mesh.spatialDim(),0,0)),
00068     elemDofs_(nElems_ * nFuncs * nNodesPerElem_),
00069     nodeDofs_(mesh.numCells(0)*nFuncs_, -2),
00070     structure_(rcp(new MapStructure(nFuncs_, rcp(new Lagrange(1))))),
00071     hasCellHanging_(nElems_),
00072     nodeIsHanging_(nElems_ * nFuncs * nNodesPerElem_),
00073     cellsWithHangingDoF_globalDoFs_(),
00074     cells_To_NodeLIDs_(),
00075     hangingNodeLID_to_NodesLIDs_(),
00076     hangindNodeLID_to_Coefs_(),
00077     matrixStore_(),
00078     facetLID_()
00079 {
00080   // init the matrix store with one chunck
00081   matrixStore_.init(1);
00082   init();
00083 }
00084 
00085 void NodalDOFMapHN::init()
00086 { 
00087   Tabs tab;
00088 
00089   SUNDANCE_MSG2(setupVerb(), tab << "NodalDOFMapHN initializing nodal DOF map nrFunc:"
00090       << nFuncs_ << "  nNodes_:" << nNodes_ << " nElems_:" <<nElems_);
00091 
00092   Array<Array<int> > remoteNodes(mesh().comm().getNProc());
00093   Array<int> hasProcessedCell(nNodes_, 0);
00094 
00095   /* start the DOF count at zero. */
00096   int nextDOF = 0;
00097   int owner;
00098 
00099   nFacets_ = mesh().numFacets(dim_, 0, 0);
00100   Array<int> elemLID(nElems_);
00101   Array<int> facetOrientations(nFacets_*nElems_);
00102 
00103   /* Assign node DOFs for locally owned 0-cells */
00104   CellSet maxCells = maxCellFilter_.getCells(mesh());
00105 
00106   int cc = 0;
00107   for (CellIterator iter=maxCells.begin(); iter != maxCells.end(); iter++, cc++)
00108     {
00109       int c = *iter;
00110       elemLID[cc] = c;
00111     }
00112   /* look up the LIDs of the facets (points)*/
00113   /* This is important so that we have locality in the DOF numbering */
00114   mesh().getFacetLIDs(dim_, elemLID, 0, facetLID_, facetOrientations);
00115   
00116   for (int c=0; c<nElems_; c++) {
00117     hasCellHanging_[c] = false;
00118       /* for each facet, process its DOFs */
00119       for (int f=0; f<nFacets_; f++) {
00120           /* if the facet's DOFs have been assigned already,
00121            * we're done */
00122           int fLID = facetLID_[c*nFacets_+f];
00123           SUNDANCE_MSG2(setupVerb(), "NodalDOFMapHN::init() CellLID:"<< c <<"Try point LID:" << fLID << " facet:" << f);
00124           if (hasProcessedCell[fLID] == 0) {
00125               /* the facet may be owned by another processor */
00126             /* Do this only when that node is not HANGING! */
00127               if ( isRemote(0, fLID, owner) && (!mesh().isElementHangingNode(0,fLID)) ) {
00128                   int facetGID 
00129                     = mesh().mapLIDToGID(0, fLID);
00130                   remoteNodes[owner].append(facetGID);
00131                 }
00132               else {/* we can assign a DOF locally */
00133                   SUNDANCE_MSG2(setupVerb(), "NodalDOFMapHN::init() Doing point LID:" << fLID << " facet:" << f);
00134                     // test if the node is not a hanging node
00135                     if ( mesh().isElementHangingNode(0,fLID) == false ){
00136                        /* assign DOFs , (for each function space) */
00137                        for (int i=0; i<nFuncs_; i++){
00138                           nodeDofs_[fLID*nFuncs_ + i] = nextDOF;
00139                           nextDOF++;
00140                        }
00141                     } else {
00142                        SUNDANCE_MSG2(setupVerb(), "NodalDOFMapHN::init() Hanging node found LID:" << fLID);
00143                        hasCellHanging_[c] = true;
00144                        for (int i=0; i<nFuncs_; i++){
00145                          nodeDofs_[fLID*nFuncs_ + i] = -1; // this means that this is not golbal DoF
00146                        }
00147                        Array<int> pointsLIDs;
00148                        Array<int> facetIndex;
00149                        Array<double> coefs;
00150                        // get the global DoFs which contribute (what if that is not yet numbered?, then only the "fLIDs")
00151                        getPointLIDsForHN( fLID, f, c , pointsLIDs, coefs , facetIndex);
00152 
00153                      // also store the corresponding coefficients
00154                        hangingNodeLID_to_NodesLIDs_.put( fLID , pointsLIDs );
00155                        hangindNodeLID_to_Coefs_.put(fLID,coefs);
00156                     }
00157                 }
00158               hasProcessedCell[fLID] = 1;
00159             }
00160             // if this node is hanging then mark the cell as hanging
00161             if (mesh().isElementHangingNode(0,fLID) == true) {
00162                     hasCellHanging_[c] = true;
00163             }
00164        }
00165   }
00166   
00167   //SUNDANCE_MSG2(setupVerb(), "Before Communication: " << nodeDofs_);
00168 
00169   /* Compute offsets for each processor */
00170   int localCount = nextDOF;
00171   computeOffsets(localCount);
00172   
00173   /* Resolve remote DOF numbers */
00174   shareRemoteDOFs(remoteNodes);
00175 
00176   //SUNDANCE_MSG2(setupVerb(), "After Communication: " << nodeDofs_);
00177 
00178   /* Assign DOFs for elements */
00179   for (int c=0; c<nElems_; c++)
00180     {
00181       if (hasCellHanging_[c]){
00182         Array<int> HNDoFs(nFacets_);
00183         Array<double> transMatrix;
00184         Array<double> coefs;
00185 
00186         transMatrix.resize(nFacets_*nFacets_);
00187         for (int ii = 0 ; ii < nFacets_*nFacets_ ; ii++) transMatrix[ii] = 0.0;
00188 
00189         for (int f=0; f<nFacets_; f++)
00190         {
00191           int fLID = facetLID_[c*nFacets_+f];
00192         SUNDANCE_MSG2(setupVerb(), tab << "NodalDOFMapHN cell:" << c << " facetLID:" << fLID
00193               << " hanging:"<< nodeDofs_[fLID*nFuncs_] << "  array:" << HNDoFs);
00194               if (nodeDofs_[fLID*nFuncs_] < 0)
00195               {
00196                   Array<int> pointsLIDs;
00197                   Array<int> facetIndex;
00198                   Array<double> coefs;
00199                   // get the composing points
00200                   getPointLIDsForHN( fLID, f, c , pointsLIDs, coefs , facetIndex);
00201 
00202                   for (int j=0 ; j < pointsLIDs.size() ; j++){
00203                     // look for tmpArray[j] in the existing set, put there coefs[j]
00204                     HNDoFs[facetIndex[j]] = pointsLIDs[j];
00205                     transMatrix[f*nFacets_  + facetIndex[j]] = coefs[j];
00206                   }
00207               }
00208               else
00209               {
00210                 // look for fLID in the actual set and put there 1.0, if not found then size+1
00211                 HNDoFs[f] = fLID;
00212                 transMatrix[f*nFacets_  + f] = 1.0;
00213               }
00214         }
00215         // store the matrix corresponding to this cell
00216         int matrixIndex = matrixStore_.addMatrix(0,transMatrix);
00217         maxCellLIDwithHN_to_TrafoMatrix_.put( c , matrixIndex );
00218 
00219         // store the point LID's which contribute to this cell
00220         cellsWithHangingDoF_globalDoFs_.put( c , HNDoFs );
00221 
00222         SUNDANCE_MSG2(setupVerb(), tab << "NodalDOFMapHN initializing cellLID:" << c << " array:" << HNDoFs);
00223         SUNDANCE_MSG2(setupVerb(), tab << "NodalDOFMapHN initializing cellLID:" << c << " Trafo array:" << transMatrix);
00224 
00225         // add the global DOFs to the array
00226         for (int f=0; f<nFacets_; f++)
00227         {
00228            int fLID = HNDoFs[f];
00229            for (int i=0; i<nFuncs_; i++) {
00230             elemDofs_[(c*nFuncs_+i)*nFacets_ + f] = nodeDofs_[fLID*nFuncs_ + i];
00231            }
00232 
00233         }
00234         SUNDANCE_MSG2(setupVerb(),tab << "NodalDOFMapHN HN initializing cellLID:" << c << " elemDofs_:" << elemDofs_);
00235       }
00236       else {
00237     /* set the element DOFs given the dofs of the facets */
00238         for (int f=0; f<nFacets_; f++)
00239         {
00240           int fLID = facetLID_[c*nFacets_+f];
00241           for (int i=0; i<nFuncs_; i++)
00242           {
00243             elemDofs_[(c*nFuncs_+i)*nFacets_ + f] = nodeDofs_[fLID*nFuncs_ + i];
00244           }
00245         }
00246           SUNDANCE_MSG2(setupVerb(),tab << "NodalDOFMapHN initializing cellLID:" << c << " elemDofs_:" << elemDofs_);
00247       }
00248     }
00249   SUNDANCE_MSG2(setupVerb(),tab << "NodalDOFMapHN initializing DONE");
00250 
00251 }
00252 
00253 RCP<const MapStructure>
00254 NodalDOFMapHN::getDOFsForCellBatch(int cellDim,
00255   const Array<int>& cellLID,
00256   const Set<int>& requestedFuncSet,
00257   Array<Array<int> >& dofs,
00258   Array<int>& nNodes,
00259   int verbosity) const
00260 {
00261   TimeMonitor timer(batchedDofLookupTimer());
00262 
00263   Tabs tab;
00264   SUNDANCE_MSG2(verbosity,
00265                tab << "NodalDOFMapHN::getDOFsForCellBatch(): cellDim=" << cellDim
00266                << " requestedFuncSet:" << requestedFuncSet
00267                << " cellLID=" << cellLID);
00268 
00269 
00270   dofs.resize(1);
00271   nNodes.resize(1);
00272 
00273   int nCells = cellLID.size();
00274 
00275 
00276   if (cellDim == dim_)
00277     {
00278       int dofsPerElem = nFuncs_ * nNodesPerElem_;
00279       nNodes[0] = nNodesPerElem_;
00280       dofs[0].resize(nCells * dofsPerElem);
00281       Array<int>& dof0 = dofs[0];
00282       Array<int> tmpArray;
00283 
00284     tmpArray.resize(dofsPerElem);
00285 
00286       for (int c=0; c<nCells; c++)
00287         {
00288           // here , nothing to do ... in elemDofs_ should be the proper DoFs
00289             for (int i=0; i<dofsPerElem; i++) {
00290                dof0[c*dofsPerElem + i] = elemDofs_[cellLID[c]*dofsPerElem+i];
00291                tmpArray[i] = elemDofs_[cellLID[c]*dofsPerElem+i];
00292             }
00293             SUNDANCE_MSG2(verbosity,tab << "NodalDOFMapHN::getDOFsForCellBatch cellDim:" <<
00294                 cellDim << " cellLID:" << c << " array:" << tmpArray);
00295         }
00296     }
00297   else if (cellDim == 0)
00298     { // point integrals are also mostly used for BCs
00299       nNodes[0] = 1;
00300       dofs[0].resize(nCells * nFuncs_);
00301       Array<int>& dof0 = dofs[0];
00302       Array<int> tmpArray;
00303     tmpArray.resize(nFuncs_);
00304 
00305       for (int c=0; c<nCells; c++)
00306         {
00307           for (int i=0; i<nFuncs_; i++)
00308             {
00309               dof0[c*nFuncs_ + i] = nodeDofs_[cellLID[c]*nFuncs_+i];
00310               tmpArray[i] = nodeDofs_[cellLID[c]*nFuncs_+i];
00311             }
00312           SUNDANCE_MSG2(verbosity,tab << "NodalDOFMapHN::getDOFsForCellBatch cellDim:" <<
00313               cellDim << " pointLID:" << cellLID[c] << " array:" << tmpArray);
00314         }
00315     }
00316   else
00317     {
00318     // since edge or surface Integrals are mostly used for BCs, where are NO HN
00319       int nFacets = mesh().numFacets(cellDim, cellLID[0], 0);
00320       nNodes[0] = nFacets;
00321       int dofsPerCell = nFuncs_ * nNodes[0];
00322       dofs[0].resize(nCells * dofsPerCell);
00323       Array<int>& dof0 = dofs[0];
00324       Array<int> facetLIDs(nCells * nNodes[0]);
00325       Array<int> dummy(nCells * nNodes[0]);
00326       Array<int> tmpArray;
00327     tmpArray.resize(nFuncs_*nFacets);
00328 
00329       mesh().getFacetLIDs(cellDim, cellLID, 0, facetLIDs, dummy);
00330 
00331       for (int c=0; c<nCells; c++)
00332         {
00333           for (int f=0; f<nFacets; f++)
00334             {
00335               int facetCellLID = facetLIDs[c*nFacets+f];
00336               for (int i=0; i<nFuncs_; i++)
00337                 {
00338                   dof0[(c*nFuncs_+i)*nFacets + f]
00339                     = nodeDofs_[facetCellLID*nFuncs_+i];
00340                   // when we want to pass a hanging DoF , we correct the result
00341                   if ( nodeDofs_[facetCellLID*nFuncs_+i] < 0){
00342                     int tmp = 1;
00343                     // get any cell which has this element
00344                     int maxCell = mesh().maxCofacetLID( cellDim , cellLID[c] , 0 , tmp);
00345                       Array<int> facetsLIDs;
00346                       mesh().returnParentFacets( maxCell , 0 , facetsLIDs , tmp );
00347                       // get in the same way the point children from the child cell
00348                       Array<int> childFacets(mesh().numFacets(mesh().spatialDim(),0,0));
00349                       for (int jk = 0 ; jk < childFacets.size() ; jk++)
00350                         childFacets[jk] = mesh().facetLID( mesh().spatialDim() , maxCell, 0 , jk , tmp);
00351                       int fIndex = 0;
00352                       // get the correct point facet index, by comparing the child cell point facets to the HN LID
00353                       for (int jk = 0 ; jk < childFacets.size() ; jk++)
00354                         if ( childFacets[jk] == facetCellLID) { fIndex = jk; break;}
00355                       dof0[(c*nFuncs_+i)*nFacets + f] = nodeDofs_[facetsLIDs[fIndex]*nFuncs_ + i];
00356                   }
00357                   tmpArray[f*nFuncs_+i] = dof0[(c*nFuncs_+i)*nFacets + f];
00358                 }
00359             }
00360           SUNDANCE_MSG2(verbosity,tab << "NodalDOFMapHN::getDOFsForCellBatch cellDim:" <<
00361               cellDim << " edge or face LID:" << cellLID[c] << " array:" << tmpArray);
00362         }
00363     }
00364   SUNDANCE_MSG2(verbosity,
00365                 tab << "NodalDOFMapHN::getDOFsForCellBatch(): DONE");
00366   return structure_;
00367 }
00368 
00369 
00370 void NodalDOFMapHN::getTrafoMatrixForCell(
00371       int cellLID,
00372       int funcID,
00373       int& trafoMatrixSize,
00374       bool& doTransform,
00375       Array<double>& transfMatrix ) const {
00376 
00377   trafoMatrixSize = nFacets_;
00378 
00379   if (cellsWithHangingDoF_globalDoFs_.containsKey(cellLID))
00380   {
00381     // return the transformation matrix from the Map
00382     int matrixIndex = maxCellLIDwithHN_to_TrafoMatrix_.get( cellLID ); // this should return a valid array
00383     matrixStore_.getMatrix( 0 , matrixIndex , transfMatrix );
00384     doTransform = true;
00385   }
00386   else  // no transformation needed, return false
00387   {
00388     doTransform = false;
00389   }
00390 }
00391 
00392 void NodalDOFMapHN::getTrafoMatrixForFacet(
00393       int cellDim,
00394       int cellLID,
00395       int facetIndex,
00396       int funcID,
00397       int& trafoMatrixSize,
00398       bool& doTransform,
00399       Array<double>& transfMatrix ) const {
00400 
00401   int fIndex;
00402   int maxCellLID;
00403   // here we ask for cofacet 0 , assuming that these are anyhow boundary facets
00404   SUNDANCE_MSG2(setupVerb() , "NodalDOFMapHN::getTrafoMatrixForFacet() cellDim :" << cellDim << ", cellLID:" << cellLID);
00405   maxCellLID = mesh().maxCofacetLID( cellDim, cellLID, 0 , fIndex);
00406   SUNDANCE_MSG2(setupVerb() , "NodalDOFMapHN::getTrafoMatrixForFacet() testing :" << maxCellLID);
00407 
00408   // todo: we might pre filter cases when this is not necessary
00409 
00410   if (cellsWithHangingDoF_globalDoFs_.containsKey(maxCellLID))
00411   {
00412     int matrixIndex    =    maxCellLIDwithHN_to_TrafoMatrix_.get( maxCellLID );
00413     matrixStore_.getMatrix( 0 , matrixIndex , transfMatrix );
00414     doTransform = true;
00415   }
00416   else  // no transformation needed, return false
00417   {
00418     doTransform = false;
00419   }
00420 }
00421 
00422 /** Function for nodal plotting */
00423 void NodalDOFMapHN::getDOFsForHNCell(
00424     int cellDim,
00425     int cellLID,
00426       int funcID,
00427       Array<int>& dofs ,
00428       Array<double>& coefs ) const {
00429 
00430   // treat the cells only of dimension zero
00431   if (  (cellDim == 0) && (hangingNodeLID_to_NodesLIDs_.containsKey(cellLID))  )
00432   {
00433     Array<int> pointLIDs;
00434     Array<int> pointCoefs;
00435     pointLIDs = hangingNodeLID_to_NodesLIDs_.get( cellLID );
00436     dofs.resize(pointLIDs.size());
00437     // return the DoFs belonging to the points and function which collaborate to the hanging node
00438     for (int ind = 0 ; ind < pointLIDs.size() ; ind++){
00439       dofs[ind] = nodeDofs_[ pointLIDs[ind] *nFuncs_ + funcID ]; // return the DoF corresp. to function ID
00440     }
00441     // get the coefficients
00442     coefs = hangindNodeLID_to_Coefs_.get( cellLID );
00443   }
00444 }
00445 
00446 /** This function is only for TRISECTION implemented */
00447 // we might use the method of BasisFunction->getConstraintForHN(), but this should be faster
00448 void NodalDOFMapHN::getPointLIDsForHN( int pointLID , int facetIndex ,
00449     int maxCellIndex ,Array<int>& glbLIDs, Array<double>& coefsArray , Array<int>& nodeIndex){
00450 
00451   Array<int> facets;
00452     int indexInParent , parentLID , facetCase = 0;
00453     double divRatio = 0.5;
00454   switch (dim_){
00455   case 2:
00456     // todo: eventually implement bisection as well (if it will be needed)
00457     glbLIDs.resize(2);
00458     nodeIndex.resize(2);
00459     indexInParent = mesh().indexInParent(maxCellIndex);
00460     mesh().returnParentFacets(maxCellIndex , 0 ,facets , parentLID );
00461     switch( mesh().maxChildren()) {
00462       // trisection
00463       case 9: {
00464       switch (indexInParent){
00465       case 0: {facetCase = (facetIndex == 1)? 0 : 1;
00466             divRatio = (1.0/3.0);  break;}
00467       case 1: {facetCase = 0;
00468             divRatio = (facetIndex == 0)? (1.0/3.0) : (2.0/3.0);  break;}
00469       case 2: {facetCase = (facetIndex == 0)? 0 : 2;
00470             divRatio = (facetIndex == 0)? (2.0/3.0) : (1.0/3.0);  break;}
00471       case 5: {facetCase = 1;
00472                   divRatio = (facetIndex == 0)? (1.0/3.0) : (2.0/3.0);  break;}
00473       case 3: {facetCase = 2;
00474                   divRatio = (facetIndex == 1)? (1.0/3.0) : (2.0/3.0);  break;}
00475       case 6: {facetCase = (facetIndex == 0)? 1 : 3;
00476                   divRatio = (facetIndex == 0)? (2.0/3.0) : (1.0/3.0);  break;}
00477       case 7: {facetCase = 3;
00478                   divRatio = (facetIndex == 2)? (1.0/3.0) : (2.0/3.0);  break;}
00479       case 8: {facetCase = (facetIndex == 1)? 2 : 3;
00480                   divRatio = (2.0/3.0);  break;}
00481       }
00482       break;
00483       }
00484       // bisection
00485       case 4:{
00486         divRatio = 0.5; // constant div factor
00487         switch (indexInParent){
00488         case 0: {facetCase = (facetIndex == 1)? 0 : 1; break;}
00489         case 1: {facetCase = (facetIndex == 0)? 0 : 2; break;}
00490         case 2: {facetCase = (facetIndex == 0)? 1 : 3; break;}
00491         case 3: {facetCase = (facetIndex == 1)? 2 : 3; break;}
00492       }
00493       break;
00494       }
00495       default: {} //error
00496     }
00497     // get the facet indices
00498     switch (facetCase){
00499     case 0: {glbLIDs[0] = facets[0]; glbLIDs[1] = facets[1];
00500               nodeIndex[0] = 0;  nodeIndex[1] = 1;  break;}
00501     case 1: {glbLIDs[0] = facets[0]; glbLIDs[1] = facets[2];
00502               nodeIndex[0] = 0;  nodeIndex[1] = 2;  break;}
00503     case 2: {glbLIDs[0] = facets[1]; glbLIDs[1] = facets[3];
00504               nodeIndex[0] = 1;  nodeIndex[1] = 3;   break;}
00505     case 3: {glbLIDs[0] = facets[2]; glbLIDs[1] = facets[3];
00506               nodeIndex[0] = 2;  nodeIndex[1] = 3;  break;}
00507     }
00508     coefsArray.resize(2); coefsArray[0] = 1 - divRatio; coefsArray[1] = divRatio;
00509     SUNDANCE_MSG2(setupVerb(),"NodalDOFMapHN::getPointLIDsForHN() fc=" << facetCase << " R=" << divRatio
00510                    << " facetIndex:" << facetIndex <<   " indexInParent:" << indexInParent <<" glbLIDs:"
00511                    << glbLIDs << " maxCellIndex:" << maxCellIndex << " nodeIndex:" << nodeIndex);
00512     break;
00513   case 3:{
00514         // 3D hanging node
00515     double ind_x = 0 , ind_y = 0 , ind_z = 0;
00516     double f_x = 0.0 , f_y = 0.0 , f_z = 0.0;
00517     double xx = 0.0  , yy = 0.0  , zz = 0.0;
00518     double values[8];
00519     indexInParent = mesh().indexInParent(maxCellIndex);
00520     mesh().returnParentFacets(maxCellIndex , 0 ,facets , parentLID );
00521     // choose either tri- or bisectionin 3D
00522     switch( mesh().maxChildren()) {
00523     // trisection
00524     case 27:{
00525       switch (indexInParent){
00526       case 0:  { ind_x = 0.0; ind_y = 0.0; ind_z = 0.0; break;}
00527       case 1:  { ind_x = 1.0; ind_y = 0.0; ind_z = 0.0; break;}
00528       case 2:  { ind_x = 2.0; ind_y = 0.0; ind_z = 0.0; break;}
00529       case 3:  { ind_x = 0.0; ind_y = 1.0; ind_z = 0.0; break;}
00530       case 4:  { ind_x = 1.0; ind_y = 1.0; ind_z = 0.0; break;}
00531       case 5:  { ind_x = 2.0; ind_y = 1.0; ind_z = 0.0; break;}
00532       case 6:  { ind_x = 0.0; ind_y = 2.0; ind_z = 0.0; break;}
00533       case 7:  { ind_x = 1.0; ind_y = 2.0; ind_z = 0.0; break;}
00534       case 8:  { ind_x = 2.0; ind_y = 2.0; ind_z = 0.0; break;}
00535       case 9:  { ind_x = 0.0; ind_y = 0.0; ind_z = 1.0; break;}
00536       case 10: { ind_x = 1.0; ind_y = 0.0; ind_z = 1.0; break;}
00537       case 11: { ind_x = 2.0; ind_y = 0.0; ind_z = 1.0; break;}
00538       case 12: { ind_x = 0.0; ind_y = 1.0; ind_z = 1.0; break;}
00539       case 14: { ind_x = 2.0; ind_y = 1.0; ind_z = 1.0; break;}
00540       case 15: { ind_x = 0.0; ind_y = 2.0; ind_z = 1.0; break;}
00541       case 16: { ind_x = 1.0; ind_y = 2.0; ind_z = 1.0; break;}
00542       case 17: { ind_x = 2.0; ind_y = 2.0; ind_z = 1.0; break;}
00543       case 18: { ind_x = 0.0; ind_y = 0.0; ind_z = 2.0; break;}
00544       case 19: { ind_x = 1.0; ind_y = 0.0; ind_z = 2.0; break;}
00545       case 20: { ind_x = 2.0; ind_y = 0.0; ind_z = 2.0; break;}
00546       case 21: { ind_x = 0.0; ind_y = 1.0; ind_z = 2.0; break;}
00547       case 22: { ind_x = 1.0; ind_y = 1.0; ind_z = 2.0; break;}
00548       case 23: { ind_x = 2.0; ind_y = 1.0; ind_z = 2.0; break;}
00549       case 24: { ind_x = 0.0; ind_y = 2.0; ind_z = 2.0; break;}
00550       case 25: { ind_x = 1.0; ind_y = 2.0; ind_z = 2.0; break;}
00551       case 26: { ind_x = 2.0; ind_y = 2.0; ind_z = 2.0; break;}
00552       default: {}// error this should not occur
00553       }
00554       // get the facet coordinates
00555       switch (facetIndex){
00556       case 0:  { f_x = 0.0 , f_y = 0.0 , f_z = 0.0; break;}
00557       case 1:  { f_x = 1.0 , f_y = 0.0 , f_z = 0.0; break;}
00558       case 2:  { f_x = 0.0 , f_y = 1.0 , f_z = 0.0; break;}
00559       case 3:  { f_x = 1.0 , f_y = 1.0 , f_z = 0.0; break;}
00560       case 4:  { f_x = 0.0 , f_y = 0.0 , f_z = 1.0; break;}
00561       case 5:  { f_x = 1.0 , f_y = 0.0 , f_z = 1.0; break;}
00562       case 6:  { f_x = 0.0 , f_y = 1.0 , f_z = 1.0; break;}
00563       case 7:  { f_x = 1.0 , f_y = 1.0 , f_z = 1.0; break;}
00564       default: {}// error this should not occur
00565       }
00566       break;
00567       }
00568     // bisection
00569     case 8:{
00570       // 3 is one unit ..., therefore 1.5 is half
00571       switch (indexInParent){
00572       case 0:  { ind_x = 0.0; ind_y = 0.0; ind_z = 0.0; break;}
00573       case 1:  { ind_x = 1.5; ind_y = 0.0; ind_z = 0.0; break;}
00574       case 2:  { ind_x = 0.0; ind_y = 1.5; ind_z = 0.0; break;}
00575       case 3:  { ind_x = 1.5; ind_y = 1.5; ind_z = 0.0; break;}
00576       case 4:  { ind_x = 0.0; ind_y = 0.0; ind_z = 1.5; break;}
00577       case 5:  { ind_x = 1.5; ind_y = 0.0; ind_z = 1.5; break;}
00578       case 6:  { ind_x = 0.0; ind_y = 1.5; ind_z = 1.5; break;}
00579       case 7:  { ind_x = 1.5; ind_y = 1.5; ind_z = 1.5; break;}
00580       default: {}// error this should not occur
00581       }
00582       // get the facet coordinates, 3 is one unit
00583       switch (facetIndex){
00584       case 0:  { f_x = 0.0 , f_y = 0.0 , f_z = 0.0; break;}
00585       case 1:  { f_x = 1.5 , f_y = 0.0 , f_z = 0.0; break;}
00586       case 2:  { f_x = 0.0 , f_y = 1.5 , f_z = 0.0; break;}
00587       case 3:  { f_x = 1.5 , f_y = 1.5 , f_z = 0.0; break;}
00588       case 4:  { f_x = 0.0 , f_y = 0.0 , f_z = 1.5; break;}
00589       case 5:  { f_x = 1.5 , f_y = 0.0 , f_z = 1.5; break;}
00590       case 6:  { f_x = 0.0 , f_y = 1.5 , f_z = 1.5; break;}
00591       case 7:  { f_x = 1.5 , f_y = 1.5 , f_z = 1.5; break;}
00592       default: {}// error this should not occur
00593       }
00594       break;
00595       }
00596     default: {} //error
00597     }
00598     // evaluate the bilinear basis function at the given point
00599       xx = (ind_x + f_x)/3.0;
00600       yy = (ind_y + f_y)/3.0;
00601       zz = (ind_z + f_z)/3.0;
00602       values[0] = (1.0 - xx)*(1.0 - yy)*(1.0 - zz);
00603       values[1] = (xx)*(1.0 - yy)*(1.0 - zz);
00604       values[2] = (1.0 - xx)*(yy)*(1.0 - zz);
00605       values[3] = (xx)*(yy)*(1.0 - zz);
00606       values[4] = (1.0 - xx)*(1.0 - yy)*(zz);
00607       values[5] = (xx)*(1.0 - yy)*(zz);
00608       values[6] = (1.0 - xx)*(yy)*(zz);
00609       values[7] = (xx)*(yy)*(zz);
00610     // resize the array to zero and add
00611       glbLIDs.resize(0);
00612       nodeIndex.resize(0);
00613       coefsArray.resize(0);
00614       for (int ii = 0 ; ii < 8 ; ii++ ){
00615         // add the facet point if the basis is not zero
00616         if (fabs(values[ii]) > 1e-5){
00617           glbLIDs.append(facets[ii]);
00618           nodeIndex.append(ii);
00619           coefsArray.append(values[ii]);
00620         }
00621       }
00622       SUNDANCE_MSG2(setupVerb(),"NodalDOFMapHN::getPointLIDsForHN()" << " facetIndex:" << facetIndex << " indexInParent:"
00623          << indexInParent <<" glbLIDs:" << glbLIDs << " maxCellIndex:" << maxCellIndex << " nodeIndex:" << nodeIndex);
00624     break;
00625       }
00626   }
00627 
00628 }
00629 
00630 
00631 
00632 void NodalDOFMapHN::computeOffsets(int localCount)
00633 {
00634   Array<int> dofOffsets;
00635   int totalDOFCount;
00636   int myOffset = 0;
00637   int np = mesh().comm().getNProc();
00638   if (np > 1)
00639     {
00640     SUNDANCE_MSG2(setupVerb(),"NodalDOFMapHN::computeOffsets, localCount:" << localCount);
00641       MPIContainerComm<int>::accumulate(localCount, dofOffsets, totalDOFCount,
00642                                         mesh().comm());
00643       myOffset = dofOffsets[mesh().comm().getRank()];
00644 
00645       SUNDANCE_MSG2(setupVerb(),"NodalDOFMapHN::computeOffsets, offset:" << myOffset);
00646       int nDofs = nNodes_ * nFuncs_;
00647       for (int i=0; i<nDofs; i++)
00648         {
00649           if (nodeDofs_[i] >= 0) nodeDofs_[i] += myOffset;
00650         }
00651     }
00652   else
00653     {
00654       totalDOFCount = localCount;
00655     }
00656   
00657   setLowestLocalDOF(myOffset);
00658   setNumLocalDOFs(localCount);
00659   setTotalNumDOFs(totalDOFCount);
00660 }
00661 
00662 
00663 void NodalDOFMapHN::shareRemoteDOFs(const Array<Array<int> >& outgoingCellRequests)
00664 {
00665   int np = mesh().comm().getNProc();
00666   if (np==1) return;
00667   int rank = mesh().comm().getRank();
00668 
00669   Array<Array<int> > incomingCellRequests;
00670   Array<Array<int> > outgoingDOFs(np);
00671   Array<Array<int> > incomingDOFs;
00672 
00673   SUNDANCE_MSG2(setupVerb(),
00674                "p=" << mesh().comm().getRank()
00675                << "synchronizing DOFs for cells of dimension 0");
00676   SUNDANCE_MSG2(setupVerb(),
00677                "p=" << mesh().comm().getRank()
00678                << " sending cell reqs d=0, GID=" 
00679                << outgoingCellRequests);
00680 
00681   /* share the cell requests */
00682   MPIContainerComm<int>::allToAll(outgoingCellRequests, 
00683                                   incomingCellRequests,
00684                                   mesh().comm());
00685   
00686   /* get DOF numbers for the zeroth function index on every node that's been 
00687    * requested by someone else */
00688   for (int p=0; p<np; p++)
00689     {
00690       if (p==rank) continue;
00691       const Array<int>& requestsFromProc = incomingCellRequests[p];
00692       int nReq = requestsFromProc.size();
00693 
00694       SUNDANCE_MSG3(setupVerb(),"p=" << mesh().comm().getRank()
00695                             << " recv'd from proc=" << p
00696                             << " reqs for DOFs for cells " 
00697                             << requestsFromProc);
00698 
00699       outgoingDOFs[p].resize(nReq);
00700 
00701       for (int c=0; c<nReq; c++)
00702         {
00703           int GID = requestsFromProc[c];
00704           SUNDANCE_MSG2(setupVerb(),
00705                        "p=" << rank
00706                        << " processing zero-cell with GID=" << GID); 
00707           int LID = mesh().mapGIDToLID(0, GID);
00708           SUNDANCE_MSG2(setupVerb(),
00709                        "p=" << rank
00710                        << " LID=" << LID << " dofs=" 
00711                        << nodeDofs_[LID*nFuncs_]);
00712           outgoingDOFs[p][c] = nodeDofs_[LID*nFuncs_];
00713           SUNDANCE_MSG2(setupVerb(),
00714                        "p=" << rank
00715                        << " done processing cell with GID=" << GID);
00716         }
00717     }
00718 
00719   SUNDANCE_MSG2(setupVerb(),
00720                "p=" << mesh().comm().getRank()
00721                << "answering DOF requests for cells of dimension 0");
00722 
00723   /* share the DOF numbers */
00724   MPIContainerComm<int>::allToAll(outgoingDOFs,
00725                                   incomingDOFs,
00726                                   mesh().comm());
00727 
00728   SUNDANCE_MSG2(setupVerb(),
00729                "p=" << mesh().comm().getRank()
00730                << "communicated DOF answers for cells of dimension 0" );
00731 
00732   
00733   /* now assign the DOFs from the other procs */
00734 
00735   for (int p=0; p<mesh().comm().getNProc(); p++)
00736     {
00737       if (p==mesh().comm().getRank()) continue;
00738       const Array<int>& dofsFromProc = incomingDOFs[p];
00739       int numCells = dofsFromProc.size();
00740       for (int c=0; c<numCells; c++)
00741         {
00742           int cellGID = outgoingCellRequests[p][c];
00743           int cellLID = mesh().mapGIDToLID(0, cellGID);
00744           int dof = dofsFromProc[c];
00745           for (int i=0; i<nFuncs_; i++)
00746             {
00747               nodeDofs_[cellLID*nFuncs_ + i] = dof+i;
00748               addGhostIndex(dof+i);
00749             }
00750         }
00751     }
00752 }

Site Contact