opm-common
Math.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_LOCAL_AD_MATH_HPP
33 #define OPM_LOCAL_AD_MATH_HPP
34 
35 #include "Evaluation.hpp"
36 
38 
39 #include <opm/common/utility/gpuDecorators.hpp>
40 namespace Opm {
41 namespace DenseAd {
42 // forward declaration of the Evaluation template class
43 template <class ValueT, int numVars, unsigned staticSize>
44 class Evaluation;
45 
46 // provide some algebraic functions
47 template <class ValueType, int numVars, unsigned staticSize>
48 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> abs(const Evaluation<ValueType, numVars, staticSize>& x)
49 { return (x > 0.0)?x:-x; }
50 
51 template <class ValueType, int numVars, unsigned staticSize>
52 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> min(const Evaluation<ValueType, numVars, staticSize>& x1,
53  const Evaluation<ValueType, numVars, staticSize>& x2)
54 { return (x1 < x2)?x1:x2; }
55 
56 template <class Arg1ValueType, class ValueType, int numVars, unsigned staticSize>
57 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> min(const Arg1ValueType& x1,
58  const Evaluation<ValueType, numVars, staticSize>& x2)
59 {
60  if (x1 < x2) {
61  Evaluation<ValueType, numVars, staticSize> ret(x2);
62  ret = x1;
63  return ret;
64  }
65  else
66  return x2;
67 }
68 
69 template <class ValueType, int numVars, unsigned staticSize, class Arg2ValueType>
70 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> min(const Evaluation<ValueType, numVars, staticSize>& x1,
71  const Arg2ValueType& x2)
72 { return min(x2, x1); }
73 
74 template <class ValueType, int numVars, unsigned staticSize>
75 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> max(const Evaluation<ValueType, numVars, staticSize>& x1,
76  const Evaluation<ValueType, numVars, staticSize>& x2)
77 { return (x1 > x2)?x1:x2; }
78 
79 template <class Arg1ValueType, class ValueType, int numVars, unsigned staticSize>
80 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> max(const Arg1ValueType& x1,
81  const Evaluation<ValueType, numVars, staticSize>& x2)
82 {
83  if (x1 > x2) {
84  Evaluation<ValueType, numVars, staticSize> ret(x2);
85  ret = x1;
86  return ret;
87  }
88  else
89  return x2;
90 }
91 
92 template <class ValueType, int numVars, unsigned staticSize, class Arg2ValueType>
93 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> max(const Evaluation<ValueType, numVars, staticSize>& x1,
94  const Arg2ValueType& x2)
95 { return max(x2, x1); }
96 
97 template <class ValueType, int numVars, unsigned staticSize>
98 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> tan(const Evaluation<ValueType, numVars, staticSize>& x)
99 {
100  typedef MathToolbox<ValueType> ValueTypeToolbox;
101 
102  Evaluation<ValueType, numVars, staticSize> result(x);
103 
104  const ValueType& tmp = ValueTypeToolbox::tan(x.value());
105  result.setValue(tmp);
106 
107  // derivatives use the chain rule
108  const ValueType& df_dx = 1 + tmp*tmp;
109  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
110  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
111 
112  return result;
113 }
114 
115 template <class ValueType, int numVars, unsigned staticSize>
116 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> atan(const Evaluation<ValueType, numVars, staticSize>& x)
117 {
118  typedef MathToolbox<ValueType> ValueTypeToolbox;
119 
120  Evaluation<ValueType, numVars, staticSize> result(x);
121 
122  result.setValue(ValueTypeToolbox::atan(x.value()));
123 
124  // derivatives use the chain rule
125  const ValueType& df_dx = 1/(1 + x.value()*x.value());
126  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
127  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
128 
129  return result;
130 }
131 
132 template <class ValueType, int numVars, unsigned staticSize>
133 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> atan2(const Evaluation<ValueType, numVars, staticSize>& x,
134  const Evaluation<ValueType, numVars, staticSize>& y)
135 {
136  typedef MathToolbox<ValueType> ValueTypeToolbox;
137 
138  Evaluation<ValueType, numVars, staticSize> result(x);
139 
140  result.setValue(ValueTypeToolbox::atan2(x.value(), y.value()));
141 
142  // derivatives use the chain rule
143  const ValueType& alpha = 1/(1 + (x.value()*x.value())/(y.value()*y.value()));
144  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx) {
145  result.setDerivative(curVarIdx,
146  alpha/(y.value()*y.value())
147  *(x.derivative(curVarIdx)*y.value() - x.value()*y.derivative(curVarIdx)));
148  }
149 
150  return result;
151 }
152 
153 template <class ValueType, int numVars, unsigned staticSize>
154 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> atan2(const Evaluation<ValueType, numVars, staticSize>& x,
155  const ValueType& y)
156 {
157  typedef MathToolbox<ValueType> ValueTypeToolbox;
158 
159  Evaluation<ValueType, numVars, staticSize> result(x);
160 
161  result.setValue(ValueTypeToolbox::atan2(x.value(), y));
162 
163  // derivatives use the chain rule
164  const ValueType& alpha = 1/(1 + (x.value()*x.value())/(y*y));
165  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx) {
166  result.setDerivative(curVarIdx,
167  alpha/(y*y)
168  *(x.derivative(curVarIdx)*y));
169  }
170 
171  return result;
172 }
173 
174 template <class ValueType, int numVars, unsigned staticSize>
175 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> atan2(const ValueType& x,
176  const Evaluation<ValueType, numVars, staticSize>& y)
177 {
178  typedef MathToolbox<ValueType> ValueTypeToolbox;
179 
180  Evaluation<ValueType, numVars, staticSize> result(y);
181 
182  result.setValue(ValueTypeToolbox::atan2(x, y.value()));
183 
184  // derivatives use the chain rule
185  const ValueType& alpha = 1/(1 + (x.value()*x.value())/(y.value()*y.value()));
186  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx) {
187  result.setDerivative(curVarIdx,
188  alpha/(y.value()*y.value())
189  *x*y.derivative(curVarIdx));
190  }
191 
192  return result;
193 }
194 
195 template <class ValueType, int numVars, unsigned staticSize>
196 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> sin(const Evaluation<ValueType, numVars, staticSize>& x)
197 {
198  typedef MathToolbox<ValueType> ValueTypeToolbox;
199 
200  Evaluation<ValueType, numVars, staticSize> result(x);
201 
202  result.setValue(ValueTypeToolbox::sin(x.value()));
203 
204  // derivatives use the chain rule
205  const ValueType& df_dx = ValueTypeToolbox::cos(x.value());
206  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
207  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
208 
209  return result;
210 }
211 
212 template <class ValueType, int numVars, unsigned staticSize>
213 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> asin(const Evaluation<ValueType, numVars, staticSize>& x)
214 {
215  typedef MathToolbox<ValueType> ValueTypeToolbox;
216 
217  Evaluation<ValueType, numVars, staticSize> result(x);
218 
219  result.setValue(ValueTypeToolbox::asin(x.value()));
220 
221  // derivatives use the chain rule
222  const ValueType& df_dx = 1.0/ValueTypeToolbox::sqrt(1 - x.value()*x.value());
223  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
224  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
225 
226  return result;
227 }
228 
229 template <class ValueType, int numVars, unsigned staticSize>
230 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> sinh(const Evaluation<ValueType, numVars, staticSize>& x)
231 {
232  typedef MathToolbox<ValueType> ValueTypeToolbox;
233 
234  Evaluation<ValueType, numVars, staticSize> result(x);
235 
236  result.setValue(ValueTypeToolbox::sinh(x.value()));
237 
238  // derivatives use the chain rule
239  const ValueType& df_dx = ValueTypeToolbox::cosh(x.value());
240  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
241  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
242 
243  return result;
244 }
245 
246 template <class ValueType, int numVars, unsigned staticSize>
247 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> asinh(const Evaluation<ValueType, numVars, staticSize>& x)
248 {
249  typedef MathToolbox<ValueType> ValueTypeToolbox;
250 
251  Evaluation<ValueType, numVars, staticSize> result(x);
252 
253  result.setValue(ValueTypeToolbox::asinh(x.value()));
254 
255  // derivatives use the chain rule
256  const ValueType& df_dx = 1.0/ValueTypeToolbox::sqrt(x.value()*x.value() + 1);
257  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
258  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
259 
260  return result;
261 }
262 
263 template <class ValueType, int numVars, unsigned staticSize>
264 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> cos(const Evaluation<ValueType, numVars, staticSize>& x)
265 {
266  typedef MathToolbox<ValueType> ValueTypeToolbox;
267 
268  Evaluation<ValueType, numVars, staticSize> result(x);
269 
270  result.setValue(ValueTypeToolbox::cos(x.value()));
271 
272  // derivatives use the chain rule
273  const ValueType& df_dx = -ValueTypeToolbox::sin(x.value());
274  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
275  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
276 
277  return result;
278 }
279 
280 template <class ValueType, int numVars, unsigned staticSize>
281 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> acos(const Evaluation<ValueType, numVars, staticSize>& x)
282 {
283  typedef MathToolbox<ValueType> ValueTypeToolbox;
284 
285  Evaluation<ValueType, numVars, staticSize> result(x);
286 
287  result.setValue(ValueTypeToolbox::acos(x.value()));
288 
289  // derivatives use the chain rule
290  const ValueType& df_dx = - 1.0/ValueTypeToolbox::sqrt(1 - x.value()*x.value());
291  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
292  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
293 
294  return result;
295 }
296 
297 template <class ValueType, int numVars, unsigned staticSize>
298 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> cosh(const Evaluation<ValueType, numVars, staticSize>& x)
299 {
300  typedef MathToolbox<ValueType> ValueTypeToolbox;
301 
302  Evaluation<ValueType, numVars, staticSize> result(x);
303 
304  result.setValue(ValueTypeToolbox::cosh(x.value()));
305 
306  // derivatives use the chain rule
307  const ValueType& df_dx = ValueTypeToolbox::sinh(x.value());
308  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
309  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
310 
311  return result;
312 }
313 
314 template <class ValueType, int numVars, unsigned staticSize>
315 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> acosh(const Evaluation<ValueType, numVars, staticSize>& x)
316 {
317  typedef MathToolbox<ValueType> ValueTypeToolbox;
318 
319  Evaluation<ValueType, numVars, staticSize> result(x);
320 
321  result.setValue(ValueTypeToolbox::acosh(x.value()));
322 
323  // derivatives use the chain rule
324  const ValueType& df_dx = 1.0/ValueTypeToolbox::sqrt(x.value()*x.value() - 1);
325  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
326  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
327 
328  return result;
329 }
330 
331 template <class ValueType, int numVars, unsigned staticSize>
332 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> sqrt(const Evaluation<ValueType, numVars, staticSize>& x)
333 {
334  typedef MathToolbox<ValueType> ValueTypeToolbox;
335 
336  Evaluation<ValueType, numVars, staticSize> result(x);
337 
338  const ValueType& sqrt_x = ValueTypeToolbox::sqrt(x.value());
339  result.setValue(sqrt_x);
340 
341  // derivatives use the chain rule
342  ValueType df_dx = 0.5/sqrt_x;
343  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx) {
344  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
345  }
346 
347  return result;
348 }
349 
350 template <class ValueType, int numVars, unsigned staticSize>
351 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> exp(const Evaluation<ValueType, numVars, staticSize>& x)
352 {
353  typedef MathToolbox<ValueType> ValueTypeToolbox;
354  Evaluation<ValueType, numVars, staticSize> result(x);
355 
356  const ValueType& exp_x = ValueTypeToolbox::exp(x.value());
357  result.setValue(exp_x);
358 
359  // derivatives use the chain rule
360  const ValueType& df_dx = exp_x;
361  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
362  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
363 
364  return result;
365 }
366 
367 // exponentiation of arbitrary base with a fixed constant
368 template <class ValueType, int numVars, unsigned staticSize, class ExpType>
369 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> pow(const Evaluation<ValueType, numVars, staticSize>& base,
370  const ExpType& exp)
371 {
372  typedef MathToolbox<ValueType> ValueTypeToolbox;
373  Evaluation<ValueType, numVars, staticSize> result(base);
374 
375  const ValueType& pow_x = ValueTypeToolbox::pow(base.value(), exp);
376  result.setValue(pow_x);
377 
378  if (base == 0.0) {
379  // we special case the base 0 case because 0.0 is in the valid range of the
380  // base but the generic code leads to NaNs.
381  result = 0.0;
382  }
383  else {
384  // derivatives use the chain rule
385  const ValueType& df_dx = pow_x/base.value()*exp;
386  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
387  result.setDerivative(curVarIdx, df_dx*base.derivative(curVarIdx));
388  }
389 
390  return result;
391 }
392 
393 // exponentiation of constant base with an arbitrary exponent
394 template <class BaseType, class ValueType, int numVars, unsigned staticSize>
395 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> pow(const BaseType& base,
396  const Evaluation<ValueType, numVars, staticSize>& exp)
397 {
398  typedef MathToolbox<ValueType> ValueTypeToolbox;
399 
400  Evaluation<ValueType, numVars, staticSize> result(exp);
401 
402  if (base == 0.0) {
403  // we special case the base 0 case because 0.0 is in the valid range of the
404  // base but the generic code leads to NaNs.
405  result = 0.0;
406  }
407  else {
408  const ValueType& lnBase = ValueTypeToolbox::log(base);
409  result.setValue(ValueTypeToolbox::exp(lnBase*exp.value()));
410 
411  // derivatives use the chain rule
412  const ValueType& df_dx = lnBase*result.value();
413  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
414  result.setDerivative(curVarIdx, df_dx*exp.derivative(curVarIdx));
415  }
416 
417  return result;
418 }
419 
420 // this is the most expensive power function. Computationally it is pretty expensive, so
421 // one of the above two variants above should be preferred if possible.
422 template <class ValueType, int numVars, unsigned staticSize>
423 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> pow(const Evaluation<ValueType, numVars, staticSize>& base,
424  const Evaluation<ValueType, numVars, staticSize>& exp)
425 {
426  typedef MathToolbox<ValueType> ValueTypeToolbox;
427 
428  Evaluation<ValueType, numVars, staticSize> result(base);
429 
430  if (base == 0.0) {
431  // we special case the base 0 case because 0.0 is in the valid range of the
432  // base but the generic code leads to NaNs.
433  result = 0.0;
434  }
435  else {
436  ValueType valuePow = ValueTypeToolbox::pow(base.value(), exp.value());
437  result.setValue(valuePow);
438 
439  // use the chain rule for the derivatives. since both, the base and the exponent can
440  // potentially depend on the variable set, calculating these is quite elaborate...
441  const ValueType& f = base.value();
442  const ValueType& g = exp.value();
443  const ValueType& logF = ValueTypeToolbox::log(f);
444  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx) {
445  const ValueType& fPrime = base.derivative(curVarIdx);
446  const ValueType& gPrime = exp.derivative(curVarIdx);
447  result.setDerivative(curVarIdx, (g*fPrime/f + logF*gPrime) * valuePow);
448  }
449  }
450 
451  return result;
452 }
453 
454 template <class ValueType, int numVars, unsigned staticSize>
455 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> log(const Evaluation<ValueType, numVars, staticSize>& x)
456 {
457  typedef MathToolbox<ValueType> ValueTypeToolbox;
458 
459  Evaluation<ValueType, numVars, staticSize> result(x);
460 
461  result.setValue(ValueTypeToolbox::log(x.value()));
462 
463  // derivatives use the chain rule
464  const ValueType& df_dx = 1/x.value();
465  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
466  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
467 
468  return result;
469 }
470 
471 
472 template <class ValueType, int numVars, unsigned staticSize>
473 OPM_HOST_DEVICE Evaluation<ValueType, numVars, staticSize> log10(const Evaluation<ValueType, numVars, staticSize>& x)
474 {
475  typedef MathToolbox<ValueType> ValueTypeToolbox;
476 
477  Evaluation<ValueType, numVars, staticSize> result(x);
478 
479  result.setValue(ValueTypeToolbox::log10(x.value()));
480 
481  // derivatives use the chain rule
482  const ValueType& df_dx = 1/x.value() * ValueTypeToolbox::log10(ValueTypeToolbox::exp(1.0));
483  for (int curVarIdx = 0; curVarIdx < result.size(); ++curVarIdx)
484  result.setDerivative(curVarIdx, df_dx*x.derivative(curVarIdx));
485 
486  return result;
487 }
488 
489 } // namespace DenseAd
490 
491 // a kind of traits class for the automatic differentiation case. (The toolbox for the
492 // scalar case is provided by the MathToolbox.hpp header file.)
493 template <class ValueT, int numVars, unsigned staticSize>
494 struct MathToolbox<DenseAd::Evaluation<ValueT, numVars, staticSize> >
495 {
496 private:
497 public:
498  typedef ValueT ValueType;
500  typedef typename InnerToolbox::Scalar Scalar;
502 
503  OPM_HOST_DEVICE static ValueType value(const Evaluation& eval)
504  { return eval.value(); }
505 
506  OPM_HOST_DEVICE static decltype(InnerToolbox::scalarValue(0.0)) scalarValue(const Evaluation& eval)
507  { return InnerToolbox::scalarValue(eval.value()); }
508 
509  OPM_HOST_DEVICE static Evaluation createBlank(const Evaluation& x)
510  { return Evaluation::createBlank(x); }
511 
512  OPM_HOST_DEVICE static Evaluation createConstantZero(const Evaluation& x)
513  { return Evaluation::createConstantZero(x); }
514 
515  OPM_HOST_DEVICE static Evaluation createConstantOne(const Evaluation& x)
516  { return Evaluation::createConstantOne(x); }
517 
518  OPM_HOST_DEVICE static Evaluation createConstant(ValueType value)
519  { return Evaluation::createConstant(value); }
520 
521  OPM_HOST_DEVICE static Evaluation createConstant(unsigned numDeriv, const ValueType value)
522  { return Evaluation::createConstant(numDeriv, value); }
523 
524  OPM_HOST_DEVICE static Evaluation createConstant(const Evaluation& x, const ValueType value)
525  { return Evaluation::createConstant(x, value); }
526 
527  OPM_HOST_DEVICE static Evaluation createVariable(ValueType value, int varIdx)
528  { return Evaluation::createVariable(value, varIdx); }
529 
530  template <class LhsEval>
531  OPM_HOST_DEVICE static typename std::enable_if<std::is_same<Evaluation, LhsEval>::value,
532  LhsEval>::type
533  decay(const Evaluation& eval)
534  { return eval; }
535 
536  template <class LhsEval>
537  OPM_HOST_DEVICE static typename std::enable_if<std::is_same<Evaluation, LhsEval>::value,
538  LhsEval>::type
539  decay(const Evaluation&& eval)
540  { return eval; }
541 
542  template <class LhsEval>
543  OPM_HOST_DEVICE static typename std::enable_if<std::is_floating_point<LhsEval>::value,
544  LhsEval>::type
545  decay(const Evaluation& eval)
546  { return eval.value(); }
547 
548  // comparison
549  OPM_HOST_DEVICE static bool isSame(const Evaluation& a, const Evaluation& b, Scalar tolerance)
550  {
551  typedef MathToolbox<ValueType> ValueTypeToolbox;
552 
553  // make sure that the value of the evaluation is identical
554  if (!ValueTypeToolbox::isSame(a.value(), b.value(), tolerance))
555  return false;
556 
557  // make sure that the derivatives are identical
558  for (int curVarIdx = 0; curVarIdx < numVars; ++curVarIdx)
559  if (!ValueTypeToolbox::isSame(a.derivative(curVarIdx), b.derivative(curVarIdx), tolerance))
560  return false;
561 
562  return true;
563  }
564 
565  // arithmetic functions
566  template <class Arg1Eval, class Arg2Eval>
567  OPM_HOST_DEVICE static Evaluation max(const Arg1Eval& arg1, const Arg2Eval& arg2)
568  { return DenseAd::max(arg1, arg2); }
569 
570  template <class Arg1Eval, class Arg2Eval>
571  OPM_HOST_DEVICE static Evaluation min(const Arg1Eval& arg1, const Arg2Eval& arg2)
572  { return DenseAd::min(arg1, arg2); }
573 
574  OPM_HOST_DEVICE static Evaluation abs(const Evaluation& arg)
575  { return DenseAd::abs(arg); }
576 
577  OPM_HOST_DEVICE static Evaluation tan(const Evaluation& arg)
578  { return DenseAd::tan(arg); }
579 
580  OPM_HOST_DEVICE static Evaluation atan(const Evaluation& arg)
581  { return DenseAd::atan(arg); }
582 
583  OPM_HOST_DEVICE static Evaluation atan2(const Evaluation& arg1, const Evaluation& arg2)
584  { return DenseAd::atan2(arg1, arg2); }
585 
586  template <class Eval2>
587  OPM_HOST_DEVICE static Evaluation atan2(const Evaluation& arg1, const Eval2& arg2)
588  { return DenseAd::atan2(arg1, arg2); }
589 
590  template <class Eval1>
591  OPM_HOST_DEVICE static Evaluation atan2(const Eval1& arg1, const Evaluation& arg2)
592  { return DenseAd::atan2(arg1, arg2); }
593 
594  OPM_HOST_DEVICE static Evaluation sin(const Evaluation& arg)
595  { return DenseAd::sin(arg); }
596 
597  OPM_HOST_DEVICE static Evaluation asin(const Evaluation& arg)
598  { return DenseAd::asin(arg); }
599 
600  OPM_HOST_DEVICE static Evaluation cos(const Evaluation& arg)
601  { return DenseAd::cos(arg); }
602 
603  OPM_HOST_DEVICE static Evaluation acos(const Evaluation& arg)
604  { return DenseAd::acos(arg); }
605 
606  OPM_HOST_DEVICE static Evaluation sqrt(const Evaluation& arg)
607  { return DenseAd::sqrt(arg); }
608 
609  OPM_HOST_DEVICE static Evaluation exp(const Evaluation& arg)
610  { return DenseAd::exp(arg); }
611 
612  OPM_HOST_DEVICE static Evaluation log(const Evaluation& arg)
613  { return DenseAd::log(arg); }
614 
615  OPM_HOST_DEVICE static Evaluation log10(const Evaluation& arg)
616  { return DenseAd::log10(arg); }
617 
618  template <class RhsValueType>
619  OPM_HOST_DEVICE static Evaluation pow(const Evaluation& arg1, const RhsValueType& arg2)
620  { return DenseAd::pow(arg1, arg2); }
621 
622  template <class RhsValueType>
623  OPM_HOST_DEVICE static Evaluation pow(const RhsValueType& arg1, const Evaluation& arg2)
624  { return DenseAd::pow(arg1, arg2); }
625 
626  OPM_HOST_DEVICE static Evaluation pow(const Evaluation& arg1, const Evaluation& arg2)
627  { return DenseAd::pow(arg1, arg2); }
628 
629  OPM_HOST_DEVICE static bool isfinite(const Evaluation& arg)
630  {
631  if (!InnerToolbox::isfinite(arg.value()))
632  return false;
633 
634  for (int i = 0; i < numVars; ++i)
635  if (!InnerToolbox::isfinite(arg.derivative(i)))
636  return false;
637 
638  return true;
639  }
640 
641  OPM_HOST_DEVICE static bool isnan(const Evaluation& arg)
642  {
643  if (InnerToolbox::isnan(arg.value()))
644  return true;
645 
646  for (int i = 0; i < numVars; ++i)
647  if (InnerToolbox::isnan(arg.derivative(i)))
648  return true;
649 
650  return false;
651  }
652 };
653 
654 }
655 
656 #endif
static OPM_HOST_DEVICE bool isnan(Scalar arg)
Return true iff the argument&#39;s value or any of its derivatives are NaN values.
Definition: MathToolbox.hpp:278
A traits class which provides basic mathematical functions for arbitrary scalar floating point values...
static OPM_HOST_DEVICE Scalar tan(Scalar arg)
The tangens of a value.
Definition: MathToolbox.hpp:210
static OPM_HOST_DEVICE Scalar max(Scalar arg1, Scalar arg2)
The maximum of two arguments.
Definition: MathToolbox.hpp:198
static OPM_HOST_DEVICE LhsEval decay(Scalar value)
Given a function evaluation, constrain it to its value (if necessary).
Definition: MathToolbox.hpp:174
static OPM_HOST_DEVICE Scalar createBlank(Scalar)
Given a scalar value, return a "compatible" object.
Definition: MathToolbox.hpp:102
static OPM_HOST_DEVICE Scalar sqrt(Scalar arg)
The square root of a value.
Definition: MathToolbox.hpp:254
static OPM_HOST_DEVICE Scalar cos(Scalar arg)
The cosine of a value.
Definition: MathToolbox.hpp:238
static OPM_HOST_DEVICE Scalar atan2(Scalar arg1, Scalar arg2)
The arcus tangens of a value.
Definition: MathToolbox.hpp:218
static OPM_HOST_DEVICE Scalar log10(Scalar arg)
The 10 logarithm of a value.
Definition: MathToolbox.hpp:262
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
static OPM_HOST_DEVICE Scalar log(Scalar arg)
The natural logarithm of a value.
Definition: MathToolbox.hpp:266
ScalarT ValueType
The type used to represent values.
Definition: MathToolbox.hpp:67
static OPM_HOST_DEVICE Scalar abs(Scalar arg)
The absolute value.
Definition: MathToolbox.hpp:206
static OPM_HOST_DEVICE bool isfinite(Scalar arg)
Return true iff the argument&#39;s value and all its derivatives are finite values.
Definition: MathToolbox.hpp:274
static OPM_HOST_DEVICE Scalar asin(Scalar arg)
The arcus sine of a value.
Definition: MathToolbox.hpp:226
static OPM_HOST_DEVICE Scalar value(Scalar value)
Return the value of the function at a given evaluation point.
Definition: MathToolbox.hpp:84
Definition: MathToolbox.hpp:50
ScalarT Scalar
The type used to represent "primitive" scalar values.
Definition: MathToolbox.hpp:53
static OPM_HOST_DEVICE bool isSame(Scalar a, Scalar b, Scalar tolerance)
Returns true if two values are identical up to a specified tolerance.
Definition: MathToolbox.hpp:185
static OPM_HOST_DEVICE Scalar scalarValue(Scalar value)
Return the primitive scalar value of a value object.
Definition: MathToolbox.hpp:93
static OPM_HOST_DEVICE Scalar pow(Scalar base, Scalar exp)
Exponentiation to an arbitrary base.
Definition: MathToolbox.hpp:270
static OPM_HOST_DEVICE Scalar createConstant(Scalar value)
Given a scalar value, return an evaluation of a constant function.
Definition: MathToolbox.hpp:112
static OPM_HOST_DEVICE Scalar acos(Scalar arg)
The arcus cosine of a value.
Definition: MathToolbox.hpp:242
static OPM_HOST_DEVICE Scalar atan(Scalar arg)
The arcus tangens of a value.
Definition: MathToolbox.hpp:214
MathToolbox< Scalar > InnerToolbox
The toolbox for the type of value objects.
Definition: MathToolbox.hpp:76
Represents a function evaluation and its derivatives w.r.t.
Definition: Evaluation.hpp:62
static OPM_HOST_DEVICE Scalar exp(Scalar arg)
The natural exponentiation of a value.
Definition: MathToolbox.hpp:258
static OPM_HOST_DEVICE Scalar sin(Scalar arg)
The sine of a value.
Definition: MathToolbox.hpp:222
static OPM_HOST_DEVICE Scalar createVariable(Scalar, unsigned)
Given a scalar value, return an evaluation of a linear function.
Definition: MathToolbox.hpp:148
Representation of an evaluation of a function and its derivatives w.r.t.
static OPM_HOST_DEVICE Scalar min(Scalar arg1, Scalar arg2)
The minimum of two arguments.
Definition: MathToolbox.hpp:202