COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
operations.hpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2013 von Karman Institute for Fluid Dynamics, Belgium
2 //
3 // This software is distributed under the terms of the
4 // GNU Lesser General Public License version 3 (LGPLv3).
5 // See doc/lgpl.txt and doc/gpl.txt for the license text.
6 
7 #ifndef cf3_common_PE_operations_hpp
8 #define cf3_common_PE_operations_hpp
9 
11 
12 #include <mpi.h>
13 
14 #include <boost/type_traits/is_arithmetic.hpp>
15 
16 #include "common/PE/types.hpp"
17 // #include "common/PE/debug.hpp" // for debugging mpi
18 
20 
30 
32 namespace cf3 {
33  namespace common {
34  namespace PE {
35 
37 
38 namespace detail {
39 
44 template<typename T, typename Op> Operation get_mpi_op_impl() {
45  static Operation op((Operation)nullptr);
46  if (op==(Operation)nullptr) {
47  MPI_CHECK_RESULT(MPI_Op_create, (Op::template func<T>, Op::is_commutative, &op));
48  }
49  return op;
50 }
51 
52 } // namespace detail
53 
55 
60 template<typename T, typename Op, typename selector = void > class get_mpi_op
61 {
62  public:
65  static Operation op() { return detail::get_mpi_op_impl<T,Op>(); }
66 };
67 
75 #define MPI_CUSTOM_OPERATION(name,commutative,expression) class name \
76  { \
77  public: \
78  static const bool is_commutative=commutative; \
79  template<typename T> static void func(void* in_, void* out_, int* len, Datatype* type) \
80  { \
81  T *in=(T*)in_; \
82  T *out=(T*)out_; \
83  for (int i=0; i<*len; i++) \
84  { \
85  expression; \
86  in++; \
87  out++; \
88  } \
89  } \
90  }
91 
93 
95 MPI_CUSTOM_OPERATION(max, true, *out= *in > *out ? *in : *out );
96 MPI_CUSTOM_OPERATION(min, true, *out= *in < *out ? *in : *out );
97 MPI_CUSTOM_OPERATION(plus, true, *out= *in + *out );
98 MPI_CUSTOM_OPERATION(multiplies, true, *out= *in * *out );
99 MPI_CUSTOM_OPERATION(logical_and, true, *out= *in && *out );
100 MPI_CUSTOM_OPERATION(logical_or, true, *out= *in || *out );
101 MPI_CUSTOM_OPERATION(logical_xor, true, *out= !*in ^ !*out );
102 MPI_CUSTOM_OPERATION(bitwise_and, true, *out= *in & *out );
103 MPI_CUSTOM_OPERATION(bitwise_or, true, *out= *in | *out );
104 MPI_CUSTOM_OPERATION(bitwise_xor, true, *out= *in ^ *out );
105 
106 template<typename T> struct get_mpi_op<T, max, typename boost::enable_if<boost::is_arithmetic<T> >::type > { public: static Operation op() { return MPI_MAX; } };
107 template<typename T> struct get_mpi_op<T, min, typename boost::enable_if<boost::is_arithmetic<T> >::type > { public: static Operation op() { return MPI_MIN; } };
108 template<typename T> struct get_mpi_op<T, plus, typename boost::enable_if<boost::is_arithmetic<T> >::type > { public: static Operation op() { return MPI_SUM; } };
109 template<typename T> struct get_mpi_op<T, multiplies, typename boost::enable_if<boost::is_arithmetic<T> >::type > { public: static Operation op() { return MPI_PROD; } };
110 template<typename T> struct get_mpi_op<T, logical_and, typename boost::enable_if<boost::is_arithmetic<T> >::type > { public: static Operation op() { return MPI_LAND; } };
111 template<typename T> struct get_mpi_op<T, logical_or, typename boost::enable_if<boost::is_arithmetic<T> >::type > { public: static Operation op() { return MPI_LOR; } };
112 template<typename T> struct get_mpi_op<T, logical_xor, typename boost::enable_if<boost::is_arithmetic<T> >::type > { public: static Operation op() { return MPI_LXOR; } };
113 template<typename T> struct get_mpi_op<T, bitwise_and, typename boost::enable_if<boost::is_arithmetic<T> >::type > { public: static Operation op() { return MPI_BAND; } };
114 template<typename T> struct get_mpi_op<T, bitwise_or, typename boost::enable_if<boost::is_arithmetic<T> >::type > { public: static Operation op() { return MPI_BOR; } };
115 template<typename T> struct get_mpi_op<T, bitwise_xor, typename boost::enable_if<boost::is_arithmetic<T> >::type > { public: static Operation op() { return MPI_BXOR; } };
116 
117 // TODO: maybe worth implementing those?
118 //#define MPI_MAXLOC OMPI_PREDEFINED_GLOBAL(Operation, ompi_mpi_op_maxloc)
119 //#define MPI_MINLOC OMPI_PREDEFINED_GLOBAL(Operation, ompi_mpi_op_minloc)
120 //#define MPI_REPLACE OMPI_PREDEFINED_GLOBAL(Operation, ompi_mpi_op_replace)
121 
123 
125 
132 MPI_CUSTOM_OPERATION(customplus,true,*out=*in+*out);
133 
135 
137 
138  } // namespace PE
139  } // namespace common
140 } // namespace cf3
141 
143 
144 #endif // cf3_common_PE_operations_hpp
MPI_CUSTOM_OPERATION(max, true,*out=*in > *out?*in:*out)
BUILT-IN OPERATIONS.
external boost library namespace
static Operation op()
Definition: operations.hpp:65
Real max(const Real a, const Real b)
Maximum between two scalars.
Definition: Terminals.hpp:228
Real min(const Real a, const Real b)
Minimum between two scalars.
Definition: Terminals.hpp:234
Top-level namespace for coolfluid.
Definition: Action.cpp:18
#define MPI_CHECK_RESULT(MPIFunc, Args)
Macro for checking return values of any mpi calls and throws exception on error.
Definition: types.hpp:20
Operation get_mpi_op_impl()
Definition: operations.hpp:44
ACCESS AND REGISTRATION MECHANISM.
Definition: operations.hpp:60
MPI_Op Operation
operation (mostly for reduce and all_reduce)
Definition: types.hpp:44
Send comments to:
COOLFluiD Web Admin