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