Merge pull request #32 from atgeirr/minor_improvements

A collection of minor improvements
This commit is contained in:
Bård Skaflestad
2013-09-24 01:31:15 -07:00
31 changed files with 588 additions and 430 deletions

View File

@@ -1,18 +1,3 @@
/*===========================================================================
//
// File: AutoDiff.hpp
//
// Created: 2013-04-29 10:51:23+0200
//
// Authors: Knut-Andreas Lie <Knut-Andreas.Lie@sintef.no>
// Halvor M. Nilsen <HalvorMoll.Nilsen@sintef.no>
// Atgeirr F. Rasmussen <atgeirr@sintef.no>
// Xavier Raynaud <Xavier.Raynaud@sintef.no>
// Bård Skaflestad <Bard.Skaflestad@sintef.no>
//
//==========================================================================*/
/*
Copyright 2013 SINTEF ICT, Applied Mathematics.
Copyright 2013 Statoil ASA.
@@ -33,33 +18,46 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cmath>
#ifndef OPM_AUTODIFF_HPP_HEADER
#define OPM_AUTODIFF_HPP_HEADER
namespace AutoDiff {
#include <cmath>
namespace Opm
{
/// A simple class for forward-mode automatic differentiation.
///
/// The class represents a single value and a single derivative.
/// Only basic arithmetic operators and a few functions are
/// implemented for it, it is mostly intended for simple
/// experimentation.
template <typename Scalar>
class Forward {
class AutoDiff
{
public:
static Forward
/// Create an AutoDiff object representing a constant, that
/// is, its derivative is zero.
static AutoDiff
constant(const Scalar x)
{
// Constant is function with zero derivative.
return function(x, Scalar(0));
}
static Forward
/// Create an AutoDiff object representing a primary variable,
/// that is, its derivative is one.
static AutoDiff
variable(const Scalar x)
{
// Variable is function with unit derivative (wrt. itself).
return function(x, Scalar(1));
}
static Forward
/// Create an AutoDiff object representing a function value
/// and its derivative.
static AutoDiff
function(const Scalar x, const Scalar dx)
{
return Forward(x, dx);
return AutoDiff(x, dx);
}
void
@@ -69,7 +67,7 @@ namespace AutoDiff {
}
void
operator +=(const Forward& rhs)
operator +=(const AutoDiff& rhs)
{
val_ += rhs.val_;
der_ += rhs.der_;
@@ -82,7 +80,7 @@ namespace AutoDiff {
}
void
operator -=(const Forward& rhs)
operator -=(const AutoDiff& rhs)
{
val_ -= rhs.val_;
der_ -= rhs.der_;
@@ -96,7 +94,7 @@ namespace AutoDiff {
}
void
operator *=(const Forward& rhs)
operator *=(const AutoDiff& rhs)
{
der_ = der_*rhs.val_ + val_*rhs.der_;
val_ *= rhs.val_;
@@ -110,7 +108,7 @@ namespace AutoDiff {
}
void
operator /=(const Forward& rhs)
operator /=(const AutoDiff& rhs)
{
der_ = (der_*rhs.val_ - val_*rhs.der_) / (rhs.val_ * rhs.val_);
val_ /= rhs.val_;
@@ -129,7 +127,7 @@ namespace AutoDiff {
const Scalar der() const { return der_; }
private:
Forward(const Scalar x, const Scalar dx)
AutoDiff(const Scalar x, const Scalar dx)
: val_(x), der_(dx)
{}
@@ -140,164 +138,165 @@ namespace AutoDiff {
template <class Ostream, typename Scalar>
Ostream&
operator<<(Ostream& os, const Forward<Scalar>& fw)
operator<<(Ostream& os, const AutoDiff<Scalar>& fw)
{
return fw.print(os);
}
template <typename Scalar>
Forward<Scalar>
operator +(const Forward<Scalar>& lhs,
const Forward<Scalar>& rhs)
AutoDiff<Scalar>
operator +(const AutoDiff<Scalar>& lhs,
const AutoDiff<Scalar>& rhs)
{
Forward<Scalar> ret = lhs;
AutoDiff<Scalar> ret = lhs;
ret += rhs;
return ret;
}
template <typename Scalar, typename T>
Forward<Scalar>
AutoDiff<Scalar>
operator +(const T lhs,
const Forward<Scalar>& rhs)
const AutoDiff<Scalar>& rhs)
{
Forward<Scalar> ret = rhs;
AutoDiff<Scalar> ret = rhs;
ret += Scalar(lhs);
return ret;
}
template <typename Scalar, typename T>
Forward<Scalar>
operator +(const Forward<Scalar>& lhs,
AutoDiff<Scalar>
operator +(const AutoDiff<Scalar>& lhs,
const T rhs)
{
Forward<Scalar> ret = lhs;
AutoDiff<Scalar> ret = lhs;
ret += Scalar(rhs);
return ret;
}
template <typename Scalar>
Forward<Scalar>
operator -(const Forward<Scalar>& lhs,
const Forward<Scalar>& rhs)
AutoDiff<Scalar>
operator -(const AutoDiff<Scalar>& lhs,
const AutoDiff<Scalar>& rhs)
{
Forward<Scalar> ret = lhs;
AutoDiff<Scalar> ret = lhs;
ret -= rhs;
return ret;
}
template <typename Scalar, typename T>
Forward<Scalar>
AutoDiff<Scalar>
operator -(const T lhs,
const Forward<Scalar>& rhs)
const AutoDiff<Scalar>& rhs)
{
return Forward<Scalar>::function(Scalar(lhs) - rhs.val(), -rhs.der());
return AutoDiff<Scalar>::function(Scalar(lhs) - rhs.val(), -rhs.der());
}
template <typename Scalar, typename T>
Forward<Scalar>
operator -(const Forward<Scalar>& lhs,
AutoDiff<Scalar>
operator -(const AutoDiff<Scalar>& lhs,
const T rhs)
{
Forward<Scalar> ret = lhs;
AutoDiff<Scalar> ret = lhs;
ret -= Scalar(rhs);
return ret;
}
template <typename Scalar>
Forward<Scalar>
operator *(const Forward<Scalar>& lhs,
const Forward<Scalar>& rhs)
AutoDiff<Scalar>
operator *(const AutoDiff<Scalar>& lhs,
const AutoDiff<Scalar>& rhs)
{
Forward<Scalar> ret = lhs;
AutoDiff<Scalar> ret = lhs;
ret *= rhs;
return ret;
}
template <typename Scalar, typename T>
Forward<Scalar>
AutoDiff<Scalar>
operator *(const T lhs,
const Forward<Scalar>& rhs)
const AutoDiff<Scalar>& rhs)
{
Forward<Scalar> ret = rhs;
AutoDiff<Scalar> ret = rhs;
ret *= Scalar(lhs);
return ret;
}
template <typename Scalar, typename T>
Forward<Scalar>
operator *(const Forward<Scalar>& lhs,
AutoDiff<Scalar>
operator *(const AutoDiff<Scalar>& lhs,
const T rhs)
{
Forward<Scalar> ret = lhs;
AutoDiff<Scalar> ret = lhs;
ret *= Scalar(rhs);
return ret;
}
template <typename Scalar>
Forward<Scalar>
operator /(const Forward<Scalar>& lhs,
const Forward<Scalar>& rhs)
AutoDiff<Scalar>
operator /(const AutoDiff<Scalar>& lhs,
const AutoDiff<Scalar>& rhs)
{
Forward<Scalar> ret = lhs;
AutoDiff<Scalar> ret = lhs;
ret /= rhs;
return ret;
}
template <typename Scalar, typename T>
Forward<Scalar>
AutoDiff<Scalar>
operator /(const T lhs,
const Forward<Scalar>& rhs)
const AutoDiff<Scalar>& rhs)
{
Scalar a = Scalar(lhs) / rhs.val();
Scalar b = -Scalar(lhs) / (rhs.val() * rhs.val());
return Forward<Scalar>::function(a, b);
return AutoDiff<Scalar>::function(a, b);
}
template <typename Scalar, typename T>
Forward<Scalar>
operator /(const Forward<Scalar>& lhs,
AutoDiff<Scalar>
operator /(const AutoDiff<Scalar>& lhs,
const T rhs)
{
Scalar a = lhs.val() / Scalar(rhs);
Scalar b = lhs.der() / Scalar(rhs);
return Forward<Scalar>::function(a, b);
return AutoDiff<Scalar>::function(a, b);
}
template <typename Scalar>
Forward<Scalar>
cos(const Forward<Scalar>& x)
AutoDiff<Scalar>
cos(const AutoDiff<Scalar>& x)
{
Scalar a = std::cos(x.val());
Scalar b = -std::sin(x.val()) * x.der();
return Forward<Scalar>::function(a, b);
return AutoDiff<Scalar>::function(a, b);
}
template <typename Scalar>
Forward<Scalar>
sqrt(const Forward<Scalar>& x)
AutoDiff<Scalar>
sqrt(const AutoDiff<Scalar>& x)
{
Scalar a = std::sqrt(x.val());
Scalar b = (Scalar(1.0) / (Scalar(2.0) * a)) * x.der();
return Forward<Scalar>::function(a, b);
return AutoDiff<Scalar>::function(a, b);
}
} // namespace AutoDiff
} // namespace Opm
namespace std {
using AutoDiff::cos;
using AutoDiff::sqrt;
using Opm::cos;
using Opm::sqrt;
}
#endif /* OPM_AUTODIFF_HPP_HEADER */

