ImplicitTransport.hpp
Go to the documentation of this file.
1/*===========================================================================
2//
3// File: ImplicitTransport.hpp
4//
5// Created: 2011-09-29 10:38:42+0200
6//
7// Authors: Ingeborg S. Ligaarden <Ingeborg.Ligaarden@sintef.no>
8// Jostein R. Natvig <Jostein.R.Natvig@sintef.no>
9// Halvor M. Nilsen <HalvorMoll.Nilsen@sintef.no>
10// Atgeirr F. Rasmussen <atgeirr@sintef.no>
11// Bård Skaflestad <Bard.Skaflestad@sintef.no>
12//
13//==========================================================================*/
14
15
16/*
17 Copyright 2011 SINTEF ICT, Applied Mathematics.
18 Copyright 2011 Statoil ASA.
19
20 This file is part of the Open Porous Media Project (OPM).
21
22 OPM is free software: you can redistribute it and/or modify
23 it under the terms of the GNU General Public License as published by
24 the Free Software Foundation, either version 3 of the License, or
25 (at your option) any later version.
26
27 OPM is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License
33 along with OPM. If not, see <http://www.gnu.org/licenses/>.
34*/
35
36#ifndef OPM_IMPLICITTRANSPORT_HPP_HEADER
37#define OPM_IMPLICITTRANSPORT_HPP_HEADER
38
40
41#include <iostream>
42
43namespace Opm {
44 namespace ImplicitTransportDetails {
45 struct NRControl {
47 : max_it(1),
48 atol(1.0e-6),
49 rtol(5.0e-7),
50 dxtol(1.0e-8),
51 max_it_ls(5),
52 verbosity(0)
53 {}
54
55 int max_it;
56 double atol ;
57 double rtol ;
58 double dxtol ;
61 };
62
63 struct NRReport {
64 int nit;
65 int flag;
66 double norm_res;
67 double norm_dx;
68 };
69
70 template <class Ostream>
71 Ostream& operator<<(Ostream& os, const NRReport& rpt)
72 {
73 os << "Number of linear solves: " << rpt.nit << '\n'
74 << "Process converged: " << (rpt.flag > 0) << '\n'
75 << "Convergence flag: " << rpt.flag;
76 switch (rpt.flag) {
77 case 1:
78 os << " (absolute tolerance satisfied)\n";
79 break;
80 case 2:
81 os << " (relative tolerance satisfied)\n";
82 break;
83 case 3:
84 os << " (solution change tolerance satisfied)\n";
85 break;
86 case -1:
87 os << " (failed to converge)\n";
88 break;
89 default:
90 os << " (unknown convergence flag)\n";
91 }
92 os << "Final residual norm: " << rpt.norm_res << '\n'
93 << "Final increment norm: " << rpt.norm_dx << '\n';
94 return os;
95 }
96 }
97
98 template <class Model ,
99 class JacobianSystem ,
100 template <class> class VNorm ,
101 template <class> class VNeg ,
102 template <class> class VZero ,
103 template <class> class MZero ,
104 template <class> class VAsgn >
106 public:
107 ImplicitTransport(Model& model)
108 : model_(model),
109 asm_ (model)
110 {}
111
112 template <class Grid ,
113 class SourceTerms ,
114 class ReservoirState,
115 class LinearSolver >
116 void solve(const Grid& g ,
117 const SourceTerms* src ,
118 const double dt ,
120 ReservoirState& state ,
121 LinearSolver& linsolve,
123 bool init;
124 typedef typename JacobianSystem::vector_type vector_type;
125 typedef typename JacobianSystem::matrix_type matrix_type;
126
127 asm_.createSystem(g, sys_);
128 model_.initStep(state, g, sys_);
129 init = model_.initIteration(state, g, sys_);
130
131 MZero<matrix_type>::zero(sys_.writableMatrix());
132 VZero<vector_type>::zero(sys_.vector().writableResidual());
133
134 asm_.assemble(state, g, src, dt, sys_);
135
136 const double nrm_res0 =
137 VNorm<vector_type>::norm(sys_.vector().residual());
138
139 rpt.norm_res = nrm_res0;
140 rpt.norm_dx = -1.0;
141 rpt.nit = 0;
142
143 bool done = false; //rpt.norm_res < ctrl.atol;
144
145 while (! done) {
146 VZero<vector_type>::zero(sys_.vector().writableIncrement());
147
148 linsolve.solve(sys_.matrix(),
149 sys_.vector().residual(),
150 sys_.vector().writableIncrement());
151
152 VNeg<vector_type>::negate(sys_.vector().writableIncrement());
153
154 //model_.finishIteration(state, g, sys_.vector());
155
156 rpt.norm_dx =
157 VNorm<vector_type>::norm(sys_.vector().increment());
158
159 // Begin line search
160 double residual=VNorm<vector_type>::norm(sys_.vector().residual());
161 int lin_it=0;
162 bool finished=rpt.norm_res<ctrl.atol;
163 double alpha=2.0;
164 // store old solution and increment before line search
165 vector_type dx_old(sys_.vector().increment());
166 vector_type x_old(sys_.vector().solution());
167 while(! finished){
168 alpha/=2.0;
169 VAsgn<vector_type>::assign(alpha, dx_old,
170 sys_.vector().writableIncrement());
171 VAsgn<vector_type>::assign(x_old,
172 sys_.vector().writableSolution());
173
174 sys_.vector().addIncrement();
175 init = model_.initIteration(state, g, sys_);
176 if (init) {
177 MZero<matrix_type>::zero(sys_.writableMatrix());
178 VZero<vector_type>::zero(sys_.vector().writableResidual());
179 asm_.assemble(state, g, src, dt, sys_);
180 residual = VNorm<vector_type>::norm(sys_.vector().residual());
181 if (ctrl.verbosity > 1){
182 std::cout << "Line search iteration " << std::scientific << lin_it
183 << " norm :" << residual << " alpha " << alpha << '\n';
184 }
185 }else{
186 if (ctrl.verbosity > 1){
187 std::cout << "Line search iteration " << std::scientific << lin_it
188 << " Value out of range, continue search. alpha " << alpha << '\n';
189 }
190 residual = 1e99;
191 }
192 finished=(residual < rpt.norm_res) || (lin_it> ctrl.max_it_ls);
193 lin_it +=1;
194 }// End line search
195 rpt.norm_res =
196 VNorm<vector_type>::norm(sys_.vector().residual());
197
198 rpt.nit++;
199 if (ctrl.verbosity > 0){
200 std::cout << "Iteration " << std::scientific << rpt.nit
201 << " norm :" << rpt.norm_res << " alpha " << alpha << std::endl;
202 }
203 done = (rpt.norm_res < ctrl.atol) ||
204 (rpt.norm_res < ctrl.rtol * nrm_res0) ||
205 (rpt.norm_dx < ctrl.dxtol) ||
206 (lin_it > ctrl.max_it_ls) ||
207 (rpt.nit == ctrl.max_it);
208 }
209
210 model_.finishStep(g, sys_.vector().solution(), state);
211
212 if (rpt.norm_res < ctrl.atol) { rpt.flag = 1; }
213 else if (rpt.norm_res < ctrl.rtol * nrm_res0) { rpt.flag = 2; }
214 else if (rpt.norm_dx < ctrl.dxtol) { rpt.flag = 3; }
215 else { rpt.flag = -1; }
216 }
217
218 private:
220 ImplicitTransport& operator=(const ImplicitTransport&);
221
222#if 0
223 using Model::initStep;
224 using Model::initIteration;
225 using Model::finishIteration;
226 using Model::finishStep;
227#endif
228
229 Model& model_;
231 JacobianSystem sys_;
232 };
233}
234#endif /* OPM_IMPLICITTRANSPORT_HPP_HEADER */
Definition: ImplicitAssembly.hpp:45
Definition: ImplicitTransport.hpp:105
void solve(const Grid &g, const SourceTerms *src, const double dt, const ImplicitTransportDetails::NRControl &ctrl, ReservoirState &state, LinearSolver &linsolve, ImplicitTransportDetails::NRReport &rpt)
Definition: ImplicitTransport.hpp:116
ImplicitTransport(Model &model)
Definition: ImplicitTransport.hpp:107
Definition: ImplicitTransportDefs.hpp:52
Ostream & operator<<(Ostream &os, const NRReport &rpt)
Definition: ImplicitTransport.hpp:71
Definition: ImplicitAssembly.hpp:43
void zero(Matrix &A)
Zero-fill a.
Definition: Matrix.hpp:602
Definition: ImplicitTransport.hpp:45
double atol
Definition: ImplicitTransport.hpp:56
int max_it
Definition: ImplicitTransport.hpp:55
NRControl()
Definition: ImplicitTransport.hpp:46
double dxtol
Definition: ImplicitTransport.hpp:58
double rtol
Definition: ImplicitTransport.hpp:57
int verbosity
Definition: ImplicitTransport.hpp:60
int max_it_ls
Definition: ImplicitTransport.hpp:59
Definition: ImplicitTransport.hpp:63
double norm_res
Definition: ImplicitTransport.hpp:66
double norm_dx
Definition: ImplicitTransport.hpp:67
int nit
Definition: ImplicitTransport.hpp:64
int flag
Definition: ImplicitTransport.hpp:65