$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 #ifndef LIBMESH_PARALLEL_ALGEBRA_H 00020 #define LIBMESH_PARALLEL_ALGEBRA_H 00021 00022 // This class contains all the functionality for bin sorting 00023 // Templated on the type of keys you will be sorting and the 00024 // type of iterator you will be using. 00025 00026 00027 // Local Includes 00028 #include "libmesh/libmesh_config.h" 00029 00030 #include "libmesh/auto_ptr.h" 00031 #include "libmesh/parallel.h" 00032 #include "libmesh/point.h" 00033 #include "libmesh/tensor_value.h" 00034 #include "libmesh/vector_value.h" 00035 00036 // C++ includes 00037 #include <cstddef> 00038 00039 namespace libMesh { 00040 namespace Parallel { 00041 // StandardType<> specializations to return a derived MPI datatype 00042 // to handle communication of LIBMESH_DIM-vectors. 00043 // 00044 // We use static variables to minimize the number of MPI datatype 00045 // construction calls executed over the course of the program. 00046 // 00047 // We use a singleton pattern because a global variable would 00048 // have tried to call MPI functions before MPI got initialized. 00049 // 00050 // We use MPI_Create_struct here because our vector classes might 00051 // have vptrs, and I'd rather not have the datatype break in those 00052 // cases. 00053 template <typename T> 00054 class StandardType<TypeVector<T> > : public DataType 00055 { 00056 public: 00057 explicit 00058 StandardType(const TypeVector<T> *example=NULL) { 00059 // We need an example for MPI_Address to use 00060 TypeVector<T> *ex; 00061 UniquePtr<TypeVector<T> > temp; 00062 if (example) 00063 ex = const_cast<TypeVector<T> *>(example); 00064 else 00065 { 00066 temp.reset(new TypeVector<T>()); 00067 ex = temp.get(); 00068 } 00069 00070 // _static_type never gets freed, but it only gets committed once 00071 // per T, so it's not a *huge* memory leak... 00072 static data_type _static_type; 00073 static bool _is_initialized = false; 00074 if (!_is_initialized) 00075 { 00076 #ifdef LIBMESH_HAVE_MPI 00077 StandardType<T> T_type(&((*ex)(0))); 00078 00079 #if MPI_VERSION == 1 00080 00081 int blocklengths[LIBMESH_DIM+2]; 00082 MPI_Aint displs[LIBMESH_DIM+2]; 00083 MPI_Datatype types[LIBMESH_DIM+2]; 00084 MPI_Aint start, later; 00085 00086 MPI_Address(ex, &start); 00087 blocklengths[0] = 1; 00088 displs[0] = 0; 00089 types[0] = MPI_LB; 00090 for (unsigned int i=0; i != LIBMESH_DIM; ++i) 00091 { 00092 MPI_Address(&((*ex)(i)), &later); 00093 blocklengths[i+1] = 1; 00094 displs[i+1] = later - start; 00095 types[i+1] = T_type; 00096 } 00097 MPI_Address((ex+1), &later); 00098 blocklengths[LIBMESH_DIM+1] = 1; 00099 displs[LIBMESH_DIM+1] = later - start; 00100 types[LIBMESH_DIM+1] = MPI_UB; 00101 00102 MPI_Type_struct (LIBMESH_DIM+2, blocklengths, displs, types, &_static_type); 00103 00104 #else // MPI_VERSION >= 2 00105 00106 int blocklength = LIBMESH_DIM; 00107 MPI_Aint displs, start; 00108 MPI_Datatype tmptype, type = T_type; 00109 00110 MPI_Get_address (ex, &start); 00111 MPI_Get_address (&((*ex)(0)), &displs); 00112 00113 // subtract off offset to first value from the beginning of the structure 00114 displs -= start; 00115 00116 // create a prototype structure 00117 MPI_Type_create_struct (1, &blocklength, &displs, &type, &tmptype); 00118 00119 // resize the structure type to account for padding, if any 00120 MPI_Type_create_resized (tmptype, 0, sizeof(TypeVector<T>), &_static_type); 00121 #endif 00122 00123 MPI_Type_commit (&_static_type); 00124 #endif // #ifdef LIBMESH_HAVE_MPI 00125 00126 _is_initialized = true; 00127 } 00128 _datatype = _static_type; 00129 } 00130 }; 00131 00132 template <typename T> 00133 class StandardType<VectorValue<T> > : public DataType 00134 { 00135 public: 00136 explicit 00137 StandardType(const VectorValue<T> *example=NULL) { 00138 // We need an example for MPI_Address to use 00139 VectorValue<T> *ex; 00140 UniquePtr<VectorValue<T> > temp; 00141 if (example) 00142 ex = const_cast<VectorValue<T> *>(example); 00143 else 00144 { 00145 temp.reset(new VectorValue<T>()); 00146 ex = temp.get(); 00147 } 00148 00149 // _static_type never gets freed, but it only gets committed once 00150 // per T, so it's not a *huge* memory leak... 00151 static data_type _static_type; 00152 static bool _is_initialized = false; 00153 if (!_is_initialized) 00154 { 00155 #ifdef LIBMESH_HAVE_MPI 00156 StandardType<T> T_type(&((*ex)(0))); 00157 00158 #if MPI_VERSION == 1 00159 00160 int blocklengths[LIBMESH_DIM+2]; 00161 MPI_Aint displs[LIBMESH_DIM+2]; 00162 MPI_Datatype types[LIBMESH_DIM+2]; 00163 MPI_Aint start, later; 00164 00165 MPI_Address(ex, &start); 00166 blocklengths[0] = 1; 00167 displs[0] = 0; 00168 types[0] = MPI_LB; 00169 for (unsigned int i=0; i != LIBMESH_DIM; ++i) 00170 { 00171 MPI_Address(&((*ex)(i)), &later); 00172 blocklengths[i+1] = 1; 00173 displs[i+1] = later - start; 00174 types[i+1] = T_type; 00175 } 00176 MPI_Address((ex+1), &later); 00177 blocklengths[LIBMESH_DIM+1] = 1; 00178 displs[LIBMESH_DIM+1] = later - start; 00179 types[LIBMESH_DIM+1] = MPI_UB; 00180 00181 MPI_Type_struct (LIBMESH_DIM+2, blocklengths, displs, types, &_static_type); 00182 00183 #else // MPI_VERSION >= 2 00184 00185 int blocklength = LIBMESH_DIM; 00186 MPI_Aint displs, start; 00187 MPI_Datatype tmptype, type = T_type; 00188 00189 MPI_Get_address (ex, &start); 00190 MPI_Get_address (&((*ex)(0)), &displs); 00191 00192 // subtract off offset to first value from the beginning of the structure 00193 displs -= start; 00194 00195 // create a prototype structure 00196 MPI_Type_create_struct (1, &blocklength, &displs, &type, &tmptype); 00197 00198 // resize the structure type to account for padding, if any 00199 MPI_Type_create_resized (tmptype, 0, sizeof(VectorValue<T>), &_static_type); 00200 #endif 00201 00202 MPI_Type_commit (&_static_type); 00203 #endif // #ifdef LIBMESH_HAVE_MPI 00204 00205 _is_initialized = true; 00206 } 00207 _datatype = _static_type; 00208 } 00209 }; 00210 00211 template <> 00212 class StandardType<Point> : public DataType 00213 { 00214 public: 00215 explicit 00216 StandardType(const Point *example=NULL) 00217 { 00218 // Prevent unused variable warnings when !LIBMESH_HAVE_MPI 00219 libmesh_ignore(example); 00220 00221 // _static_type never gets freed, but it only gets committed once 00222 // per T, so it's not a *huge* memory leak... 00223 static data_type _static_type; 00224 static bool _is_initialized = false; 00225 if (!_is_initialized) 00226 { 00227 #ifdef LIBMESH_HAVE_MPI 00228 00229 // We need an example for MPI_Address to use 00230 Point *ex; 00231 00232 UniquePtr<Point> temp; 00233 if (example) 00234 ex = const_cast<Point *>(example); 00235 else 00236 { 00237 temp.reset(new Point()); 00238 ex = temp.get(); 00239 } 00240 00241 StandardType<Real> T_type(&((*ex)(0))); 00242 00243 #if MPI_VERSION == 1 00244 00245 int blocklengths[LIBMESH_DIM+2]; 00246 MPI_Aint displs[LIBMESH_DIM+2]; 00247 MPI_Datatype types[LIBMESH_DIM+2]; 00248 MPI_Aint start, later; 00249 00250 MPI_Address(ex, &start); 00251 blocklengths[0] = 1; 00252 displs[0] = 0; 00253 types[0] = MPI_LB; 00254 for (unsigned int i=0; i != LIBMESH_DIM; ++i) 00255 { 00256 MPI_Address(&((*ex)(i)), &later); 00257 blocklengths[i+1] = 1; 00258 displs[i+1] = later - start; 00259 types[i+1] = T_type; 00260 } 00261 MPI_Address((ex+1), &later); 00262 blocklengths[LIBMESH_DIM+1] = 1; 00263 displs[LIBMESH_DIM+1] = later - start; 00264 types[LIBMESH_DIM+1] = MPI_UB; 00265 00266 MPI_Type_struct (LIBMESH_DIM+2, blocklengths, displs, types, &_static_type); 00267 00268 #else // MPI_VERSION >= 2 00269 00270 int blocklength = LIBMESH_DIM; 00271 MPI_Aint displs, start; 00272 MPI_Datatype tmptype, type = T_type; 00273 00274 MPI_Get_address (ex, &start); 00275 MPI_Get_address (&((*ex)(0)), &displs); 00276 00277 // subtract off offset to first value from the beginning of the structure 00278 displs -= start; 00279 00280 // create a prototype structure 00281 MPI_Type_create_struct (1, &blocklength, &displs, &type, &tmptype); 00282 00283 // resize the structure type to account for padding, if any 00284 MPI_Type_create_resized (tmptype, 0, sizeof(Point), &_static_type); 00285 #endif 00286 00287 MPI_Type_commit (&_static_type); 00288 #endif // #ifdef LIBMESH_HAVE_MPI 00289 00290 _is_initialized = true; 00291 } 00292 _datatype = _static_type; 00293 } 00294 }; 00295 00296 // StandardType<> specializations to return a derived MPI datatype 00297 // to handle communication of LIBMESH_DIM*LIBMESH_DIM-tensors. 00298 // 00299 // We use a singleton pattern here because a global variable would 00300 // have tried to call MPI functions before MPI got initialized. 00301 // 00302 // We assume contiguous storage here 00303 template <typename T> 00304 class StandardType<TypeTensor<T> > : public DataType 00305 { 00306 public: 00307 explicit 00308 StandardType(const TypeTensor<T> *example=NULL) : 00309 DataType(StandardType<T>(example ? &((*example)(0,0)) : NULL), LIBMESH_DIM*LIBMESH_DIM) {} 00310 00311 inline ~StandardType() { this->free(); } 00312 }; 00313 00314 template <typename T> 00315 class StandardType<TensorValue<T> > : public DataType 00316 { 00317 public: 00318 explicit 00319 StandardType(const TensorValue<T> *example=NULL) : 00320 DataType(StandardType<T>(example ? &((*example)(0,0)) : NULL), LIBMESH_DIM*LIBMESH_DIM) {} 00321 00322 inline ~StandardType() { this->free(); } 00323 }; 00324 } // namespace Parallel 00325 } // namespace libMesh 00326 00327 #endif // LIBMESH_PARALLEL_ALGEBRA_H