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 
43 namespace 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 ;
59  int max_it_ls;
60  int verbosity;
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());
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 */
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
Definition: AnisotropicEikonal.hpp:43
void assign(const Grid &G, const std::array< PressFunction, 2 > &f, const double split, const CellRange &cells, std::vector< double > &p)
Definition: initStateEquil_impl.hpp:310
int verbosity
Definition: ImplicitTransport.hpp:60
double norm_res
Definition: ImplicitTransport.hpp:66
double rtol
Definition: ImplicitTransport.hpp:57
ImplicitTransport(Model &model)
Definition: ImplicitTransport.hpp:107
int max_it
Definition: ImplicitTransport.hpp:55
double norm_dx
Definition: ImplicitTransport.hpp:67
Definition: ImplicitTransport.hpp:45
int max_it_ls
Definition: ImplicitTransport.hpp:59
Definition: ImplicitAssembly.hpp:45
int nit
Definition: ImplicitTransport.hpp:64
double dxtol
Definition: ImplicitTransport.hpp:58
Definition: ImplicitTransport.hpp:63
int flag
Definition: ImplicitTransport.hpp:65
NRControl()
Definition: ImplicitTransport.hpp:46
double atol
Definition: ImplicitTransport.hpp:56
Ostream & operator<<(Ostream &os, const NRReport &rpt)
Definition: ImplicitTransport.hpp:71
Definition: ImplicitTransport.hpp:105