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

Site Contact