opm-common
Evaluation4.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 */
31 #ifndef OPM_DENSEAD_EVALUATION4_HPP
32 #define OPM_DENSEAD_EVALUATION4_HPP
33 
34 #ifndef NDEBUG
36 #endif
37 
38 #include <array>
39 #include <cassert>
40 #include <iosfwd>
41 #include <stdexcept>
42 
43 #include <opm/common/ErrorMacros.hpp>
44 #include <opm/common/utility/gpuDecorators.hpp>
45 
46 namespace Opm {
47 namespace DenseAd {
48 
49 template <class ValueT>
50 class Evaluation<ValueT, 4>
51 {
52 public:
55  static const int numVars = 4;
56 
58  typedef ValueT ValueType;
59 
61  OPM_HOST_DEVICE constexpr int size() const
62  { return 4; };
63 
64 protected:
66  OPM_HOST_DEVICE constexpr int length_() const
67  { return size() + 1; }
68 
69 
71  OPM_HOST_DEVICE constexpr int valuepos_() const
72  { return 0; }
74  OPM_HOST_DEVICE constexpr int dstart_() const
75  { return 1; }
77  OPM_HOST_DEVICE constexpr int dend_() const
78  { return length_(); }
79 
82  OPM_HOST_DEVICE constexpr void checkDefined_() const
83  {
84 #ifndef NDEBUG
85  for (const auto& v: data_)
86  Valgrind::CheckDefined(v);
87 #endif
88  }
89 
90 public:
92  OPM_HOST_DEVICE Evaluation() : data_()
93  {}
94 
96  Evaluation(const Evaluation& other) = default;
97 
98 
99  // create an evaluation which represents a constant function
100  //
101  // i.e., f(x) = c. this implies an evaluation with the given value and all
102  // derivatives being zero.
103  template <class RhsValueType>
104  OPM_HOST_DEVICE constexpr Evaluation(const RhsValueType& c): data_{}
105  {
106  setValue(c);
107  clearDerivatives();
108 
109  //checkDefined_();
110  }
111 
112  // create an evaluation representing a variable with the variable position of varPos
113  // The value is set to c, all derivatives are zero except for the one at varPos, which is set to 1.
114  template <class RhsValueType>
115  OPM_HOST_DEVICE Evaluation(const RhsValueType& c, int varPos)
116  {
117  // The variable position must be in represented by the given variable descriptor
118  assert(0 <= varPos && varPos < size());
119 
120  setValue( c );
121  clearDerivatives();
122 
123  data_[varPos + dstart_()] = 1.0;
124 
125  checkDefined_();
126  }
127 
128  // set all derivatives to zero
129  OPM_HOST_DEVICE constexpr void clearDerivatives()
130  {
131  data_[1] = 0.0;
132  data_[2] = 0.0;
133  data_[3] = 0.0;
134  data_[4] = 0.0;
135  }
136 
137  // create an uninitialized Evaluation object that is compatible with the
138  // argument, but not initialized
139  //
140  // This basically boils down to the copy constructor without copying
141  // anything. If the number of derivatives is known at compile time, this
142  // is equivalent to creating an uninitialized object using the default
143  // constructor, while for dynamic evaluations, it creates an Evaluation
144  // object which exhibits the same number of derivatives as the argument.
145  OPM_HOST_DEVICE static Evaluation createBlank(const Evaluation&)
146  { return Evaluation(); }
147 
148  // create an Evaluation with value and all the derivatives to be zero
149  OPM_HOST_DEVICE static Evaluation createConstantZero(const Evaluation&)
150  { return Evaluation(0.); }
151 
152  // create an Evaluation with value to be one and all the derivatives to be zero
153  OPM_HOST_DEVICE static Evaluation createConstantOne(const Evaluation&)
154  { return Evaluation(1.); }
155 
156  // create a function evaluation for a "naked" depending variable (i.e., f(x) = x)
157  template <class RhsValueType>
158  OPM_HOST_DEVICE static Evaluation createVariable(const RhsValueType& value, int varPos)
159  {
160  // copy function value and set all derivatives to 0, except for the variable
161  // which is represented by the value (which is set to 1.0)
162  return Evaluation(value, varPos);
163  }
164 
165  template <class RhsValueType>
166  OPM_HOST_DEVICE static Evaluation createVariable(int nVars, const RhsValueType& value, int varPos)
167  {
168  if (nVars != 4)
169  throw std::logic_error("This statically-sized evaluation can only represent objects"
170  " with 4 derivatives");
171 
172  // copy function value and set all derivatives to 0, except for the variable
173  // which is represented by the value (which is set to 1.0)
174  return Evaluation(nVars, value, varPos);
175  }
176 
177  template <class RhsValueType>
178  OPM_HOST_DEVICE static Evaluation createVariable(const Evaluation&, const RhsValueType& value, int varPos)
179  {
180  // copy function value and set all derivatives to 0, except for the variable
181  // which is represented by the value (which is set to 1.0)
182  return Evaluation(value, varPos);
183  }
184 
185 
186  // "evaluate" a constant function (i.e. a function that does not depend on the set of
187  // relevant variables, f(x) = c).
188  template <class RhsValueType>
189  OPM_HOST_DEVICE static Evaluation createConstant(int nVars, const RhsValueType& value)
190  {
191  if (nVars != 4)
192  throw std::logic_error("This statically-sized evaluation can only represent objects"
193  " with 4 derivatives");
194  return Evaluation(value);
195  }
196 
197  // "evaluate" a constant function (i.e. a function that does not depend on the set of
198  // relevant variables, f(x) = c).
199  template <class RhsValueType>
200  OPM_HOST_DEVICE static Evaluation createConstant(const RhsValueType& value)
201  {
202  return Evaluation(value);
203  }
204 
205  // "evaluate" a constant function (i.e. a function that does not depend on the set of
206  // relevant variables, f(x) = c).
207  template <class RhsValueType>
208  OPM_HOST_DEVICE static Evaluation createConstant(const Evaluation&, const RhsValueType& value)
209  {
210  return Evaluation(value);
211  }
212 
213  // copy all derivatives from other
214  OPM_HOST_DEVICE void copyDerivatives(const Evaluation& other)
215  {
216  assert(size() == other.size());
217 
218  data_[1] = other.data_[1];
219  data_[2] = other.data_[2];
220  data_[3] = other.data_[3];
221  data_[4] = other.data_[4];
222  }
223 
224 
225  // add value and derivatives from other to this value and derivatives
226  OPM_HOST_DEVICE Evaluation& operator+=(const Evaluation& other)
227  {
228  assert(size() == other.size());
229 
230  data_[0] += other.data_[0];
231  data_[1] += other.data_[1];
232  data_[2] += other.data_[2];
233  data_[3] += other.data_[3];
234  data_[4] += other.data_[4];
235 
236  return *this;
237  }
238 
239  // add value from other to this values
240  template <class RhsValueType>
241  OPM_HOST_DEVICE Evaluation& operator+=(const RhsValueType& other)
242  {
243  // value is added, derivatives stay the same
244  data_[valuepos_()] += other;
245 
246  return *this;
247  }
248 
249  // subtract other's value and derivatives from this values
250  OPM_HOST_DEVICE Evaluation& operator-=(const Evaluation& other)
251  {
252  assert(size() == other.size());
253 
254  data_[0] -= other.data_[0];
255  data_[1] -= other.data_[1];
256  data_[2] -= other.data_[2];
257  data_[3] -= other.data_[3];
258  data_[4] -= other.data_[4];
259 
260  return *this;
261  }
262 
263  // subtract other's value from this values
264  template <class RhsValueType>
265  OPM_HOST_DEVICE Evaluation& operator-=(const RhsValueType& other)
266  {
267  // for constants, values are subtracted, derivatives stay the same
268  data_[valuepos_()] -= other;
269 
270  return *this;
271  }
272 
273  // multiply values and apply chain rule to derivatives: (u*v)' = (v'u + u'v)
274  OPM_HOST_DEVICE Evaluation& operator*=(const Evaluation& other)
275  {
276  assert(size() == other.size());
277 
278  // while the values are multiplied, the derivatives follow the product rule,
279  // i.e., (u*v)' = (v'u + u'v).
280  const ValueType u = this->value();
281  const ValueType v = other.value();
282 
283  // value
284  data_[valuepos_()] *= v ;
285 
286  // derivatives
287  data_[1] = data_[1] * v + other.data_[1] * u;
288  data_[2] = data_[2] * v + other.data_[2] * u;
289  data_[3] = data_[3] * v + other.data_[3] * u;
290  data_[4] = data_[4] * v + other.data_[4] * 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  data_[0] *= other;
300  data_[1] *= other;
301  data_[2] *= other;
302  data_[3] *= other;
303  data_[4] *= other;
304 
305  return *this;
306  }
307 
308  // m(u*v)' = (vu' - uv')/v^2
309  OPM_HOST_DEVICE Evaluation& operator/=(const Evaluation& other)
310  {
311  assert(size() == other.size());
312 
313  // values are divided, derivatives follow the rule for division, i.e., (u/v)' = (v'u -
314  // u'v)/v^2.
315  ValueType& u = data_[valuepos_()];
316  const ValueType& v = other.value();
317  data_[1] = (v*data_[1] - u*other.data_[1])/(v*v);
318  data_[2] = (v*data_[2] - u*other.data_[2])/(v*v);
319  data_[3] = (v*data_[3] - u*other.data_[3])/(v*v);
320  data_[4] = (v*data_[4] - u*other.data_[4])/(v*v);
321  u /= v;
322 
323  return *this;
324  }
325 
326  // divide value and derivatives by value of other
327  template <class RhsValueType>
328  OPM_HOST_DEVICE Evaluation& operator/=(const RhsValueType& other)
329  {
330  const ValueType tmp = 1.0/other;
331 
332  data_[0] *= tmp;
333  data_[1] *= tmp;
334  data_[2] *= tmp;
335  data_[3] *= tmp;
336  data_[4] *= tmp;
337 
338  return *this;
339  }
340 
341  // add two evaluation objects
342  OPM_HOST_DEVICE Evaluation operator+(const Evaluation& other) const
343  {
344  assert(size() == other.size());
345 
346  Evaluation result(*this);
347 
348  result += other;
349 
350  return result;
351  }
352 
353  // add constant to this object
354  template <class RhsValueType>
355  OPM_HOST_DEVICE Evaluation operator+(const RhsValueType& other) const
356  {
357  Evaluation result(*this);
358 
359  result += other;
360 
361  return result;
362  }
363 
364  // subtract two evaluation objects
365  OPM_HOST_DEVICE Evaluation operator-(const Evaluation& other) const
366  {
367  assert(size() == other.size());
368 
369  Evaluation result(*this);
370 
371  result -= other;
372 
373  return result;
374  }
375 
376  // subtract constant from evaluation object
377  template <class RhsValueType>
378  OPM_HOST_DEVICE Evaluation operator-(const RhsValueType& other) const
379  {
380  Evaluation result(*this);
381 
382  result -= other;
383 
384  return result;
385  }
386 
387  // negation (unary minus) operator
388  OPM_HOST_DEVICE Evaluation operator-() const
389  {
390  Evaluation result;
391 
392  // set value and derivatives to negative
393  result.data_[0] = - data_[0];
394  result.data_[1] = - data_[1];
395  result.data_[2] = - data_[2];
396  result.data_[3] = - data_[3];
397  result.data_[4] = - data_[4];
398 
399  return result;
400  }
401 
402  OPM_HOST_DEVICE Evaluation operator*(const Evaluation& other) const
403  {
404  assert(size() == other.size());
405 
406  Evaluation result(*this);
407 
408  result *= other;
409 
410  return result;
411  }
412 
413  template <class RhsValueType>
414  OPM_HOST_DEVICE Evaluation operator*(const RhsValueType& other) const
415  {
416  Evaluation result(*this);
417 
418  result *= other;
419 
420  return result;
421  }
422 
423  OPM_HOST_DEVICE Evaluation operator/(const Evaluation& other) const
424  {
425  assert(size() == other.size());
426 
427  Evaluation result(*this);
428 
429  result /= other;
430 
431  return result;
432  }
433 
434  template <class RhsValueType>
435  OPM_HOST_DEVICE Evaluation operator/(const RhsValueType& other) const
436  {
437  Evaluation result(*this);
438 
439  result /= other;
440 
441  return result;
442  }
443 
444  template <class RhsValueType>
445  OPM_HOST_DEVICE Evaluation& operator=(const RhsValueType& other)
446  {
447  setValue( other );
448  clearDerivatives();
449 
450  return *this;
451  }
452 
453  // copy assignment from evaluation
454  Evaluation& operator=(const Evaluation& other) = default;
455 
456  template <class RhsValueType>
457  OPM_HOST_DEVICE bool operator==(const RhsValueType& other) const
458  { return value() == other; }
459 
460  OPM_HOST_DEVICE bool operator==(const Evaluation& other) const
461  {
462  assert(size() == other.size());
463 
464  for (int idx = 0; idx < length_(); ++idx) {
465  if (data_[idx] != other.data_[idx]) {
466  return false;
467  }
468  }
469  return true;
470  }
471 
472  OPM_HOST_DEVICE bool operator!=(const Evaluation& other) const
473  { return !operator==(other); }
474 
475  template <class RhsValueType>
476  OPM_HOST_DEVICE bool operator!=(const RhsValueType& other) const
477  { return !operator==(other); }
478 
479  template <class RhsValueType>
480  OPM_HOST_DEVICE bool operator>(RhsValueType other) const
481  { return value() > other; }
482 
483  OPM_HOST_DEVICE bool operator>(const Evaluation& other) const
484  {
485  assert(size() == other.size());
486 
487  return value() > other.value();
488  }
489 
490  template <class RhsValueType>
491  OPM_HOST_DEVICE bool operator<(RhsValueType other) const
492  { return value() < other; }
493 
494  OPM_HOST_DEVICE bool operator<(const Evaluation& other) const
495  {
496  assert(size() == other.size());
497 
498  return value() < other.value();
499  }
500 
501  template <class RhsValueType>
502  OPM_HOST_DEVICE bool operator>=(RhsValueType other) const
503  { return value() >= other; }
504 
505  OPM_HOST_DEVICE bool operator>=(const Evaluation& other) const
506  {
507  assert(size() == other.size());
508 
509  return value() >= other.value();
510  }
511 
512  template <class RhsValueType>
513  OPM_HOST_DEVICE bool operator<=(RhsValueType other) const
514  { return value() <= other; }
515 
516  OPM_HOST_DEVICE bool operator<=(const Evaluation& other) const
517  {
518  assert(size() == other.size());
519 
520  return value() <= other.value();
521  }
522 
523  // return value of variable
524  OPM_HOST_DEVICE const ValueType& value() const
525  { return data_[valuepos_()]; }
526 
527  // set value of variable
528  template <class RhsValueType>
529  OPM_HOST_DEVICE constexpr void setValue(const RhsValueType& val)
530  { data_[valuepos_()] = val; }
531 
532  // return varIdx'th derivative
533  OPM_HOST_DEVICE const ValueType& derivative(int varIdx) const
534  {
535  assert(0 <= varIdx && varIdx < size());
536 
537  return data_[dstart_() + varIdx];
538  }
539 
540  // set derivative at position varIdx
541  OPM_HOST_DEVICE void setDerivative(int varIdx, const ValueType& derVal)
542  {
543  assert(0 <= varIdx && varIdx < size());
544 
545  data_[dstart_() + varIdx] = derVal;
546  }
547 
548  template<class Serializer>
549  OPM_HOST_DEVICE void serializeOp(Serializer& serializer)
550  {
551  serializer(data_);
552  }
553 
554 private:
555  std::array<ValueT, 5> data_;
556 };
557 
558 } // namespace DenseAd
559 } // namespace Opm
560 
561 #endif // OPM_DENSEAD_EVALUATION4_HPP
OPM_HOST_DEVICE constexpr int dstart_() const
start index for derivatives
Definition: Evaluation.hpp:87
ValueT ValueType
field type
Definition: Evaluation4.hpp:58
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:95
OPM_HOST_DEVICE constexpr int valuepos_() const
position index for value
Definition: Evaluation.hpp:84
OPM_HOST_DEVICE Evaluation()
default constructor
Definition: Evaluation.hpp:105
OPM_HOST_DEVICE Evaluation()
default constructor
Definition: Evaluation4.hpp:92
OPM_HOST_DEVICE constexpr int length_() const
length of internal data vector
Definition: Evaluation.hpp:79
OPM_HOST_DEVICE constexpr int length_() const
length of internal data vector
Definition: Evaluation4.hpp:66
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
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: Evaluation4.hpp:82
ValueT ValueType
field type
Definition: Evaluation.hpp:71
OPM_HOST_DEVICE constexpr int size() const
number of derivatives
Definition: Evaluation.hpp:74
OPM_HOST_DEVICE constexpr int size() const
number of derivatives
Definition: Evaluation4.hpp:61
OPM_HOST_DEVICE constexpr int dstart_() const
start index for derivatives
Definition: Evaluation4.hpp:74
static const int numVars
the template argument which specifies the number of derivatives (-1 == "DynamicSize" means runtime de...
Definition: Evaluation.hpp:68
OPM_HOST_DEVICE constexpr int dend_() const
end+1 index for derivatives
Definition: Evaluation4.hpp:77
Some templates to wrap the valgrind client request macros.
Represents a function evaluation and its derivatives w.r.t.
Definition: Evaluation.hpp:63
OPM_HOST_DEVICE constexpr int valuepos_() const
position index for value
Definition: Evaluation4.hpp:71