auto-generate and specialize the whole Evaluation class
older compilers (-> GCC < 5) seem to have trouble with inlining here which leads to sub-optimal performance. since it is not a big problem to also generate the unspecialized Evaluation class, let's do that instead. (for hand-written code, this would be a huge consistency/maintainance problem, though.)
This commit is contained in:
@@ -49,125 +49,609 @@ specializationTemplate = \
|
||||
/*!
|
||||
* \\file
|
||||
*
|
||||
{% if numDerivs < 0 %}
|
||||
* \\brief Representation of an evaluation of a function and its derivatives w.r.t. a set
|
||||
* of variables in the localized OPM automatic differentiation (AD) framework.
|
||||
{% else %}
|
||||
* \\brief This file specializes the dense-AD Evaluation class for {{ numDerivs }} derivatives.
|
||||
{% endif %}
|
||||
*
|
||||
* \\attention THIS FILE GETS AUTOMATICALLY GENERATED BY THE "{{ scriptName }}"
|
||||
* SCRIPT. DO NOT EDIT IT MANUALLY!
|
||||
*/
|
||||
{% if numDerivs < 0 %}
|
||||
#ifndef OPM_DENSEAD_EVALUATION_HPP
|
||||
#define OPM_DENSEAD_EVALUATION_HPP
|
||||
{% else %}
|
||||
#ifndef OPM_DENSEAD_EVALUATION{{numDerivs}}_HPP
|
||||
#define OPM_DENSEAD_EVALUATION{{numDerivs}}_HPP
|
||||
{% endif %}
|
||||
|
||||
#include "Math.hpp"
|
||||
|
||||
#include <opm/common/Valgrind.hpp>
|
||||
|
||||
#include <dune/common/version.hh>
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Opm {
|
||||
namespace DenseAd {
|
||||
|
||||
{% if numDerivs < 0 %}
|
||||
/*!
|
||||
* \\brief Represents a function evaluation and its derivatives w.r.t. a fixed set of
|
||||
* variables.
|
||||
*/
|
||||
template <class ValueT, int numDerivs>
|
||||
class Evaluation
|
||||
{% else %}
|
||||
template <class ValueT>
|
||||
struct EvaluationOps<ValueT, {{numDerivs}}>
|
||||
class Evaluation<ValueT, {{ numDerivs }}>
|
||||
{% endif %}
|
||||
{
|
||||
private:
|
||||
typedef Evaluation<ValueT, {{numDerivs}} > Eval;
|
||||
public:
|
||||
//! field type
|
||||
typedef ValueT ValueType;
|
||||
|
||||
//! number of derivatives
|
||||
{% if numDerivs < 0 %}
|
||||
static constexpr int size = numDerivs;
|
||||
{% else %}
|
||||
static constexpr int size = {{ numDerivs }};
|
||||
{% endif %}
|
||||
|
||||
protected:
|
||||
//! length of internal data vector
|
||||
static constexpr int length_ = size + 1;
|
||||
|
||||
//! position index for value
|
||||
static constexpr int valuepos_ = 0;
|
||||
//! start index for derivatives
|
||||
static constexpr int dstart_ = 1;
|
||||
//! end+1 index for derivatives
|
||||
static constexpr int dend_ = length_;
|
||||
|
||||
public:
|
||||
typedef std::array<ValueT, {{numDerivs + 1}} > DataVector;
|
||||
|
||||
static inline void assign(Eval& a, const Eval& b)
|
||||
//! default constructor
|
||||
Evaluation() : data_()
|
||||
{}
|
||||
|
||||
//! copy other function evaluation
|
||||
Evaluation(const Evaluation& other)
|
||||
{% if numDerivs < 0 %}
|
||||
: data_(other.data_)
|
||||
{ }
|
||||
{% else %}
|
||||
{
|
||||
{% for i in range(0, numDerivs+1) %}
|
||||
a.data_[{{i}}] = b.data_[{{i}}];{% endfor %}
|
||||
data_[{{i}}] = other.data_[{{i}}];{% endfor %}
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
// create an evaluation which represents a constant function
|
||||
//
|
||||
// i.e., f(x) = c. this implies an evaluation with the given value and all
|
||||
// derivatives being zero.
|
||||
template <class RhsValueType>
|
||||
Evaluation(const RhsValueType& c)
|
||||
{
|
||||
setValue( c );
|
||||
clearDerivatives();
|
||||
Valgrind::CheckDefined( data_ );
|
||||
}
|
||||
|
||||
static inline void assignNegative(Eval& a, const Eval& b)
|
||||
// create an evaluation which represents a constant function
|
||||
//
|
||||
// i.e., f(x) = c. this implies an evaluation with the given value and all
|
||||
// derivatives being zero.
|
||||
template <class RhsValueType>
|
||||
Evaluation(const RhsValueType& c, int varPos)
|
||||
{
|
||||
{% for i in range(0, numDerivs+1) %}
|
||||
a.data_[{{i}}] = - b.data_[{{i}}];{% endfor %}
|
||||
setValue( c );
|
||||
clearDerivatives();
|
||||
// The variable position must be in represented by the given variable descriptor
|
||||
assert(0 <= varPos && varPos < size);
|
||||
|
||||
data_[varPos + dstart_] = 1.0;
|
||||
Valgrind::CheckDefined(data_);
|
||||
}
|
||||
|
||||
static inline void clearDerivatives(Eval& a)
|
||||
// set all derivatives to zero
|
||||
void clearDerivatives()
|
||||
{
|
||||
{% if numDerivs < 0 %}
|
||||
for (int i = dstart_; i < dend_; ++i)
|
||||
data_[i] = 0.0;
|
||||
{% else %}
|
||||
{% for i in range(1, numDerivs+1) %}
|
||||
a.data_[{{i}}] = 0.0;{% endfor %}
|
||||
data_[{{i}}] = 0.0;{% endfor %}
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
static inline Eval& addEq(Eval& a, const Eval& b)
|
||||
// create a function evaluation for a "naked" depending variable (i.e., f(x) = x)
|
||||
template <class RhsValueType>
|
||||
static Evaluation createVariable(const RhsValueType& value, int varPos)
|
||||
{
|
||||
{% for i in range(0, numDerivs+1) %}
|
||||
a.data_[{{i}}] += b.data_[{{i}}];{% endfor %}
|
||||
|
||||
return a;
|
||||
// copy function value and set all derivatives to 0, except for the variable
|
||||
// which is represented by the value (which is set to 1.0)
|
||||
return Evaluation( value, varPos );
|
||||
}
|
||||
|
||||
static inline Eval& subEq(Eval& a, const Eval& b)
|
||||
// "evaluate" a constant function (i.e. a function that does not depend on the set of
|
||||
// relevant variables, f(x) = c).
|
||||
template <class RhsValueType>
|
||||
static Evaluation createConstant(const RhsValueType& value)
|
||||
{
|
||||
{% for i in range(0, numDerivs+1) %}
|
||||
a.data_[{{i}}] -= b.data_[{{i}}];{% endfor %}
|
||||
|
||||
return a;
|
||||
return Evaluation( value );
|
||||
}
|
||||
|
||||
static inline Eval& mulEq(Eval& a, const Eval& b)
|
||||
// print the value and the derivatives of the function evaluation
|
||||
void print(std::ostream& os = std::cout) const
|
||||
{
|
||||
// print value
|
||||
os << "v: " << value() << " / d:";
|
||||
// print derivatives
|
||||
for (int varIdx = 0; varIdx < size; ++varIdx)
|
||||
os << " " << derivative(varIdx);
|
||||
}
|
||||
|
||||
// copy all derivatives from other
|
||||
void copyDerivatives(const Evaluation& other)
|
||||
{
|
||||
for (int i = dstart_; 0 < dend_; ++i)
|
||||
data_[i] = other.data_[i];
|
||||
}
|
||||
|
||||
|
||||
// add value and derivatives from other to this values and derivatives
|
||||
Evaluation& operator+=(const Evaluation& other)
|
||||
{
|
||||
{% if numDerivs < 0 %}
|
||||
for (int i = 0; i < length_; ++i)
|
||||
data_[i] += other.data_[i];
|
||||
{% else %}
|
||||
{% for i in range(0, numDerivs+1) %}
|
||||
data_[{{i}}] += other.data_[{{i}}];{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// add value from other to this values
|
||||
template <class RhsValueType>
|
||||
Evaluation& operator+=(const RhsValueType& other)
|
||||
{
|
||||
// value is added, derivatives stay the same
|
||||
data_[valuepos_] += other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// subtract other's value and derivatives from this values
|
||||
Evaluation& operator-=(const Evaluation& other)
|
||||
{
|
||||
{% if numDerivs < 0 %}
|
||||
for (int i = 0; i < length_; ++i)
|
||||
data_[i] -= other.data_[i];
|
||||
{% else %}
|
||||
{% for i in range(0, numDerivs+1) %}
|
||||
data_[{{i}}] -= other.data_[{{i}}];{% endfor %}
|
||||
{% endif %}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// subtract other's value from this values
|
||||
template <class RhsValueType>
|
||||
Evaluation& operator-=(const RhsValueType& other)
|
||||
{
|
||||
// for constants, values are subtracted, derivatives stay the same
|
||||
data_[ valuepos_ ] -= other;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// multiply values and apply chain rule to derivatives: (u*v)' = (v'u + u'v)
|
||||
Evaluation& operator*=(const Evaluation& other)
|
||||
{
|
||||
// while the values are multiplied, the derivatives follow the product rule,
|
||||
// i.e., (u*v)' = (v'u + u'v).
|
||||
const ValueT u = a.value();
|
||||
const ValueT v = b.value();
|
||||
const ValueT u = this->value();
|
||||
const ValueT v = other.value();
|
||||
|
||||
// value
|
||||
a.data_[0] *= v ;
|
||||
this->data_[valuepos_] *= v ;
|
||||
|
||||
// derivatives{% for i in range(1, numDerivs+1) %}
|
||||
a.data_[{{i}}] = a.data_[{{i}}]*v + b.data_[{{i}}] * u;{% endfor %}
|
||||
// derivatives
|
||||
{% if numDerivs < 0 %}
|
||||
for (int i = 0; i < length_; ++i)
|
||||
this->data_[i] = this->data_[i]*v + other.data_[i] * u;
|
||||
{% else %}
|
||||
{% for i in range(1, numDerivs+1) %}
|
||||
this->data_[{{i}}] = this->data_[{{i}}]*v + other.data_[{{i}}] * u;{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
return a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class RhsType>
|
||||
static inline Eval& scalarMulEq(Eval& a, const RhsType& other)
|
||||
// m(c*u)' = c*u'
|
||||
template <class RhsValueType>
|
||||
Evaluation& operator*=(const RhsValueType& other)
|
||||
{
|
||||
{% if numDerivs < 0 %}
|
||||
for (int i = 0; i < length_; ++i)
|
||||
data_[i] *= other;
|
||||
{% else %}
|
||||
{% for i in range(0, numDerivs+1) %}
|
||||
a.data_[{{i}}] *= other;{% endfor %}
|
||||
data_[{{i}}] *= other;{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
return a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
static inline Eval& divEq(Eval& a, const Eval& b)
|
||||
// m(u*v)' = (v'u + u'v)
|
||||
Evaluation& operator/=(const Evaluation& other)
|
||||
{
|
||||
// values are divided, derivatives follow the rule for division, i.e., (u/v)' = (v'u - u'v)/v^2.
|
||||
const ValueT v_vv = 1.0 / b.value();
|
||||
const ValueT u_vv = a.value() * v_vv * v_vv;
|
||||
const ValueT v_vv = 1.0 / other.value();
|
||||
const ValueT u_vv = value() * v_vv * v_vv;
|
||||
|
||||
// value
|
||||
a.data_[0] *= v_vv;
|
||||
data_[valuepos_] *= v_vv;
|
||||
|
||||
// derivatives{% for i in range(1, numDerivs+1) %}
|
||||
a.data_[{{i}}] = a.data_[{{i}}]*v_vv - b.data_[{{i}}]*u_vv;{% endfor %}
|
||||
// derivatives
|
||||
{% if numDerivs < 0 %}
|
||||
for (int i = 0; i < length_; ++i)
|
||||
data_[i] = data_[i]*v_vv - other.data_[i]*u_vv;
|
||||
{% else %}
|
||||
{% for i in range(1, numDerivs+1) %}
|
||||
data_[{{i}}] = data_[{{i}}]*v_vv - other.data_[{{i}}]*u_vv;{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
template <class RhsType>
|
||||
static inline Eval& scalarDivEq(Eval& a, const RhsType& other)
|
||||
{
|
||||
{% for i in range(0, numDerivs+1) %}
|
||||
a.data_[{{i}}] /= other;{% endfor %}
|
||||
|
||||
return a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// divide value and derivatives by value of other
|
||||
template <class RhsValueType>
|
||||
static inline Eval divide(const RhsValueType& a, const Eval& b)
|
||||
Evaluation& operator/=(const RhsValueType& other)
|
||||
{
|
||||
Eval result;
|
||||
result.setValue( a/b.value() );
|
||||
const ValueT df_dg = - result.value()/b.value();
|
||||
ValueType tmp = 1.0/other;
|
||||
{% if numDerivs < 0 %}
|
||||
for (int i = 0; i < length_; ++i)
|
||||
data_[i] *= tmp;
|
||||
{% else %}
|
||||
{% for i in range(0, numDerivs+1) %}
|
||||
data_[{{i}}] *= tmp;{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// division of a constant by an Evaluation
|
||||
template <class RhsValueType>
|
||||
static inline Evaluation divide(const RhsValueType& a, const Evaluation& b)
|
||||
{
|
||||
Evaluation result;
|
||||
ValueType tmp = 1.0/b.value();
|
||||
result.setValue( a*tmp );
|
||||
const ValueT df_dg = - result.value()*tmp;
|
||||
|
||||
{% if numDerivs < 0 %}
|
||||
for (int i = dstart_; i < dend_; ++i)
|
||||
result.data_[i] = df_dg*b.data_[i];
|
||||
{% else %}
|
||||
{% for i in range(1, numDerivs+1) %}
|
||||
result.data_[{{i}}] = df_dg*b.data_[{{i}}];{% endfor %}
|
||||
{% endif %}
|
||||
return result;
|
||||
}
|
||||
|
||||
// add two evaluation objects
|
||||
Evaluation operator+(const Evaluation& other) const
|
||||
{
|
||||
Evaluation result(*this);
|
||||
result += other;
|
||||
return result;
|
||||
}
|
||||
|
||||
// add constant to this object
|
||||
template <class RhsValueType>
|
||||
Evaluation operator+(const RhsValueType& other) const
|
||||
{
|
||||
Evaluation result(*this);
|
||||
result += other;
|
||||
return result;
|
||||
}
|
||||
|
||||
// subtract two evaluation objects
|
||||
Evaluation operator-(const Evaluation& other) const
|
||||
{
|
||||
Evaluation result(*this);
|
||||
return (result -= other);
|
||||
}
|
||||
|
||||
// subtract constant from evaluation object
|
||||
template <class RhsValueType>
|
||||
Evaluation operator-(const RhsValueType& other) const
|
||||
{
|
||||
Evaluation result(*this);
|
||||
return (result -= other);
|
||||
}
|
||||
|
||||
// negation (unary minus) operator
|
||||
Evaluation operator-() const
|
||||
{
|
||||
Evaluation result;
|
||||
// set value and derivatives to negative
|
||||
{% if numDerivs < 0 %}
|
||||
for (int i = 0; i < length_; ++i)
|
||||
result.data_[i] = - data_[i];
|
||||
{% else %}
|
||||
{% for i in range(0, numDerivs+1) %}
|
||||
result.data_[{{i}}] = - data_[{{i}}];{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Evaluation operator*(const Evaluation& other) const
|
||||
{
|
||||
Evaluation result(*this);
|
||||
result *= other;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class RhsValueType>
|
||||
Evaluation operator*(const RhsValueType& other) const
|
||||
{
|
||||
Evaluation result(*this);
|
||||
result *= other;
|
||||
return result;
|
||||
}
|
||||
|
||||
Evaluation operator/(const Evaluation& other) const
|
||||
{
|
||||
Evaluation result(*this);
|
||||
result /= other;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class RhsValueType>
|
||||
Evaluation operator/(const RhsValueType& other) const
|
||||
{
|
||||
Evaluation result(*this);
|
||||
result /= other;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class RhsValueType>
|
||||
Evaluation& operator=(const RhsValueType& other)
|
||||
{
|
||||
setValue( other );
|
||||
clearDerivatives();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// copy assignment from evaluation
|
||||
Evaluation& operator=(const Evaluation& other)
|
||||
{
|
||||
{% if numDerivs < 0 %}
|
||||
for (int i = 0; i < length_; ++i)
|
||||
data_[i] = other.data_[i];
|
||||
{% else %}
|
||||
{% for i in range(0, numDerivs+1) %}
|
||||
data_[{{i}}] = other.data_[{{i}}];{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class RhsValueType>
|
||||
bool operator==(const RhsValueType& other) const
|
||||
{ return value() == other; }
|
||||
|
||||
bool operator==(const Evaluation& other) const
|
||||
{
|
||||
for (int idx = 0; idx < length_; ++idx)
|
||||
if (data_[idx] != other.data_[idx])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!=(const Evaluation& other) const
|
||||
{ return !operator==(other); }
|
||||
|
||||
template <class RhsValueType>
|
||||
bool operator>(RhsValueType other) const
|
||||
{ return value() > other; }
|
||||
|
||||
bool operator>(const Evaluation& other) const
|
||||
{ return value() > other.value(); }
|
||||
|
||||
template <class RhsValueType>
|
||||
bool operator<(RhsValueType other) const
|
||||
{ return value() < other; }
|
||||
|
||||
bool operator<(const Evaluation& other) const
|
||||
{ return value() < other.value(); }
|
||||
|
||||
template <class RhsValueType>
|
||||
bool operator>=(RhsValueType other) const
|
||||
{ return value() >= other; }
|
||||
|
||||
bool operator>=(const Evaluation& other) const
|
||||
{ return value() >= other.value(); }
|
||||
|
||||
template <class RhsValueType>
|
||||
bool operator<=(RhsValueType other) const
|
||||
{ return value() <= other; }
|
||||
|
||||
bool operator<=(const Evaluation& other) const
|
||||
{ return value() <= other.value(); }
|
||||
|
||||
// return value of variable
|
||||
const ValueType& value() const
|
||||
{ return data_[valuepos_]; }
|
||||
|
||||
// set value of variable
|
||||
template <class RhsValueType>
|
||||
void setValue(const RhsValueType& val)
|
||||
{ data_[valuepos_] = val; }
|
||||
|
||||
// return varIdx'th derivative
|
||||
const ValueType& derivative(int varIdx) const
|
||||
{
|
||||
assert(0 <= varIdx && varIdx < size);
|
||||
return data_[dstart_ + varIdx];
|
||||
}
|
||||
|
||||
// set derivative at position varIdx
|
||||
void setDerivative(int varIdx, const ValueType& derVal)
|
||||
{
|
||||
assert(0 <= varIdx && varIdx < size);
|
||||
data_[dstart_ + varIdx] = derVal;
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<ValueT, length_> data_;
|
||||
};
|
||||
|
||||
{# the generic operators are only required for the unspecialized case #}
|
||||
{% if numDerivs < 0 %}
|
||||
template <class RhsValueType, class ValueType, int numVars>
|
||||
bool operator<(const RhsValueType& a, const Evaluation<ValueType, numVars>& b)
|
||||
{ return b > a; }
|
||||
|
||||
template <class RhsValueType, class ValueType, int numVars>
|
||||
bool operator>(const RhsValueType& a, const Evaluation<ValueType, numVars>& b)
|
||||
{ return b < a; }
|
||||
|
||||
template <class RhsValueType, class ValueType, int numVars>
|
||||
bool operator<=(const RhsValueType& a, const Evaluation<ValueType, numVars>& b)
|
||||
{ return b >= a; }
|
||||
|
||||
template <class RhsValueType, class ValueType, int numVars>
|
||||
bool operator>=(const RhsValueType& a, const Evaluation<ValueType, numVars>& b)
|
||||
{ return b <= a; }
|
||||
|
||||
template <class RhsValueType, class ValueType, int numVars>
|
||||
bool operator!=(const RhsValueType& a, const Evaluation<ValueType, numVars>& b)
|
||||
{ return a != b.value(); }
|
||||
|
||||
template <class RhsValueType, class ValueType, int numVars>
|
||||
Evaluation<ValueType, numVars> operator+(const RhsValueType& a, const Evaluation<ValueType, numVars>& b)
|
||||
{
|
||||
Evaluation<ValueType, numVars> result(b);
|
||||
result += a;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class RhsValueType, class ValueType, int numVars>
|
||||
Evaluation<ValueType, numVars> operator-(const RhsValueType& a, const Evaluation<ValueType, numVars>& b)
|
||||
{
|
||||
Evaluation<ValueType, numVars> result(a);
|
||||
result -= b;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class RhsValueType, class ValueType, int numVars>
|
||||
Evaluation<ValueType, numVars> operator/(const RhsValueType& a, const Evaluation<ValueType, numVars>& b)
|
||||
{
|
||||
return Evaluation<ValueType, numVars>::divide(a, b);
|
||||
}
|
||||
|
||||
template <class RhsValueType, class ValueType, int numVars>
|
||||
Evaluation<ValueType, numVars> operator*(const RhsValueType& a, const Evaluation<ValueType, numVars>& b)
|
||||
{
|
||||
Evaluation<ValueType, numVars> result(b);
|
||||
result *= a;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class ValueType, int numVars>
|
||||
std::ostream& operator<<(std::ostream& os, const Evaluation<ValueType, numVars>& eval)
|
||||
{
|
||||
os << eval.value();
|
||||
return os;
|
||||
}
|
||||
{% endif %}
|
||||
} } // namespace DenseAd, Opm
|
||||
|
||||
{% if numDerivs < 0 %}
|
||||
// In Dune 2.3, the Evaluation.hpp header must be included before the fmatrix.hh
|
||||
// header. Dune 2.4+ does not suffer from this because of some c++-foo.
|
||||
//
|
||||
// for those who are wondering: in C++ function templates cannot be partially
|
||||
// specialized, and function argument overloads must be known _before_ they are used. The
|
||||
// latter is what we do for the 'Dune::fvmeta::absreal()' function.
|
||||
//
|
||||
// consider the following test program:
|
||||
//
|
||||
// double foo(double i)
|
||||
// { return i; }
|
||||
//
|
||||
// void bar()
|
||||
// { std::cout << foo(0) << "\\n"; }
|
||||
//
|
||||
// int foo(int i)
|
||||
// { return i + 1; }
|
||||
//
|
||||
// void foobar()
|
||||
// { std::cout << foo(0) << "\\n"; }
|
||||
//
|
||||
// this will print '0' for bar() and '1' for foobar()...
|
||||
#if !(DUNE_VERSION_NEWER(DUNE_COMMON, 2,4))
|
||||
|
||||
namespace Opm {
|
||||
namespace DenseAd {
|
||||
template <class ValueType, int numVars>
|
||||
Evaluation<ValueType, numVars> abs(const Evaluation<ValueType, numVars>&);
|
||||
}}
|
||||
|
||||
namespace std {
|
||||
template <class ValueType, int numVars>
|
||||
const Opm::DenseAd::Evaluation<ValueType, numVars> abs(const Opm::DenseAd::Evaluation<ValueType, numVars>& x)
|
||||
{ return Opm::DenseAd::abs(x); }
|
||||
|
||||
} // namespace std
|
||||
|
||||
#if defined DUNE_DENSEMATRIX_HH
|
||||
#warning \\
|
||||
"Due to some C++ peculiarity regarding function overloads, the 'Evaluation.hpp'" \\
|
||||
"header file must be included before Dune's 'densematrix.hh' for Dune < 2.4. " \\
|
||||
"(If Evaluations are to be used in conjunction with a dense matrix.)"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// this makes the Dune matrix/vector classes happy...
|
||||
#include <dune/common/ftraits.hh>
|
||||
|
||||
namespace Dune {
|
||||
template <class ValueType, int numVars>
|
||||
struct FieldTraits<Opm::DenseAd::Evaluation<ValueType, numVars> >
|
||||
{
|
||||
public:
|
||||
typedef Opm::DenseAd::Evaluation<ValueType, numVars> field_type;
|
||||
// setting real_type to field_type here potentially leads to slightly worse
|
||||
// performance, but at least it makes things compile.
|
||||
typedef field_type real_type;
|
||||
};
|
||||
|
||||
} // namespace Dune
|
||||
|
||||
#include "EvaluationSpecializations.hpp"
|
||||
|
||||
#endif // OPM_DENSEAD_EVALUATION_HPP
|
||||
{% else %}
|
||||
#endif // OPM_DENSEAD_EVALUATION{{numDerivs}}_HPP
|
||||
{% endif %}
|
||||
"""
|
||||
|
||||
includeSpecializationsTemplate = \
|
||||
@@ -210,6 +694,15 @@ includeSpecializationsTemplate = \
|
||||
#endif // OPM_DENSEAD_EVALUATION_SPECIALIZATIONS_HPP
|
||||
"""
|
||||
|
||||
print "Generating generic template class"
|
||||
fileName = "opm/material/densead/Evaluation.hpp"
|
||||
template = jinja2.Template(specializationTemplate)
|
||||
fileContents = template.render(numDerivs=-1, scriptName=os.path.basename(sys.argv[0]))
|
||||
|
||||
f = open(fileName, "w")
|
||||
f.write(fileContents)
|
||||
f.close()
|
||||
|
||||
for numDerivs in range(1, maxDerivs + 1):
|
||||
print "Generating specialization for %d derivatives"%numDerivs
|
||||
|
||||
|
||||
Reference in New Issue
Block a user