dune-istl  2.11
multitypeblockvector.hh
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
2 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4 // vi: set et ts=4 sw=2 sts=2:
5 #ifndef DUNE_ISTL_MULTITYPEBLOCKVECTOR_HH
6 #define DUNE_ISTL_MULTITYPEBLOCKVECTOR_HH
7 
8 #include <cmath>
9 #include <iostream>
10 #include <tuple>
11 
12 #include <dune/common/dotproduct.hh>
13 #include <dune/common/ftraits.hh>
14 #include <dune/common/hybridutilities.hh>
15 #include <dune/common/typetraits.hh>
16 #include <dune/common/std/type_traits.hh>
17 
18 #include "istlexception.hh"
19 
20 // forward declaration
21 namespace Dune {
22  template < typename... Args >
23  class MultiTypeBlockVector;
24 }
25 
26 #include "gsetc.hh"
27 
28 namespace Dune {
29 
41  template <typename... Args>
42  struct FieldTraits< MultiTypeBlockVector<Args...> >
43  {
44  using field_type = typename MultiTypeBlockVector<Args...>::field_type;
45  using real_type = typename MultiTypeBlockVector<Args...>::real_type;
46  };
56  template < typename... Args >
58  : public std::tuple<Args...>
59  {
61  typedef std::tuple<Args...> TupleType;
62  public:
63 
65  using size_type = std::size_t;
66 
70  using TupleType::TupleType;
71 
75  typedef MultiTypeBlockVector<Args...> type;
76 
82  using field_type = Std::detected_t<std::common_type_t, typename FieldTraits< std::decay_t<Args> >::field_type...>;
83 
89  using real_type = Std::detected_t<std::common_type_t, typename FieldTraits< std::decay_t<Args> >::real_type...>;
90 
91  // make sure that we have an std::common_type: using an assertion produces a more readable error message
92  // than a compiler template instantiation error
93  static_assert ( sizeof...(Args) == 0 or
94  not (std::is_same_v<field_type, Std::nonesuch> or std::is_same_v<real_type, Std::nonesuch>),
95  "No std::common_type implemented for the given field_type/real_type of the Args. Please provide an implementation and check that a FieldTraits class is present for your type.");
96 
97 
103  static constexpr size_type size()
104  {
105  return sizeof...(Args);
106  }
107 
110  static constexpr size_type N()
111  {
112  return sizeof...(Args);
113  }
114 
116  size_type dim() const
117  {
118  size_type result = 0;
119  Hybrid::forEach(std::make_index_sequence<N()>{},
120  [&](auto i){result += std::get<i>(*this).dim();});
121 
122  return result;
123  }
124 
143  template< size_type index >
144  typename std::tuple_element<index,TupleType>::type&
145  operator[] ([[maybe_unused]] const std::integral_constant< size_type, index > indexVariable)
146  {
147  return std::get<index>(*this);
148  }
149 
155  template< size_type index >
156  const typename std::tuple_element<index,TupleType>::type&
157  operator[] ([[maybe_unused]] const std::integral_constant< size_type, index > indexVariable) const
158  {
159  return std::get<index>(*this);
160  }
161 
164  template<typename T>
165  void operator= (const T& newval) {
166  Dune::Hybrid::forEach(*this, [&](auto&& entry) {
167  entry = newval;
168  });
169  }
170 
174  void operator+= (const type& newv) {
175  using namespace Dune::Hybrid;
176  forEach(integralRange(Hybrid::size(*this)), [&](auto&& i) {
177  (*this)[i] += newv[i];
178  });
179  }
180 
184  void operator-= (const type& newv) {
185  using namespace Dune::Hybrid;
186  forEach(integralRange(Hybrid::size(*this)), [&](auto&& i) {
187  (*this)[i] -= newv[i];
188  });
189  }
190 
192  template<class T,
193  std::enable_if_t< IsNumber<T>::value, int> = 0>
194  void operator*= (const T& w) {
195  Hybrid::forEach(*this, [&](auto&& entry) {
196  entry *= w;
197  });
198  }
199 
201  template<class T,
202  std::enable_if_t< IsNumber<T>::value, int> = 0>
203  void operator/= (const T& w) {
204  Hybrid::forEach(*this, [&](auto&& entry) {
205  entry /= w;
206  });
207  }
208 
209  field_type operator* (const type& newv) const {
210  using namespace Dune::Hybrid;
211  return accumulate(integralRange(Hybrid::size(*this)), field_type(0), [&](auto&& a, auto&& i) {
212  return a + (*this)[i]*newv[i];
213  });
214  }
215 
216  field_type dot (const type& newv) const {
217  using namespace Dune::Hybrid;
218  return accumulate(integralRange(Hybrid::size(*this)), field_type(0), [&](auto&& a, auto&& i) {
219  return a + (*this)[i].dot(newv[i]);
220  });
221  }
222 
225  auto one_norm() const {
226  using namespace Dune::Hybrid;
227  return accumulate(*this, real_type(0), [&](auto&& a, auto&& entry) {
228  return a + entry.one_norm();
229  });
230  }
231 
234  auto one_norm_real() const {
235  using namespace Dune::Hybrid;
236  return accumulate(*this, real_type(0), [&](auto&& a, auto&& entry) {
237  return a + entry.one_norm_real();
238  });
239  }
240 
244  using namespace Dune::Hybrid;
245  return accumulate(*this, real_type(0), [&](auto&& a, auto&& entry) {
246  return a + entry.two_norm2();
247  });
248  }
249 
252  real_type two_norm() const {return sqrt(this->two_norm2());}
253 
257  {
258  using namespace Dune::Hybrid;
259  using std::max;
260 
261  real_type result = 0.0;
262  // Compute max norm tracking appearing nan values
263  // if the field type supports nan.
264  if constexpr (HasNaN<field_type>()) {
265  // This variable will preserve any nan value
266  real_type nanTracker = 1.0;
267  using namespace Dune::Hybrid; // needed for icc, see issue #31
268  forEach(*this, [&](auto&& entry) {
269  real_type entryNorm = entry.infinity_norm();
270  result = max(entryNorm, result);
271  nanTracker += entryNorm;
272  });
273  // Incorporate possible nan value into result
274  result *= (nanTracker / nanTracker);
275  } else {
276  using namespace Dune::Hybrid; // needed for icc, see issue #31
277  forEach(*this, [&](auto&& entry) {
278  result = max(entry.infinity_norm(), result);
279  });
280  }
281  return result;
282  }
283 
287  {
288  using namespace Dune::Hybrid;
289  using std::max;
290 
291  real_type result = 0.0;
292  // Compute max norm tracking appearing nan values
293  // if the field type supports nan.
294  if constexpr (HasNaN<field_type>()) {
295  // This variable will preserve any nan value
296  real_type nanTracker = 1.0;
297  using namespace Dune::Hybrid; // needed for icc, see issue #31
298  forEach(*this, [&](auto&& entry) {
299  real_type entryNorm = entry.infinity_norm_real();
300  result = max(entryNorm, result);
301  nanTracker += entryNorm;
302  });
303  // Incorporate possible nan value into result
304  result *= (nanTracker / nanTracker);
305  } else {
306  using namespace Dune::Hybrid; // needed for icc, see issue #31
307  forEach(*this, [&](auto&& entry) {
308  result = max(entry.infinity_norm_real(), result);
309  });
310  }
311  return result;
312  }
313 
318  template<typename Ta>
319  void axpy (const Ta& a, const type& y) {
320  using namespace Dune::Hybrid;
321  forEach(integralRange(Hybrid::size(*this)), [&](auto&& i) {
322  (*this)[i].axpy(a, y[i]);
323  });
324  }
325 
326  };
327 
328 
329 
332  template <typename... Args>
333  std::ostream& operator<< (std::ostream& s, const MultiTypeBlockVector<Args...>& v) {
334  using namespace Dune::Hybrid;
335  forEach(integralRange(Dune::Hybrid::size(v)), [&](auto&& i) {
336  s << "\t(" << i << "):\n" << v[i] << "\n";
337  });
338  return s;
339  }
340 
341 } // end namespace Dune
342 
343 namespace std
344 {
349  template <size_t i, typename... Args>
350  struct tuple_element<i,Dune::MultiTypeBlockVector<Args...> >
351  {
352  using type = typename std::tuple_element<i, std::tuple<Args...> >::type;
353  };
354 
359  template <typename... Args>
360  struct tuple_size<Dune::MultiTypeBlockVector<Args...> >
361  : std::integral_constant<std::size_t, sizeof...(Args)>
362  {};
363 }
364 
365 #endif
auto one_norm() const
Compute the 1-norm.
Definition: multitypeblockvector.hh:225
typename std::tuple_element< i, std::tuple< Args... > >::type type
Definition: multitypeblockvector.hh:352
real_type infinity_norm_real() const
Compute the simplified maximum norm (uses 1-norm for complex values)
Definition: multitypeblockvector.hh:286
void operator=(const T &newval)
Assignment operator.
Definition: multitypeblockvector.hh:165
Std::detected_t< std::common_type_t, typename FieldTraits< std::decay_t< Args > >::field_type... > field_type
The type used for scalars.
Definition: multitypeblockvector.hh:82
Simple iterative methods like Jacobi, Gauss-Seidel, SOR, SSOR, etc. in a generic way.
Std::detected_t< std::common_type_t, typename FieldTraits< std::decay_t< Args > >::real_type... > real_type
The type used for real values.
Definition: multitypeblockvector.hh:89
std::tuple_element< index, TupleType >::type & operator[]([[maybe_unused]] const std::integral_constant< size_type, index > indexVariable)
Random-access operator.
Definition: multitypeblockvector.hh:145
MultiTypeBlockVector< Args... > type
Definition: multitypeblockvector.hh:75
STL namespace.
field_type dot(const type &newv) const
Definition: multitypeblockvector.hh:216
field_type operator*(const type &newv) const
Definition: multitypeblockvector.hh:209
void axpy(const Ta &a, const type &y)
Axpy operation on this vector (*this += a * y)
Definition: multitypeblockvector.hh:319
A Vector class to support different block types.
Definition: blocklevel.hh:24
typename MultiTypeBlockVector< Args... >::real_type real_type
Definition: multitypeblockvector.hh:45
static constexpr size_type N()
Number of elements.
Definition: multitypeblockvector.hh:110
auto one_norm_real() const
Compute the simplified 1-norm (uses 1-norm also for complex values)
Definition: multitypeblockvector.hh:234
void operator+=(const type &newv)
Definition: multitypeblockvector.hh:174
void operator/=(const T &w)
Division by a scalar.
Definition: multitypeblockvector.hh:203
void operator-=(const type &newv)
Definition: multitypeblockvector.hh:184
std::ostream & operator<<(std::ostream &s, const BlockVector< K, A > &v)
Send BlockVector to an output stream.
Definition: bvector.hh:583
real_type two_norm2() const
Compute the squared Euclidean norm.
Definition: multitypeblockvector.hh:243
real_type two_norm() const
Compute the Euclidean norm.
Definition: multitypeblockvector.hh:252
typename MultiTypeBlockVector< Args... >::field_type field_type
Definition: multitypeblockvector.hh:44
real_type infinity_norm() const
Compute the maximum norm.
Definition: multitypeblockvector.hh:256
static constexpr size_type size()
Return the number of non-zero vector entries.
Definition: multitypeblockvector.hh:103
std::size_t size_type
Type used for vector sizes.
Definition: multitypeblockvector.hh:65
void operator*=(const T &w)
Multiplication with a scalar.
Definition: multitypeblockvector.hh:194
Definition: allocator.hh:11
size_type dim() const
Number of scalar elements.
Definition: multitypeblockvector.hh:116