ParallelIstlInformation.hpp
Go to the documentation of this file.
1/*
2 Copyright 2014, 2015 Dr. Markus Blatt - HPC-Simulation-Software & Services
3 Copyright 2014, 2015 Statoil ASA
4 Copyright 2015 NTNU
5
6 This file is part of the Open Porous Media project (OPM).
7
8 OPM is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 OPM is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with OPM. If not, see <http://www.gnu.org/licenses/>.
20*/
21#ifndef OPM_PARALLELISTLINFORMATION_HEADER_INCLUDED
22#define OPM_PARALLELISTLINFORMATION_HEADER_INCLUDED
23
24#include <vector>
25
26#if HAVE_MPI && HAVE_DUNE_ISTL
27
28#include <algorithm>
29#include <limits>
30#include <memory>
31#include <tuple>
32#include <type_traits>
33
34#include <dune/istl/owneroverlapcopy.hh>
35
37
38namespace Opm
39{
40
43class ParallelISTLInformation
44{
45public:
47 using ParallelIndexSet = Dune::OwnerOverlapCopyCommunication<int, int>::ParallelIndexSet;
49 using RemoteIndices = Dune::OwnerOverlapCopyCommunication<int, int>::RemoteIndices;
50
52 ParallelISTLInformation();
53
56 ParallelISTLInformation(MPI_Comm communicator);
57
62 ParallelISTLInformation(const std::shared_ptr<ParallelIndexSet>& indexSet,
63 const std::shared_ptr<RemoteIndices>& remoteIndices,
64 MPI_Comm communicator);
65
69 ParallelISTLInformation(const ParallelISTLInformation& other);
70
72 std::shared_ptr<ParallelIndexSet> indexSet() const
73 {
74 return indexSet_;
75 }
76
78 std::shared_ptr<RemoteIndices> remoteIndices() const
79 {
80 return remoteIndices_;
81 }
82
84 Parallel::Communication communicator() const
85 {
86 return communicator_;
87 }
91 void copyValuesTo(ParallelIndexSet& indexSet, RemoteIndices& remoteIndices,
92 std::size_t local_component_size = 0,
93 std::size_t num_components = 1) const;
94
98 template<class T>
99 void copyOwnerToAll (const T& source, T& dest) const;
100
101 template<class T>
102 const std::vector<double>& updateOwnerMask(const T& container) const;
103
109 const std::vector<double>& getOwnerMask() const
110 {
111 return ownerMask_;
112 }
113
133 template<typename Container, typename BinaryOperator, typename T>
134 void computeReduction(const Container& container, BinaryOperator binaryOperator,
135 T& value) const;
136
137private:
138 template<typename... Containers, typename... BinaryOperators, typename... ReturnValues>
139 void computeTupleReduction(const std::tuple<Containers...>& containers,
140 std::tuple<BinaryOperators...>& operators,
141 std::tuple<ReturnValues...>& values) const;
142
143 std::shared_ptr<ParallelIndexSet> indexSet_;
144 std::shared_ptr<RemoteIndices> remoteIndices_;
145 Parallel::Communication communicator_;
146 mutable std::vector<double> ownerMask_;
147};
148
149 namespace Reduction
150 {
155 // the reduction operation.
156 template<typename BinaryOperator>
157 struct MaskIDOperator
158 {
159 // This is a real nice one: numeric limits needs a type without const
160 // or reference qualifier. Otherwise we get complete nonesense.
161 typedef typename std::remove_cv<
162 typename std::remove_reference<typename BinaryOperator::result_type>::type
163 >::type Result;
170 template<class T, class T1>
171 T operator()(const T& t1, const T& t2, const T1& mask)
172 {
173 return b_(t1, maskValue(t2, mask));
174 }
175 template<class T, class T1>
176 T maskValue(const T& t, const T1& mask)
177 {
178 return t*mask;
179 }
180 BinaryOperator& localOperator()
181 {
182 return b_;
183 }
184 Result getInitialValue()
185 {
186 return Result();
187 }
188 private:
189 BinaryOperator b_;
190 };
191
193 template<class T>
194 struct InnerProductFunctor
195 {
202 template<class T1>
203 T operator()(const T& t1, const T& t2, const T1& mask)
204 {
205 T masked = maskValue(t2, mask);
206 return t1 + masked * masked;
207 }
208 template<class T1>
209 T maskValue(const T& t, const T1& mask)
210 {
211 return t*mask;
212 }
213 std::plus<T> localOperator()
214 {
215 return std::plus<T>();
216 }
217 T getInitialValue()
218 {
219 return T();
220 }
221 };
222
227 // the reduction operation.
228 template<typename BinaryOperator>
229 struct MaskToMinOperator
230 {
231 // This is a real nice one: numeric limits has to a type without const
232 // or reference. Otherwise we get complete nonesense.
233 typedef typename std::remove_reference<
234 typename std::remove_const<typename BinaryOperator::result_type>::type
235 >::type Result;
236
237 MaskToMinOperator(BinaryOperator b)
238 : b_(b)
239 {}
246 template<class T, class T1>
247 T operator()(const T& t1, const T& t2, const T1& mask)
248 {
249 return b_(t1, maskValue(t2, mask));
250 }
251 template<class T, class T1>
252 T maskValue(const T& t, const T1& mask)
253 {
254 if( mask )
255 {
256 return t;
257 }
258 else
259 {
260 return getInitialValue();
261 }
262 }
263 Result getInitialValue()
264 {
265 //g++-4.4 does not support std::numeric_limits<T>::lowest();
266 // we rely on IEE 754 for floating point values and use min()
267 // for integral types.
268 if( std::is_integral<Result>::value )
269 {
270 return std::numeric_limits<Result>::min();
271 }
272 else
273 {
274 return -std::numeric_limits<Result>::max();
275 }
276 }
281 BinaryOperator& localOperator()
282 {
283 return b_;
284 }
285 private:
286 BinaryOperator b_;
287 };
288
292 template<typename BinaryOperator>
293 struct MaskToMaxOperator
294 {
295 // This is a real nice one: numeric limits has to a type without const
296 // or reference. Otherwise we get complete nonesense.
297 typedef typename std::remove_cv<
298 typename std::remove_reference<typename BinaryOperator::result_type>::type
299 >::type Result;
300
301 MaskToMaxOperator(BinaryOperator b)
302 : b_(b)
303 {}
310 template<class T, class T1>
311 T operator()(const T& t1, const T& t2, const T1& mask)
312 {
313 return b_(t1, maskValue(t2, mask));
314 }
315 template<class T, class T1>
316 T maskValue(const T& t, const T1& mask)
317 {
318 if( mask )
319 {
320 return t;
321 }
322 else
323 {
324 return std::numeric_limits<T>::max();
325 }
326 }
327 BinaryOperator& localOperator()
328 {
329 return b_;
330 }
331 Result getInitialValue()
332 {
333 return std::numeric_limits<Result>::max();
334 }
335 private:
336 BinaryOperator b_;
337 };
341 template<class T>
342 MaskIDOperator<std::plus<T> >
343 makeGlobalSumFunctor()
344 {
345 return MaskIDOperator<std::plus<T> >();
346 }
350 template<class T>
351 auto makeGlobalMaxFunctor()
352 {
353 struct MaxOp
354 {
355 using result_type = T;
356 const result_type& operator()(const T& t1, const T& t2)
357 {
358 return std::max(t1, t2);
359 }
360 };
361 return MaskToMinOperator(MaxOp());
362 }
363
364 namespace detail
365 {
367 template<typename T, typename Enable = void>
368 struct MaxAbsFunctor
369 {
370 using result_type = T;
371 result_type operator()(const T& t1,
372 const T& t2)
373 {
374 return std::max(std::abs(t1), std::abs(t2));
375 }
376 };
377
378 // Specialization for unsigned integers. They need their own
379 // version since abs(x) is ambiguous (as well as somewhat
380 // meaningless).
381 template<typename T>
382 struct MaxAbsFunctor<T, typename std::enable_if<std::is_unsigned<T>::value>::type>
383 {
384 using result_type = T;
385 result_type operator()(const T& t1,
386 const T& t2)
387 {
388 return std::max(t1, t2);
389 }
390 };
391 }
392
396 template<class T>
397 MaskIDOperator<detail::MaxAbsFunctor<T> >
398 makeLInfinityNormFunctor()
399 {
400 return MaskIDOperator<detail::MaxAbsFunctor<T> >();
401 }
405 template<class T>
406 auto
407 makeGlobalMinFunctor()
408 {
409 struct MinOp
410 {
411 using result_type = T;
412 const result_type& operator()(const T& t1, const T& t2)
413 {
414 return std::min(t1, t2);
415 }
416 };
417 return MaskToMaxOperator(MinOp());
418 }
419 template<class T>
420 InnerProductFunctor<T>
421 makeInnerProductFunctor()
422 {
423 return InnerProductFunctor<T>();
424 }
425 } // end namespace Reduction
426} // end namespace Opm
427
428#endif
429
430namespace Opm
431{
438template<class T1>
439auto
440accumulateMaskedValues(const T1& container, const std::vector<double>* maskContainer)
441 -> decltype(container[0]*(*maskContainer)[0]);
442
443} // end namespace Opm
444
445#endif
Dune::Communication< MPIComm > Communication
Definition: ParallelCommunication.hpp:30
Definition: BlackoilPhases.hpp:27
auto accumulateMaskedValues(const T1 &container, const std::vector< double > *maskContainer) -> decltype(container[0] *(*maskContainer)[0])
Accumulates entries masked with 1.