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