View File

@@ -20,32 +20,86 @@
#ifndef OPM_AUTODIFFBLOCK_HEADER_INCLUDED
#define OPM_AUTODIFFBLOCK_HEADER_INCLUDED
#include <opm/autodiff/AutoDiff.hpp>
#include <Eigen/Eigen>
#include <Eigen/Sparse>
#include <vector>
#include <cassert>
namespace AutoDiff
namespace Opm
{
/// A class for forward-mode automatic differentiation with vector
/// values and sparse jacobian matrices.
///
/// The class contains a (column) vector of values and multiple
/// sparse matrices representing its partial derivatives. Each
/// such matrix has a number of rows equal to the number of rows
/// in the value vector, and a number of columns equal to the
/// number of discrete variables we want to compute the
/// derivatives with respect to. The reason to have multiple such
/// jacobians instead of just one is to allow simpler grouping of
/// variables, making it easier to implement various
/// preconditioning schemes. Only basic arithmetic operators are
/// implemented for this class, reflecting our needs so far.
///
/// The class is built on the Eigen library, using an Eigen array
/// type to contain the values and Eigen sparse matrices for the
/// jacobians. The overloaded operators are intended to behave in
/// a similar way to Eigen arrays, meaning for example that the *
/// operator is elementwise multiplication. The only exception is
/// multiplication with a sparse matrix from the left, which is
/// treated as an Eigen matrix operation.
///
/// There are no public constructors, instead we use the Named
/// Constructor pattern. In general, one needs to know which
/// variables one wants to compute the derivatives with respect to
/// before constructing an AutoDiffBlock. Some of the constructors
/// require you to pass a block pattern. This should be a vector
/// containing the number of columns you want for each jacobian
/// matrix.
///
/// For example: you want the derivatives with respect to three
/// different variables p, r and s. Assuming that there are 10
/// elements in p, and 20 in each of r and s, the block pattern is
/// { 10, 20, 20 }. When creating the variables p, r and s in your
/// program you have two options:
/// - Use the variable() constructor three times, passing the
/// index (0 for p, 1 for r and 2 for s), initial value of
/// each variable and the block pattern.
/// - Use the variables() constructor passing only the initial
/// values of each variable. The block pattern will be
/// inferred from the size of the initial value vectors.
/// This is usually the simplest option if you have multiple
/// variables. Note that this constructor returns a vector
/// of all three variables, so you need to use index access
/// (operator[]) to get the individual variables (that is p,
/// r and s).
///
/// After this, the r variable for example will have a size() of
/// 20 and three jacobian matrices. The first is a 20 by 10 zero
/// matrix, the second is a 20 by 20 identity matrix, and the
/// third is a 20 by 20 zero matrix.
template <typename Scalar>
class ForwardBlock
class AutoDiffBlock
{
public:
/// Underlying types for scalar vectors and jacobians.
/// Underlying type for values.
typedef Eigen::Array<Scalar, Eigen::Dynamic, 1> V;
/// Underlying type for jacobians.
typedef Eigen::SparseMatrix<Scalar> M;
/// Named constructor pattern used here.
static ForwardBlock null()
/// Construct an empty AutoDiffBlock.
static AutoDiffBlock null()
{
V val;
std::vector<M> jac;
return ForwardBlock(val, jac);
return AutoDiffBlock(val, jac);
}
static ForwardBlock constant(const V& val, const std::vector<int>& blocksizes)
/// Create an AutoDiffBlock representing a constant.
/// \param[in] val values
/// \param[in] blocksizes block pattern
static AutoDiffBlock constant(const V& val, const std::vector<int>& blocksizes)
{
std::vector<M> jac;
const int num_elem = val.size();
@@ -55,10 +109,17 @@ namespace AutoDiff
for (int i = 0; i < num_blocks; ++i) {
jac[i] = M(num_elem, blocksizes[i]);
}
return ForwardBlock(val, jac);
return AutoDiffBlock(val, jac);
}
static ForwardBlock variable(const int index, const V& val, const std::vector<int>& blocksizes)
/// Create an AutoDiffBlock representing a single variable block.
/// \param[in] index index of the variable you are constructing
/// \param[in] val values
/// \param[in] blocksizes block pattern
/// The resulting object will have size() equal to block_pattern[index].
/// Its jacobians will all be zero, except for derivative()[index], which
/// will be an identity matrix.
static AutoDiffBlock variable(const int index, const V& val, const std::vector<int>& blocksizes)
{
std::vector<M> jac;
const int num_elem = val.size();
@@ -74,32 +135,35 @@ namespace AutoDiff
for (typename M::Index row = 0; row < val.size(); ++row) {
jac[index].insert(row, row) = Scalar(1.0);
}
return ForwardBlock(val, jac);
return AutoDiffBlock(val, jac);
}
static ForwardBlock function(const V& val, const std::vector<M>& jac)
/// Create an AutoDiffBlock by directly specifying values and jacobians.
/// \param[in] val values
/// \param[in] jac vector of jacobians
static AutoDiffBlock function(const V& val, const std::vector<M>& jac)
{
return ForwardBlock(val, jac);
return AutoDiffBlock(val, jac);
}
/// Construct a set of primary variables,
/// each initialized to a given vector.
static std::vector<ForwardBlock> variables(const std::vector<V>& initial_values)
/// Construct a set of primary variables, each initialized to
/// a given vector.
static std::vector<AutoDiffBlock> variables(const std::vector<V>& initial_values)
{
const int num_vars = initial_values.size();
std::vector<int> bpat;
for (int v = 0; v < num_vars; ++v) {
bpat.push_back(initial_values[v].size());
}
std::vector<ForwardBlock> vars;
std::vector<AutoDiffBlock> vars;
for (int v = 0; v < num_vars; ++v) {
vars.emplace_back(variable(v, initial_values[v], bpat));
}
return vars;
}
/// Operator +=
ForwardBlock& operator+=(const ForwardBlock& rhs)
/// Elementwise operator +=
AutoDiffBlock& operator+=(const AutoDiffBlock& rhs)
{
assert (numBlocks() == rhs.numBlocks());
assert (value().size() == rhs.value().size());
@@ -116,8 +180,8 @@ namespace AutoDiff
return *this;
}
/// Operator +
ForwardBlock operator+(const ForwardBlock& rhs) const
/// Elementwise operator +
AutoDiffBlock operator+(const AutoDiffBlock& rhs) const
{
std::vector<M> jac = jac_;
assert(numBlocks() == rhs.numBlocks());
@@ -130,8 +194,8 @@ namespace AutoDiff
return function(val_ + rhs.val_, jac);
}
/// Operator -
ForwardBlock operator-(const ForwardBlock& rhs) const
/// Elementwise operator -
AutoDiffBlock operator-(const AutoDiffBlock& rhs) const
{
std::vector<M> jac = jac_;
assert(numBlocks() == rhs.numBlocks());
@@ -144,8 +208,8 @@ namespace AutoDiff
return function(val_ - rhs.val_, jac);
}
/// Operator *
ForwardBlock operator*(const ForwardBlock& rhs) const
/// Elementwise operator *
AutoDiffBlock operator*(const AutoDiffBlock& rhs) const
{
int num_blocks = numBlocks();
std::vector<M> jac(num_blocks);
@@ -161,8 +225,8 @@ namespace AutoDiff
return function(val_ * rhs.val_, jac);
}
/// Operator /
ForwardBlock operator/(const ForwardBlock& rhs) const
/// Elementwise operator /
AutoDiffBlock operator/(const AutoDiffBlock& rhs) const
{
int num_blocks = numBlocks();
std::vector<M> jac(num_blocks);
@@ -178,6 +242,7 @@ namespace AutoDiff
}
return function(val_ / rhs.val_, jac);
}
/// I/O.
template <class Ostream>
Ostream&
@@ -214,21 +279,21 @@ namespace AutoDiff
return bp;
}
/// Function value
/// Function value.
const V& value() const
{
return val_;
}
/// Function derivatives
/// Function derivatives.
const std::vector<M>& derivative() const
{
return jac_;
}
private:
ForwardBlock(const V& val,
const std::vector<M>& jac)
AutoDiffBlock(const V& val,
const std::vector<M>& jac)
: val_(val), jac_(jac)
{
#ifndef NDEBUG
@@ -242,12 +307,15 @@ namespace AutoDiff
V val_;
std::vector<M> jac_;
};
};
// --------- Free functions and operators for AutoDiffBlock ---------
/// Stream output.
template <class Ostream, typename Scalar>
Ostream&
operator<<(Ostream& os, const ForwardBlock<Scalar>& fw)
operator<<(Ostream& os, const AutoDiffBlock<Scalar>& fw)
{
return fw.print(os);
}
@@ -255,81 +323,89 @@ namespace AutoDiff
/// Multiply with sparse matrix from the left.
template <typename Scalar>
ForwardBlock<Scalar> operator*(const typename ForwardBlock<Scalar>::M& lhs,
const ForwardBlock<Scalar>& rhs)
AutoDiffBlock<Scalar> operator*(const typename AutoDiffBlock<Scalar>::M& lhs,
const AutoDiffBlock<Scalar>& rhs)
{
int num_blocks = rhs.numBlocks();
std::vector<typename ForwardBlock<Scalar>::M> jac(num_blocks);
std::vector<typename AutoDiffBlock<Scalar>::M> jac(num_blocks);
assert(lhs.cols() == rhs.value().rows());
for (int block = 0; block < num_blocks; ++block) {
jac[block] = lhs*rhs.derivative()[block];
}
typename ForwardBlock<Scalar>::V val = lhs*rhs.value().matrix();
return ForwardBlock<Scalar>::function(val, jac);
typename AutoDiffBlock<Scalar>::V val = lhs*rhs.value().matrix();
return AutoDiffBlock<Scalar>::function(val, jac);
}
/// Elementwise multiplication with constant on the left.
template <typename Scalar>
ForwardBlock<Scalar> operator*(const typename ForwardBlock<Scalar>::V& lhs,
const ForwardBlock<Scalar>& rhs)
AutoDiffBlock<Scalar> operator*(const typename AutoDiffBlock<Scalar>::V& lhs,
const AutoDiffBlock<Scalar>& rhs)
{
return ForwardBlock<Scalar>::constant(lhs, rhs.blockPattern()) * rhs;
return AutoDiffBlock<Scalar>::constant(lhs, rhs.blockPattern()) * rhs;
}
/// Elementwise multiplication with constant on the right.
template <typename Scalar>
ForwardBlock<Scalar> operator*(const ForwardBlock<Scalar>& lhs,
const typename ForwardBlock<Scalar>::V& rhs)
AutoDiffBlock<Scalar> operator*(const AutoDiffBlock<Scalar>& lhs,
const typename AutoDiffBlock<Scalar>::V& rhs)
{
return rhs * lhs; // Commutative operation.
}
/// Elementwise addition with constant on the left.
template <typename Scalar>
ForwardBlock<Scalar> operator+(const typename ForwardBlock<Scalar>::V& lhs,
const ForwardBlock<Scalar>& rhs)
AutoDiffBlock<Scalar> operator+(const typename AutoDiffBlock<Scalar>::V& lhs,
const AutoDiffBlock<Scalar>& rhs)
{
return ForwardBlock<Scalar>::constant(lhs, rhs.blockPattern()) + rhs;
return AutoDiffBlock<Scalar>::constant(lhs, rhs.blockPattern()) + rhs;
}
/// Elementwise addition with constant on the right.
template <typename Scalar>
ForwardBlock<Scalar> operator+(const ForwardBlock<Scalar>& lhs,
const typename ForwardBlock<Scalar>::V& rhs)
AutoDiffBlock<Scalar> operator+(const AutoDiffBlock<Scalar>& lhs,
const typename AutoDiffBlock<Scalar>::V& rhs)
{
return rhs + lhs; // Commutative operation.
}
/// Elementwise subtraction with constant on the left.
template <typename Scalar>
ForwardBlock<Scalar> operator-(const typename ForwardBlock<Scalar>::V& lhs,
const ForwardBlock<Scalar>& rhs)
AutoDiffBlock<Scalar> operator-(const typename AutoDiffBlock<Scalar>::V& lhs,
const AutoDiffBlock<Scalar>& rhs)
{
return ForwardBlock<Scalar>::constant(lhs, rhs.blockPattern()) - rhs;
return AutoDiffBlock<Scalar>::constant(lhs, rhs.blockPattern()) - rhs;
}
/// Elementwise subtraction with constant on the right.
template <typename Scalar>
ForwardBlock<Scalar> operator-(const ForwardBlock<Scalar>& lhs,
const typename ForwardBlock<Scalar>::V& rhs)
AutoDiffBlock<Scalar> operator-(const AutoDiffBlock<Scalar>& lhs,
const typename AutoDiffBlock<Scalar>::V& rhs)
{
return lhs - ForwardBlock<Scalar>::constant(rhs, lhs.blockPattern());
return lhs - AutoDiffBlock<Scalar>::constant(rhs, lhs.blockPattern());
}
/// Elementwise division with constant on the left.
template <typename Scalar>
ForwardBlock<Scalar> operator/(const typename ForwardBlock<Scalar>::V& lhs,
const ForwardBlock<Scalar>& rhs)
AutoDiffBlock<Scalar> operator/(const typename AutoDiffBlock<Scalar>::V& lhs,
const AutoDiffBlock<Scalar>& rhs)
{
return ForwardBlock<Scalar>::constant(lhs, rhs.blockPattern()) / rhs;
return AutoDiffBlock<Scalar>::constant(lhs, rhs.blockPattern()) / rhs;
}
/// Elementwise division with constant on the right.
template <typename Scalar>
ForwardBlock<Scalar> operator/(const ForwardBlock<Scalar>& lhs,
const typename ForwardBlock<Scalar>::V& rhs)
AutoDiffBlock<Scalar> operator/(const AutoDiffBlock<Scalar>& lhs,
const typename AutoDiffBlock<Scalar>::V& rhs)
{
return lhs / ForwardBlock<Scalar>::constant(rhs, lhs.blockPattern());
return lhs / AutoDiffBlock<Scalar>::constant(rhs, lhs.blockPattern());
}
@@ -341,15 +417,15 @@ namespace AutoDiff
* @return The product
*/
template <typename Scalar>
ForwardBlock<Scalar> operator*(const ForwardBlock<Scalar>& lhs,
const Scalar& rhs)
AutoDiffBlock<Scalar> operator*(const AutoDiffBlock<Scalar>& lhs,
const Scalar& rhs)
{
std::vector< typename ForwardBlock<Scalar>::M > jac;
std::vector< typename AutoDiffBlock<Scalar>::M > jac;
jac.reserve( lhs.numBlocks() );
for (int block=0; block<lhs.numBlocks(); block++) {
jac.emplace_back( lhs.derivative()[block] * rhs );
}
return ForwardBlock<Scalar>::function( lhs.value() * rhs, jac );
return AutoDiffBlock<Scalar>::function( lhs.value() * rhs, jac );
}
@@ -361,14 +437,14 @@ namespace AutoDiff
* @return The product
*/
template <typename Scalar>
ForwardBlock<Scalar> operator*(const Scalar& lhs,
const ForwardBlock<Scalar>& rhs)
AutoDiffBlock<Scalar> operator*(const Scalar& lhs,
const AutoDiffBlock<Scalar>& rhs)
{
return rhs * lhs; // Commutative operation.
}
} // namespace Autodiff
} // namespace Opm

