dune-common  2.2.1
mpitraits.hh
Go to the documentation of this file.
1 // $Id: mpitraits.hh 1083 2009-09-28 17:13:20Z mblatt $
2 #ifndef DUNE_MPITRAITS_HH
3 #define DUNE_MPITRAITS_HH
4 
5 #if HAVE_MPI
6 #include"mpi.h"
7 #endif
8 
9 #include <utility>
10 
11 namespace Dune
12 {
23 #if HAVE_MPI
24 
33  template<typename T>
34  struct MPITraits
35  {
36  private:
37  MPITraits(){}
38  MPITraits(const MPITraits&){}
39  static MPI_Datatype datatype;
40  static MPI_Datatype vectortype;
41  public:
42  static inline MPI_Datatype getType()
43  {
44  if(datatype==MPI_DATATYPE_NULL){
45  MPI_Type_contiguous(sizeof(T),MPI_BYTE,&datatype);
46  MPI_Type_commit(&datatype);
47  }
48  return datatype;
49  }
50 
51  };
52  template<class T>
53  MPI_Datatype MPITraits<T>::datatype = MPI_DATATYPE_NULL;
54 
55 #ifndef DOXYGEN
56 #if HAVE_MPI
57 
58  // A Macro for defining traits for the primitive data types
59 #define ComposeMPITraits(p,m) \
60  template<> \
61  struct MPITraits<p>{ \
62  static inline MPI_Datatype getType(){ \
63  return m; \
64  } \
65  }
66 
67  ComposeMPITraits(char, MPI_CHAR);
68  ComposeMPITraits(unsigned char,MPI_UNSIGNED_CHAR);
69  ComposeMPITraits(short,MPI_SHORT);
70  ComposeMPITraits(unsigned short,MPI_UNSIGNED_SHORT);
71  ComposeMPITraits(int,MPI_INT);
72  ComposeMPITraits(unsigned int,MPI_UNSIGNED);
73  ComposeMPITraits(long,MPI_LONG);
74  ComposeMPITraits(unsigned long,MPI_UNSIGNED_LONG);
75  ComposeMPITraits(float,MPI_FLOAT);
76  ComposeMPITraits(double,MPI_DOUBLE);
77  ComposeMPITraits(long double,MPI_LONG_DOUBLE);
78 
79 
80 #undef ComposeMPITraits
81 
82  template<class K, int n> class FieldVector;
83 
84  template<class K, int n>
85  struct MPITraits<FieldVector<K,n> >
86  {
87  static MPI_Datatype datatype;
88  static MPI_Datatype vectortype;
89 
90  static inline MPI_Datatype getType()
91  {
92  if(datatype==MPI_DATATYPE_NULL){
93  MPI_Type_contiguous(n, MPITraits<K>::getType(), &vectortype);
94  MPI_Type_commit(&vectortype);
95  FieldVector<K,n> fvector;
96  MPI_Aint base;
97  MPI_Aint displ;
98  MPI_Address(&fvector, &base);
99  MPI_Address(&(fvector[0]), &displ);
100  displ -= base;
101  int length[1]={1};
102 
103  MPI_Type_struct(1, length, &displ, &vectortype, &datatype);
104  MPI_Type_commit(&datatype);
105  }
106  return datatype;
107  }
108 
109  };
110 
111  template<class K, int n>
112  MPI_Datatype MPITraits<FieldVector<K,n> >::datatype = MPI_DATATYPE_NULL;
113  template<class K, int n>
114  MPI_Datatype MPITraits<FieldVector<K,n> >::vectortype = {MPI_DATATYPE_NULL};
115 
116 
117  template<int k>
118  class bigunsignedint;
119 
120  template<int k>
121  struct MPITraits<bigunsignedint<k> >
122  {
123  static MPI_Datatype datatype;
124  static MPI_Datatype vectortype;
125 
126  static inline MPI_Datatype getType()
127  {
128  if(datatype==MPI_DATATYPE_NULL){
129  MPI_Type_contiguous(bigunsignedint<k>::n, MPITraits<unsigned short>::getType(),
130  &vectortype);
131  //MPI_Type_commit(&vectortype);
132  bigunsignedint<k> data;
133  MPI_Aint base;
134  MPI_Aint displ;
135  MPI_Address(&data, &base);
136  MPI_Address(&(data.digit), &displ);
137  displ -= base;
138  int length[1]={1};
139  MPI_Type_struct(1, length, &displ, &vectortype, &datatype);
140  MPI_Type_commit(&datatype);
141  }
142  return datatype;
143  }
144  };
145 }
146 
147 namespace Dune
148 {
149  template<int k>
150  MPI_Datatype MPITraits<bigunsignedint<k> >::datatype = MPI_DATATYPE_NULL;
151  template<int k>
152  MPI_Datatype MPITraits<bigunsignedint<k> >::vectortype = MPI_DATATYPE_NULL;
153 
154  template<typename T1, typename T2>
155  struct MPITraits<std::pair<T1,T2 > >
156  {
157  public:
158  inline static MPI_Datatype getType();
159  private:
160  static MPI_Datatype type;
161  };
162  template<typename T1, typename T2>
163  MPI_Datatype MPITraits<std::pair<T1,T2> >::getType()
164  {
165  if(type==MPI_DATATYPE_NULL){
166  int length[4];
167  MPI_Aint disp[4];
168  MPI_Datatype types[4] = {MPI_LB, MPITraits<T1>::getType(),
169  MPITraits<T2>::getType(), MPI_UB};
170  std::pair<T1,T2> rep[2];
171  length[0]=length[1]=length[2]=length[3]=1;
172  MPI_Address(rep, disp); // lower bound of the datatype
173  MPI_Address(&(rep[0].first), disp+1);
174  MPI_Address(&(rep[0].second), disp+2);
175  MPI_Address(rep+1, disp+3); // upper bound of the datatype
176  for(int i=3; i >= 0; --i)
177  disp[i] -= disp[0];
178  MPI_Type_struct(4, length, disp, types, &type);
179  MPI_Type_commit(&type);
180  }
181  return type;
182  }
183 
184  template<typename T1, typename T2>
185  MPI_Datatype MPITraits<std::pair<T1,T2> >::type=MPI_DATATYPE_NULL;
186 #endif
187 #endif
188 #endif
189 
190 }
191 
192 #endif