00001
00002
00003 #ifndef DUNE_MPITRAITS_HH
00004 #define DUNE_MPITRAITS_HH
00005
00006 #if HAVE_MPI
00007 #include <mpi.h>
00008 #endif
00009
00010 #include <cstddef>
00011 #include <cstdint>
00012 #include <type_traits>
00013 #include <utility>
00014
00015 namespace Dune
00016 {
00027 #if HAVE_MPI
00028
00037 template<typename T>
00038 struct MPITraits
00039 {
00040 private:
00041 MPITraits(){}
00042 MPITraits(const MPITraits&){}
00043 static MPI_Datatype datatype;
00044 static MPI_Datatype vectortype;
00045 public:
00046 static inline MPI_Datatype getType()
00047 {
00048 if(datatype==MPI_DATATYPE_NULL) {
00049 MPI_Type_contiguous(sizeof(T),MPI_BYTE,&datatype);
00050 MPI_Type_commit(&datatype);
00051 }
00052 return datatype;
00053 }
00054
00055 };
00056 template<class T>
00057 MPI_Datatype MPITraits<T>::datatype = MPI_DATATYPE_NULL;
00058
00059 #ifndef DOXYGEN
00060 #if HAVE_MPI
00061
00062
00063 #define ComposeMPITraits(p,m) \
00064 template<> \
00065 struct MPITraits<p>{ \
00066 static inline MPI_Datatype getType(){ \
00067 return m; \
00068 } \
00069 }
00070
00071 ComposeMPITraits(char, MPI_CHAR);
00072 ComposeMPITraits(unsigned char,MPI_UNSIGNED_CHAR);
00073 ComposeMPITraits(short,MPI_SHORT);
00074 ComposeMPITraits(unsigned short,MPI_UNSIGNED_SHORT);
00075 ComposeMPITraits(int,MPI_INT);
00076 ComposeMPITraits(unsigned int,MPI_UNSIGNED);
00077 ComposeMPITraits(long,MPI_LONG);
00078 ComposeMPITraits(unsigned long,MPI_UNSIGNED_LONG);
00079 ComposeMPITraits(float,MPI_FLOAT);
00080 ComposeMPITraits(double,MPI_DOUBLE);
00081 ComposeMPITraits(long double,MPI_LONG_DOUBLE);
00082
00083
00084 #undef ComposeMPITraits
00085
00086 template<class K, int n> class FieldVector;
00087
00088 template<class K, int n>
00089 struct MPITraits<FieldVector<K,n> >
00090 {
00091 static MPI_Datatype datatype;
00092 static MPI_Datatype vectortype;
00093
00094 static inline MPI_Datatype getType()
00095 {
00096 if(datatype==MPI_DATATYPE_NULL) {
00097 MPI_Type_contiguous(n, MPITraits<K>::getType(), &vectortype);
00098 MPI_Type_commit(&vectortype);
00099 FieldVector<K,n> fvector;
00100 MPI_Aint base;
00101 MPI_Aint displ;
00102 MPI_Get_address(&fvector, &base);
00103 MPI_Get_address(&(fvector[0]), &displ);
00104 displ -= base;
00105 int length[1]={1};
00106
00107 MPI_Type_create_struct(1, length, &displ, &vectortype, &datatype);
00108 MPI_Type_commit(&datatype);
00109 }
00110 return datatype;
00111 }
00112
00113 };
00114
00115 template<class K, int n>
00116 MPI_Datatype MPITraits<FieldVector<K,n> >::datatype = MPI_DATATYPE_NULL;
00117 template<class K, int n>
00118 MPI_Datatype MPITraits<FieldVector<K,n> >::vectortype = {MPI_DATATYPE_NULL};
00119
00120
00121 template<int k>
00122 class bigunsignedint;
00123
00124 template<int k>
00125 struct MPITraits<bigunsignedint<k> >
00126 {
00127 static MPI_Datatype datatype;
00128 static MPI_Datatype vectortype;
00129
00130 static inline MPI_Datatype getType()
00131 {
00132 if(datatype==MPI_DATATYPE_NULL) {
00133 MPI_Type_contiguous(bigunsignedint<k>::n, MPITraits<std::uint16_t>::getType(),
00134 &vectortype);
00135
00136 bigunsignedint<k> data;
00137 MPI_Aint base;
00138 MPI_Aint displ;
00139 MPI_Get_address(&data, &base);
00140 MPI_Get_address(&(data.digit), &displ);
00141 displ -= base;
00142 int length[1]={1};
00143 MPI_Type_create_struct(1, length, &displ, &vectortype, &datatype);
00144 MPI_Type_commit(&datatype);
00145 }
00146 return datatype;
00147 }
00148 };
00149 }
00150
00151 namespace Dune
00152 {
00153 template<int k>
00154 MPI_Datatype MPITraits<bigunsignedint<k> >::datatype = MPI_DATATYPE_NULL;
00155 template<int k>
00156 MPI_Datatype MPITraits<bigunsignedint<k> >::vectortype = MPI_DATATYPE_NULL;
00157
00158 template<typename T1, typename T2>
00159 struct MPITraits<std::pair<T1,T2 > >
00160 {
00161 public:
00162 inline static MPI_Datatype getType();
00163 private:
00164 static MPI_Datatype type;
00165 };
00166 template<typename T1, typename T2>
00167 MPI_Datatype MPITraits<std::pair<T1,T2> >::getType()
00168 {
00169 if(type==MPI_DATATYPE_NULL) {
00170 int length[2] = {1, 1};
00171 MPI_Aint disp[2];
00172 MPI_Datatype types[2] = {MPITraits<T1>::getType(),
00173 MPITraits<T2>::getType()};
00174
00175 using Pair = std::pair<T1, T2>;
00176 static_assert(std::is_standard_layout<Pair>::value, "offsetof() is only defined for standard layout types");
00177 disp[0] = offsetof(Pair, first);
00178 disp[1] = offsetof(Pair, second);
00179
00180 MPI_Datatype tmp;
00181 MPI_Type_create_struct(2, length, disp, types, &tmp);
00182
00183 MPI_Type_create_resized(tmp, 0, sizeof(Pair), &type);
00184 MPI_Type_commit(&type);
00185
00186 MPI_Type_free(&tmp);
00187 }
00188 return type;
00189 }
00190
00191 template<typename T1, typename T2>
00192 MPI_Datatype MPITraits<std::pair<T1,T2> >::type=MPI_DATATYPE_NULL;
00193 #endif
00194 #endif
00195 #endif
00196
00197 }
00198
00199 #endif