4 #include <opm/common/ErrorMacros.hpp>
18 namespace ProductionControl
29 Mode mode(
const std::string& control);
32 Mode mode(Opm::WellProducer::ControlModeEnum controlMode);
36 namespace InjectionControl
46 Mode mode(
const std::string& control);
48 Mode mode(Opm::WellInjector::ControlModeEnum controlMode);
53 const std::array<double, 3>& cubical,
54 const double* cell_permeability,
55 const double skin_factor,
56 const Opm::WellCompletion::DirectionEnum direction,
59 template <
int dim,
class C2F,
class FC>
60 std::array<double, dim>
62 FC begin_face_centroids,
65 std::array< std::vector<double>, dim > X;
67 const std::vector<double>::size_type
68 nf = std::distance(c2f[cell].begin(),
71 for (
int d = 0; d < dim; ++d) {
76 typedef typename C2F::row_type::const_iterator FI;
78 for (FI f = c2f[cell].begin(), e = c2f[cell].end(); f != e; ++f) {
82 const FC& fc =
increment(begin_face_centroids, *f, dim);
84 for (
int d = 0; d < dim; ++d) {
89 std::array<double, dim> cube;
90 for (
int d = 0; d < dim; ++d) {
91 typedef std::vector<double>::iterator VI;
92 typedef std::pair<VI,VI> PVI;
94 const PVI m = std::minmax_element(X[d].begin(), X[d].end());
96 cube[d] = *m.second - *m.first;
105 template<
class C2F,
class FC,
class NTG>
106 void WellsManager::createWellsFromSpecs(std::vector<WellConstPtr>& wells,
size_t timeStep,
108 const int* cart_dims,
109 FC begin_face_centroids,
111 std::vector<double>& dz,
112 std::vector<std::string>& well_names,
113 std::vector<WellData>& well_data,
114 std::map<std::string, int>& well_names_to_index,
115 const PhaseUsage& phaseUsage,
116 const std::map<int,int>& cartesian_to_compressed,
117 const double* permeability,
119 std::vector<int>& wells_on_proc)
121 if (dimensions != 3) {
122 OPM_THROW(std::domain_error,
123 "WellsManager::createWellsFromSpecs() only "
124 "supported in three space dimensions");
127 std::vector<std::vector<PerfData> > wellperf_data;
128 wellperf_data.resize(wells.size());
129 wells_on_proc.resize(wells.size(), 1);
135 int well_index_on_proc = 0;
136 for (
auto wellIter= wells.begin(); wellIter != wells.end(); ++wellIter) {
137 WellConstPtr well = (*wellIter);
139 if (well->getStatus(timeStep) == WellCommon::SHUT) {
144 CompletionSetConstPtr completionSet = well->getCompletions(timeStep);
146 std::vector<std::size_t> completion_on_proc(completionSet->size(), 1);
147 std::size_t shut_completions_number = 0;
148 for (
size_t c=0; c<completionSet->size(); c++) {
149 CompletionConstPtr completion = completionSet->get(c);
150 if (completion->getState() == WellCompletion::OPEN) {
151 int i = completion->getI();
152 int j = completion->getJ();
153 int k = completion->getK();
155 const int* cpgdim = cart_dims;
156 int cart_grid_indx = i + cpgdim[0]*(j + cpgdim[1]*k);
157 std::map<int, int>::const_iterator cgit = cartesian_to_compressed.find(cart_grid_indx);
158 if (cgit == cartesian_to_compressed.end()) {
159 if ( is_parallel_run_ )
161 completion_on_proc[c]=0;
166 OPM_MESSAGE(
"****Warning: Cell with i,j,k indices " << i <<
' ' << j <<
' '
167 << k <<
" not found in grid. The completion will be igored (well = "
168 << well->name() <<
')');
173 int cell = cgit->second;
177 const Value<double>& transmissibilityFactor = completion->getConnectionTransmissibilityFactorAsValueObject();
178 const double wellPi = completion ->getWellPi();
179 if (transmissibilityFactor.hasValue()) {
180 pd.well_index = transmissibilityFactor.getValue();
182 double radius = 0.5*completion->getDiameter();
185 OPM_MESSAGE(
"**** Warning: Well bore internal radius set to " << radius);
188 std::array<double, 3> cubical =
189 WellsManagerDetail::getCubeDim<3>(c2f, begin_face_centroids, cell);
193 cubical[2] = dz[cell];
196 const double* cell_perm = &permeability[dimensions*dimensions*cell];
199 completion->getSkinFactor(),
200 completion->getDirection(),
203 pd.well_index *= wellPi;
205 wellperf_data[well_index_on_proc].push_back(pd);
208 ++shut_completions_number;
209 if (completion->getState() != WellCompletion::SHUT) {
210 OPM_THROW(std::runtime_error,
"Completion state: " << WellCompletion::StateEnum2String( completion->getState() ) <<
" not handled");
214 if ( is_parallel_run_ )
218 std::size_t sum_completions_on_proc = std::accumulate(completion_on_proc.begin(),
219 completion_on_proc.end(),0);
222 if ( sum_completions_on_proc == shut_completions_number )
225 wells_on_proc[wellIter-wells.begin()] = 0;
231 if ( sum_completions_on_proc < completionSet->size() )
233 std::cout<<
"Well "<< well->name() <<
" does not seem to be"
234 <<
"completely in the disjoint partition of "
235 <<
"process. Therefore we deactivate it here." << std::endl;
237 wells_on_proc[wellIter-wells.begin()] = 0;
238 wellperf_data[well_index_on_proc].clear();
245 well_names_to_index[well->name()] = well_index_on_proc;
246 well_names.push_back(well->name());
249 wd.reference_bhp_depth = well->getRefDepth();
250 wd.welspecsline = -1;
251 if (well->isInjector( timeStep ))
256 wd.allowCrossFlow = well->getAllowCrossFlow();
257 well_data.push_back(wd);
261 well_index_on_proc++;
265 const int num_wells = well_data.size();
268 assert (dimensions == 3);
269 for (
int w = 0; w < num_wells; ++w) {
270 num_perfs += wellperf_data[w].size();
274 w_ =
create_wells(phaseUsage.num_phases, num_wells, num_perfs);
276 OPM_THROW(std::runtime_error,
"Failed creating Wells struct.");
281 for (
int w = 0; w < num_wells; ++w) {
282 const int w_num_perf = wellperf_data[w].size();
283 std::vector<int> perf_cells (w_num_perf);
284 std::vector<double> perf_prodind(w_num_perf);
286 for (
int perf = 0; perf < w_num_perf; ++perf) {
287 perf_cells [perf] = wellperf_data[w][perf].cell;
288 perf_prodind[perf] = wellperf_data[w][perf].well_index;
291 const double* comp_frac = NULL;
297 well_data[w].reference_bhp_depth,
302 well_names[w].c_str(),
303 well_data[w].allowCrossFlow,
307 OPM_THROW(std::runtime_error,
308 "Failed adding well "
310 <<
" to Wells data structure.");
315 template <
class C2F,
class FC>
318 const size_t timeStep,
320 const int* global_cell,
321 const int* cart_dims,
323 const C2F& cell_to_faces,
324 FC begin_face_centroids,
325 const double* permeability,
326 bool is_parallel_run)
327 : w_(0), is_parallel_run_(is_parallel_run)
329 init(eclipseState, timeStep, number_of_cells, global_cell,
330 cart_dims, dimensions,
331 cell_to_faces, begin_face_centroids, permeability);
335 template <
class C2F,
class FC>
337 WellsManager::init(
const Opm::EclipseStateConstPtr eclipseState,
338 const size_t timeStep,
340 const int* global_cell,
341 const int* cart_dims,
343 const C2F& cell_to_faces,
344 FC begin_face_centroids,
345 const double* permeability)
347 if (dimensions != 3) {
348 OPM_THROW(std::runtime_error,
349 "We cannot initialize wells from a deck unless "
350 "the corresponding grid is 3-dimensional.");
353 if (eclipseState->getSchedule()->numWells() == 0) {
354 OPM_MESSAGE(
"No wells specified in Schedule section, "
355 "initializing no wells");
359 std::map<int,int> cartesian_to_compressed;
360 setupCompressedToCartesian(global_cell, number_of_cells,
361 cartesian_to_compressed);
368 std::vector<std::string> well_names;
369 std::vector<WellData> well_data;
373 std::map<std::string, int> well_names_to_index;
375 ScheduleConstPtr schedule = eclipseState->getSchedule();
376 std::vector<WellConstPtr> wells = schedule->getWells(timeStep);
377 std::vector<int> wells_on_proc;
379 well_names.reserve(wells.size());
380 well_data.reserve(wells.size());
382 typedef GridPropertyAccess::ArrayPolicy::ExtractFromDeck<double> DoubleArray;
383 typedef GridPropertyAccess::Compressed<DoubleArray, GridPropertyAccess::Tag::NTG> NTGArray;
385 DoubleArray ntg_glob(eclipseState,
"NTG", 1.0);
386 NTGArray ntg(ntg_glob, global_cell);
388 EclipseGridConstPtr eclGrid = eclipseState->getEclipseGrid();
392 std::vector<double> dz(number_of_cells);
395 for (
int cell = 0; cell < number_of_cells; ++cell) {
396 dz[cell] = eclGrid->getCellThicknes(gc[cell]);
400 createWellsFromSpecs(wells, timeStep, cell_to_faces,
402 begin_face_centroids,
405 well_names, well_data, well_names_to_index,
406 pu, cartesian_to_compressed, permeability, ntg,
409 setupWellControls(wells, timeStep, well_names, pu, wells_on_proc);
412 GroupTreeNodeConstPtr fieldNode =
413 schedule->getGroupTree(timeStep)->getNode(
"FIELD");
415 GroupConstPtr fieldGroup =
416 schedule->getGroup(fieldNode->name());
418 well_collection_.
addField(fieldGroup, timeStep, pu);
419 addChildGroups(fieldNode, schedule, timeStep, pu);
422 for (
auto w = wells.begin(), e = wells.end(); w != e; ++w) {
423 well_collection_.
addWell(*w, timeStep, pu);
429 setupGuideRates(wells, timeStep, well_data, well_names_to_index);
void applyGroupControls()
Applies all group controls (injection and production)
Definition: WellsManager_impl.hpp:22
Definition: WellsManager_impl.hpp:20
void setWellsPointer(Wells *wells)
Adds the well pointer to each leaf node (does not take ownership).
Definition: WellsManager_impl.hpp:20
double getCoordinate(T *cc, int i)
Get the i-th corrdinate of a centroid.
Definition: GridHelpers.hpp:337
Definition: WellsManager_impl.hpp:38
Definition: AnisotropicEikonal.hpp:43
const double feet
Definition: Units.hpp:88
double computeWellIndex(const double radius, const std::array< double, 3 > &cubical, const double *cell_permeability, const double skin_factor, const Opm::WellCompletion::DirectionEnum direction, const double ntg)
std::array< double, dim > getCubeDim(const C2F &c2f, FC begin_face_centroids, int cell)
Definition: WellsManager_impl.hpp:61
Definition: WellsManager_impl.hpp:38
Definition: WellsManager_impl.hpp:21
Definition: WellsManager_impl.hpp:20
Definition: WellsManager_impl.hpp:22
Mode mode(const std::string &control)
int add_well(enum WellType type, double depth_ref, int nperf, const double *comp_frac, const int *cells, const double *WI, const char *name, int allow_cf, struct Wells *W)
Definition: WellsManager_impl.hpp:14
WellsManager()
Default constructor – no wells.
Mode
Definition: WellsManager_impl.hpp:38
Definition: WellsManager_impl.hpp:38
void addField(GroupConstPtr fieldGroup, size_t timeStep, const PhaseUsage &phaseUsage)
int dimensions(const UnstructuredGrid &grid)
Get the dimensions of a grid.
struct Wells * create_wells(int nphases, int nwells, int nperf)
Definition: WellsManager_impl.hpp:39
std::vector< int > compressedToCartesian(const int num_cells, const int *global_cell)
T * increment(T *cc, int i, int dim)
Increment an iterator over an array that reresents a dense row-major matrix with dims columns...
Definition: GridHelpers.hpp:318
Mode
Definition: WellsManager_impl.hpp:20
void addWell(WellConstPtr wellChild, size_t timeStep, const PhaseUsage &phaseUsage)
Definition: WellsManager_impl.hpp:21
Definition: WellsManager_impl.hpp:22
Definition: WellsManager_impl.hpp:21
Definition: WellsManager_impl.hpp:39
Definition: legacy_well.h:37
PhaseUsage phaseUsageFromDeck(Opm::EclipseStateConstPtr eclipseState)
Definition: phaseUsageFromDeck.hpp:35
Definition: legacy_well.h:37
Mode mode(const std::string &control)