View File

@@ -26,25 +26,35 @@
#include <iostream>
namespace Opm
{
// -------------------- class HelperOps --------------------
/// Contains vectors and sparse matrices that represent subsets or
/// operations on (AD or regular) vectors of data.
struct HelperOps
{
typedef AutoDiff::ForwardBlock<double>::M M;
typedef AutoDiff::ForwardBlock<double>::V V;
typedef AutoDiffBlock<double>::M M;
typedef AutoDiffBlock<double>::V V;
/// A list of internal faces.
typedef Eigen::Array<int, Eigen::Dynamic, 1> IFaces;
IFaces internal_faces;
/// Extract for each face the difference of its adjacent cells'values.
/// Extract for each internal face the difference of its adjacent cells' values (first - second).
M ngrad;
/// Extract for each face the difference of its adjacent cells' values (second - first).
M grad;
/// Extract for each face the average of its adjacent cells' values.
M caver;
/// Extract for each cell the sum of its adjacent faces' (signed) values.
/// Extract for each cell the sum of its adjacent interior faces' (signed) values.
M div;
/// Extract for each face the difference of its adjacent cells' values (first - second).
/// For boundary faces, one of the entries per row (corresponding to the outside) is zero.
M fullngrad;
/// Extract for each cell the sum of all its adjacent faces' (signed) values.
M fulldiv;
/// Constructs all helper vectors and matrices.
HelperOps(const UnstructuredGrid& grid)
@@ -89,7 +99,21 @@ struct HelperOps
}
ngrad.setFromTriplets(ngrad_tri.begin(), ngrad_tri.end());
caver.setFromTriplets(caver_tri.begin(), caver_tri.end());
grad = -ngrad;
div = ngrad.transpose();
std::vector<Tri> fullngrad_tri;
fullngrad_tri.reserve(2*nf);
for (int i = 0; i < nf; ++i) {
if (nb(i,0) >= 0) {
fullngrad_tri.emplace_back(i, nb(i,0), 1.0);
}
if (nb(i,1) >= 0) {
fullngrad_tri.emplace_back(i, nb(i,1), -1.0);
}
}
fullngrad.resize(nf, nc);
fullngrad.setFromTriplets(fullngrad_tri.begin(), fullngrad_tri.end());
fulldiv = fullngrad.transpose();
}
};
@@ -181,7 +205,7 @@ namespace {
template <typename Scalar>
class UpwindSelector {
public:
typedef AutoDiff::ForwardBlock<Scalar> ADB;
typedef AutoDiffBlock<Scalar> ADB;
UpwindSelector(const UnstructuredGrid& g,
const HelperOps& h,
@@ -276,11 +300,11 @@ namespace {
/// Returns x(indices).
template <typename Scalar, class IntVec>
AutoDiff::ForwardBlock<Scalar>
subset(const AutoDiff::ForwardBlock<Scalar>& x,
AutoDiffBlock<Scalar>
subset(const AutoDiffBlock<Scalar>& x,
const IntVec& indices)
{
return ::constructSubsetSparseMatrix<Scalar>(x.value().size(), indices) * x;
return constructSubsetSparseMatrix<Scalar>(x.value().size(), indices) * x;
}
@@ -291,19 +315,19 @@ Eigen::Array<Scalar, Eigen::Dynamic, 1>
subset(const Eigen::Array<Scalar, Eigen::Dynamic, 1>& x,
const IntVec& indices)
{
return (::constructSubsetSparseMatrix<Scalar>(x.size(), indices) * x.matrix()).array();
return (constructSubsetSparseMatrix<Scalar>(x.size(), indices) * x.matrix()).array();
}
/// Returns v where v(indices) == x, v(!indices) == 0 and v.size() == n.
template <typename Scalar, class IntVec>
AutoDiff::ForwardBlock<Scalar>
superset(const AutoDiff::ForwardBlock<Scalar>& x,
AutoDiffBlock<Scalar>
superset(const AutoDiffBlock<Scalar>& x,
const IntVec& indices,
const int n)
{
return ::constructSupersetSparseMatrix<Scalar>(n, indices) * x;
return constructSupersetSparseMatrix<Scalar>(n, indices) * x;
}
@@ -315,7 +339,7 @@ superset(const Eigen::Array<Scalar, Eigen::Dynamic, 1>& x,
const IntVec& indices,
const int n)
{
return ::constructSupersetSparseMatrix<Scalar>(n, indices) * x.matrix();
return constructSupersetSparseMatrix<Scalar>(n, indices) * x.matrix();
}
@@ -324,10 +348,10 @@ superset(const Eigen::Array<Scalar, Eigen::Dynamic, 1>& x,
/// elements of d on the diagonal.
/// Need to mark this as inline since it is defined in a header and not a template.
inline
AutoDiff::ForwardBlock<double>::M
spdiag(const AutoDiff::ForwardBlock<double>::V& d)
AutoDiffBlock<double>::M
spdiag(const AutoDiffBlock<double>::V& d)
{
typedef AutoDiff::ForwardBlock<double>::M M;
typedef AutoDiffBlock<double>::M M;
const int n = d.size();
M mat(n, n);
@@ -346,7 +370,7 @@ spdiag(const AutoDiff::ForwardBlock<double>::V& d)
template <typename Scalar>
class Selector {
public:
typedef AutoDiff::ForwardBlock<Scalar> ADB;
typedef AutoDiffBlock<Scalar> ADB;
Selector(const typename ADB::V& selection_basis)
{
@@ -400,10 +424,10 @@ spdiag(const AutoDiff::ForwardBlock<double>::V& d)
/// Returns the input expression, but with all Jacobians collapsed to one.
inline
AutoDiff::ForwardBlock<double>
collapseJacs(const AutoDiff::ForwardBlock<double>& x)
AutoDiffBlock<double>
collapseJacs(const AutoDiffBlock<double>& x)
{
typedef AutoDiff::ForwardBlock<double> ADB;
typedef AutoDiffBlock<double> ADB;
const int nb = x.numBlocks();
typedef Eigen::Triplet<double> Tri;
int nnz = 0;
@@ -436,9 +460,9 @@ collapseJacs(const AutoDiff::ForwardBlock<double>& x)
/// Returns the vertical concatenation [ x; y ] of the inputs.
inline
AutoDiff::ForwardBlock<double>
vertcat(const AutoDiff::ForwardBlock<double>& x,
const AutoDiff::ForwardBlock<double>& y)
AutoDiffBlock<double>
vertcat(const AutoDiffBlock<double>& x,
const AutoDiffBlock<double>& y)
{
const int nx = x.size();
const int ny = y.size();
@@ -564,4 +588,7 @@ inline Eigen::ArrayXd sign (const Eigen::ArrayXd& x)
return retval;
}
} // namespace Opm
#endif // OPM_AUTODIFFHELPERS_HEADER_INCLUDED

View File

@@ -29,9 +29,16 @@ namespace Opm
class BlackoilPropertiesInterface;
/// This class is intended to present a fluid interface for
/// three-phase black-oil that is easy to use with the AD-using
/// simulators.
/// This class implements the AD-adapted fluid interface for
/// three-phase black-oil.
///
/// It is implemented by wrapping a BlackoilPropertiesInterface
/// object (the interface class defined in opm-core) and calling
/// its methods. This class does not implement rsMax() because the
/// required information is not available when wrapping a
/// BlackoilPropertiesInterface. Consequently, class
/// BlackoilPropsAd cannot be used to simulate problems involving
/// miscibility.
///
/// Most methods are available in two overloaded versions, one
/// taking a constant vector and returning the same, and one
@@ -67,7 +74,7 @@ namespace Opm
// Fluid interface //
////////////////////////////
typedef AutoDiff::ForwardBlock<double> ADB;
typedef AutoDiffBlock<double> ADB;
typedef ADB::V V;
typedef std::vector<int> Cells;

View File

@@ -35,9 +35,9 @@ namespace Opm
class SinglePvtInterface;
/// This class is intended to present a fluid interface for
/// three-phase black-oil that is easy to use with the AD-using
/// simulators.
/// This class implements the AD-adapted fluid interface for
/// three-phase black-oil. It requires an input deck from which it
/// reads all relevant property data.
///
/// Most methods are available in two overloaded versions, one
/// taking a constant vector and returning the same, and one
@@ -75,7 +75,7 @@ namespace Opm
// Fluid interface //
////////////////////////////
typedef AutoDiff::ForwardBlock<double> ADB;
typedef AutoDiffBlock<double> ADB;
typedef ADB::V V;
typedef std::vector<int> Cells;

View File

@@ -64,7 +64,7 @@ namespace Opm
// Fluid interface //
////////////////////////////
typedef AutoDiff::ForwardBlock<double> ADB;
typedef AutoDiffBlock<double> ADB;
typedef ADB::V V;
typedef ADB::M M;
typedef std::vector<int> Cells;

View File

@@ -37,6 +37,7 @@
#include <iostream>
#include <iomanip>
// A debugging utility.
#define DUMP(foo) \
do { \
std::cout << "==========================================\n" \
@@ -44,7 +45,11 @@
<< collapseJacs(foo) << std::endl; \
} while (0)
typedef AutoDiff::ForwardBlock<double> ADB;
namespace Opm {
typedef AutoDiffBlock<double> ADB;
typedef ADB::V V;
typedef ADB::M M;
typedef Eigen::Array<double,
@@ -69,7 +74,7 @@ namespace {
template <class GeoProps>
AutoDiff::ForwardBlock<double>::M
AutoDiffBlock<double>::M
gravityOperator(const UnstructuredGrid& grid,
const HelperOps& ops ,
const GeoProps& geo )
@@ -86,8 +91,8 @@ namespace {
}
}
typedef AutoDiff::ForwardBlock<double>::V V;
typedef AutoDiff::ForwardBlock<double>::M M;
typedef AutoDiffBlock<double>::V V;
typedef AutoDiffBlock<double>::M M;
const V& gpot = geo.gravityPotential();
const V& trans = geo.transmissibility();
@@ -182,8 +187,6 @@ namespace {
namespace Opm {
FullyImplicitBlackoilSolver::
FullyImplicitBlackoilSolver(const UnstructuredGrid& grid ,

View File

@@ -36,10 +36,27 @@ namespace Opm {
class WellState;
/// A fully implicit TPFA-based solver for the black-oil problem.
/// A fully implicit solver for the black-oil problem.
///
/// The simulator is capable of handling three-phase problems
/// where gas can be dissolved in oil (but not vice versa). It
/// uses an industry-standard TPFA discretization with per-phase
/// upwind weighting of mobilities.
///
/// It uses automatic differentiation via the class AutoDiffBlock
/// to simplify assembly of the jacobian matrix.
class FullyImplicitBlackoilSolver
{
public:
/// Construct a solver. It will retain references to the
/// arguments of this functions, and they are expected to
/// remain in scope for the lifetime of the solver.
/// \param[in] grid grid data structure
/// \param[in] fluid fluid properties
/// \param[in] geo rock properties
/// \param[in] rock_comp_props if non-null, rock compressibility properties
/// \param[in] wells well structure
/// \param[in] linsolver linear solver
FullyImplicitBlackoilSolver(const UnstructuredGrid& grid ,
const BlackoilPropsAdInterface& fluid,
const DerivedGeology& geo ,
@@ -53,6 +70,9 @@ namespace Opm {
/// state.saturation()
/// state.gasoilratio()
/// wstate.bhp()
/// \param[in] dt time step size
/// \param[in] state reservoir state
/// \param[in] wstate well state
void
step(const double dt ,
BlackoilState& state ,
@@ -60,7 +80,7 @@ namespace Opm {
private:
// Types and enums
typedef AutoDiff::ForwardBlock<double> ADB;
typedef AutoDiffBlock<double> ADB;
typedef ADB::V V;
typedef ADB::M M;
typedef Eigen::Array<double,

View File

@@ -27,6 +27,11 @@
namespace Opm
{
/// Class containing static geological properties that are
/// derived from grid and petrophysical properties:
/// - pore volume
/// - transmissibilities
/// - gravity potentials
class DerivedGeology
{
public:

View File

@@ -29,9 +29,10 @@
#include <iostream>
#include <iomanip>
namespace Opm {
// Repeated from inside ImpesTPFAAD for convenience.
typedef AutoDiff::ForwardBlock<double> ADB;
typedef AutoDiffBlock<double> ADB;
typedef ADB::V V;
typedef ADB::M M;
@@ -48,7 +49,7 @@ namespace {
}
template <class GeoProps>
AutoDiff::ForwardBlock<double>::M
AutoDiffBlock<double>::M
gravityOperator(const UnstructuredGrid& grid,
const HelperOps& ops ,
const GeoProps& geo )
@@ -65,8 +66,8 @@ namespace {
}
}
typedef AutoDiff::ForwardBlock<double>::V V;
typedef AutoDiff::ForwardBlock<double>::M M;
typedef AutoDiffBlock<double>::V V;
typedef AutoDiffBlock<double>::M M;
const V& gpot = geo.gravityPotential();
const V& trans = geo.transmissibility();
@@ -122,7 +123,6 @@ namespace {
} // anonymous namespace
namespace Opm {
@@ -183,7 +183,7 @@ namespace Opm {
well_kr_ = fluid_.relperm(well_s.col(0), well_s.col(1), V::Zero(nperf,1), well_cells);
const double atol = 1.0e-10;
const double rtol = 5.0e-8;
const double rtol = 5.0e-6;
const int maxit = 15;
assemble(dt, state, well_state);

View File

@@ -63,7 +63,7 @@ namespace Opm {
ImpesTPFAAD& operator=(const ImpesTPFAAD& rhs);
// Types
typedef AutoDiff::ForwardBlock<double> ADB;
typedef AutoDiffBlock<double> ADB;
typedef ADB::V V;
typedef ADB::M M;
typedef Eigen::Array<double,

View File

@@ -70,7 +70,6 @@ namespace Opm
const BlackoilPropertiesInterface& props,
const RockCompressibility* rock_comp_props,
WellsManager& wells_manager,
const std::vector<double>& src,
const FlowBoundaryConditions* bcs,
LinearSolverInterface& linsolver,
const double* gravity);
@@ -99,7 +98,6 @@ namespace Opm
const RockCompressibility* rock_comp_props_;
WellsManager& wells_manager_;
const Wells* wells_;
const std::vector<double>& src_;
const FlowBoundaryConditions* bcs_;
const double* gravity_;
// Solvers
@@ -121,12 +119,11 @@ namespace Opm
const BlackoilPropertiesInterface& props,
const RockCompressibility* rock_comp_props,
WellsManager& wells_manager,
const std::vector<double>& src,
const FlowBoundaryConditions* bcs,
LinearSolverInterface& linsolver,
const double* gravity)
{
pimpl_.reset(new Impl(param, grid, props, rock_comp_props, wells_manager, src, bcs, linsolver, gravity));
pimpl_.reset(new Impl(param, grid, props, rock_comp_props, wells_manager, bcs, linsolver, gravity));
}
@@ -235,13 +232,12 @@ namespace Opm
// \TODO: make CompressibleTpfa take src and bcs.
// \TODO: make CompressibleTpfa take bcs.
SimulatorCompressibleAd::Impl::Impl(const parameter::ParameterGroup& param,
const UnstructuredGrid& grid,
const BlackoilPropertiesInterface& props,
const RockCompressibility* rock_comp_props,
WellsManager& wells_manager,
const std::vector<double>& src,
const FlowBoundaryConditions* bcs,
LinearSolverInterface& linsolver,
const double* gravity)
@@ -250,7 +246,6 @@ namespace Opm
rock_comp_props_(rock_comp_props),
wells_manager_(wells_manager),
wells_(wells_manager.c_wells()),
src_(src),
bcs_(bcs),
gravity_(gravity),
fluid_(props_),

View File

@@ -62,8 +62,7 @@ namespace Opm
/// \param[in] grid grid data structure
/// \param[in] props fluid and rock properties
/// \param[in] rock_comp_props if non-null, rock compressibility properties
/// \param[in] well_manager well manager, may manage no (null) wells
/// \param[in] src source terms
/// \param[in] well_manager well manager
/// \param[in] bcs boundary conditions, treat as all noflow if null
/// \param[in] linsolver linear solver
/// \param[in] gravity if non-null, gravity vector
@@ -72,7 +71,6 @@ namespace Opm
const BlackoilPropertiesInterface& props,
const RockCompressibility* rock_comp_props,
WellsManager& wells_manager,
const std::vector<double>& src,
const FlowBoundaryConditions* bcs,
LinearSolverInterface& linsolver,
const double* gravity);

View File

@@ -70,7 +70,6 @@ namespace Opm
const BlackoilPropsAdInterface& props,
const RockCompressibility* rock_comp_props,
WellsManager& wells_manager,
const std::vector<double>& src,
const FlowBoundaryConditions* bcs,
LinearSolverInterface& linsolver,
const double* gravity);
@@ -99,7 +98,6 @@ namespace Opm
const RockCompressibility* rock_comp_props_;
WellsManager& wells_manager_;
const Wells* wells_;
const std::vector<double>& src_;
const FlowBoundaryConditions* bcs_;
const double* gravity_;
// Solvers
@@ -117,12 +115,11 @@ namespace Opm
const BlackoilPropsAdInterface& props,
const RockCompressibility* rock_comp_props,
WellsManager& wells_manager,
const std::vector<double>& src,
const FlowBoundaryConditions* bcs,
LinearSolverInterface& linsolver,
const double* gravity)
{
pimpl_.reset(new Impl(param, grid, props, rock_comp_props, wells_manager, src, bcs, linsolver, gravity));
pimpl_.reset(new Impl(param, grid, props, rock_comp_props, wells_manager, bcs, linsolver, gravity));
}
@@ -231,13 +228,12 @@ namespace Opm
#endif
// \TODO: make CompressibleTpfa take src and bcs.
// \TODO: Treat bcs properly.
SimulatorFullyImplicitBlackoil::Impl::Impl(const parameter::ParameterGroup& param,
const UnstructuredGrid& grid,
const BlackoilPropsAdInterface& props,
const RockCompressibility* rock_comp_props,
WellsManager& wells_manager,
const std::vector<double>& src,
const FlowBoundaryConditions* bcs,
LinearSolverInterface& linsolver,
const double* gravity)
@@ -246,7 +242,6 @@ namespace Opm
rock_comp_props_(rock_comp_props),
wells_manager_(wells_manager),
wells_(wells_manager.c_wells()),
src_(src),
bcs_(bcs),
gravity_(gravity),
geo_(grid_, props_, gravity_),
@@ -256,6 +251,10 @@ namespace Opm
param.getDefault("nl_pressure_maxiter", 10),
gravity, */
{
// Intercept usage of bcs, since we do not handle it.
if (bcs) {
OPM_THROW(std::runtime_error, "SimulatorFullyImplicitBlackoil cannot handle boundary conditions other than no-flow. Not implemented yet.");
}
// For output.
output_ = param.getDefault("output", true);
if (output_) {

View File

@@ -63,7 +63,6 @@ namespace Opm
/// \param[in] props fluid and rock properties
/// \param[in] rock_comp_props if non-null, rock compressibility properties
/// \param[in] well_manager well manager, may manage no (null) wells
/// \param[in] src source terms
/// \param[in] bcs boundary conditions, treat as all noflow if null
/// \param[in] linsolver linear solver
/// \param[in] gravity if non-null, gravity vector
@@ -72,7 +71,6 @@ namespace Opm
const BlackoilPropsAdInterface& props,
const RockCompressibility* rock_comp_props,
WellsManager& wells_manager,
const std::vector<double>& src,
const FlowBoundaryConditions* bcs,
LinearSolverInterface& linsolver,
const double* gravity);

View File

@@ -22,7 +22,7 @@
#include "config.h"
#endif // HAVE_CONFIG_H
#include <opm/autodiff/SimulatorIncompTwophaseAdfi.hpp>
#include <opm/autodiff/SimulatorIncompTwophaseAd.hpp>
#include <opm/core/utility/parameters/ParameterGroup.hpp>
#include <opm/core/utility/ErrorMacros.hpp>
@@ -60,7 +60,7 @@
namespace Opm
{
class SimulatorIncompTwophaseAdfi::Impl
class SimulatorIncompTwophaseAd::Impl
{
public:
Impl(const parameter::ParameterGroup& param,
@@ -109,7 +109,7 @@ namespace Opm
SimulatorIncompTwophaseAdfi::SimulatorIncompTwophaseAdfi(const parameter::ParameterGroup& param,
SimulatorIncompTwophaseAd::SimulatorIncompTwophaseAd(const parameter::ParameterGroup& param,
const UnstructuredGrid& grid,
const IncompPropertiesInterface& props,
const RockCompressibility* rock_comp_props,
@@ -126,7 +126,7 @@ namespace Opm
SimulatorReport SimulatorIncompTwophaseAdfi::run(SimulatorTimer& timer,
SimulatorReport SimulatorIncompTwophaseAd::run(SimulatorTimer& timer,
TwophaseState& state,
WellState& well_state)
{
@@ -310,7 +310,7 @@ namespace Opm
SimulatorIncompTwophaseAdfi::Impl::Impl(const parameter::ParameterGroup& param,
SimulatorIncompTwophaseAd::Impl::Impl(const parameter::ParameterGroup& param,
const UnstructuredGrid& grid,
const IncompPropertiesInterface& props,
const RockCompressibility* rock_comp_props,
@@ -409,7 +409,7 @@ namespace Opm
SimulatorReport SimulatorIncompTwophaseAdfi::Impl::run(SimulatorTimer& timer,
SimulatorReport SimulatorIncompTwophaseAd::Impl::run(SimulatorTimer& timer,
TwophaseState& state,
WellState& well_state)
{

View File

@@ -17,8 +17,8 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_SIMULATORINCOMPTWOPHASEADFI_HEADER_INCLUDED
#define OPM_SIMULATORINCOMPTWOPHASEADFI_HEADER_INCLUDED
#ifndef OPM_SIMULATORINCOMPTWOPHASEAD_HEADER_INCLUDED
#define OPM_SIMULATORINCOMPTWOPHASEAD_HEADER_INCLUDED
#include <boost/shared_ptr.hpp>
#include <vector>
@@ -40,7 +40,7 @@ namespace Opm
struct SimulatorReport;
/// Class collecting all necessary components for a two-phase simulation.
class SimulatorIncompTwophaseAdfi
class SimulatorIncompTwophaseAd
{
public:
/// Initialise from parameters and objects to observe.
@@ -67,14 +67,14 @@ namespace Opm
/// \param[in] bcs boundary conditions, treat as all noflow if null
/// \param[in] linsolver linear solver
/// \param[in] gravity if non-null, gravity vector
SimulatorIncompTwophaseAdfi(const parameter::ParameterGroup& param,
const UnstructuredGrid& grid,
const IncompPropertiesInterface& props,
const RockCompressibility* rock_comp_props,
WellsManager& wells_manager,
const std::vector<double>& src,
const FlowBoundaryConditions* bcs,
LinearSolverInterface& linsolver,
SimulatorIncompTwophaseAd(const parameter::ParameterGroup& param,
const UnstructuredGrid& grid,
const IncompPropertiesInterface& props,
const RockCompressibility* rock_comp_props,
WellsManager& wells_manager,
const std::vector<double>& src,
const FlowBoundaryConditions* bcs,
LinearSolverInterface& linsolver,
const double* gravity);
/// Run the simulation.
@@ -96,4 +96,4 @@ namespace Opm
} // namespace Opm
#endif // OPM_SIMULATORINCOMPTWOPHASEADFI_HEADER_INCLUDED
#endif // OPM_SIMULATORINCOMPTWOPHASEAD_HEADER_INCLUDED

View File

@@ -68,7 +68,7 @@ namespace Opm
TwophaseState& state);
private:
typedef AutoDiff::ForwardBlock<double> ADB;
typedef AutoDiffBlock<double> ADB;
typedef ADB::V V;
typedef ADB::M M;

View File

@@ -0,0 +1,49 @@
/*
Copyright 2013 SINTEF ICT, Applied Mathematics.
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_OPM-AUTODIFF_DOXYGEN_MAIN_HEADER_INCLUDED
#define OPM_OPM-AUTODIFF_DOXYGEN_MAIN_HEADER_INCLUDED
/** \mainpage Documentation for the opm-autodiff library.
<h3>Automatic differentiation</h3>
This library implements automatic differentiation for vector data with
multiple blocks of sparse jacobians. This is contained in the class
Opm::AutoDiffBlock. Also available is Opm::AutoDiff, a much simpler
single-value single-derivative AD class.
There are also some helper classes and functions that are intended to
aid in the development of solvers and simulators with AD, these
include Opm::HelperOps, Opm::UpwindSelector, Opm::subset,
Opm::superset, Opm::Selector, Opm::collapseJacs, Opm::vertcat,
Opm::Span and Opm::sign.
<h3>Solvers and simulators</h3>
There are some solvers and simulators in opm-autodiff. They should all
be considered experimental prototypes at this point. Notable simulator
prototypes include
- examples/sim_fibo_ad.cpp, a fully implicit black-oil simulator.
- examples/sim_2p_incomp_ad.cpp, a sequential incompressible 2-phase simulator.
*/
#endif // OPM_OPM-AUTODIFF_DOXYGEN_MAIN_HEADER_INCLUDED