00001
00002 #ifndef DUNE_MPITRAITS_HH
00003 #define DUNE_MPITRAITS_HH
00004
00005 #if HAVE_MPI
00006 #include"mpi.h"
00007 #endif
00008
00009 namespace Dune
00010 {
00029 template<typename T>
00030 class MPITraits
00031 {};
00032
00033 #if HAVE_MPI
00034
00035
00036 #define ComposeMPITraits(p,m) \
00037 template<> \
00038 struct MPITraits<p>{ \
00039 static inline MPI_Datatype getType(){ \
00040 return m; \
00041 } \
00042 }
00043
00044 ComposeMPITraits(char, MPI_CHAR);
00045 ComposeMPITraits(unsigned char,MPI_UNSIGNED_CHAR);
00046 ComposeMPITraits(short,MPI_SHORT);
00047 ComposeMPITraits(unsigned short,MPI_UNSIGNED_SHORT);
00048 ComposeMPITraits(int,MPI_INT);
00049 ComposeMPITraits(unsigned int,MPI_UNSIGNED);
00050 ComposeMPITraits(long,MPI_LONG);
00051 ComposeMPITraits(unsigned long,MPI_UNSIGNED_LONG);
00052 ComposeMPITraits(float,MPI_FLOAT);
00053 ComposeMPITraits(double,MPI_DOUBLE);
00054 ComposeMPITraits(long double,MPI_LONG_DOUBLE);
00055
00056 #undef ComposeMPITraits
00057
00058 template<class K, int n> class FieldVector;
00059
00060 template<class K, int n>
00061 struct MPITraits<FieldVector<K,n> >
00062 {
00063 static MPI_Datatype datatype;
00064 static MPI_Datatype vectortype;
00065
00066 static inline MPI_Datatype getType()
00067 {
00068 if(datatype==MPI_DATATYPE_NULL){
00069 MPI_Type_contiguous(n, MPITraits<K>::getType(), &vectortype);
00070 MPI_Type_commit(&vectortype);
00071 FieldVector<K,n> fvector;
00072 MPI_Aint base;
00073 MPI_Aint displ;
00074 MPI_Address(&fvector, &base);
00075 MPI_Address(&(fvector[0]), &displ);
00076 displ -= base;
00077 int length[1]={1};
00078
00079 MPI_Type_struct(1, length, &displ, &vectortype, &datatype);
00080 MPI_Type_commit(&datatype);
00081 }
00082 return datatype;
00083 }
00084
00085 };
00086
00087 template<class K, int n>
00088 MPI_Datatype MPITraits<FieldVector<K,n> >::datatype = MPI_DATATYPE_NULL;
00089 template<class K, int n>
00090 MPI_Datatype MPITraits<FieldVector<K,n> >::vectortype = {MPI_DATATYPE_NULL};
00091
00092
00093 template<int k>
00094 class bigunsignedint;
00095
00096 template<int k>
00097 struct MPITraits<bigunsignedint<k> >
00098 {
00099 static MPI_Datatype datatype;
00100 static MPI_Datatype vectortype;
00101
00102 static inline MPI_Datatype getType()
00103 {
00104 if(datatype==MPI_DATATYPE_NULL){
00105 MPI_Type_contiguous(bigunsignedint<k>::n, MPITraits<unsigned short>::getType(),
00106 &vectortype);
00107
00108 bigunsignedint<k> data;
00109 MPI_Aint base;
00110 MPI_Aint displ;
00111 MPI_Address(&data, &base);
00112 MPI_Address(&(data.digit), &displ);
00113 displ -= base;
00114 int length[1]={1};
00115 MPI_Type_struct(1, length, &displ, &vectortype, &datatype);
00116 MPI_Type_commit(&datatype);
00117 }
00118 return datatype;
00119 }
00120 };
00121 }
00122 namespace std
00123 {
00124 template<typename T1,typename T2> class pair;
00125 }
00126
00127 namespace Dune
00128 {
00129 template<int k>
00130 MPI_Datatype MPITraits<bigunsignedint<k> >::datatype = MPI_DATATYPE_NULL;
00131 template<int k>
00132 MPI_Datatype MPITraits<bigunsignedint<k> >::vectortype = MPI_DATATYPE_NULL;
00133
00134 template<typename T1, typename T2>
00135 class MPITraits<std::pair<T1,T2 > >
00136 {
00137 public:
00138 inline static MPI_Datatype getType();
00139 private:
00140 static MPI_Datatype type;
00141 };
00142 template<typename T1, typename T2>
00143 MPI_Datatype MPITraits<std::pair<T1,T2> >::getType()
00144 {
00145 if(type==MPI_DATATYPE_NULL){
00146 int length[4];
00147 MPI_Aint disp[4];
00148 MPI_Datatype types[4] = {MPI_LB, MPITraits<T1>::getType(),
00149 MPITraits<T2>::getType(), MPI_UB};
00150 std::pair<T1,T2> rep[2];
00151 length[0]=length[1]=length[2]=length[3]=1;
00152 MPI_Address(rep, disp);
00153 MPI_Address(&(rep[0].first), disp+1);
00154 MPI_Address(&(rep[0].second), disp+2);
00155 MPI_Address(rep+1, disp+3);
00156 for(int i=3; i >= 0; --i)
00157 disp[i] -= disp[0];
00158 MPI_Type_struct(4, length, disp, types, &type);
00159 MPI_Type_commit(&type);
00160 }
00161 return type;
00162 }
00163
00164 template<typename T1, typename T2>
00165 MPI_Datatype MPITraits<std::pair<T1,T2> >::type=MPI_DATATYPE_NULL;
00166 #endif
00167
00169 }
00170
00171 #endif