opm-simulators
MultiComm.hpp
1 /*
2  Copyright Equinor ASA 2026
3 
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #ifndef OPM_MULTICOMM_HEADER_INCLUDED
20 #define OPM_MULTICOMM_HEADER_INCLUDED
21 
22 #include <dune/common/hybridutilities.hh>
23 
24 #if HAVE_MPI
25 #include <mpi.h>
26 #include <dune/common/parallel/mpicommunication.hh>
27 #endif
28 
29 #include <cmath>
30 #include <cstddef>
31 #include <tuple>
32 #include <type_traits>
33 
34 namespace Dune
35 {
36 
37 class SeqComm
38 {
39 public:
40  using size_type = std::size_t;
41 
42  static constexpr size_type size()
43  {
44  return 0;
45  }
46  template <typename T>
47  void project(T& /*x*/) const
48  {
49  }
50  template <typename T1, typename T2>
51  void dot(const T1& x, const T1& y, T2& result) const
52  {
53  result = x.dot(y);
54  }
55  template <typename T>
56  double norm(const T& x) const
57  {
58  return x.two_norm();
59  }
60  template <typename T>
61  void copyOwnerToAll(const T& x, T& y) const
62  {
63  y = x;
64  }
65 
66  auto communicator() const
67  {
68  return Dune::Communication<int>{};
69  }
70 };
71 
72 #if HAVE_MPI
73 class JacComm
74 {
75 public:
76  using size_type = std::size_t;
77 
78  JacComm()
79  : colcom_(MPI_COMM_WORLD)
80  {
81  }
82  static constexpr size_type size()
83  {
84  return 0;
85  }
86  template <typename T>
87  void project(T& /*x*/) const
88  {
89  }
90 
91  template <typename T1, typename T2>
92  void dot(const T1& x, const T1& y, T2& result) const
93  {
94  result = x.dot(y);
95  result = colcom_.sum(result);
96  }
97 
98  template <typename T>
99  double norm(const T& x) const
100  {
101  double result = x.dot(x);
102  result = colcom_.sum(result);
103  return std::sqrt(result);
104  }
105 
106  template <typename T>
107  void copyOwnerToAll(const T& x, T& y) const
108  {
109  y = x;
110  }
111 
112 private:
113  Communication<MPI_Comm> colcom_;
114 };
115 #endif
116 
117 template <typename... Args>
118 class MultiCommunicator : public std::tuple<Args...>
119 {
120  using TupleType = std::tuple<Args...>;
121  using type = MultiCommunicator<Args...>;
122  using field_type = double;
123 
124 public:
125  using std::tuple<Args...>::tuple;
126  using size_type = std::size_t;
127 
128  static constexpr size_type size()
129  {
130  return sizeof...(Args);
131  }
132 
133  template <size_type index>
134  typename std::tuple_element<index, TupleType>::type&
135  operator[]([[maybe_unused]] const std::integral_constant<size_type, index> indexVariable)
136  {
137  return std::get<index>(*this);
138  }
139  template <size_type index>
140  const typename std::tuple_element<index, TupleType>::type&
141  operator[]([[maybe_unused]] const std::integral_constant<size_type, index> indexVariable) const
142  {
143  return std::get<index>(*this);
144  }
145 
146  template <typename T>
147  void project(T& x) const
148  {
149  using namespace Dune::Hybrid;
150  forEach(integralRange(Hybrid::size(*this)), [&](auto&& i) { (*this)[i].project(x[i]); });
151  }
152  template <typename T1, typename T2>
153  void dot(const T1& x, const T1& y, T2& result) const
154  {
155  result = field_type(0);
156  using namespace Dune::Hybrid;
157  forEach(integralRange(Hybrid::size(*this)), [&](auto&& i) {
158  double result_tmp = 0;
159  (*this)[i].dot(x[i], y[i], result_tmp);
160  result += result_tmp;
161  });
162  }
163  template <typename T>
164  field_type norm(const T& x) const
165  {
166  field_type result(0);
167  using namespace Dune::Hybrid;
168  forEach(integralRange(Hybrid::size(*this)), [&](auto&& i) {
169  double result_tmp = 0.0;
170  (*this)[i].dot(x[i], x[i], result_tmp);
171  result += result_tmp;
172  });
173  return std::sqrt(result);
174  }
175  template <typename T>
176  void copyOwnerToAll(const T& x, T& y) const
177  {
178  using namespace Dune::Hybrid;
179  forEach(integralRange(Hybrid::size(*this)),
180  [&](auto&& i) { (*this)[i].copyOwnerToAll(x[i], y[i]); });
181  }
182 
183  decltype(auto) communicator() const
184  {
185  return std::get<0>(*this).communicator();
186  }
187 };
188 
189 } // namespace Dune
190 
191 #endif // OPM_MULTICOMM_HEADER_INCLUDED
Definition: MultiComm.hpp:118
Definition: fvbaseprimaryvariables.hh:161
Definition: MultiComm.hpp:37