SundanceDOFMapBase.hpp
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 #ifndef SUNDANCE_DOFMAPBASE_H
00043 #define SUNDANCE_DOFMAPBASE_H
00044 
00045 #include "SundanceDefs.hpp"
00046 #include "SundanceMesh.hpp"
00047 #include "SundanceCellSet.hpp"
00048 #include "SundanceCellFilter.hpp"
00049 #include "SundanceMapStructure.hpp"
00050 #include "SundanceObjectWithVerbosity.hpp"
00051 
00052 namespace Teuchos {class Time;}
00053 
00054 namespace Sundance
00055 {
00056 using namespace Teuchos;
00057 
00058 /** \brief Base interface for implementations of a degree of freedom map.
00059  *
00060  * A degree of freedom (DOF) map is a parallel-aware object that takes
00061  * takes DOFs on individual cells in the whole mesh, and creates global
00062  * IDs for them on the whole mesh across processes.
00063  *
00064  * A DOF map is constructed out of a mesh and assignment of various
00065  * discrete functions with various basis-es assigned to the different
00066  * cells in the mesh;
00067  *
00068  * This interface assumes that the global DOFs owned in this process are
00069  * ordered sequentially so the DOFs owned in this process are given by
00070  * <tt>this->lowestLocalDOF() + k</tt>, for <tt>k =
00071  * 0...this->numLocalDOFs()-1()</tt>, where <tt>this->numLocalDOFs()</tt>
00072  * is the number of DOFs owned by this process.  Therefore, any DOF with
00073  * value less than <tt>this->numLocalDOFs()</tt> and greater than or equal
00074  * to <tt>this->lowestLocalDOF()+this->numLocalDOFs()</tt> are necessarily
00075  * ghosted DOFs.  ??? ToDo: I don't think the above is correct! ???
00076  * 
00077  * ToDo: Finish documentation!
00078  *
00079  * \section Sundance_DOFMapBase_Defintions_sec Definitions
00080  *
00081  * <ul>
00082  *
00083  * <li><b>Degree of Freedom (DOF)</b>: ???
00084  *
00085  * <li><b>Homogeneous DOF Map</b>: ???
00086  *
00087  * </ul>
00088  *
00089  * \section Sundance_DOFMapBase_ToDo_sec Possible Refactorings
00090  *
00091  * <ul>
00092  *
00093  * <li>Inherit this base class from Teuchos::Describable and remove the
00094  * print() function, replacing it with the override to
00095  * Teuchos::Describable::describe()?
00096  *
00097  * <li>Break off the default implementation in this class into another
00098  * subclass (called something like <tt>DOFMapDefaultBase</tt>) and then
00099  * make this interface a true abstract interface?  There are lots of
00100  * advantages to having pure interface classes (e.g. less documenation,
00101  * standard delegation subclasses etc.).
00102  *
00103  * <li>Add a public function to return the <tt>MeshBase</tt> object?  Is
00104  * there any reason not to give the client access to the <tt>MeshBase</tt>
00105  * object?  If you do this, then you can remove the <tt>isRemote()</tt>
00106  * function and let the client just query the map object directly.
00107  *
00108  * <li>Refactor this interface and all objects accessed to only use
00109  * absrract interfaces and not handle classes?  This would involve the
00110  * same principle as is used in Thyra.  Is this workable?
00111  *
00112  * <li>Add some function somewhere to return the total number of functions
00113  * that is defined on the mesh.  This is needed to write precise
00114  * preconditions and postconditions for many of the functions.  For
00115  * example, a function <tt>this->numTotalFunctions()</tt> would be very
00116  * helpful in this regard.
00117  *
00118  * <li>???
00119  *
00120  * </ul>
00121  */
00122 class DOFMapBase : public Playa::Printable
00123 {
00124 public:
00125 
00126   /** \brief . */
00127   DOFMapBase(const Mesh& mesh, int setupVerb);
00128       
00129   /** \brief .
00130    *
00131    * ToDo: Remove this virtual destructor since this interface already
00132    * inherits from a base interface that has a virtual destructor.
00133    */
00134   virtual ~DOFMapBase(){;}
00135 
00136   /** \brief . */
00137   const Mesh& mesh() const {return mesh_;}
00138   
00139   /** \brief Return <tt>true</tt> if the given cell is really owned by
00140    * another process and is only ghosted in this process (and optionally
00141    * return the owning process ID).
00142    *
00143    * \param  cellDim
00144    *           [in] The dimension of the cell.  
00145    * \param  cellLID
00146    *           [in] The LID of the cell in this process.  See
00147    *           <tt>MeshBase</tt> for more details, preconditions, etc.
00148    * \param  ownerProcID
00149    *           [out] The process rank ID which owns the cell
00150    *           <tt>(cellDim,cellLID)</tt>.
00151    *
00152    * <b>Preconditions:</b> See <tt>MeshBase</tt>
00153    *
00154    * ToDo: Change the <tt>ownerProcID</tt> argument to <tt>int*</tt> and
00155    * given it a default value of <tt>NULL</tt> so that it can be ignored
00156    * by the client.
00157    *
00158    * ToDo: Consider removing this function and just calling on the mesh
00159    * object directly.
00160    *
00161    * ToDo: Change name to <tt>isRemoteCell()</tt>? 
00162    */
00163   bool isRemote(int cellDim, int cellLID, int& ownerProcID) const 
00164     {return (ownerProcID=mesh_.ownerProcID(cellDim, cellLID)) != localProcID_;}
00165       
00166   /** \brief Get the global DOFs for a single function on a single
00167    * cell.
00168    *
00169    * \param  cellDim
00170    *           [in] The dimension of the cell
00171    * \param  cellLID
00172    *           [in] Local ID (LID) of the cell
00173    * \param  funcID
00174    *           [in] Function ID for which DOFs are requested
00175    * \param  dofs
00176    *           [out] Global IDs for DOFs of the requested function
00177    *           on the requested cell.
00178    *
00179    * 
00180    *
00181    */
00182   virtual void getDOFsForCell(int cellDim, int cellLID,
00183     int funcID,
00184     Array<int>& dofs) const;
00185 
00186   /** \brief Return the global DOFs for a batch of cells for a given set
00187    * of functions on those cells.
00188    *
00189    * \param  cellDim
00190    *           [in] The dimension of the cells in the batch of cells
00191    * \param  cellLIDs
00192    *           [in] Local IDs (LIDs) for the batch of cells
00193    * \param  requestedFuncSet
00194    *           [in] Set of function IDs for which DOFs are requested.
00195    *           Note that this must be equal to the allowed set of
00196    *           requested functions
00197    *           <tt>this->allowedFuncsOnCellBatch(cellDim,cellLIDs)</tt>.
00198    * \param  dofs
00199    *           [out] Global IDs for DOFs of the requested functions on the
00200    *           batch of cells.  The size of this array on output is \code
00201    *           dofs.size()==mapStructure.numBasisChunks() \endcode. The
00202    *           global DOFs for cell <tt>cellLIDs[c]</tt> (where <tt>0 <= c
00203    *           < cellLIDs.size()</tt>) for the cell for the basis chunk
00204    *           <tt>basisChunk</tt> (where <tt>0 <= basisChunk <
00205    *           mapStructure.numBasisChunks()</tt>) are given by \code
00206    *           dofs[c*nDOFsPerCell[c]+k] \endcode, where \code
00207    *           k=0...nDOFsPerCell[c]-1 \endcode and \code nDOFsPerCell[c]
00208    *           = mapStructure.basis(basisChunk).nNodes( spatialDim,
00209    *           this->mesh()->cellType(cellDim) ) *
00210    *           mapStructure.numFuncs(basisChunk) \endcode.  Note that the
00211    *           array <tt>nDOFsPerCell</tt> used above is not actually
00212    *           computed here or returned by this interface.  It is only
00213    *           used abstractly to define the <tt>dofs</tt> array above.
00214    * \param  nNodes
00215    *           [out] Array giving the number of coefficients for each type
00216    *           of basis family in <tt>mapStructure</tt> for each function.
00217    *           The size of this array on return is
00218    *           <tt>nNodes.size()==mapStructure.numBasisChunks()</tt> and
00219    *           <tt>nNodes[b]==mapStructure.basis(b).nNodes(spatialDim,cellType)</tt>,
00220    *           for <tt>b=0...mapStructure.numBasisChunks()-1</tt>.
00221    *
00222    * <b>Preconditions:</b><ul>
00223    * <li><tt>requestedFuncSet.setDifference(
00224    *           this->allowedFuncsOnCellBatch(cellDim,cellLIDs) ).size() == 0</tt>
00225    * <li>???Others???
00226    * </ul>
00227    *
00228    * \returns The map structure that groups sets of different functions
00229    * according with respect to those that have the same basis family.
00230    * Above, we will refer to this returned object as <tt>mapStructure</tt>
00231    * where <tt>mapStructure = *returnVal</tt>.
00232    *
00233    * ToDo: Remove the argument requestedFuncSet since all current use
00234    * cases and implemenations asume that all of the functions are
00235    * requested and returned.
00236    *
00237    * ToDo: Remove the nNodes return argument since this information can be
00238    * gotten just from the return <tt>mapStructure</tt> object.
00239    * Specifically, <tt>nNodes[basisChunk] =
00240    * mapStructure.basis(basisChunk).nNodes(spatialDim,cellType)</tt> so
00241    * what is the point in returning this array?  Since this is needed for
00242    * a whole batch of cells, it is cheap to just grab this from the
00243    * returned <tt>mapStructure</tt> object as shown above.
00244    */
00245   virtual RCP<const MapStructure> 
00246   getDOFsForCellBatch(
00247     int cellDim, const Array<int>& cellLIDs,
00248     const Set<int>& requestedFuncSet,
00249     Array<Array<int> >& dofs,
00250     Array<int>& nNodes,
00251     int verb
00252     ) const = 0 ;
00253 
00254   /** \brief Return the set of a function IDs for a batch of cells for
00255    * which DOFs can be obtained.
00256    *
00257    * \param  cellDim
00258    *           [in] The dimension of the cells in the batch of cells
00259    * \param  cellLIDs
00260    *           [in] Local IDs (LIDs) for the batch of cells
00261    */
00262   virtual RCP<const Set<int> >
00263   allowedFuncsOnCellBatch(int cellDim,
00264     const Array<int>& cellLIDs) const = 0 ;
00265 
00266   /** \brief Return an array of cell filters that gives, for each function
00267    * ID, the cells that the function lives on.
00268    *
00269    * \returns A reference to an array of size <tt>returnVal.size() ==
00270    * numTotalFunctcions</tt> where <tt>returnVal[funcID]</tt> gives a
00271    * handle to a <tt>CellFilterBase</tt> object where the function
00272    * <tt>funcID</tt> lives, where <tt>0 <= funcID <
00273    * numTotalFunctions</tt>.
00274    */
00275   virtual const Array<CellFilter>& funcDomains() const = 0 ;
00276 
00277   /** \brief Return the lowest DOF for DOFs owned in this process. */
00278   int lowestLocalDOF() const {return lowestLocalDOF_;}
00279 
00280   /** \brief Returns <tt>true</tt> if the given global DOF is owned in
00281    * this process.
00282    */
00283   bool isLocalDOF(int dof) const 
00284     {return (lowestLocalDOF_ <= dof && dof < lowestLocalDOF_+numLocalDOFs_);}
00285 
00286   /** \brief Return the number of DOFs owned in this process.
00287    *
00288    * ToDo: Is this the number of owned + ghosted DOFs or is it just owned
00289    * DOFs?
00290    */
00291   int numLocalDOFs() const {return numLocalDOFs_;}
00292 
00293   /** \brief Return the global number of DOFs over all processes.
00294    *
00295    * <b>Postconditions:</b><ul>
00296    * <li><tt>returnVal >= this->numLocalDOFs()</tt>
00297    * </ul>
00298    */
00299   int numDOFs() const {return numDOFs_;}
00300 
00301   /** \brief Return an array of the global DOFs for the DOFs that are
00302    * locally accessed in this process.
00303    *
00304    * <b>Postconditions:</b><ul>
00305    * <li><tt>returnVal->size() == ( this->numDOFs() - this->numLocalDOFs() )</tt>
00306    * <li><tt>returnVal[k] < this->lowsetLocalDOF() &&
00307    *     this->lowsetLocalDOF() + this->numLocalDOFs() <= returnVal[k]</tt>,
00308    *     for <tt>k=0...(this->numDOFs()-this->numLocalDOFs())-1</tt>.
00309    * </ul>
00310    *
00311    * ToDo: Change the return type to <tt>RCP<const Array<int> ></tt> since
00312    * I doubt that the client is allowed to change this array through this
00313    * function!
00314    *
00315    * ToDo: Change the name of this function to something like
00316    * <tt>getGhostDOFs()</tt>?
00317    */
00318   const RCP<Array<int> >& ghostIndices() const 
00319     {return ghostIndices_;}
00320 
00321   /** \brief Print the DOF map.
00322    *
00323    * ToDo: Replace this with override of Teuchos::Describable::describe().
00324    */
00325   virtual void print(std::ostream& os) const = 0 ;
00326 
00327   /** \brief Returns <tt>true</tt> if the map is homogeneous.
00328    *
00329    * See above defintion for a "Homogeneous" map.
00330    */
00331   virtual bool isHomogeneous() const {return false;}
00332 
00333   /**
00334    * \brief The largest dimension cell supported by this DOF map. Usually, this will
00335    * be the spatial dimension of the mesh. However, for functions defined only on a surface,
00336    * curve, or point set it may be lower. Such maps should override the default. 
00337    */
00338   virtual int cellDim() const {return mesh_.spatialDim();}
00339 
00340 
00341   int setupVerb() const {return setupVerb_;}
00342 protected:
00343 
00344   void setLowestLocalDOF(int low) {lowestLocalDOF_ = low;}
00345 
00346   void setNumLocalDOFs(int numDOFs) {numLocalDOFs_ = numDOFs;}
00347 
00348   void setTotalNumDOFs(int numDOFs) {numDOFs_ = numDOFs;}
00349 
00350   const MPIComm& comm() const {return mesh().comm();}
00351 
00352   void addGhostIndex(int dof) {ghostIndices_->append(dof);}
00353 
00354   static Teuchos::Time& dofLookupTimer() ;
00355 
00356   static Teuchos::Time& batchedDofLookupTimer() ;
00357 
00358 
00359 
00360 private:
00361 
00362   int setupVerb_;
00363 
00364   int localProcID_;
00365 
00366   Mesh mesh_;
00367 
00368   int lowestLocalDOF_;
00369 
00370   int numLocalDOFs_;
00371 
00372   int numDOFs_;
00373 
00374   RCP<Array<int> > ghostIndices_;
00375 
00376 };
00377 }
00378 
00379 
00380 #endif

Site Contact