opm-simulators
WellConnectionAuxiliaryModule.hpp
1 /*
2  Copyright 2017 Dr. Blatt - HPC-Simulation-Software & Services
3  Copyright 2017 Statoil ASA.
4 
5  This file is part of the Open Porous Media project (OPM).
6 
7  OPM is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  OPM is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with OPM. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #ifndef OPM_WELLCONNECTIONAUXILIARYMODULE_HEADER_INCLUDED
22 #define OPM_WELLCONNECTIONAUXILIARYMODULE_HEADER_INCLUDED
23 
25 
26 #include <opm/simulators/flow/SubDomain.hpp>
27 
28 #include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp>
29 #include <opm/simulators/utils/ParallelCommunication.hpp>
30 
31 #if HAVE_MPI
32 #include <opm/simulators/utils/MPISerializer.hpp>
33 #endif
34 
35 namespace Opm {
36 
37 template<class TypeTag, class Model>
39 {
43 
44 public:
45  using NeighborSet = typename
46  ::Opm::BaseAuxiliaryModule<TypeTag>::NeighborSet;
47 
48  using Domain = SubDomain<Grid>;
49 
50  WellConnectionAuxiliaryModule(Model& model, Parallel::Communication comm)
51  : model_(model)
52  , lin_comm_(std::move(comm))
53  {
54  }
55 
56  unsigned numDofs() const override
57  {
58  // No extra dofs are inserted for wells.
59  return 0;
60  }
61 
62  void addNeighbors(std::vector<NeighborSet>& neighbors) const override
63  {
64  if (!model_.addMatrixContributions()) {
65  return;
66  }
67 
68  // Create cartesian to compressed mapping
69  const auto& schedule_wells = model_.schedule().getWellsatEnd();
70  auto possibleFutureConnections = model_.schedule().getPossibleFutureConnections();
71 
72 #if HAVE_MPI
73  // Communicate Map to other processes, since it is only available on rank 0
74  Parallel::MpiSerializer ser(lin_comm_);
75  ser.broadcast(Parallel::RootRank{0}, possibleFutureConnections);
76 #endif
77  // initialize the additional cell connections introduced by wells.
78  for (const auto& well : schedule_wells)
79  {
80  std::vector<int> wellCells = model_.getCellsForConnections(well);
81  // Now add the cells of the possible future connections
82  const auto possibleFutureConnectionSetIt = possibleFutureConnections.find(well.name());
83  if (possibleFutureConnectionSetIt != possibleFutureConnections.end()) {
84  for (const auto& global_index : possibleFutureConnectionSetIt->second) {
85  int compressed_idx = model_.compressedIndexForInterior(global_index);
86  if (compressed_idx >= 0) { // Ignore connections in inactive/remote cells.
87  wellCells.push_back(compressed_idx);
88  }
89  }
90  }
91  for (int cellIdx : wellCells) {
92  neighbors[cellIdx].insert(wellCells.begin(),
93  wellCells.end());
94  }
95  }
96  }
97 
98  void applyInitial() override
99  {}
100 
101  void linearize(SparseMatrixAdapter& jacobian, GlobalEqVector& res) override
102  {
103  OPM_BEGIN_PARALLEL_TRY_CATCH();
104  for (const auto& well : model_) {
105  this->linearizeSingleWell(jacobian, res, well);
106  }
107  OPM_END_PARALLEL_TRY_CATCH("BlackoilWellModel::linearize failed: ", lin_comm_);
108  }
109 
110  void postSolve(GlobalEqVector& deltaX) override
111  {
112  model_.recoverWellSolutionAndUpdateWellState(deltaX);
113  }
114 
115  void linearizeDomain(const Domain& domain,
116  SparseMatrixAdapter& jacobian,
117  GlobalEqVector& res)
118  {
119  OPM_TIMEBLOCK(wellLinearizeDomain);
120  // Note: no point in trying to do a parallel gathering
121  // try/catch here, as this function is not called in
122  // parallel but for each individual domain of each rank.
123  for (const auto& well : model_) {
124  if (model_.well_domain().at(well->name()) == domain.index) {
125  this->linearizeSingleWell(jacobian, res, well);
126  }
127  }
128  }
129 
130  void postSolveDomain(const GlobalEqVector& deltaX, const Domain& domain)
131  {
132  model_.recoverWellSolutionAndUpdateWellStateDomain(deltaX, domain.index);
133  }
134 
135  template <class Restarter>
136  void deserialize(Restarter& /* res */)
137  {
138  // TODO (?)
139  }
140 
145  template <class Restarter>
146  void serialize(Restarter& /* res*/)
147  {
148  // TODO (?)
149  }
150 
151 private:
152  template<class WellType>
153  void linearizeSingleWell(SparseMatrixAdapter& jacobian,
154  GlobalEqVector& res,
155  const WellType& well)
156  {
157  if (model_.addMatrixContributions()) {
158  well->addWellContributions(jacobian);
159  }
160 
161  const auto& cells = well->cells();
162  linearize_res_local_.resize(cells.size());
163 
164  for (size_t i = 0; i < cells.size(); ++i) {
165  linearize_res_local_[i] = res[cells[i]];
166  }
167 
168  well->apply(linearize_res_local_);
169 
170  for (size_t i = 0; i < cells.size(); ++i) {
171  res[cells[i]] = linearize_res_local_[i];
172  }
173  }
174 
175  Model& model_;
176  GlobalEqVector linearize_res_local_{};
177  Parallel::Communication lin_comm_;
178 };
179 
180 } // end namespace OPM
181 #endif
void postSolve(GlobalEqVector &deltaX) override
This method is called after the linear solver has been called but before the solution is updated for ...
Definition: WellConnectionAuxiliaryModule.hpp:110
void serialize(Restarter &)
This method writes the complete state of the well to the harddisk.
Definition: WellConnectionAuxiliaryModule.hpp:146
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(...))
Definition: propertysystem.hh:233
Representing a part of a grid, in a way suitable for performing local solves.
Definition: SubDomain.hpp:84
Base class for specifying auxiliary equations.
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
void linearize(SparseMatrixAdapter &jacobian, GlobalEqVector &res) override
Linearize the auxiliary equation.
Definition: WellConnectionAuxiliaryModule.hpp:101
unsigned numDofs() const override
Returns the number of additional degrees of freedom required for the auxiliary module.
Definition: WellConnectionAuxiliaryModule.hpp:56
void applyInitial() override
Set the initial condition of the auxiliary module in the solution vector.
Definition: WellConnectionAuxiliaryModule.hpp:98
void addNeighbors(std::vector< NeighborSet > &neighbors) const override
Specify the additional neighboring correlations caused by the auxiliary module.
Definition: WellConnectionAuxiliaryModule.hpp:62
Class for serializing and broadcasting data using MPI.
Definition: MPISerializer.hpp:38
Definition: WellConnectionAuxiliaryModule.hpp:38
Base class for specifying auxiliary equations.
Definition: baseauxiliarymodule.hh:55
Avoid mistakes in calls to broadcast() by wrapping the root argument in an explicit type...
Definition: MPISerializer.hpp:32