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