My Project
ParallelIstlInformation.hpp
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 
36 #include <opm/simulators/utils/ParallelCommunication.hpp>
37 
38 namespace Opm
39 {
40 
43 class ParallelISTLInformation
44 {
45 public:
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 
137 private:
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 
430 namespace Opm
431 {
438 template<class T1>
439 auto
440 accumulateMaskedValues(const T1& container, const std::vector<double>* maskContainer)
441  -> decltype(container[0]*(*maskContainer)[0]);
442 
443 } // end namespace Opm
444 
445 #endif
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: BlackoilPhases.hpp:27
auto accumulateMaskedValues(const T1 &container, const std::vector< double > *maskContainer) -> decltype(container[0] *(*maskContainer)[0])
Accumulates entries masked with 1.