SimulatorFullyImplicitBlackoilPolymer_impl.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2013 SINTEF ICT, Applied Mathematics.
3  Copyright 2014 IRIS AS
4  Copyright 2014 STATOIL ASA.
5 
6  This file is part of the Open Porous Media project (OPM).
7 
8  OPM is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  OPM is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with OPM. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 namespace Opm
23 {
24  template <class GridT>
26  SimulatorFullyImplicitBlackoilPolymer(const parameter::ParameterGroup& param,
27  const GridT& grid,
28  const DerivedGeology& geo,
29  BlackoilPropsAdInterface& props,
30  const PolymerPropsAd& polymer_props,
31  const RockCompressibility* rock_comp_props,
32  NewtonIterationBlackoilInterface& linsolver,
33  const double* gravity,
34  const bool has_disgas,
35  const bool has_vapoil,
36  const bool has_polymer,
37  const bool has_plyshlog,
38  const bool has_shrate,
39  std::shared_ptr<EclipseState> eclipse_state,
40  BlackoilOutputWriter& output_writer,
41  Opm::DeckConstPtr& deck,
42  const std::vector<double>& threshold_pressures_by_face)
43  : BaseType(param,
44  grid,
45  geo,
46  props,
47  rock_comp_props,
48  linsolver,
49  gravity,
50  has_disgas,
51  has_vapoil,
52  eclipse_state,
53  output_writer,
54  threshold_pressures_by_face)
55  , polymer_props_(polymer_props)
56  , has_polymer_(has_polymer)
57  , has_plyshlog_(has_plyshlog)
58  , has_shrate_(has_shrate)
59  , deck_(deck)
60  {
61  }
62 
63  template <class GridT>
65  createSolver(const Wells* wells)
66  -> std::unique_ptr<Solver>
67  {
68  typedef typename Traits::Model Model;
69 
70 
71  auto model = std::unique_ptr<Model>(new Model(BaseType::model_param_,
72  BaseType::grid_,
73  BaseType::props_,
74  BaseType::geo_,
75  BaseType::rock_comp_props_,
76  polymer_props_,
77  wells,
78  BaseType::solver_,
79  BaseType::eclipse_state_,
80  BaseType::has_disgas_,
81  BaseType::has_vapoil_,
82  has_polymer_,
83  has_plyshlog_,
84  has_shrate_,
85  wells_rep_radius_,
86  wells_perf_length_,
87  wells_bore_diameter_,
88  BaseType::terminal_output_));
89 
90  if (!BaseType::threshold_pressures_by_face_.empty()) {
91  model->setThresholdPressures(BaseType::threshold_pressures_by_face_);
92  }
93 
94  return std::unique_ptr<Solver>(new Solver(BaseType::solver_param_, std::move(model)));
95  }
96 
97 
98 
99 
100  template <class GridT>
102  handleAdditionalWellInflow(SimulatorTimer& timer,
103  WellsManager& wells_manager,
104  typename BaseType::WellState& well_state,
105  const Wells* wells)
106  {
107  // compute polymer inflow
108  std::unique_ptr<PolymerInflowInterface> polymer_inflow_ptr;
109  if (deck_->hasKeyword("WPOLYMER")) {
110  if (wells_manager.c_wells() == 0) {
111  OPM_THROW(std::runtime_error, "Cannot control polymer injection via WPOLYMER without wells.");
112  }
113  polymer_inflow_ptr.reset(new PolymerInflowFromDeck(deck_, BaseType::eclipse_state_, *wells, Opm::UgGridHelpers::numCells(BaseType::grid_), timer.currentStepNum()));
114  } else {
115  polymer_inflow_ptr.reset(new PolymerInflowBasic(0.0*Opm::unit::day,
116  1.0*Opm::unit::day,
117  0.0));
118  }
119  std::vector<double> polymer_inflow_c(Opm::UgGridHelpers::numCells(BaseType::grid_));
120  polymer_inflow_ptr->getInflowValues(timer.simulationTimeElapsed(),
121  timer.simulationTimeElapsed() + timer.currentStepLength(),
122  polymer_inflow_c);
123  well_state.polymerInflow() = polymer_inflow_c;
124 
125  computeRepRadiusPerfLength(BaseType::eclipse_state_, timer.currentStepNum(), BaseType::grid_, wells_rep_radius_, wells_perf_length_, wells_bore_diameter_);
126  }
127 
128 
129  template <class GridT>
131  setupCompressedToCartesian(const int* global_cell, int number_of_cells,
132  std::map<int,int>& cartesian_to_compressed )
133  {
134  if (global_cell) {
135  for (int i = 0; i < number_of_cells; ++i) {
136  cartesian_to_compressed.insert(std::make_pair(global_cell[i], i));
137  }
138  }
139  else {
140  for (int i = 0; i < number_of_cells; ++i) {
141  cartesian_to_compressed.insert(std::make_pair(i, i));
142  }
143  }
144 
145  }
146 
147 
148  template <class GridT>
149  void SimulatorFullyImplicitBlackoilPolymer<GridT>::
150  computeRepRadiusPerfLength(const Opm::EclipseStateConstPtr eclipseState,
151  const size_t timeStep,
152  const GridT& grid,
153  std::vector<double>& wells_rep_radius,
154  std::vector<double>& wells_perf_length,
155  std::vector<double>& wells_bore_diameter)
156  {
157 
158  // TODO, the function does not work for parallel running
159  // to be fixed later.
160  int number_of_cells = Opm::UgGridHelpers::numCells(grid);
161  const int* global_cell = Opm::UgGridHelpers::globalCell(grid);
162  const int* cart_dims = Opm::UgGridHelpers::cartDims(grid);
163  auto cell_to_faces = Opm::UgGridHelpers::cell2Faces(grid);
164  auto begin_face_centroids = Opm::UgGridHelpers::beginFaceCentroids(grid);
165 
166  if (eclipseState->getSchedule()->numWells() == 0) {
167  OPM_MESSAGE("No wells specified in Schedule section, "
168  "initializing no wells");
169  return;
170  }
171 
172  const size_t n_perf = wells_rep_radius.size();
173 
174  wells_rep_radius.clear();
175  wells_perf_length.clear();
176  wells_bore_diameter.clear();
177 
178  wells_rep_radius.reserve(n_perf);
179  wells_perf_length.reserve(n_perf);
180  wells_bore_diameter.reserve(n_perf);
181 
182  std::map<int,int> cartesian_to_compressed;
183 
184  setupCompressedToCartesian(global_cell, number_of_cells,
185  cartesian_to_compressed);
186 
187  ScheduleConstPtr schedule = eclipseState->getSchedule();
188  std::vector<WellConstPtr> wells = schedule->getWells(timeStep);
189 
190  int well_index = 0;
191 
192  for (auto wellIter= wells.begin(); wellIter != wells.end(); ++wellIter) {
193  WellConstPtr well = (*wellIter);
194 
195  if (well->getStatus(timeStep) == WellCommon::SHUT) {
196  continue;
197  }
198  { // COMPDAT handling
199  CompletionSetConstPtr completionSet = well->getCompletions(timeStep);
200  for (size_t c=0; c<completionSet->size(); c++) {
201  CompletionConstPtr completion = completionSet->get(c);
202  if (completion->getState() == WellCompletion::OPEN) {
203  int i = completion->getI();
204  int j = completion->getJ();
205  int k = completion->getK();
206 
207  const int* cpgdim = cart_dims;
208  int cart_grid_indx = i + cpgdim[0]*(j + cpgdim[1]*k);
209  std::map<int, int>::const_iterator cgit = cartesian_to_compressed.find(cart_grid_indx);
210  if (cgit == cartesian_to_compressed.end()) {
211  OPM_THROW(std::runtime_error, "Cell with i,j,k indices " << i << ' ' << j << ' '
212  << k << " not found in grid (well = " << well->name() << ')');
213  }
214  int cell = cgit->second;
215 
216  {
217  double radius = 0.5*completion->getDiameter();
218  if (radius <= 0.0) {
219  radius = 0.5*unit::feet;
220  OPM_MESSAGE("**** Warning: Well bore internal radius set to " << radius);
221  }
222 
223  const std::array<double, 3> cubical =
224  WellsManagerDetail::getCubeDim<3>(cell_to_faces, begin_face_centroids, cell);
225 
226  WellCompletion::DirectionEnum direction = completion->getDirection();
227 
228  double re; // area equivalent radius of the grid block
229  double perf_length; // the length of the well perforation
230 
231  switch (direction) {
232  case Opm::WellCompletion::DirectionEnum::X:
233  re = std::sqrt(cubical[1] * cubical[2] / M_PI);
234  perf_length = cubical[0];
235  break;
236  case Opm::WellCompletion::DirectionEnum::Y:
237  re = std::sqrt(cubical[0] * cubical[2] / M_PI);
238  perf_length = cubical[1];
239  break;
240  case Opm::WellCompletion::DirectionEnum::Z:
241  re = std::sqrt(cubical[0] * cubical[1] / M_PI);
242  perf_length = cubical[2];
243  break;
244  default:
245  OPM_THROW(std::runtime_error, " Dirtecion of well is not supported ");
246  }
247 
248  double repR = std::sqrt(re * radius);
249  wells_rep_radius.push_back(repR);
250  wells_perf_length.push_back(perf_length);
251  wells_bore_diameter.push_back(2. * radius);
252  }
253  } else {
254  if (completion->getState() != WellCompletion::SHUT) {
255  OPM_THROW(std::runtime_error, "Completion state: " << WellCompletion::StateEnum2String( completion->getState() ) << " not handled");
256  }
257  }
258 
259  }
260  }
261  well_index++;
262  }
263  }
264 
265 } // namespace Opm
Definition: SimulatorFullyImplicitBlackoilPolymer.hpp:82
std::unique_ptr< Solver > createSolver(const Wells *wells)
Definition: SimulatorFullyImplicitBlackoilPolymer_impl.hpp:65
Definition: CompressibleTpfaPolymer.hpp:32
void handleAdditionalWellInflow(SimulatorTimer &timer, WellsManager &wells_manager, typename BaseType::WellState &well_state, const Wells *wells)
Definition: SimulatorFullyImplicitBlackoilPolymer_impl.hpp:102
virtual void getInflowValues(const double step_start, const double step_end, std::vector< double > &poly_inflow_c) const =0
Basic polymer injection behaviour class. This class gives all injectors the same polymer concentratio...
Definition: PolymerInflow.hpp:59
SimulatorFullyImplicitBlackoilPolymer(const parameter::ParameterGroup &param, const GridT &grid, const DerivedGeology &geo, BlackoilPropsAdInterface &props, const PolymerPropsAd &polymer_props, const RockCompressibility *rock_comp_props, NewtonIterationBlackoilInterface &linsolver, const double *gravity, const bool disgas, const bool vapoil, const bool polymer, const bool plyshlog, const bool shrate, std::shared_ptr< EclipseState > eclipse_state, BlackoilOutputWriter &output_writer, Opm::DeckConstPtr &deck, const std::vector< double > &threshold_pressures_by_face)
Definition: SimulatorFullyImplicitBlackoilPolymer_impl.hpp:26
Polymer injection behaviour class using deck WPOLYMER. This class reads the accumulated WPOLYMER line...
Definition: PolymerInflow.hpp:88
Definition: PolymerPropsAd.hpp:32