PressureFunction.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 3 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*/
30#ifndef OPM_EQUIL_PRESSURE_FUNCTION_HPP
31#define OPM_EQUIL_PRESSURE_FUNCTION_HPP
32
33#include <array>
34#include <cassert>
35#include <cstddef>
36#include <memory>
37#include <utility>
38#include <vector>
39
40namespace Opm::EQUIL::Details {
41
45template <class Scalar, class RHS>
46class RK4IVP
47{
48public:
49 RK4IVP(const RHS& f,
50 const std::array<Scalar,2>& span,
51 const Scalar y0,
52 const int N)
53 : N_(N)
54 , span_(span)
55 {
56 // stepsize() divides by N_ and operator() evaluates interval N_ - 1.
57 // A non-positive sample count is rejected when the value is loaded in
58 // FlowGenericProblem, where its source is known.
59 assert(N >= 1);
60
61 const Scalar h = stepsize();
62 const Scalar h2 = h / 2;
63 const Scalar h6 = h / 6;
64
65 y_.reserve(N + 1);
66 f_.reserve(N + 1);
67
68 y_.push_back(y0);
69 f_.push_back(f(span_[0], y0));
70
71 for (int i = 0; i < N; ++i) {
72 const Scalar x = span_[0] + i*h;
73 const Scalar y = y_.back();
74
75 const Scalar k1 = f_[i];
76 const Scalar k2 = f(x + h2, y + h2*k1);
77 const Scalar k3 = f(x + h2, y + h2*k2);
78 const Scalar k4 = f(x + h, y + h*k3);
79
80 y_.push_back(y + h6*(k1 + 2*(k2 + k3) + k4));
81 f_.push_back(f(x + h, y_.back()));
82 }
83
84 assert (y_.size() == typename std::vector<Scalar>::size_type(N + 1));
85 }
86
87 Scalar operator()(const Scalar x) const
88 {
89 // Dense output (O(h**3)) according to Shampine
90 // (Hermite interpolation)
91 const Scalar h = stepsize();
92 int i = (x - span_[0]) / h;
93 // Crude handling of evaluation point outside "span_";
94 if (i < 0) { i = 0; }
95 if (N_ <= i) { i = N_ - 1; }
96
97 // Relative to the interval actually used, so that a point at the end of
98 // the span lands on t = 1 of the final interval rather than t = 0.
99 const Scalar t = (x - (span_[0] + i*h)) / h;
100
101 const Scalar y0 = y_[i], y1 = y_[i + 1];
102 const Scalar f0 = f_[i], f1 = f_[i + 1];
103
104 Scalar u = (1 - 2*t) * (y1 - y0);
105 u += h * ((t - 1)*f0 + t*f1);
106 u *= t * (t - 1);
107 u += (1 - t)*y0 + t*y1;
108
109 return u;
110 }
111
112private:
113 int N_;
114 std::array<Scalar,2> span_;
115 std::vector<Scalar> y_;
116 std::vector<Scalar> f_;
117
118 Scalar stepsize() const
119 { return (span_[1] - span_[0]) / N_; }
120};
121
126template <class Scalar, class ODE>
128{
129public:
130 using VSpan = std::array<Scalar, 2>;
131
132 struct InitCond {
133 Scalar depth;
134 Scalar pressure;
135 };
136
137 explicit PressureFunction(const ODE& ode,
138 const InitCond& ic,
139 const int nsample,
140 const VSpan& span)
141 : initial_(ic)
142 {
143 this->value_[Direction::Up] = std::make_unique<Distribution>
144 (ode, VSpan {{ ic.depth, span[0] }}, ic.pressure, nsample);
145
146 this->value_[Direction::Down] = std::make_unique<Distribution>
147 (ode, VSpan {{ ic.depth, span[1] }}, ic.pressure, nsample);
148 }
149
151 : initial_(rhs.initial_)
152 {
153 this->value_[Direction::Up] =
154 std::make_unique<Distribution>(*rhs.value_[Direction::Up]);
155
156 this->value_[Direction::Down] =
157 std::make_unique<Distribution>(*rhs.value_[Direction::Down]);
158 }
159
161
163 {
164 this->initial_ = rhs.initial_;
165
166 this->value_[Direction::Up] =
167 std::make_unique<Distribution>(*rhs.value_[Direction::Up]);
168
169 this->value_[Direction::Down] =
170 std::make_unique<Distribution>(*rhs.value_[Direction::Down]);
171
172 return *this;
173 }
174
176 {
177 this->initial_ = rhs.initial_;
178 this->value_ = std::move(rhs.value_);
179
180 return *this;
181 }
182
183 Scalar value(const Scalar depth) const
184 {
185 if (depth < this->initial_.depth) {
186 // Value above initial condition depth.
187 return (*this->value_[Direction::Up])(depth);
188 }
189 else if (depth > this->initial_.depth) {
190 // Value below initial condition depth.
191 return (*this->value_[Direction::Down])(depth);
192 }
193 else {
194 // Value *at* initial condition depth.
195 return this->initial_.pressure;
196 }
197 }
198
199private:
200 enum Direction : std::size_t { Up, Down, NumDir };
201
202 using Distribution = RK4IVP<Scalar, ODE>;
203 using DistrPtr = std::unique_ptr<Distribution>;
204
205 InitCond initial_;
206 std::array<DistrPtr, Direction::NumDir> value_;
207};
208
209} // namespace Opm::EQUIL::Details
210
211#endif // OPM_EQUIL_PRESSURE_FUNCTION_HPP
Definition: PressureFunction.hpp:128
PressureFunction(const PressureFunction &rhs)
Definition: PressureFunction.hpp:150
std::array< Scalar, 2 > VSpan
Definition: PressureFunction.hpp:130
PressureFunction(const ODE &ode, const InitCond &ic, const int nsample, const VSpan &span)
Definition: PressureFunction.hpp:137
PressureFunction(PressureFunction &&rhs)=default
PressureFunction & operator=(PressureFunction &&rhs)
Definition: PressureFunction.hpp:175
Scalar value(const Scalar depth) const
Definition: PressureFunction.hpp:183
PressureFunction & operator=(const PressureFunction &rhs)
Definition: PressureFunction.hpp:162
Definition: PressureFunction.hpp:47
Scalar operator()(const Scalar x) const
Definition: PressureFunction.hpp:87
RK4IVP(const RHS &f, const std::array< Scalar, 2 > &span, const Scalar y0, const int N)
Definition: PressureFunction.hpp:49
Definition: InitStateEquil.hpp:78
Definition: PressureFunction.hpp:132
Scalar pressure
Definition: PressureFunction.hpp:134
Scalar depth
Definition: PressureFunction.hpp:133