40 #include <opm/core/linalg/blas_lapack.h>
41 #include <opm/common/ErrorMacros.hpp>
50 template <
class FluxModel,
class Model>
53 const UnstructuredGrid& grid,
56 : fmodel_(fmodel), model_(model), grid_(grid), tol_(tol), maxit_(maxit)
63 double operator[](
int)
const {
return 0.0; }
65 struct StateWithZeroFlux
67 StateWithZeroFlux(std::vector<double>& s, std::vector<double>& c, std::vector<double>& cmax_arg) :
sat(s),
cpoly(c),
cmax(cmax_arg) {}
68 const ZeroVec& faceflux()
const {
return zv; }
69 const std::vector<double>& saturation()
const {
return sat; }
70 std::vector<double>& saturation() {
return sat; }
71 const std::vector<double>& concentration()
const {
return cpoly; }
72 std::vector<double>& concentration() {
return cpoly; }
73 const std::vector<double>& maxconcentration()
const {
return cmax; }
74 std::vector<double>& maxconcentration() {
return cmax; }
76 std::vector<double>&
sat;
83 Vecs(
int sz) :
sol(sz, 0.0) {}
84 const std::vector<double>& solution()
const {
return sol; }
85 std::vector<double>& writableSolution() {
return sol; }
86 std::vector<double>
sol;
90 JacSys(
int sz) :
v(sz) {}
91 const Vecs& vector()
const {
return v; }
92 Vecs& vector() {
return v; }
94 typedef std::vector<double> vector_type;
97 struct BandMatrixCoeff
99 BandMatrixCoeff(
int N,
int ku,
int kl) :
N_(N),
ku_(ku),
kl_(kl),
nrow_(2*kl + ku + 1) {
105 int operator ()(
int i,
int j)
const {
124 template <
class FluxModel,
class Model>
127 std::vector<double>& s,
128 std::vector<double>& c,
129 std::vector<double>&
cmax
133 StateWithZeroFlux state(s, c, cmax);
134 JacSys sys(2*grid_.number_of_cells);
135 std::vector<double> increment(2*grid_.number_of_cells, 0.0);
136 fmodel_.initStep(state, grid_, sys);
139 double max_delta = 1e100;
140 const double cmax_cell = 2.0*model_.cMax();
141 const double tol_c_cell = 1e-2*cmax_cell;
142 while (iter < maxit_) {
143 fmodel_.initIteration(state, grid_, sys);
144 int size = columns.size();
145 for(
int i = 0; i < size; ++i) {
146 solveSingleColumn(columns[i], dt, s, c, cmax, increment);
148 for (
int cell = 0; cell < grid_.number_of_cells; ++cell) {
149 double& s_cell = sys.vector().writableSolution()[2*cell + 0];
150 double& c_cell = sys.vector().writableSolution()[2*cell + 1];
151 s_cell += increment[2*cell + 0];
152 c_cell += increment[2*cell + 1];
154 double& incr = increment[2*cell + 0];
156 if (std::fabs(incr) < 1e-2) {
165 double& incr = increment[2*cell + 0];
167 if (std::fabs(incr) < 1e-2) {
171 incr = (1 - s_cell)/2.0;
172 s_cell = (1 + s_cell)/2.0;
176 double& incr = increment[2*cell + 1];
178 if (std::fabs(incr) < tol_c_cell) {
186 if (c_cell > cmax_cell) {
187 double& incr = increment[2*cell + 1];
189 if (std::fabs(incr) < tol_c_cell) {
190 incr = cmax_cell - c_cell;
193 incr = (cmax_cell - c_cell)/2.0;
194 c_cell = (cmax_cell + c_cell)/2.0;
213 const double maxelem = *std::max_element(increment.begin(), increment.end());
214 const double minelem = *std::min_element(increment.begin(), increment.end());
215 max_delta = std::max(maxelem, -minelem);
216 std::cout <<
"Iteration " << iter <<
" max_delta = " << max_delta << std::endl;
217 if (max_delta < tol_) {
222 if (max_delta >= tol_) {
223 OPM_THROW(std::runtime_error,
"Failed to converge!");
229 fmodel_.finishStep(grid_, sys.vector().solution(), state);
238 template <
class FluxModel,
class Model>
241 std::vector<double>& s,
242 std::vector<double>& c,
243 std::vector<double>&
cmax,
244 std::vector<double>& sol_vec)
248 int col_size = column_cells.size();
256 StateWithZeroFlux state(s, c, cmax);
261 const int nrow = 2*kl + ku + 1;
262 const int N = 2*col_size;
263 std::vector<double> hm(nrow*N, 0.0);
264 std::vector<double> rhs(N, 0.0);
265 const BandMatrixCoeff bmc(N, ku, kl);
268 for (
int ci = 0; ci < col_size; ++ci) {
269 std::vector<double> F(2, 0.);
270 std::vector<double> dFd1(4, 0.);
271 std::vector<double> dFd2(4, 0.);
272 std::vector<double> dF(4, 0.);
273 const int cell = column_cells[ci];
274 const int prev_cell = (ci == 0) ? -999 : column_cells[ci - 1];
275 const int next_cell = (ci == col_size - 1) ? -999 : column_cells[ci + 1];
277 for (
int j = grid_.cell_facepos[cell]; j < grid_.cell_facepos[cell+1]; ++j) {
278 const int face = grid_.cell_faces[j];
279 const int c1 = grid_.face_cells[2*face + 0];
280 const int c2 = grid_.face_cells[2*face + 1];
281 if (c1 == prev_cell || c2 == prev_cell || c1 == next_cell || c2 == next_cell) {
285 fmodel_.fluxConnection(state, grid_, dt, cell, face, &F[0], &dFd1[0], &dFd2[0]);
286 if (c1 == prev_cell || c2 == prev_cell) {
287 hm[bmc(2*ci + 0, 2*(ci - 1) + 0)] += dFd2[0];
288 hm[bmc(2*ci + 0, 2*(ci - 1) + 1)] += dFd2[1];
289 hm[bmc(2*ci + 1, 2*(ci - 1) + 0)] += dFd2[2];
290 hm[bmc(2*ci + 1, 2*(ci - 1) + 1)] += dFd2[3];
292 assert(c1 == next_cell || c2 == next_cell);
293 hm[bmc(2*ci + 0, 2*(ci + 1) + 0)] += dFd2[0];
294 hm[bmc(2*ci + 0, 2*(ci + 1) + 1)] += dFd2[1];
295 hm[bmc(2*ci + 1, 2*(ci + 1) + 0)] += dFd2[2];
296 hm[bmc(2*ci + 1, 2*(ci + 1) + 1)] += dFd2[3];
298 hm[bmc(2*ci + 0, 2*ci + 0)] += dFd1[0];
299 hm[bmc(2*ci + 0, 2*ci + 1)] += dFd1[1];
300 hm[bmc(2*ci + 1, 2*ci + 0)] += dFd1[2];
301 hm[bmc(2*ci + 1, 2*ci + 1)] += dFd1[3];
303 rhs[2*ci + 0] += F[0];
304 rhs[2*ci + 1] += F[1];
309 fmodel_.accumulation(grid_, cell, &F[0], &dF[0]);
310 hm[bmc(2*ci + 0, 2*ci + 0)] += dF[0];
311 hm[bmc(2*ci + 0, 2*ci + 1)] += dF[1];
312 hm[bmc(2*ci + 1, 2*ci + 0)] += dF[2];
313 if (std::abs(dF[3]) < 1e-12) {
314 hm[bmc(2*ci + 1, 2*ci + 1)] += 1e-12;
316 hm[bmc(2*ci + 1, 2*ci + 1)] += dF[3];
319 rhs[2*ci + 0] += F[0];
320 rhs[2*ci + 1] += F[1];
325 const int num_rhs = 1;
327 std::vector<int> ipiv(N, 0);
329 dgbsv_(&N, &kl, &ku, &num_rhs, &hm[0], &nrow, &ipiv[0], &rhs[0], &N, &info);
331 std::cerr <<
"Failed column cells: ";
332 std::copy(column_cells.begin(), column_cells.end(), std::ostream_iterator<int>(std::cerr,
" "));
334 OPM_THROW(std::runtime_error,
"Lapack reported error in dgtsv: " << info);
336 for (
int ci = 0; ci < col_size; ++ci) {
337 sol_vec[2*column_cells[ci] + 0] = -rhs[2*ci + 0];
338 sol_vec[2*column_cells[ci] + 1] = -rhs[2*ci + 1];
Definition: CompressibleTpfaPolymer.hpp:32
std::vector< double > & sat
Definition: GravityColumnSolverPolymer_impl.hpp:76
const int N_
Definition: GravityColumnSolverPolymer_impl.hpp:109
std::vector< double > & cmax
Definition: GravityColumnSolverPolymer_impl.hpp:78
const int kl_
Definition: GravityColumnSolverPolymer_impl.hpp:111
GravityColumnSolverPolymer(FluxModel &fmodel, const Model &model, const UnstructuredGrid &grid, const double tol, const int maxit)
Definition: GravityColumnSolverPolymer_impl.hpp:51
const int nrow_
Definition: GravityColumnSolverPolymer_impl.hpp:112
std::vector< double > & cpoly
Definition: GravityColumnSolverPolymer_impl.hpp:77
Vecs v
Definition: GravityColumnSolverPolymer_impl.hpp:93
const int ku_
Definition: GravityColumnSolverPolymer_impl.hpp:110
Definition: GravityColumnSolverPolymer.hpp:33
ZeroVec zv
Definition: GravityColumnSolverPolymer_impl.hpp:75
void solve(const std::vector< std::vector< int > > &columns, const double dt, std::vector< double > &s, std::vector< double > &c, std::vector< double > &cmax)
Definition: GravityColumnSolverPolymer_impl.hpp:125
std::vector< double > sol
Definition: GravityColumnSolverPolymer_impl.hpp:86