opm-common
Evaluation.hpp
Go to the documentation of this file.
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
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 2 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  Consult the COPYING file in the top-level source directory of this
20  module for the precise wording of the license and the list of
21  copyright holders.
22 */
32 #ifndef OPM_DENSEAD_EVALUATION_HPP
33 #define OPM_DENSEAD_EVALUATION_HPP
34 
35 #ifndef NDEBUG
37 #endif
38 
39 #include <array>
40 #include <cassert>
41 #include <iosfwd>
42 #include <stdexcept>
43 
44 #include <opm/common/utility/gpuDecorators.hpp>
45 
46 #if HAVE_DUNE_COMMON
47 #include <dune/common/typetraits.hh>
48 #endif
49 
50 namespace Opm {
51 namespace DenseAd {
52 
55 static constexpr int DynamicSize = -1;
56 
61 template <class ValueT, int numDerivs, unsigned staticSize = 0>
63 {
64 public:
67  static const int numVars = numDerivs;
68 
70  typedef ValueT ValueType;
71 
73  OPM_HOST_DEVICE constexpr int size() const
74  { return numDerivs; }
75 
76 protected:
78  OPM_HOST_DEVICE constexpr int length_() const
79  { return size() + 1; }
80 
81 
83  OPM_HOST_DEVICE constexpr int valuepos_() const
84  { return 0; }
86  OPM_HOST_DEVICE constexpr int dstart_() const
87  { return 1; }
89  OPM_HOST_DEVICE constexpr int dend_() const
90  { return length_(); }
91 
94  OPM_HOST_DEVICE constexpr void checkDefined_() const
95  {
96 #ifndef NDEBUG
97  for (const auto& v: data_)
98  Valgrind::CheckDefined(v);
99 #endif
100  }
101 
102 public:
104  OPM_HOST_DEVICE Evaluation() : data_()
105  {}
106 
108  Evaluation(const Evaluation& other) = default;
109 
110 
111  // create an evaluation which represents a constant function
112  //
113  // i.e., f(x) = c. this implies an evaluation with the given value and all
114  // derivatives being zero.
115  template <class RhsValueType>
116  OPM_HOST_DEVICE constexpr Evaluation(const RhsValueType& c): data_{}
117  {
118  setValue(c);
119  clearDerivatives();
120 
121  //checkDefined_();
122  }
123 
124  // create an evaluation representing a variable with the variable position of varPos
125  // The value is set to c, all derivatives are zero except for the one at varPos, which is set to 1.
126  template <class RhsValueType>
127  OPM_HOST_DEVICE Evaluation(const RhsValueType& c, int varPos)
128  {
129  // The variable position must be in represented by the given variable descriptor
130  assert(0 <= varPos && varPos < size());
131 
132  setValue( c );
133  clearDerivatives();
134 
135  data_[varPos + dstart_()] = 1.0;
136 
137  checkDefined_();
138  }
139 
140  // set all derivatives to zero
141  OPM_HOST_DEVICE constexpr void clearDerivatives()
142  {
143  for (int i = dstart_(); i < dend_(); ++i)
144  data_[i] = 0.0;
145  }
146 
147  // create an uninitialized Evaluation object that is compatible with the
148  // argument, but not initialized
149  //
150  // This basically boils down to the copy constructor without copying
151  // anything. If the number of derivatives is known at compile time, this
152  // is equivalent to creating an uninitialized object using the default
153  // constructor, while for dynamic evaluations, it creates an Evaluation
154  // object which exhibits the same number of derivatives as the argument.
155  OPM_HOST_DEVICE static Evaluation createBlank(const Evaluation&)
156  { return Evaluation(); }
157 
158  // create an Evaluation with value and all the derivatives to be zero
159  OPM_HOST_DEVICE static Evaluation createConstantZero(const Evaluation&)
160  { return Evaluation(0.); }
161 
162  // create an Evaluation with value to be one and all the derivatives to be zero
163  OPM_HOST_DEVICE static Evaluation createConstantOne(const Evaluation&)
164  { return Evaluation(1.); }
165 
166  // create a function evaluation for a "naked" depending variable (i.e., f(x) = x)
167  template <class RhsValueType>
168  OPM_HOST_DEVICE static Evaluation createVariable(const RhsValueType& value, int varPos)
169  {
170  // copy function value and set all derivatives to 0, except for the variable
171  // which is represented by the value (which is set to 1.0)
172  return Evaluation(value, varPos);
173  }
174 
175  template <class RhsValueType>
176  OPM_HOST_DEVICE static Evaluation createVariable(int nVars, const RhsValueType& value, int varPos)
177  {
178  if (nVars != 0)
179  throw std::logic_error("This statically-sized evaluation can only represent objects"
180  " with 0 derivatives");
181 
182  // copy function value and set all derivatives to 0, except for the variable
183  // which is represented by the value (which is set to 1.0)
184  return Evaluation(nVars, value, varPos);
185  }
186 
187  template <class RhsValueType>
188  OPM_HOST_DEVICE static Evaluation createVariable(const Evaluation&, const RhsValueType& value, int varPos)
189  {
190  // copy function value and set all derivatives to 0, except for the variable
191  // which is represented by the value (which is set to 1.0)
192  return Evaluation(value, varPos);
193  }
194 
195 
196  // "evaluate" a constant function (i.e. a function that does not depend on the set of
197  // relevant variables, f(x) = c).
198  template <class RhsValueType>
199  OPM_HOST_DEVICE static Evaluation createConstant(int nVars, const RhsValueType& value)
200  {
201  if (nVars != 0)
202  throw std::logic_error("This statically-sized evaluation can only represent objects"
203  " with 0 derivatives");
204  return Evaluation(value);
205  }
206 
207  // "evaluate" a constant function (i.e. a function that does not depend on the set of
208  // relevant variables, f(x) = c).
209  template <class RhsValueType>
210  OPM_HOST_DEVICE static Evaluation createConstant(const RhsValueType& value)
211  {
212  return Evaluation(value);
213  }
214 
215  // "evaluate" a constant function (i.e. a function that does not depend on the set of
216  // relevant variables, f(x) = c).
217  template <class RhsValueType>
218  OPM_HOST_DEVICE static Evaluation createConstant(const Evaluation&, const RhsValueType& value)
219  {
220  return Evaluation(value);
221  }
222 
223  // copy all derivatives from other
224  OPM_HOST_DEVICE void copyDerivatives(const Evaluation& other)
225  {
226  assert(size() == other.size());
227 
228  for (int i = dstart_(); i < dend_(); ++i)
229  data_[i] = other.data_[i];
230  }
231 
232 
233  // add value and derivatives from other to this value and derivatives
234  OPM_HOST_DEVICE Evaluation& operator+=(const Evaluation& other)
235  {
236  assert(size() == other.size());
237 
238  for (int i = 0; i < length_(); ++i)
239  data_[i] += other.data_[i];
240 
241  return *this;
242  }
243 
244  // add value from other to this values
245  template <class RhsValueType>
246  OPM_HOST_DEVICE Evaluation& operator+=(const RhsValueType& other)
247  {
248  // value is added, derivatives stay the same
249  data_[valuepos_()] += other;
250 
251  return *this;
252  }
253 
254  // subtract other's value and derivatives from this values
255  OPM_HOST_DEVICE Evaluation& operator-=(const Evaluation& other)
256  {
257  assert(size() == other.size());
258 
259  for (int i = 0; i < length_(); ++i)
260  data_[i] -= other.data_[i];
261 
262  return *this;
263  }
264 
265  // subtract other's value from this values
266  template <class RhsValueType>
267  OPM_HOST_DEVICE Evaluation& operator-=(const RhsValueType& other)
268  {
269  // for constants, values are subtracted, derivatives stay the same
270  data_[valuepos_()] -= other;
271 
272  return *this;
273  }
274 
275  // multiply values and apply chain rule to derivatives: (u*v)' = (v'u + u'v)
276  OPM_HOST_DEVICE Evaluation& operator*=(const Evaluation& other)
277  {
278  assert(size() == other.size());
279 
280  // while the values are multiplied, the derivatives follow the product rule,
281  // i.e., (u*v)' = (v'u + u'v).
282  const ValueType u = this->value();
283  const ValueType v = other.value();
284 
285  // value
286  data_[valuepos_()] *= v ;
287 
288  // derivatives
289  for (int i = dstart_(); i < dend_(); ++i)
290  data_[i] = data_[i] * v + other.data_[i] * u;
291 
292  return *this;
293  }
294 
295  // m(c*u)' = c*u'
296  template <class RhsValueType>
297  OPM_HOST_DEVICE Evaluation& operator*=(const RhsValueType& other)
298  {
299  for (int i = 0; i < length_(); ++i)
300  data_[i] *= other;
301 
302  return *this;
303  }
304 
305  // m(u*v)' = (vu' - uv')/v^2
306  OPM_HOST_DEVICE Evaluation& operator/=(const Evaluation& other)
307  {
308  assert(size() == other.size());
309 
310  // values are divided, derivatives follow the rule for division, i.e., (u/v)' = (v'u -
311  // u'v)/v^2.
312  ValueType& u = data_[valuepos_()];
313  const ValueType& v = other.value();
314  for (int idx = dstart_(); idx < dend_(); ++idx) {
315  const ValueType& uPrime = data_[idx];
316  const ValueType& vPrime = other.data_[idx];
317 
318  data_[idx] = (v*uPrime - u*vPrime)/(v*v);
319  }
320  u /= v;
321 
322  return *this;
323  }
324 
325  // divide value and derivatives by value of other
326  template <class RhsValueType>
327  OPM_HOST_DEVICE Evaluation& operator/=(const RhsValueType& other)
328  {
329  const ValueType tmp = 1.0/other;
330 
331  for (int i = 0; i < length_(); ++i)
332  data_[i] *= tmp;
333 
334  return *this;
335  }
336 
337  // add two evaluation objects
338  OPM_HOST_DEVICE Evaluation operator+(const Evaluation& other) const
339  {
340  assert(size() == other.size());
341 
342  Evaluation result(*this);
343 
344  result += other;
345 
346  return result;
347  }
348 
349  // add constant to this object
350  template <class RhsValueType>
351  OPM_HOST_DEVICE Evaluation operator+(const RhsValueType& other) const
352  {
353  Evaluation result(*this);
354 
355  result += other;
356 
357  return result;
358  }
359 
360  // subtract two evaluation objects
361  OPM_HOST_DEVICE Evaluation operator-(const Evaluation& other) const
362  {
363  assert(size() == other.size());
364 
365  Evaluation result(*this);
366 
367  result -= other;
368 
369  return result;
370  }
371 
372  // subtract constant from evaluation object
373  template <class RhsValueType>
374  OPM_HOST_DEVICE Evaluation operator-(const RhsValueType& other) const
375  {
376  Evaluation result(*this);
377 
378  result -= other;
379 
380  return result;
381  }
382 
383  // negation (unary minus) operator
384  OPM_HOST_DEVICE Evaluation operator-() const
385  {
386  Evaluation result;
387 
388  // set value and derivatives to negative
389  for (int i = 0; i < length_(); ++i)
390  result.data_[i] = - data_[i];
391 
392  return result;
393  }
394 
395  OPM_HOST_DEVICE Evaluation operator*(const Evaluation& other) const
396  {
397  assert(size() == other.size());
398 
399  Evaluation result(*this);
400 
401  result *= other;
402 
403  return result;
404  }
405 
406  template <class RhsValueType>
407  OPM_HOST_DEVICE Evaluation operator*(const RhsValueType& other) const
408  {
409  Evaluation result(*this);
410 
411  result *= other;
412 
413  return result;
414  }
415 
416  OPM_HOST_DEVICE Evaluation operator/(const Evaluation& other) const
417  {
418  assert(size() == other.size());
419 
420  Evaluation result(*this);
421 
422  result /= other;
423 
424  return result;
425  }
426 
427  template <class RhsValueType>
428  OPM_HOST_DEVICE Evaluation operator/(const RhsValueType& other) const
429  {
430  Evaluation result(*this);
431 
432  result /= other;
433 
434  return result;
435  }
436 
437  template <class RhsValueType>
438  OPM_HOST_DEVICE Evaluation& operator=(const RhsValueType& other)
439  {
440  setValue( other );
441  clearDerivatives();
442 
443  return *this;
444  }
445 
446  // copy assignment from evaluation
447  Evaluation& operator=(const Evaluation& other) = default;
448 
449  template <class RhsValueType>
450  OPM_HOST_DEVICE bool operator==(const RhsValueType& other) const
451  { return value() == other; }
452 
453  OPM_HOST_DEVICE bool operator==(const Evaluation& other) const
454  {
455  assert(size() == other.size());
456 
457  for (int idx = 0; idx < length_(); ++idx) {
458  if (data_[idx] != other.data_[idx]) {
459  return false;
460  }
461  }
462  return true;
463  }
464 
465  OPM_HOST_DEVICE bool operator!=(const Evaluation& other) const
466  { return !operator==(other); }
467 
468  template <class RhsValueType>
469  OPM_HOST_DEVICE bool operator!=(const RhsValueType& other) const
470  { return !operator==(other); }
471 
472  template <class RhsValueType>
473  OPM_HOST_DEVICE bool operator>(RhsValueType other) const
474  { return value() > other; }
475 
476  OPM_HOST_DEVICE bool operator>(const Evaluation& other) const
477  {
478  assert(size() == other.size());
479 
480  return value() > other.value();
481  }
482 
483  template <class RhsValueType>
484  OPM_HOST_DEVICE bool operator<(RhsValueType other) const
485  { return value() < other; }
486 
487  OPM_HOST_DEVICE bool operator<(const Evaluation& other) const
488  {
489  assert(size() == other.size());
490 
491  return value() < other.value();
492  }
493 
494  template <class RhsValueType>
495  OPM_HOST_DEVICE bool operator>=(RhsValueType other) const
496  { return value() >= other; }
497 
498  OPM_HOST_DEVICE bool operator>=(const Evaluation& other) const
499  {
500  assert(size() == other.size());
501 
502  return value() >= other.value();
503  }
504 
505  template <class RhsValueType>
506  OPM_HOST_DEVICE bool operator<=(RhsValueType other) const
507  { return value() <= other; }
508 
509  OPM_HOST_DEVICE bool operator<=(const Evaluation& other) const
510  {
511  assert(size() == other.size());
512 
513  return value() <= other.value();
514  }
515 
516  // return value of variable
517  OPM_HOST_DEVICE const ValueType& value() const
518  { return data_[valuepos_()]; }
519 
520  // set value of variable
521  template <class RhsValueType>
522  OPM_HOST_DEVICE constexpr void setValue(const RhsValueType& val)
523  { data_[valuepos_()] = val; }
524 
525  // return varIdx'th derivative
526  OPM_HOST_DEVICE const ValueType& derivative(int varIdx) const
527  {
528  assert(0 <= varIdx && varIdx < size());
529 
530  return data_[dstart_() + varIdx];
531  }
532 
533  // set derivative at position varIdx
534  OPM_HOST_DEVICE void setDerivative(int varIdx, const ValueType& derVal)
535  {
536  assert(0 <= varIdx && varIdx < size());
537 
538  data_[dstart_() + varIdx] = derVal;
539  }
540 
541  template<class Serializer>
542  OPM_HOST_DEVICE void serializeOp(Serializer& serializer)
543  {
544  serializer(data_);
545  }
546 
547 private:
548  std::array<ValueT, numDerivs + 1> data_;
549 };
550 
551 // the generic operators are only required for the unspecialized case
552 template <class RhsValueType, class ValueType, int numVars, unsigned staticSize>
553 OPM_HOST_DEVICE bool operator<(const RhsValueType& a, const Evaluation<ValueType, numVars, staticSize>& b)
554 { return b > a; }
555 
556 template <class RhsValueType, class ValueType, int numVars, unsigned staticSize>
557 OPM_HOST_DEVICE bool operator>(const RhsValueType& a, const Evaluation<ValueType, numVars, staticSize>& b)
558 { return b < a; }
559 
560 template <class RhsValueType, class ValueType, int numVars, unsigned staticSize>
561 OPM_HOST_DEVICE bool operator<=(const RhsValueType& a, const Evaluation<ValueType, numVars, staticSize>& b)
562 { return b >= a; }
563 
564 template <class RhsValueType, class ValueType, int numVars, unsigned staticSize>
565 OPM_HOST_DEVICE bool operator>=(const RhsValueType& a, const Evaluation<ValueType, numVars, staticSize>& b)
566 { return b <= a; }
567 
568 template <class RhsValueType, class ValueType, int numVars, unsigned staticSize>
569 OPM_HOST_DEVICE bool operator!=(const RhsValueType& a, const Evaluation<ValueType, numVars, staticSize>& b)
570 { return a != b.value(); }
571 
572 template <class RhsValueType, class ValueType, int numVars, unsigned staticSize>
573 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> operator+(const RhsValueType& a, const Evaluation<ValueType, numVars, staticSize>& b)
574 {
575  Evaluation<ValueType, numVars, staticSize> result(b);
576  result += a;
577  return result;
578 }
579 
580 template <class RhsValueType, class ValueType, int numVars, unsigned staticSize>
581 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> operator-(const RhsValueType& a, const Evaluation<ValueType, numVars, staticSize>& b)
582 {
583  return -(b - a);
584 }
585 
586 template <class RhsValueType, class ValueType, int numVars, unsigned staticSize>
587 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> operator/(const RhsValueType& a, const Evaluation<ValueType, numVars, staticSize>& b)
588 {
589  Evaluation<ValueType, numVars, staticSize> tmp(a);
590  tmp /= b;
591  return tmp;
592 }
593 
594 template <class RhsValueType, class ValueType, int numVars, unsigned staticSize>
595 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> operator*(const RhsValueType& a, const Evaluation<ValueType, numVars, staticSize>& b)
596 {
597  Evaluation<ValueType, numVars, staticSize> result(b);
598  result *= a;
599  return result;
600 }
601 
602 template<class T>
604 {
605  static constexpr bool value = false;
606 };
607 
608 template <class ValueType, int numVars, unsigned staticSize>
609 struct is_evaluation<Evaluation<ValueType,numVars,staticSize>>
610 {
611  static constexpr bool value = true;
612 };
613 
614 template <class ValueType, int numVars, unsigned staticSize>
615 OPM_HOST_DEVICE void printEvaluation(std::ostream& os,
617  bool withDer = false);
618 
619 template <class ValueType, int numVars, unsigned staticSize>
620 OPM_HOST_DEVICE std::ostream& operator<<(std::ostream& os, const Evaluation<ValueType, numVars, staticSize>& eval)
621 {
622  if constexpr (is_evaluation<ValueType>::value)
623  printEvaluation(os, eval.value(), false);
624  else
625  printEvaluation(os, eval, true);
626 
627  return os;
628 }
629 
630 } // namespace DenseAd
631 } // namespace Opm
632 
634 
635 #if HAVE_DUNE_COMMON
636 namespace Dune {
638  template <class ValueT, int numDerivs, unsigned staticSize>
639  struct IsNumber<Opm::DenseAd::Evaluation<ValueT,numDerivs,staticSize>>
640  : public std::integral_constant<bool, std::is_arithmetic<ValueT>::value> {
641  };
642 } // namespace Dune
643 #endif
644 
645 #endif // OPM_DENSEAD_EVALUATION_HPP
OPM_HOST_DEVICE constexpr int dstart_() const
start index for derivatives
Definition: Evaluation.hpp:86
OPM_HOST_DEVICE constexpr void checkDefined_() const
instruct valgrind to check that the value and all derivatives of the Evaluation object are well-defin...
Definition: Evaluation.hpp:94
OPM_HOST_DEVICE constexpr int valuepos_() const
position index for value
Definition: Evaluation.hpp:83
Definition: SymmTensor.hpp:23
OPM_HOST_DEVICE Evaluation()
default constructor
Definition: Evaluation.hpp:104
OPM_HOST_DEVICE constexpr int length_() const
length of internal data vector
Definition: Evaluation.hpp:78
bool operator>(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
Greater-than comparison operator for SummaryConfigNode objects.
Definition: SummaryConfig.hpp:280
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
ValueT ValueType
field type
Definition: Evaluation.hpp:70
OPM_HOST_DEVICE constexpr int size() const
number of derivatives
Definition: Evaluation.hpp:73
bool operator>=(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
Greater-than-or-equal comparison operator for SummaryConfigNode objects.
Definition: SummaryConfig.hpp:292
This file includes all specializations for the dense-AD Evaluation class.
static const int numVars
the template argument which specifies the number of derivatives (-1 == "DynamicSize" means runtime de...
Definition: Evaluation.hpp:67
Some templates to wrap the valgrind client request macros.
Represents a function evaluation and its derivatives w.r.t.
Definition: Evaluation.hpp:62
Definition: Evaluation.hpp:603
OPM_HOST_DEVICE constexpr int dend_() const
end+1 index for derivatives
Definition: Evaluation.hpp:89
bool operator!=(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
Inequality operator for SummaryConfigNode objects.
Definition: SummaryConfig.hpp:256