parallel_algebra.h
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 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 AutoPtr<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 int blocklengths[LIBMESH_DIM+2]; 00079 MPI_Aint displs[LIBMESH_DIM+2]; 00080 MPI_Datatype types[LIBMESH_DIM+2]; 00081 MPI_Aint start, later; 00082 00083 MPI_Address(ex, &start); 00084 blocklengths[0] = 1; 00085 displs[0] = 0; 00086 types[0] = MPI_LB; 00087 for (unsigned int i=0; i != LIBMESH_DIM; ++i) 00088 { 00089 MPI_Address(&((*ex)(i)), &later); 00090 blocklengths[i+1] = 1; 00091 displs[i+1] = later - start; 00092 types[i+1] = T_type; 00093 } 00094 MPI_Address((ex+1), &later); 00095 blocklengths[LIBMESH_DIM+1] = 1; 00096 displs[LIBMESH_DIM+1] = later - start; 00097 types[LIBMESH_DIM+1] = MPI_UB; 00098 00099 #if MPI_VERSION > 1 00100 MPI_Type_create_struct (LIBMESH_DIM+2, blocklengths, displs, types, &_static_type); 00101 #else 00102 MPI_Type_struct (LIBMESH_DIM+2, blocklengths, displs, types, &_static_type); 00103 #endif // #if MPI_VERSION > 1 00104 00105 MPI_Type_commit (&_static_type); 00106 #endif 00107 _is_initialized = true; 00108 } 00109 _datatype = _static_type; 00110 } 00111 }; 00112 00113 template <typename T> 00114 class StandardType<VectorValue<T> > : public DataType 00115 { 00116 public: 00117 explicit 00118 StandardType(const VectorValue<T> *example=NULL) { 00119 // We need an example for MPI_Address to use 00120 VectorValue<T> *ex; 00121 AutoPtr<VectorValue<T> > temp; 00122 if (example) 00123 ex = const_cast<VectorValue<T> *>(example); 00124 else 00125 { 00126 temp.reset(new VectorValue<T>()); 00127 ex = temp.get(); 00128 } 00129 00130 // _static_type never gets freed, but it only gets committed once 00131 // per T, so it's not a *huge* memory leak... 00132 static data_type _static_type; 00133 static bool _is_initialized = false; 00134 if (!_is_initialized) 00135 { 00136 #ifdef LIBMESH_HAVE_MPI 00137 StandardType<T> T_type(&((*ex)(0))); 00138 int blocklengths[LIBMESH_DIM+2]; 00139 MPI_Aint displs[LIBMESH_DIM+2]; 00140 MPI_Datatype types[LIBMESH_DIM+2]; 00141 MPI_Aint start, later; 00142 00143 MPI_Address(ex, &start); 00144 blocklengths[0] = 1; 00145 displs[0] = 0; 00146 types[0] = MPI_LB; 00147 for (unsigned int i=0; i != LIBMESH_DIM; ++i) 00148 { 00149 MPI_Address(&((*ex)(i)), &later); 00150 blocklengths[i+1] = 1; 00151 displs[i+1] = later - start; 00152 types[i+1] = T_type; 00153 } 00154 MPI_Address((ex+1), &later); 00155 blocklengths[LIBMESH_DIM+1] = 1; 00156 displs[LIBMESH_DIM+1] = later - start; 00157 types[LIBMESH_DIM+1] = MPI_UB; 00158 00159 #if MPI_VERSION > 1 00160 MPI_Type_create_struct (LIBMESH_DIM+2, blocklengths, displs, types, &_static_type); 00161 #else 00162 MPI_Type_struct (LIBMESH_DIM+2, blocklengths, displs, types, &_static_type); 00163 #endif // #if MPI_VERSION > 1 00164 00165 MPI_Type_commit (&_static_type); 00166 #endif 00167 _is_initialized = true; 00168 } 00169 _datatype = _static_type; 00170 } 00171 }; 00172 00173 template <> 00174 class StandardType<Point> : public DataType 00175 { 00176 public: 00177 explicit 00178 StandardType(const Point *example=NULL) { 00179 // We need an example for MPI_Address to use 00180 Point *ex; 00181 AutoPtr<Point> temp; 00182 if (example) 00183 ex = const_cast<Point *>(example); 00184 else 00185 { 00186 temp.reset(new Point()); 00187 ex = temp.get(); 00188 } 00189 00190 // _static_type never gets freed, but it only gets committed once 00191 // per T, so it's not a *huge* memory leak... 00192 static data_type _static_type; 00193 static bool _is_initialized = false; 00194 if (!_is_initialized) 00195 { 00196 #ifdef LIBMESH_HAVE_MPI 00197 StandardType<Real> T_type(&((*ex)(0))); 00198 int blocklengths[LIBMESH_DIM+2]; 00199 MPI_Aint displs[LIBMESH_DIM+2]; 00200 MPI_Datatype types[LIBMESH_DIM+2]; 00201 MPI_Aint start, later; 00202 00203 MPI_Address(ex, &start); 00204 blocklengths[0] = 1; 00205 displs[0] = 0; 00206 types[0] = MPI_LB; 00207 for (unsigned int i=0; i != LIBMESH_DIM; ++i) 00208 { 00209 MPI_Address(&((*ex)(i)), &later); 00210 blocklengths[i+1] = 1; 00211 displs[i+1] = later - start; 00212 types[i+1] = T_type; 00213 } 00214 MPI_Address((ex+1), &later); 00215 blocklengths[LIBMESH_DIM+1] = 1; 00216 displs[LIBMESH_DIM+1] = later - start; 00217 types[LIBMESH_DIM+1] = MPI_UB; 00218 00219 #if MPI_VERSION > 1 00220 MPI_Type_create_struct (LIBMESH_DIM+2, blocklengths, displs, types, &_static_type); 00221 #else 00222 MPI_Type_struct (LIBMESH_DIM+2, blocklengths, displs, types, &_static_type); 00223 #endif // #if MPI_VERSION > 1 00224 00225 MPI_Type_commit (&_static_type); 00226 #endif 00227 _is_initialized = true; 00228 } 00229 _datatype = _static_type; 00230 } 00231 }; 00232 00233 // StandardType<> specializations to return a derived MPI datatype 00234 // to handle communication of LIBMESH_DIM*LIBMESH_DIM-tensors. 00235 // 00236 // We use a singleton pattern here because a global variable would 00237 // have tried to call MPI functions before MPI got initialized. 00238 // 00239 // We assume contiguous storage here 00240 template <typename T> 00241 class StandardType<TypeTensor<T> > : public DataType 00242 { 00243 public: 00244 explicit 00245 StandardType(const TypeTensor<T> *example=NULL) : 00246 DataType(StandardType<T>(example ? &((*example)(0,0)) : NULL), LIBMESH_DIM*LIBMESH_DIM) {} 00247 00248 inline ~StandardType() { this->free(); } 00249 }; 00250 00251 template <typename T> 00252 class StandardType<TensorValue<T> > : public DataType 00253 { 00254 public: 00255 explicit 00256 StandardType(const TensorValue<T> *example=NULL) : 00257 DataType(StandardType<T>(example ? &((*example)(0,0)) : NULL), LIBMESH_DIM*LIBMESH_DIM) {} 00258 00259 inline ~StandardType() { this->free(); } 00260 }; 00261 } // namespace Parallel 00262 } // namespace libMesh 00263 00264 #endif // LIBMESH_PARALLEL_ALGEBRA_H 00265
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:48 UTC
Hosted By: