mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge from joakim/wellmanager
This commit is contained in:
commit
41b7af408b
@ -5,7 +5,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
#include <opm/core/wells.h>
|
#include <opm/core/wells.h>
|
||||||
|
#include <opm/core/well_controls.h>
|
||||||
#include <opm/core/linalg/blas_lapack.h>
|
#include <opm/core/linalg/blas_lapack.h>
|
||||||
#include <opm/core/linalg/sparse_sys.h>
|
#include <opm/core/linalg/sparse_sys.h>
|
||||||
|
|
||||||
@ -806,7 +808,7 @@ welleq_coeff_resv(int np, struct cfs_tpfa_res_data *h,
|
|||||||
pflux = h->pimpl->flux_work;
|
pflux = h->pimpl->flux_work;
|
||||||
dpflux_w = pflux + (1 * np);
|
dpflux_w = pflux + (1 * np);
|
||||||
dpflux_c = dpflux_w + (1 * np);
|
dpflux_c = dpflux_w + (1 * np);
|
||||||
distr = ctrl->distr + (ctrl->current * np);
|
distr = well_controls_get_current_distr( ctrl );
|
||||||
|
|
||||||
*res = *w2c = *w2w = 0.0;
|
*res = *w2c = *w2w = 0.0;
|
||||||
for (p = 0; p < np; p++) {
|
for (p = 0; p < np; p++) {
|
||||||
@ -833,7 +835,7 @@ welleq_coeff_surfrate(int i, int np, struct cfs_tpfa_res_data *h,
|
|||||||
pflux = h->pimpl->compflux_p + (i * (1 * np));
|
pflux = h->pimpl->compflux_p + (i * (1 * np));
|
||||||
dpflux_w = h->pimpl->compflux_deriv_p + (i * (2 * np));
|
dpflux_w = h->pimpl->compflux_deriv_p + (i * (2 * np));
|
||||||
dpflux_c = dpflux_w + (1 * (1 * np));
|
dpflux_c = dpflux_w + (1 * (1 * np));
|
||||||
distr = ctrl->distr + (ctrl->current * (1 * np));
|
distr = well_controls_get_current_distr( ctrl );
|
||||||
|
|
||||||
*res = *w2c = *w2w = 0.0;
|
*res = *w2c = *w2w = 0.0;
|
||||||
for (p = 0; p < np; p++) {
|
for (p = 0; p < np; p++) {
|
||||||
@ -867,14 +869,14 @@ assemble_completion_to_well(int i, int w, int c, int nc, int np,
|
|||||||
W = wells->W;
|
W = wells->W;
|
||||||
ctrl = W->ctrls[ w ];
|
ctrl = W->ctrls[ w ];
|
||||||
|
|
||||||
if (ctrl->current < 0) {
|
if (well_controls_get_current(ctrl) < 0) {
|
||||||
/* Interpreting a negative current control index to mean a shut well */
|
/* Interpreting a negative current control index to mean a shut well */
|
||||||
welleq_coeff_shut(np, h, &res, &w2c, &w2w);
|
welleq_coeff_shut(np, h, &res, &w2c, &w2w);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch (ctrl->type[ ctrl->current ]) {
|
switch (well_controls_get_current_type(ctrl)) {
|
||||||
case BHP :
|
case BHP :
|
||||||
welleq_coeff_bhp(np, pw - ctrl->target[ ctrl->current ],
|
welleq_coeff_bhp(np, pw - well_controls_get_current_target( ctrl ),
|
||||||
h, &res, &w2c, &w2w);
|
h, &res, &w2c, &w2w);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -931,7 +933,7 @@ assemble_well_contrib(struct cfs_tpfa_res_wells *wells ,
|
|||||||
|
|
||||||
for (w = i = 0; w < W->number_of_wells; w++) {
|
for (w = i = 0; w < W->number_of_wells; w++) {
|
||||||
pw = wpress[ w ];
|
pw = wpress[ w ];
|
||||||
is_open = W->ctrls[w]->current >= 0;
|
is_open = (well_controls_get_current(W->ctrls[w]) >= 0);
|
||||||
|
|
||||||
for (; i < W->well_connpos[w + 1]; i++, pmobp += np) {
|
for (; i < W->well_connpos[w + 1]; i++, pmobp += np) {
|
||||||
|
|
||||||
@ -956,10 +958,10 @@ assemble_well_contrib(struct cfs_tpfa_res_wells *wells ,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctrl = W->ctrls[ w ];
|
ctrl = W->ctrls[ w ];
|
||||||
if ((ctrl->current >= 0) && /* OPEN? */
|
if ((well_controls_get_current(ctrl) >= 0) && /* OPEN? */
|
||||||
(ctrl->type[ ctrl->current ] != BHP)) {
|
(well_controls_get_current_type(ctrl) != BHP)) {
|
||||||
|
|
||||||
h->F[ nc + w ] -= dt * ctrl->target[ ctrl->current ];
|
h->F[ nc + w ] -= dt * well_controls_get_current_target(ctrl);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
is_neumann = 0;
|
is_neumann = 0;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <opm/core/linalg/sparse_sys.h>
|
#include <opm/core/linalg/sparse_sys.h>
|
||||||
|
|
||||||
#include <opm/core/wells.h>
|
#include <opm/core/wells.h>
|
||||||
|
#include <opm/core/well_controls.h>
|
||||||
#include <opm/core/pressure/flow_bc.h>
|
#include <opm/core/pressure/flow_bc.h>
|
||||||
#include <opm/core/pressure/tpfa/ifs_tpfa.h>
|
#include <opm/core/pressure/tpfa/ifs_tpfa.h>
|
||||||
|
|
||||||
@ -229,7 +230,7 @@ assemble_bhp_well(int nc, int w,
|
|||||||
|
|
||||||
ctrls = W->ctrls[ w ];
|
ctrls = W->ctrls[ w ];
|
||||||
wdof = nc + w;
|
wdof = nc + w;
|
||||||
bhp = ctrls->target[ ctrls->current ];
|
bhp = well_controls_get_current_target(ctrls);
|
||||||
|
|
||||||
jw = csrmatrix_elm_index(wdof, wdof, h->A);
|
jw = csrmatrix_elm_index(wdof, wdof, h->A);
|
||||||
|
|
||||||
@ -268,7 +269,7 @@ assemble_rate_well(int nc, int w,
|
|||||||
|
|
||||||
ctrls = W->ctrls[ w ];
|
ctrls = W->ctrls[ w ];
|
||||||
wdof = nc + w;
|
wdof = nc + w;
|
||||||
resv = ctrls->target[ ctrls->current ];
|
resv = well_controls_get_current_target(ctrls);
|
||||||
|
|
||||||
jww = csrmatrix_elm_index(wdof, wdof, h->A);
|
jww = csrmatrix_elm_index(wdof, wdof, h->A);
|
||||||
|
|
||||||
@ -362,7 +363,7 @@ assemble_well_contrib(int nc ,
|
|||||||
for (w = 0; w < W->number_of_wells; w++) {
|
for (w = 0; w < W->number_of_wells; w++) {
|
||||||
ctrls = W->ctrls[ w ];
|
ctrls = W->ctrls[ w ];
|
||||||
|
|
||||||
if (ctrls->current < 0) {
|
if (well_controls_get_current(ctrls) < 0) {
|
||||||
|
|
||||||
/* Treat this well as a shut well, isolated from the domain. */
|
/* Treat this well as a shut well, isolated from the domain. */
|
||||||
|
|
||||||
@ -370,9 +371,9 @@ assemble_well_contrib(int nc ,
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
assert (ctrls->current < ctrls->num);
|
assert (well_controls_get_current(ctrls) < well_controls_get_num(ctrls));
|
||||||
|
|
||||||
switch (ctrls->type[ ctrls->current ]) {
|
switch (well_controls_get_current_type(ctrls)) {
|
||||||
case BHP:
|
case BHP:
|
||||||
*all_rate = 0;
|
*all_rate = 0;
|
||||||
assemble_bhp_well (nc, w, W, mt, wdp, h);
|
assemble_bhp_well (nc, w, W, mt, wdp, h);
|
||||||
@ -383,8 +384,9 @@ assemble_well_contrib(int nc ,
|
|||||||
/* Ensure minimal consistency. A PRODUCER should
|
/* Ensure minimal consistency. A PRODUCER should
|
||||||
* specify a phase distribution of all ones in the
|
* specify a phase distribution of all ones in the
|
||||||
* case of RESV controls. */
|
* case of RESV controls. */
|
||||||
|
const double * distr = well_controls_get_current_distr( ctrls );
|
||||||
for (p = 0; p < np; p++) {
|
for (p = 0; p < np; p++) {
|
||||||
if (ctrls->distr[np * ctrls->current + p] != 1.0) {
|
if (distr[p] != 1.0) {
|
||||||
*ok = 0;
|
*ok = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -550,7 +552,7 @@ well_solution(const struct UnstructuredGrid *G ,
|
|||||||
if (soln->well_press != NULL) {
|
if (soln->well_press != NULL) {
|
||||||
/* Extract BHP directly from solution vector for non-shut wells */
|
/* Extract BHP directly from solution vector for non-shut wells */
|
||||||
for (w = 0; w < F->W->number_of_wells; w++) {
|
for (w = 0; w < F->W->number_of_wells; w++) {
|
||||||
if (F->W->ctrls[w]->current >= 0) {
|
if (well_controls_get_current(F->W->ctrls[w]) >= 0) {
|
||||||
soln->well_press[w] = h->x[G->number_of_cells + w];
|
soln->well_press[w] = h->x[G->number_of_cells + w];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -563,7 +565,7 @@ well_solution(const struct UnstructuredGrid *G ,
|
|||||||
|
|
||||||
for (w = i = 0; w < F->W->number_of_wells; w++) {
|
for (w = i = 0; w < F->W->number_of_wells; w++) {
|
||||||
bhp = h->x[G->number_of_cells + w];
|
bhp = h->x[G->number_of_cells + w];
|
||||||
shut = (F->W->ctrls[w]->current < 0);
|
shut = (well_controls_get_current(F->W->ctrls[w]) < 0);
|
||||||
|
|
||||||
for (; i < F->W->well_connpos[ w + 1 ]; i++) {
|
for (; i < F->W->well_connpos[ w + 1 ]; i++) {
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define OPM_WELLSTATE_HEADER_INCLUDED
|
#define OPM_WELLSTATE_HEADER_INCLUDED
|
||||||
|
|
||||||
#include <opm/core/wells.h>
|
#include <opm/core/wells.h>
|
||||||
|
#include <opm/core/well_controls.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Opm
|
namespace Opm
|
||||||
@ -50,21 +51,22 @@ namespace Opm
|
|||||||
// above or below (depending on if the well is an
|
// above or below (depending on if the well is an
|
||||||
// injector or producer) pressure in first perforation
|
// injector or producer) pressure in first perforation
|
||||||
// cell.
|
// cell.
|
||||||
if ((ctrl->current < 0) || // SHUT
|
if ((well_controls_get_current(ctrl) < 0) || // SHUT
|
||||||
(ctrl->type[ctrl->current] != BHP)) {
|
(well_controls_get_current_type(ctrl) != BHP)) {
|
||||||
const int first_cell = wells->well_cells[wells->well_connpos[w]];
|
const int first_cell = wells->well_cells[wells->well_connpos[w]];
|
||||||
const double safety_factor = (wells->type[w] == INJECTOR) ? 1.01 : 0.99;
|
const double safety_factor = (wells->type[w] == INJECTOR) ? 1.01 : 0.99;
|
||||||
bhp_[w] = safety_factor*state.pressure()[first_cell];
|
bhp_[w] = safety_factor*state.pressure()[first_cell];
|
||||||
} else {
|
} else {
|
||||||
bhp_[w] = ctrl->target[ctrl->current];
|
bhp_[w] = well_controls_get_current_target( ctrl );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize well rates to match controls if type is SURFACE_RATE
|
// Initialize well rates to match controls if type is SURFACE_RATE
|
||||||
if ((ctrl->current >= 0) && // open well
|
if ((well_controls_get_current(ctrl) >= 0) && // open well
|
||||||
(ctrl->type[ctrl->current] == SURFACE_RATE)) {
|
(well_controls_get_current_type(ctrl) == SURFACE_RATE)) {
|
||||||
const double rate_target = ctrl->target[ctrl->current];
|
const double rate_target = well_controls_get_current_target(ctrl);
|
||||||
|
const double * distr = well_controls_get_current_distr( ctrl );
|
||||||
for (int p = 0; p < np; ++p) {
|
for (int p = 0; p < np; ++p) {
|
||||||
const double phase_distr = ctrl->distr[np * ctrl->current + p];
|
wellrates_[np*w + p] = rate_target * distr[p];
|
||||||
wellrates_[np*w + p] = rate_target * phase_distr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <opm/core/utility/Units.hpp>
|
#include <opm/core/utility/Units.hpp>
|
||||||
#include <opm/core/grid.h>
|
#include <opm/core/grid.h>
|
||||||
#include <opm/core/wells.h>
|
#include <opm/core/wells.h>
|
||||||
|
#include <opm/core/well_controls.h>
|
||||||
#include <opm/core/props/IncompPropertiesInterface.hpp>
|
#include <opm/core/props/IncompPropertiesInterface.hpp>
|
||||||
#include <opm/core/props/BlackoilPropertiesInterface.hpp>
|
#include <opm/core/props/BlackoilPropertiesInterface.hpp>
|
||||||
#include <opm/core/props/rock/RockCompressibility.hpp>
|
#include <opm/core/props/rock/RockCompressibility.hpp>
|
||||||
@ -457,22 +458,25 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
src.resize(num_cells);
|
src.resize(num_cells);
|
||||||
for (int w = 0; w < wells.number_of_wells; ++w) {
|
for (int w = 0; w < wells.number_of_wells; ++w) {
|
||||||
const int cur = wells.ctrls[w]->current;
|
const int cur = well_controls_get_current(wells.ctrls[w]);
|
||||||
if (wells.ctrls[w]->num != 1) {
|
if (well_controls_get_num(wells.ctrls[w]) != 1) {
|
||||||
OPM_MESSAGE("In wellsToSrc(): well has more than one control, all but current control will be ignored.");
|
OPM_MESSAGE("In wellsToSrc(): well has more than one control, all but current control will be ignored.");
|
||||||
}
|
}
|
||||||
if (wells.ctrls[w]->type[cur] != RESERVOIR_RATE) {
|
if (well_controls_iget_type(wells.ctrls[w] , cur) != RESERVOIR_RATE) {
|
||||||
OPM_THROW(std::runtime_error, "In wellsToSrc(): well is something other than RESERVOIR_RATE.");
|
OPM_THROW(std::runtime_error, "In wellsToSrc(): well is something other than RESERVOIR_RATE.");
|
||||||
}
|
}
|
||||||
if (wells.well_connpos[w+1] - wells.well_connpos[w] != 1) {
|
if (wells.well_connpos[w+1] - wells.well_connpos[w] != 1) {
|
||||||
OPM_THROW(std::runtime_error, "In wellsToSrc(): well has multiple perforations.");
|
OPM_THROW(std::runtime_error, "In wellsToSrc(): well has multiple perforations.");
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const double * distr = well_controls_iget_distr( wells.ctrls[w] , cur);
|
||||||
for (int p = 0; p < np; ++p) {
|
for (int p = 0; p < np; ++p) {
|
||||||
if (wells.ctrls[w]->distr[np*cur + p] != 1.0) {
|
if (distr[p] != 1.0) {
|
||||||
OPM_THROW(std::runtime_error, "In wellsToSrc(): well not controlled on total rate.");
|
OPM_THROW(std::runtime_error, "In wellsToSrc(): well not controlled on total rate.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
double flow = wells.ctrls[w]->target[cur];
|
}
|
||||||
|
double flow = well_controls_iget_target(wells.ctrls[w] , cur);
|
||||||
if (wells.type[w] == INJECTOR) {
|
if (wells.type[w] == INJECTOR) {
|
||||||
flow *= wells.comp_frac[np*w + 0]; // Obtaining water rate for inflow source.
|
flow *= wells.comp_frac[np*w + 0]; // Obtaining water rate for inflow source.
|
||||||
}
|
}
|
||||||
|
108
opm/core/well_controls.h
Normal file
108
opm/core/well_controls.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2012 SINTEF ICT, Applied Mathematics.
|
||||||
|
|
||||||
|
This file is part of the Open Porous Media project (OPM).
|
||||||
|
|
||||||
|
OPM is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OPM is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OPM_WELL_CONTROLS_H_INCLUDED
|
||||||
|
#define OPM_WELL_CONTROLS_H_INCLUDED
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum WellControlType {
|
||||||
|
BHP, /**< Well constrained by BHP target */
|
||||||
|
RESERVOIR_RATE, /**< Well constrained by reservoir volume flow rate */
|
||||||
|
SURFACE_RATE /**< Well constrained by surface volume flow rate */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WellControls;
|
||||||
|
|
||||||
|
bool
|
||||||
|
well_controls_equal(const struct WellControls *ctrls1, const struct WellControls *ctrls2);
|
||||||
|
|
||||||
|
//int
|
||||||
|
//well_controls_reserve(int nctrl, int nphases, struct WellControls *ctrl);
|
||||||
|
|
||||||
|
struct WellControls *
|
||||||
|
well_controls_create(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_destroy(struct WellControls *ctrl);
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
well_controls_get_num(const struct WellControls *ctrl);
|
||||||
|
|
||||||
|
int
|
||||||
|
well_controls_get_cpty(const struct WellControls *ctrl);
|
||||||
|
|
||||||
|
int
|
||||||
|
well_controls_get_current( const struct WellControls * ctrl);
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_set_current( struct WellControls * ctrl, int current);
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_invert_current( struct WellControls * ctrl );
|
||||||
|
|
||||||
|
int
|
||||||
|
well_controls_add_new(enum WellControlType type , double target , const double * distr , struct WellControls * ctrl);
|
||||||
|
|
||||||
|
enum WellControlType
|
||||||
|
well_controls_iget_type(const struct WellControls * ctrl, int control_index);
|
||||||
|
|
||||||
|
enum WellControlType
|
||||||
|
well_controls_get_current_type(const struct WellControls * ctrl);
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_iset_type( struct WellControls * ctrls , int control_index , enum WellControlType type);
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_iset_target(struct WellControls * ctrl, int control_index , double target);
|
||||||
|
|
||||||
|
double
|
||||||
|
well_controls_iget_target(const struct WellControls * ctrl, int control_index);
|
||||||
|
|
||||||
|
double
|
||||||
|
well_controls_get_current_target(const struct WellControls * ctrl);
|
||||||
|
|
||||||
|
const double *
|
||||||
|
well_controls_iget_distr(const struct WellControls * ctrl, int control_index);
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_iset_distr(const struct WellControls * ctrl, int control_index, const double * distr);
|
||||||
|
|
||||||
|
const double *
|
||||||
|
well_controls_get_current_distr(const struct WellControls * ctrl);
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_assert_number_of_phases(struct WellControls * ctrl , int number_of_phases);
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_clear(struct WellControls * ctrl);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* OPM_WELL_CONTROLS_H_INCLUDED */
|
@ -20,6 +20,8 @@
|
|||||||
#ifndef OPM_WELLS_H_INCLUDED
|
#ifndef OPM_WELLS_H_INCLUDED
|
||||||
#define OPM_WELLS_H_INCLUDED
|
#define OPM_WELLS_H_INCLUDED
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <opm/core/well_controls.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
@ -41,75 +43,6 @@ enum WellType {
|
|||||||
PRODUCER /**< Well is a producer */
|
PRODUCER /**< Well is a producer */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Type of well control equation or inequality constraint.
|
|
||||||
*/
|
|
||||||
enum WellControlType {
|
|
||||||
BHP, /**< Well constrained by BHP target */
|
|
||||||
RESERVOIR_RATE, /**< Well constrained by reservoir volume flow rate */
|
|
||||||
SURFACE_RATE /**< Well constrained by surface volume flow rate */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controls for a single well.
|
|
||||||
* Each control specifies a well rate or bottom-hole pressure. Only
|
|
||||||
* one control can be active at a time, indicated by current. The
|
|
||||||
* meaning of each control's target value depends on the control type:
|
|
||||||
*
|
|
||||||
* - BHP -> target pressure in Pascal.
|
|
||||||
* - RESERVOIR_RATE -> target reservoir volume rate in cubic(meter)/second
|
|
||||||
* - SURFACE_RATE -> target surface volume rate in cubic(meter)/second
|
|
||||||
*
|
|
||||||
* The sign convention for RATE targets is as follows:
|
|
||||||
*
|
|
||||||
* - (+) Fluid flowing into reservoir, i.e. injecting.
|
|
||||||
* - (-) Fluid flowing out of reservoir, i.e. producing.
|
|
||||||
*
|
|
||||||
* For *_RATE controls, the distribution of phases used for the control
|
|
||||||
* is also needed. For example, a total rate control should have 1.0
|
|
||||||
* for each phase, whereas a control on oil rate should have 1.0 for
|
|
||||||
* the oil phase and 0.0 for the rest. For BHP controls, this is unused.
|
|
||||||
* The active control acts as an equality constraint, whereas the
|
|
||||||
* non-active controls should be interpreted as inequality
|
|
||||||
* constraints (upper or lower bounds). For instance, a PRODUCER's
|
|
||||||
* BHP constraint defines a minimum acceptable bottom-hole pressure
|
|
||||||
* value for the well.
|
|
||||||
*/
|
|
||||||
struct WellControls
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Number of controls.
|
|
||||||
*/
|
|
||||||
int num;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array of control types.
|
|
||||||
*/
|
|
||||||
enum WellControlType *type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array of control targets.
|
|
||||||
*/
|
|
||||||
double *target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array of rate control distributions,
|
|
||||||
* <CODE>Wells::number_of_phases</CODE> numbers for each control
|
|
||||||
*/
|
|
||||||
double *distr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Index of current active control.
|
|
||||||
*/
|
|
||||||
int current;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal management structure.
|
|
||||||
*/
|
|
||||||
void *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data structure aggregating static information about all wells in a scenario.
|
* Data structure aggregating static information about all wells in a scenario.
|
||||||
@ -282,6 +215,8 @@ add_well(enum WellType type ,
|
|||||||
* \param[in,out] W Existing set of well controls.
|
* \param[in,out] W Existing set of well controls.
|
||||||
* \return Non-zero (true) if successful and zero (false) otherwise.
|
* \return Non-zero (true) if successful and zero (false) otherwise.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
append_well_controls(enum WellControlType type ,
|
append_well_controls(enum WellControlType type ,
|
||||||
double target,
|
double target,
|
||||||
@ -327,6 +262,10 @@ destroy_wells(struct Wells *W);
|
|||||||
struct Wells *
|
struct Wells *
|
||||||
clone_wells(const struct Wells *W);
|
clone_wells(const struct Wells *W);
|
||||||
|
|
||||||
|
bool
|
||||||
|
wells_equal(const struct Wells *W1, const struct Wells *W2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2012 SINTEF ICT, Applied Mathematics.
|
Copyright 2012 SINTEF ICT, Applied Mathematics.
|
||||||
|
|
||||||
This file is part of the Open Porous Media project (OPM).
|
This file is part of the Open Porous Media project (OPM).
|
||||||
|
|
||||||
OPM is free software: you can redistribute it and/or modify
|
OPM is free software: you can redistribute it and/or modify
|
||||||
@ -20,6 +19,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <opm/core/wells/WellsGroup.hpp>
|
#include <opm/core/wells/WellsGroup.hpp>
|
||||||
#include <opm/core/wells.h>
|
#include <opm/core/wells.h>
|
||||||
|
#include <opm/core/well_controls.h>
|
||||||
#include <opm/core/props/phaseUsageFromDeck.hpp>
|
#include <opm/core/props/phaseUsageFromDeck.hpp>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -655,18 +655,19 @@ namespace Opm
|
|||||||
|
|
||||||
// Check constraints.
|
// Check constraints.
|
||||||
bool is_producer = (wells_->type[self_index_] == PRODUCER);
|
bool is_producer = (wells_->type[self_index_] == PRODUCER);
|
||||||
const WellControls& ctrls = *wells_->ctrls[self_index_];
|
const WellControls * ctrls = wells_->ctrls[self_index_];
|
||||||
for (int ctrl_index = 0; ctrl_index < ctrls.num; ++ctrl_index) {
|
for (int ctrl_index = 0; ctrl_index < well_controls_get_num(ctrls); ++ctrl_index) {
|
||||||
if (ctrl_index == ctrls.current || ctrl_index == group_control_index_) {
|
if (ctrl_index == well_controls_get_current(ctrls) || ctrl_index == group_control_index_) {
|
||||||
// We do not check constraints that either were used
|
// We do not check constraints that either were used
|
||||||
// as the active control, or that come from group control.
|
// as the active control, or that come from group control.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
bool ctrl_violated = false;
|
bool ctrl_violated = false;
|
||||||
switch (ctrls.type[ctrl_index]) {
|
switch (well_controls_iget_type(ctrls , ctrl_index)) {
|
||||||
|
|
||||||
case BHP: {
|
case BHP: {
|
||||||
const double my_well_bhp = well_bhp[self_index_];
|
const double my_well_bhp = well_bhp[self_index_];
|
||||||
const double my_target_bhp = ctrls.target[ctrl_index];
|
const double my_target_bhp = well_controls_iget_target( ctrls , ctrl_index);
|
||||||
ctrl_violated = is_producer ? (my_target_bhp > my_well_bhp)
|
ctrl_violated = is_producer ? (my_target_bhp > my_well_bhp)
|
||||||
: (my_target_bhp < my_well_bhp);
|
: (my_target_bhp < my_well_bhp);
|
||||||
if (ctrl_violated) {
|
if (ctrl_violated) {
|
||||||
@ -676,12 +677,14 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RESERVOIR_RATE: {
|
case RESERVOIR_RATE: {
|
||||||
double my_rate = 0.0;
|
double my_rate = 0.0;
|
||||||
|
const double * ctrls_distr = well_controls_iget_distr( ctrls , ctrl_index );
|
||||||
for (int phase = 0; phase < np; ++phase) {
|
for (int phase = 0; phase < np; ++phase) {
|
||||||
my_rate += ctrls.distr[np*ctrl_index + phase]*well_reservoirrates_phase[np*self_index_ + phase];
|
my_rate += ctrls_distr[phase] * well_reservoirrates_phase[np*self_index_ + phase];
|
||||||
}
|
}
|
||||||
const double my_rate_target = ctrls.target[ctrl_index];
|
const double my_rate_target = well_controls_iget_target(ctrls , ctrl_index);
|
||||||
ctrl_violated = std::fabs(my_rate) - std::fabs(my_rate_target)> std::max(std::abs(my_rate), std::abs(my_rate_target))*1e-6;
|
ctrl_violated = std::fabs(my_rate) - std::fabs(my_rate_target)> std::max(std::abs(my_rate), std::abs(my_rate_target))*1e-6;
|
||||||
if (ctrl_violated) {
|
if (ctrl_violated) {
|
||||||
std::cout << "RESERVOIR_RATE limit violated for well " << name() << ":\n";
|
std::cout << "RESERVOIR_RATE limit violated for well " << name() << ":\n";
|
||||||
@ -690,12 +693,14 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SURFACE_RATE: {
|
case SURFACE_RATE: {
|
||||||
double my_rate = 0.0;
|
double my_rate = 0.0;
|
||||||
|
const double * ctrls_distr = well_controls_iget_distr( ctrls , ctrl_index );
|
||||||
for (int phase = 0; phase < np; ++phase) {
|
for (int phase = 0; phase < np; ++phase) {
|
||||||
my_rate += ctrls.distr[np*ctrl_index + phase]*well_surfacerates_phase[np*self_index_ + phase];
|
my_rate += ctrls_distr[phase] * well_surfacerates_phase[np*self_index_ + phase];
|
||||||
}
|
}
|
||||||
const double my_rate_target = ctrls.target[ctrl_index];
|
const double my_rate_target = well_controls_iget_target(ctrls , ctrl_index);
|
||||||
ctrl_violated = std::fabs(my_rate) > std::fabs(my_rate_target);
|
ctrl_violated = std::fabs(my_rate) > std::fabs(my_rate_target);
|
||||||
if (ctrl_violated) {
|
if (ctrl_violated) {
|
||||||
std::cout << "SURFACE_RATE limit violated for well " << name() << ":\n";
|
std::cout << "SURFACE_RATE limit violated for well " << name() << ":\n";
|
||||||
@ -744,7 +749,7 @@ namespace Opm
|
|||||||
if (shut_well_) {
|
if (shut_well_) {
|
||||||
// We set the tilde of the current control
|
// We set the tilde of the current control
|
||||||
// set_current_control(self_index_, -1, wells_);
|
// set_current_control(self_index_, -1, wells_);
|
||||||
wells_->ctrls[self_index_]->current = ~ wells_->ctrls[self_index_]->current;
|
well_controls_invert_current(wells_->ctrls[self_index_]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const double target = 0.0;
|
const double target = 0.0;
|
||||||
@ -753,16 +758,16 @@ namespace Opm
|
|||||||
if (group_control_index_ < 0) {
|
if (group_control_index_ < 0) {
|
||||||
// The well only had its own controls, no group controls.
|
// The well only had its own controls, no group controls.
|
||||||
append_well_controls(SURFACE_RATE, target, distr, self_index_, wells_);
|
append_well_controls(SURFACE_RATE, target, distr, self_index_, wells_);
|
||||||
group_control_index_ = wells_->ctrls[self_index_]->num - 1;
|
group_control_index_ = well_controls_get_num(wells_->ctrls[self_index_]) - 1;
|
||||||
} else {
|
} else {
|
||||||
// We will now modify the last control, that
|
// We will now modify the last control, that
|
||||||
// "belongs to" the group control.
|
// "belongs to" the group control.
|
||||||
const int np = wells_->number_of_phases;
|
|
||||||
wells_->ctrls[self_index_]->type[group_control_index_] = SURFACE_RATE;
|
well_controls_iset_type( wells_->ctrls[self_index_] , group_control_index_ , SURFACE_RATE);
|
||||||
wells_->ctrls[self_index_]->target[group_control_index_] = target;
|
well_controls_iset_target( wells_->ctrls[self_index_] , group_control_index_ , target);
|
||||||
std::copy(distr, distr + np, wells_->ctrls[self_index_]->distr + np * group_control_index_);
|
well_controls_iset_distr(wells_->ctrls[self_index_] , group_control_index_ , distr);
|
||||||
}
|
}
|
||||||
wells_->ctrls[self_index_]->current = ~ wells_->ctrls[self_index_]->current;
|
well_controls_invert_current(wells_->ctrls[self_index_]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -808,14 +813,13 @@ namespace Opm
|
|||||||
if (group_control_index_ < 0) {
|
if (group_control_index_ < 0) {
|
||||||
// The well only had its own controls, no group controls.
|
// The well only had its own controls, no group controls.
|
||||||
append_well_controls(wct, target, distr, self_index_, wells_);
|
append_well_controls(wct, target, distr, self_index_, wells_);
|
||||||
group_control_index_ = wells_->ctrls[self_index_]->num - 1;
|
group_control_index_ = well_controls_get_num(wells_->ctrls[self_index_]) - 1;
|
||||||
} else {
|
} else {
|
||||||
// We will now modify the last control, that
|
// We will now modify the last control, that
|
||||||
// "belongs to" the group control.
|
// "belongs to" the group control.
|
||||||
const int np = wells_->number_of_phases;
|
well_controls_iset_type(wells_->ctrls[self_index_] , group_control_index_ , wct);
|
||||||
wells_->ctrls[self_index_]->type[group_control_index_] = wct;
|
well_controls_iset_target(wells_->ctrls[self_index_] , group_control_index_ ,target);
|
||||||
wells_->ctrls[self_index_]->target[group_control_index_] = target;
|
well_controls_iset_distr(wells_->ctrls[self_index_] , group_control_index_ , distr);
|
||||||
std::copy(distr, distr + np, wells_->ctrls[self_index_]->distr + np*group_control_index_);
|
|
||||||
}
|
}
|
||||||
set_current_control(self_index_, group_control_index_, wells_);
|
set_current_control(self_index_, group_control_index_, wells_);
|
||||||
}
|
}
|
||||||
@ -920,14 +924,13 @@ namespace Opm
|
|||||||
if (group_control_index_ < 0) {
|
if (group_control_index_ < 0) {
|
||||||
// The well only had its own controls, no group controls.
|
// The well only had its own controls, no group controls.
|
||||||
append_well_controls(wct, ntarget, distr, self_index_, wells_);
|
append_well_controls(wct, ntarget, distr, self_index_, wells_);
|
||||||
group_control_index_ = wells_->ctrls[self_index_]->num - 1;
|
group_control_index_ = well_controls_get_num(wells_->ctrls[self_index_]) - 1;
|
||||||
} else {
|
} else {
|
||||||
// We will now modify the last control, that
|
// We will now modify the last control, that
|
||||||
// "belongs to" the group control.
|
// "belongs to" the group control.
|
||||||
const int np = wells_->number_of_phases;
|
well_controls_iset_type(wells_->ctrls[self_index_] , group_control_index_ , wct);
|
||||||
wells_->ctrls[self_index_]->type[group_control_index_] = wct;
|
well_controls_iset_target(wells_->ctrls[self_index_] , group_control_index_ , ntarget);
|
||||||
wells_->ctrls[self_index_]->target[group_control_index_] = ntarget;
|
well_controls_iset_distr(wells_->ctrls[self_index_] , group_control_index_ , distr);
|
||||||
std::copy(distr, distr + np, wells_->ctrls[self_index_]->distr + np*group_control_index_);
|
|
||||||
}
|
}
|
||||||
set_current_control(self_index_, group_control_index_, wells_);
|
set_current_control(self_index_, group_control_index_, wells_);
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <opm/core/io/eclipse/EclipseGridParser.hpp>
|
#include <opm/core/io/eclipse/EclipseGridParser.hpp>
|
||||||
#include <opm/core/grid.h>
|
#include <opm/core/grid.h>
|
||||||
#include <opm/core/wells.h>
|
#include <opm/core/wells.h>
|
||||||
|
#include <opm/core/well_controls.h>
|
||||||
#include <opm/core/utility/ErrorMacros.hpp>
|
#include <opm/core/utility/ErrorMacros.hpp>
|
||||||
#include <opm/core/utility/Units.hpp>
|
#include <opm/core/utility/Units.hpp>
|
||||||
#include <opm/core/wells/WellCollection.hpp>
|
#include <opm/core/wells/WellCollection.hpp>
|
||||||
@ -505,7 +506,7 @@ namespace Opm
|
|||||||
int ok = 1;
|
int ok = 1;
|
||||||
int control_pos[5] = { -1, -1, -1, -1, -1 };
|
int control_pos[5] = { -1, -1, -1, -1, -1 };
|
||||||
if (ok && wci_line.surface_flow_max_rate_ >= 0.0) {
|
if (ok && wci_line.surface_flow_max_rate_ >= 0.0) {
|
||||||
control_pos[InjectionControl::RATE] = w_->ctrls[wix]->num;
|
control_pos[InjectionControl::RATE] = well_controls_get_num(w_->ctrls[wix]);
|
||||||
double distr[3] = { 0.0, 0.0, 0.0 };
|
double distr[3] = { 0.0, 0.0, 0.0 };
|
||||||
if (wci_line.injector_type_ == "WATER") {
|
if (wci_line.injector_type_ == "WATER") {
|
||||||
distr[pu.phase_pos[BlackoilPhases::Aqua]] = 1.0;
|
distr[pu.phase_pos[BlackoilPhases::Aqua]] = 1.0;
|
||||||
@ -521,7 +522,7 @@ namespace Opm
|
|||||||
distr, wix, w_);
|
distr, wix, w_);
|
||||||
}
|
}
|
||||||
if (ok && wci_line.reservoir_flow_max_rate_ >= 0.0) {
|
if (ok && wci_line.reservoir_flow_max_rate_ >= 0.0) {
|
||||||
control_pos[InjectionControl::RESV] = w_->ctrls[wix]->num;
|
control_pos[InjectionControl::RESV] = well_controls_get_num(w_->ctrls[wix]);
|
||||||
double distr[3] = { 0.0, 0.0, 0.0 };
|
double distr[3] = { 0.0, 0.0, 0.0 };
|
||||||
if (wci_line.injector_type_ == "WATER") {
|
if (wci_line.injector_type_ == "WATER") {
|
||||||
distr[pu.phase_pos[BlackoilPhases::Aqua]] = 1.0;
|
distr[pu.phase_pos[BlackoilPhases::Aqua]] = 1.0;
|
||||||
@ -537,7 +538,7 @@ namespace Opm
|
|||||||
distr, wix, w_);
|
distr, wix, w_);
|
||||||
}
|
}
|
||||||
if (ok && wci_line.BHP_limit_ > 0.0) {
|
if (ok && wci_line.BHP_limit_ > 0.0) {
|
||||||
control_pos[InjectionControl::BHP] = w_->ctrls[wix]->num;
|
control_pos[InjectionControl::BHP] = well_controls_get_num(w_->ctrls[wix]);
|
||||||
ok = append_well_controls(BHP, wci_line.BHP_limit_,
|
ok = append_well_controls(BHP, wci_line.BHP_limit_,
|
||||||
NULL, wix, w_);
|
NULL, wix, w_);
|
||||||
}
|
}
|
||||||
@ -618,7 +619,7 @@ namespace Opm
|
|||||||
if (!pu.phase_used[BlackoilPhases::Liquid]) {
|
if (!pu.phase_used[BlackoilPhases::Liquid]) {
|
||||||
OPM_THROW(std::runtime_error, "Oil phase not active and ORAT control specified.");
|
OPM_THROW(std::runtime_error, "Oil phase not active and ORAT control specified.");
|
||||||
}
|
}
|
||||||
control_pos[ProductionControl::ORAT] = w_->ctrls[wix]->num;
|
control_pos[ProductionControl::ORAT] = well_controls_get_num(w_->ctrls[wix]);
|
||||||
double distr[3] = { 0.0, 0.0, 0.0 };
|
double distr[3] = { 0.0, 0.0, 0.0 };
|
||||||
distr[pu.phase_pos[BlackoilPhases::Liquid]] = 1.0;
|
distr[pu.phase_pos[BlackoilPhases::Liquid]] = 1.0;
|
||||||
ok = append_well_controls(SURFACE_RATE, -wcp_line.oil_max_rate_,
|
ok = append_well_controls(SURFACE_RATE, -wcp_line.oil_max_rate_,
|
||||||
@ -628,7 +629,7 @@ namespace Opm
|
|||||||
if (!pu.phase_used[BlackoilPhases::Aqua]) {
|
if (!pu.phase_used[BlackoilPhases::Aqua]) {
|
||||||
OPM_THROW(std::runtime_error, "Water phase not active and WRAT control specified.");
|
OPM_THROW(std::runtime_error, "Water phase not active and WRAT control specified.");
|
||||||
}
|
}
|
||||||
control_pos[ProductionControl::WRAT] = w_->ctrls[wix]->num;
|
control_pos[ProductionControl::WRAT] = well_controls_get_num(w_->ctrls[wix]);
|
||||||
double distr[3] = { 0.0, 0.0, 0.0 };
|
double distr[3] = { 0.0, 0.0, 0.0 };
|
||||||
distr[pu.phase_pos[BlackoilPhases::Aqua]] = 1.0;
|
distr[pu.phase_pos[BlackoilPhases::Aqua]] = 1.0;
|
||||||
ok = append_well_controls(SURFACE_RATE, -wcp_line.water_max_rate_,
|
ok = append_well_controls(SURFACE_RATE, -wcp_line.water_max_rate_,
|
||||||
@ -638,7 +639,7 @@ namespace Opm
|
|||||||
if (!pu.phase_used[BlackoilPhases::Vapour]) {
|
if (!pu.phase_used[BlackoilPhases::Vapour]) {
|
||||||
OPM_THROW(std::runtime_error, "Gas phase not active and GRAT control specified.");
|
OPM_THROW(std::runtime_error, "Gas phase not active and GRAT control specified.");
|
||||||
}
|
}
|
||||||
control_pos[ProductionControl::GRAT] = w_->ctrls[wix]->num;
|
control_pos[ProductionControl::GRAT] = well_controls_get_num(w_->ctrls[wix]);
|
||||||
double distr[3] = { 0.0, 0.0, 0.0 };
|
double distr[3] = { 0.0, 0.0, 0.0 };
|
||||||
distr[pu.phase_pos[BlackoilPhases::Vapour]] = 1.0;
|
distr[pu.phase_pos[BlackoilPhases::Vapour]] = 1.0;
|
||||||
ok = append_well_controls(SURFACE_RATE, -wcp_line.gas_max_rate_,
|
ok = append_well_controls(SURFACE_RATE, -wcp_line.gas_max_rate_,
|
||||||
@ -651,7 +652,7 @@ namespace Opm
|
|||||||
if (!pu.phase_used[BlackoilPhases::Liquid]) {
|
if (!pu.phase_used[BlackoilPhases::Liquid]) {
|
||||||
OPM_THROW(std::runtime_error, "Oil phase not active and LRAT control specified.");
|
OPM_THROW(std::runtime_error, "Oil phase not active and LRAT control specified.");
|
||||||
}
|
}
|
||||||
control_pos[ProductionControl::LRAT] = w_->ctrls[wix]->num;
|
control_pos[ProductionControl::LRAT] = well_controls_get_num(w_->ctrls[wix]);
|
||||||
double distr[3] = { 0.0, 0.0, 0.0 };
|
double distr[3] = { 0.0, 0.0, 0.0 };
|
||||||
distr[pu.phase_pos[BlackoilPhases::Aqua]] = 1.0;
|
distr[pu.phase_pos[BlackoilPhases::Aqua]] = 1.0;
|
||||||
distr[pu.phase_pos[BlackoilPhases::Liquid]] = 1.0;
|
distr[pu.phase_pos[BlackoilPhases::Liquid]] = 1.0;
|
||||||
@ -659,13 +660,13 @@ namespace Opm
|
|||||||
distr, wix, w_);
|
distr, wix, w_);
|
||||||
}
|
}
|
||||||
if (ok && wcp_line.reservoir_flow_max_rate_ >= 0.0) {
|
if (ok && wcp_line.reservoir_flow_max_rate_ >= 0.0) {
|
||||||
control_pos[ProductionControl::RESV] = w_->ctrls[wix]->num;
|
control_pos[ProductionControl::RESV] = well_controls_get_num(w_->ctrls[wix]);
|
||||||
double distr[3] = { 1.0, 1.0, 1.0 };
|
double distr[3] = { 1.0, 1.0, 1.0 };
|
||||||
ok = append_well_controls(RESERVOIR_RATE, -wcp_line.reservoir_flow_max_rate_,
|
ok = append_well_controls(RESERVOIR_RATE, -wcp_line.reservoir_flow_max_rate_,
|
||||||
distr, wix, w_);
|
distr, wix, w_);
|
||||||
}
|
}
|
||||||
if (ok && wcp_line.BHP_limit_ > 0.0) {
|
if (ok && wcp_line.BHP_limit_ > 0.0) {
|
||||||
control_pos[ProductionControl::BHP] = w_->ctrls[wix]->num;
|
control_pos[ProductionControl::BHP] = well_controls_get_num(w_->ctrls[wix]);
|
||||||
ok = append_well_controls(BHP, wcp_line.BHP_limit_,
|
ok = append_well_controls(BHP, wcp_line.BHP_limit_,
|
||||||
NULL, wix, w_);
|
NULL, wix, w_);
|
||||||
}
|
}
|
||||||
@ -754,17 +755,17 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
const int index = it->second;
|
const int index = it->second;
|
||||||
if (line.openshutflag_ == "SHUT") {
|
if (line.openshutflag_ == "SHUT") {
|
||||||
int& cur_ctrl = w_->ctrls[index]->current;
|
int cur_ctrl = well_controls_get_current(w_->ctrls[index]);
|
||||||
if (cur_ctrl >= 0) {
|
if (cur_ctrl >= 0) {
|
||||||
cur_ctrl = ~cur_ctrl;
|
well_controls_invert_current(w_->ctrls[index]);
|
||||||
}
|
}
|
||||||
assert(w_->ctrls[index]->current < 0);
|
assert(well_controls_get_current(w_->ctrls[index]) < 0);
|
||||||
} else if (line.openshutflag_ == "OPEN") {
|
} else if (line.openshutflag_ == "OPEN") {
|
||||||
int& cur_ctrl = w_->ctrls[index]->current;
|
int cur_ctrl = well_controls_get_current(w_->ctrls[index]);
|
||||||
if (cur_ctrl < 0) {
|
if (cur_ctrl < 0) {
|
||||||
cur_ctrl = ~cur_ctrl;
|
well_controls_invert_current(w_->ctrls[index]);
|
||||||
}
|
}
|
||||||
assert(w_->ctrls[index]->current >= 0);
|
assert(well_controls_get_current(w_->ctrls[index]) >= 0);
|
||||||
} else {
|
} else {
|
||||||
OPM_THROW(std::runtime_error, "Unknown Open/close keyword: \"" << line.openshutflag_<< "\". Allowed values: OPEN, SHUT.");
|
OPM_THROW(std::runtime_error, "Unknown Open/close keyword: \"" << line.openshutflag_<< "\". Allowed values: OPEN, SHUT.");
|
||||||
}
|
}
|
||||||
|
318
opm/core/wells/well_controls.c
Normal file
318
opm/core/wells/well_controls.c
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
/*===========================================================================
|
||||||
|
//
|
||||||
|
// File: newwells.c
|
||||||
|
//
|
||||||
|
// Created: 2012-02-03 11:28:40+0100
|
||||||
|
//
|
||||||
|
// Authors: Knut-Andreas Lie <Knut-Andreas.Lie@sintef.no>
|
||||||
|
// Jostein R. Natvig <Jostein.R.Natvig@sintef.no>
|
||||||
|
// Halvor M. Nilsen <HalvorMoll.Nilsen@sintef.no>
|
||||||
|
// Atgeirr F. Rasmussen <atgeirr@sintef.no>
|
||||||
|
// Xavier Raynaud <Xavier.Raynaud@sintef.no>
|
||||||
|
// Bård Skaflestad <Bard.Skaflestad@sintef.no>
|
||||||
|
//
|
||||||
|
//==========================================================================*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2012 SINTEF ICT, Applied Mathematics.
|
||||||
|
Copyright 2012 Statoil ASA.
|
||||||
|
|
||||||
|
This file is part of the Open Porous Media Project (OPM).
|
||||||
|
|
||||||
|
OPM is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OPM is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <opm/core/well_controls.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls for a single well.
|
||||||
|
* Each control specifies a well rate or bottom-hole pressure. Only
|
||||||
|
* one control can be active at a time, indicated by current. The
|
||||||
|
* meaning of each control's target value depends on the control type:
|
||||||
|
*
|
||||||
|
* - BHP -> target pressure in Pascal.
|
||||||
|
* - RESERVOIR_RATE -> target reservoir volume rate in cubic(meter)/second
|
||||||
|
* - SURFACE_RATE -> target surface volume rate in cubic(meter)/second
|
||||||
|
*
|
||||||
|
* The sign convention for RATE targets is as follows:
|
||||||
|
*
|
||||||
|
* - (+) Fluid flowing into reservoir, i.e. injecting.
|
||||||
|
* - (-) Fluid flowing out of reservoir, i.e. producing.
|
||||||
|
*
|
||||||
|
* For *_RATE controls, the distribution of phases used for the control
|
||||||
|
* is also needed. For example, a total rate control should have 1.0
|
||||||
|
* for each phase, whereas a control on oil rate should have 1.0 for
|
||||||
|
* the oil phase and 0.0 for the rest. For BHP controls, this is unused.
|
||||||
|
* The active control acts as an equality constraint, whereas the
|
||||||
|
* non-active controls should be interpreted as inequality
|
||||||
|
* constraints (upper or lower bounds). For instance, a PRODUCER's
|
||||||
|
* BHP constraint defines a minimum acceptable bottom-hole pressure
|
||||||
|
* value for the well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct WellControls
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Number of controls.
|
||||||
|
*/
|
||||||
|
int num;
|
||||||
|
|
||||||
|
int number_of_phases;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of control types.
|
||||||
|
*/
|
||||||
|
enum WellControlType *type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of control targets.
|
||||||
|
*/
|
||||||
|
double *target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of rate control distributions,
|
||||||
|
* <CODE>number_of_phases</CODE> numbers for each control
|
||||||
|
*/
|
||||||
|
double *distr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index of current active control.
|
||||||
|
*/
|
||||||
|
int current;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The capacity allocated.
|
||||||
|
*/
|
||||||
|
int cpty;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
void
|
||||||
|
well_controls_destroy(struct WellControls *ctrl)
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
if (ctrl != NULL) {
|
||||||
|
free (ctrl->distr);
|
||||||
|
free (ctrl->target);
|
||||||
|
free (ctrl->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ctrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
struct WellControls *
|
||||||
|
well_controls_create(void)
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
struct WellControls *ctrl;
|
||||||
|
|
||||||
|
ctrl = malloc(1 * sizeof *ctrl);
|
||||||
|
|
||||||
|
if (ctrl != NULL) {
|
||||||
|
/* Initialise empty control set */
|
||||||
|
ctrl->num = 0;
|
||||||
|
ctrl->number_of_phases = 0;
|
||||||
|
ctrl->type = NULL;
|
||||||
|
ctrl->target = NULL;
|
||||||
|
ctrl->distr = NULL;
|
||||||
|
ctrl->current = -1;
|
||||||
|
ctrl->cpty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
static int
|
||||||
|
well_controls_reserve(int nctrl, struct WellControls *ctrl)
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
int c, p, ok;
|
||||||
|
void *type, *target, *distr;
|
||||||
|
|
||||||
|
type = realloc(ctrl->type , nctrl * 1 * sizeof *ctrl->type );
|
||||||
|
target = realloc(ctrl->target, nctrl * 1 * sizeof *ctrl->target);
|
||||||
|
distr = realloc(ctrl->distr , nctrl * ctrl->number_of_phases * sizeof *ctrl->distr );
|
||||||
|
|
||||||
|
ok = 0;
|
||||||
|
if (type != NULL) { ctrl->type = type ; ok++; }
|
||||||
|
if (target != NULL) { ctrl->target = target; ok++; }
|
||||||
|
if (distr != NULL) { ctrl->distr = distr ; ok++; }
|
||||||
|
|
||||||
|
if (ok == 3) {
|
||||||
|
for (c = ctrl->cpty; c < nctrl; c++) {
|
||||||
|
ctrl->type [c] = BHP;
|
||||||
|
ctrl->target[c] = -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (p = ctrl->cpty * ctrl->number_of_phases; p < nctrl * ctrl->number_of_phases; ++p) {
|
||||||
|
ctrl->distr[ p ] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrl->cpty = nctrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok == 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int well_controls_get_num(const struct WellControls *ctrl) {
|
||||||
|
return ctrl->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int well_controls_get_cpty(const struct WellControls *ctrl) {
|
||||||
|
return ctrl->cpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int well_controls_get_current( const struct WellControls * ctrl) {
|
||||||
|
return ctrl->current;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_set_current( struct WellControls * ctrl, int current) {
|
||||||
|
ctrl->current = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_invert_current( struct WellControls * ctrl ) {
|
||||||
|
ctrl->current = ~ctrl->current;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum WellControlType
|
||||||
|
well_controls_iget_type(const struct WellControls * ctrl, int control_index) {
|
||||||
|
return ctrl->type[control_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum WellControlType
|
||||||
|
well_controls_get_current_type(const struct WellControls * ctrl) {
|
||||||
|
return well_controls_iget_type( ctrl , ctrl->current);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_iset_type( struct WellControls * ctrls , int control_index , enum WellControlType type) {
|
||||||
|
ctrls->type[control_index] = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
well_controls_iget_target(const struct WellControls * ctrl, int control_index) {
|
||||||
|
return ctrl->target[control_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
well_controls_get_current_target(const struct WellControls * ctrl) {
|
||||||
|
return ctrl->target[ctrl->current];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_iset_target(struct WellControls * ctrl, int control_index , double target) {
|
||||||
|
ctrl->target[control_index] = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const double *
|
||||||
|
well_controls_iget_distr(const struct WellControls * ctrl, int control_index) {
|
||||||
|
int offset = control_index * ctrl->number_of_phases;
|
||||||
|
return &ctrl->distr[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const double *
|
||||||
|
well_controls_get_current_distr(const struct WellControls * ctrl) {
|
||||||
|
return well_controls_iget_distr( ctrl , ctrl->current );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_iset_distr(const struct WellControls * ctrl, int control_index, const double * distr) {
|
||||||
|
int offset = control_index * ctrl->number_of_phases;
|
||||||
|
for (int p=0; p < ctrl->number_of_phases; p++)
|
||||||
|
ctrl->distr[offset + p] = distr[p];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_assert_number_of_phases(struct WellControls * ctrl , int number_of_phases) {
|
||||||
|
if (ctrl->num == 0)
|
||||||
|
ctrl->number_of_phases = number_of_phases;
|
||||||
|
|
||||||
|
assert( ctrl->number_of_phases == number_of_phases );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
well_controls_clear(struct WellControls * ctrl) {
|
||||||
|
ctrl->num = 0;
|
||||||
|
ctrl->number_of_phases = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
well_controls_add_new(enum WellControlType type , double target , const double * distr , struct WellControls * ctrl) {
|
||||||
|
if (ctrl->num == ctrl->cpty) {
|
||||||
|
int new_cpty = 2*ctrl->cpty;
|
||||||
|
if (new_cpty == ctrl->num)
|
||||||
|
new_cpty += 1;
|
||||||
|
|
||||||
|
if (!well_controls_reserve( new_cpty , ctrl))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
well_controls_iset_type( ctrl , ctrl->num , type);
|
||||||
|
well_controls_iset_target( ctrl , ctrl->num , target);
|
||||||
|
|
||||||
|
if (distr != NULL)
|
||||||
|
well_controls_iset_distr( ctrl , ctrl->num , distr);
|
||||||
|
|
||||||
|
ctrl->num += 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
well_controls_equal(const struct WellControls *ctrls1, const struct WellControls *ctrls2)
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
bool are_equal = true;
|
||||||
|
are_equal = (ctrls1->num == ctrls2->num);
|
||||||
|
are_equal = are_equal && (ctrls1->number_of_phases == ctrls2->number_of_phases);
|
||||||
|
if (!are_equal) {
|
||||||
|
return are_equal;
|
||||||
|
}
|
||||||
|
|
||||||
|
are_equal = are_equal && (memcmp(ctrls1->type, ctrls2->type, ctrls1->num * sizeof *ctrls1->type ) == 0);
|
||||||
|
are_equal = are_equal && (memcmp(ctrls1->target, ctrls2->target, ctrls1->num * sizeof *ctrls1->target ) == 0);
|
||||||
|
are_equal = are_equal && (memcmp(ctrls1->distr, ctrls2->distr, ctrls1->num * ctrls1->number_of_phases * sizeof *ctrls1->distr ) == 0);
|
||||||
|
are_equal = are_equal && (ctrls1->cpty == ctrls2->cpty);
|
||||||
|
|
||||||
|
return are_equal;
|
||||||
|
}
|
||||||
|
|
@ -35,15 +35,15 @@
|
|||||||
*/
|
*/
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <opm/core/wells.h>
|
#include <opm/core/wells.h>
|
||||||
|
#include <opm/core/well_controls.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
struct WellControlMgmt {
|
#include <stdio.h>
|
||||||
int cpty;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WellMgmt {
|
struct WellMgmt {
|
||||||
int well_cpty;
|
int well_cpty;
|
||||||
@ -51,28 +51,6 @@ struct WellMgmt {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_ctrl_mgmt(struct WellControlMgmt *m)
|
|
||||||
{
|
|
||||||
free(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct WellControlMgmt *
|
|
||||||
create_ctrl_mgmt(void)
|
|
||||||
{
|
|
||||||
struct WellControlMgmt *m;
|
|
||||||
|
|
||||||
m = malloc(1 * sizeof *m);
|
|
||||||
|
|
||||||
if (m != NULL) {
|
|
||||||
m->cpty = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy_well_mgmt(struct WellMgmt *m)
|
destroy_well_mgmt(struct WellMgmt *m)
|
||||||
{
|
{
|
||||||
@ -96,86 +74,6 @@ create_well_mgmt(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
static void
|
|
||||||
well_controls_destroy(struct WellControls *ctrl)
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
{
|
|
||||||
if (ctrl != NULL) {
|
|
||||||
destroy_ctrl_mgmt(ctrl->data);
|
|
||||||
free (ctrl->distr);
|
|
||||||
free (ctrl->target);
|
|
||||||
free (ctrl->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(ctrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
static struct WellControls *
|
|
||||||
well_controls_create(void)
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
{
|
|
||||||
struct WellControls *ctrl;
|
|
||||||
|
|
||||||
ctrl = malloc(1 * sizeof *ctrl);
|
|
||||||
|
|
||||||
if (ctrl != NULL) {
|
|
||||||
/* Initialise empty control set */
|
|
||||||
ctrl->num = 0;
|
|
||||||
ctrl->type = NULL;
|
|
||||||
ctrl->target = NULL;
|
|
||||||
ctrl->distr = NULL;
|
|
||||||
ctrl->current = -1;
|
|
||||||
|
|
||||||
ctrl->data = create_ctrl_mgmt();
|
|
||||||
|
|
||||||
if (ctrl->data == NULL) {
|
|
||||||
well_controls_destroy(ctrl);
|
|
||||||
ctrl = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
static int
|
|
||||||
well_controls_reserve(int nctrl, int nphases, struct WellControls *ctrl)
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
{
|
|
||||||
int c, p, ok;
|
|
||||||
void *type, *target, *distr;
|
|
||||||
|
|
||||||
struct WellControlMgmt *m;
|
|
||||||
|
|
||||||
type = realloc(ctrl->type , nctrl * 1 * sizeof *ctrl->type );
|
|
||||||
target = realloc(ctrl->target, nctrl * 1 * sizeof *ctrl->target);
|
|
||||||
distr = realloc(ctrl->distr , nctrl * nphases * sizeof *ctrl->distr );
|
|
||||||
|
|
||||||
ok = 0;
|
|
||||||
if (type != NULL) { ctrl->type = type ; ok++; }
|
|
||||||
if (target != NULL) { ctrl->target = target; ok++; }
|
|
||||||
if (distr != NULL) { ctrl->distr = distr ; ok++; }
|
|
||||||
|
|
||||||
if (ok == 3) {
|
|
||||||
m = ctrl->data;
|
|
||||||
for (c = m->cpty; c < nctrl; c++) {
|
|
||||||
ctrl->type [c] = BHP;
|
|
||||||
ctrl->target[c] = -1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (p = m->cpty * nphases; p < nctrl * nphases; ++p) {
|
|
||||||
ctrl->distr[ p ] = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
m->cpty = nctrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ok == 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
@ -529,39 +427,16 @@ append_well_controls(enum WellControlType type,
|
|||||||
struct Wells *W)
|
struct Wells *W)
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
{
|
{
|
||||||
int ok, alloc, np;
|
|
||||||
struct WellControls *ctrl;
|
struct WellControls *ctrl;
|
||||||
struct WellControlMgmt *m;
|
|
||||||
|
|
||||||
assert (W != NULL);
|
assert (W != NULL);
|
||||||
assert ((0 <= well_index) && (well_index < W->number_of_wells));
|
assert ((0 <= well_index) && (well_index < W->number_of_wells));
|
||||||
|
|
||||||
ctrl = W->ctrls[well_index];
|
ctrl = W->ctrls[well_index];
|
||||||
np = W->number_of_phases;
|
|
||||||
|
|
||||||
assert (ctrl != NULL);
|
assert (ctrl != NULL);
|
||||||
|
|
||||||
m = ctrl->data;
|
well_controls_assert_number_of_phases( ctrl , W->number_of_phases);
|
||||||
ok = ctrl->num < m->cpty;
|
return well_controls_add_new(type , target , distr , ctrl);
|
||||||
|
|
||||||
if (! ok) {
|
|
||||||
alloc = alloc_size(ctrl->num, 1, m->cpty);
|
|
||||||
ok = well_controls_reserve(alloc, np, ctrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ok) {
|
|
||||||
ctrl->type [ctrl->num] = type ;
|
|
||||||
ctrl->target[ctrl->num] = target;
|
|
||||||
|
|
||||||
if (distr != NULL) {
|
|
||||||
memcpy(ctrl->distr + (ctrl->num * np), distr,
|
|
||||||
np * sizeof *ctrl->distr);
|
|
||||||
}
|
|
||||||
|
|
||||||
ctrl->num += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -572,12 +447,10 @@ set_current_control(int well_index, int current_control, struct Wells *W)
|
|||||||
{
|
{
|
||||||
assert (W != NULL);
|
assert (W != NULL);
|
||||||
assert ((0 <= well_index) && (well_index < W->number_of_wells));
|
assert ((0 <= well_index) && (well_index < W->number_of_wells));
|
||||||
|
|
||||||
assert (W->ctrls[well_index] != NULL);
|
assert (W->ctrls[well_index] != NULL);
|
||||||
|
assert (current_control < well_controls_get_num(W->ctrls[well_index]));
|
||||||
|
|
||||||
assert (current_control < W->ctrls[well_index]->num);
|
well_controls_set_current(W->ctrls[well_index] , current_control);
|
||||||
|
|
||||||
W->ctrls[well_index]->current = current_control;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -589,12 +462,13 @@ clear_well_controls(int well_index, struct Wells *W)
|
|||||||
assert (W != NULL);
|
assert (W != NULL);
|
||||||
assert ((0 <= well_index) && (well_index < W->number_of_wells));
|
assert ((0 <= well_index) && (well_index < W->number_of_wells));
|
||||||
|
|
||||||
if (W->ctrls[well_index] != NULL) {
|
if (W->ctrls[well_index] != NULL)
|
||||||
W->ctrls[well_index]->num = 0;
|
well_controls_clear( W->ctrls[well_index] );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
struct Wells *
|
struct Wells *
|
||||||
clone_wells(const struct Wells *W)
|
clone_wells(const struct Wells *W)
|
||||||
@ -607,17 +481,17 @@ clone_wells(const struct Wells *W)
|
|||||||
enum WellControlType type;
|
enum WellControlType type;
|
||||||
const struct WellControls *ctrls;
|
const struct WellControls *ctrls;
|
||||||
|
|
||||||
struct Wells *ret;
|
struct Wells *newWells;
|
||||||
|
|
||||||
if (W == NULL) {
|
if (W == NULL) {
|
||||||
ret = NULL;
|
newWells = NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
np = W->number_of_phases;
|
np = W->number_of_phases;
|
||||||
ret = create_wells(W->number_of_phases, W->number_of_wells,
|
newWells = create_wells(W->number_of_phases, W->number_of_wells,
|
||||||
W->well_connpos[ W->number_of_wells ]);
|
W->well_connpos[ W->number_of_wells ]);
|
||||||
|
|
||||||
if (ret != NULL) {
|
if (newWells != NULL) {
|
||||||
pos = W->well_connpos[ 0 ];
|
pos = W->well_connpos[ 0 ];
|
||||||
ok = 1;
|
ok = 1;
|
||||||
|
|
||||||
@ -629,7 +503,7 @@ clone_wells(const struct Wells *W)
|
|||||||
comp_frac = W->comp_frac != NULL ? W->comp_frac + w*np : NULL;
|
comp_frac = W->comp_frac != NULL ? W->comp_frac + w*np : NULL;
|
||||||
|
|
||||||
ok = add_well(W->type[ w ], W->depth_ref[ w ], nperf,
|
ok = add_well(W->type[ w ], W->depth_ref[ w ], nperf,
|
||||||
comp_frac, cells, WI, W->name[ w ], ret);
|
comp_frac, cells, WI, W->name[ w ], newWells);
|
||||||
|
|
||||||
/* Capacity should be sufficient from create_wells() */
|
/* Capacity should be sufficient from create_wells() */
|
||||||
assert (ok);
|
assert (ok);
|
||||||
@ -637,34 +511,75 @@ clone_wells(const struct Wells *W)
|
|||||||
ctrls = W->ctrls[ w ];
|
ctrls = W->ctrls[ w ];
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
ok = well_controls_reserve(ctrls->num, np, ret->ctrls[ w ]);
|
for (c = 0; ok && (c < well_controls_get_num(ctrls)); c++) {
|
||||||
|
type = well_controls_iget_type( ctrls , c );
|
||||||
|
target = well_controls_iget_target( ctrls , c );
|
||||||
|
distr = well_controls_iget_distr( ctrls , c );
|
||||||
|
|
||||||
for (c = 0; ok && (c < ctrls->num); c++) {
|
ok = append_well_controls(type, target, distr, w, newWells);
|
||||||
type = ctrls->type [ c ];
|
|
||||||
target = ctrls->target[ c ];
|
|
||||||
distr = & ctrls->distr [ c * np ];
|
|
||||||
|
|
||||||
ok = append_well_controls(type, target, distr, w, ret);
|
|
||||||
|
|
||||||
/* Capacity *should* be sufficient from
|
|
||||||
* well_controls_reserve() */
|
|
||||||
assert (ok);
|
assert (ok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
set_current_control(w, ctrls->current, ret);
|
set_current_control(w, well_controls_get_current( ctrls) , newWells);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = W->well_connpos[w + 1];
|
pos = W->well_connpos[w + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! ok) {
|
if (! ok) {
|
||||||
destroy_wells(ret);
|
destroy_wells(newWells);
|
||||||
ret = NULL;
|
newWells = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return newWells;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
bool
|
||||||
|
wells_equal(const struct Wells *W1, const struct Wells *W2)
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
bool are_equal = true;
|
||||||
|
are_equal = (W1->number_of_wells == W2->number_of_wells);
|
||||||
|
are_equal = are_equal && (W1->number_of_phases == W2->number_of_phases);
|
||||||
|
if (!are_equal) {
|
||||||
|
return are_equal;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<W1->number_of_wells; i++) {
|
||||||
|
are_equal = are_equal && (strcmp(W1->name[i], W2->name[i]) == 0);
|
||||||
|
are_equal = are_equal && (W1->type[i] == W2->type[i]);
|
||||||
|
are_equal = are_equal && (W1->depth_ref[i] == W2->depth_ref[i]);
|
||||||
|
are_equal = are_equal && (well_controls_equal(W1->ctrls[i], W2->ctrls[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
struct WellMgmt* mgmt1 = W1->data;
|
||||||
|
struct WellMgmt* mgmt2 = W2->data;
|
||||||
|
are_equal = are_equal && (mgmt1->perf_cpty == mgmt2->perf_cpty);
|
||||||
|
are_equal = are_equal && (mgmt1->well_cpty == mgmt2->well_cpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
are_equal = are_equal && (memcmp(W1->comp_frac, W2->comp_frac, W1->number_of_wells * W1->number_of_phases * sizeof *W1->comp_frac ) == 0);
|
||||||
|
are_equal = are_equal && (memcmp(W1->well_connpos, W2->well_connpos, (1 + W1->number_of_wells) * sizeof *W1->well_connpos ) == 0);
|
||||||
|
if (!are_equal) {
|
||||||
|
return are_equal;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int number_of_perforations = W1->well_connpos[W1->number_of_wells];
|
||||||
|
|
||||||
|
are_equal = are_equal && (memcmp(W1->well_cells, W2->well_cells, number_of_perforations * sizeof *W1->well_cells ) == 0);
|
||||||
|
are_equal = are_equal && (memcmp(W1->WI, W2->WI, number_of_perforations * sizeof *W1->WI ) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return are_equal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
105
tests/test_wellcontrols.cpp
Normal file
105
tests/test_wellcontrols.cpp
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 Statoil.
|
||||||
|
|
||||||
|
This file is part of the Open Porous Media project (OPM).
|
||||||
|
|
||||||
|
OPM is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OPM is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#if HAVE_DYNAMIC_BOOST_TEST
|
||||||
|
#define BOOST_TEST_DYN_LINK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NVERBOSE // Suppress own messages when throw()ing
|
||||||
|
|
||||||
|
#define BOOST_TEST_MODULE WellsModuleTest
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
#include <opm/core/wells.h>
|
||||||
|
#include <opm/core/well_controls.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(Construction)
|
||||||
|
{
|
||||||
|
struct WellControls * ctrls = well_controls_create();
|
||||||
|
|
||||||
|
well_controls_set_current( ctrls , 1 );
|
||||||
|
BOOST_CHECK_EQUAL( 1 , well_controls_get_current( ctrls ));
|
||||||
|
well_controls_set_current( ctrls , 2 );
|
||||||
|
BOOST_CHECK_EQUAL( 2 , well_controls_get_current( ctrls ));
|
||||||
|
|
||||||
|
well_controls_invert_current( ctrls );
|
||||||
|
BOOST_CHECK( well_controls_get_current( ctrls ) < 0 );
|
||||||
|
well_controls_invert_current( ctrls );
|
||||||
|
BOOST_CHECK_EQUAL( 2 , well_controls_get_current( ctrls ));
|
||||||
|
|
||||||
|
{
|
||||||
|
enum WellControlType type1 = BHP;
|
||||||
|
enum WellControlType type2 = SURFACE_RATE;
|
||||||
|
int num_phases = 3;
|
||||||
|
double dist1[3] = {0 , 1 , 2};
|
||||||
|
double dist2[3] = {10, 11 , 12};
|
||||||
|
double target = 77;
|
||||||
|
|
||||||
|
well_controls_assert_number_of_phases( ctrls , num_phases );
|
||||||
|
well_controls_add_new( type1 , target , dist1 , ctrls );
|
||||||
|
well_controls_add_new( type2 , 2*target , dist2 , ctrls );
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL( target , well_controls_iget_target(ctrls , 0 ));
|
||||||
|
BOOST_CHECK_EQUAL( type1 , well_controls_iget_type(ctrls , 0 ));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL( 2*target , well_controls_iget_target(ctrls , 1 ));
|
||||||
|
BOOST_CHECK_EQUAL( type2 , well_controls_iget_type(ctrls , 1 ));
|
||||||
|
well_controls_set_current( ctrls , 1 );
|
||||||
|
BOOST_CHECK_EQUAL( type2 , well_controls_get_current_type( ctrls ));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL( well_controls_iget_target( ctrls , 1 ) , well_controls_get_current_target( ctrls ));
|
||||||
|
|
||||||
|
{
|
||||||
|
const double * d1 = well_controls_iget_distr( ctrls , 0 );
|
||||||
|
const double * d2 = well_controls_iget_distr( ctrls , 1 );
|
||||||
|
BOOST_CHECK( memcmp(d1 , dist1 , num_phases * sizeof * d1 ) == 0);
|
||||||
|
BOOST_CHECK( memcmp(d2 , dist2 , num_phases * sizeof * d2 ) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
well_controls_iset_target( ctrls , 0 , 123);
|
||||||
|
BOOST_CHECK_EQUAL( 123 , well_controls_iget_target( ctrls , 0 ));
|
||||||
|
well_controls_iset_target( ctrls , 1 , 456);
|
||||||
|
BOOST_CHECK_EQUAL( 456 , well_controls_iget_target( ctrls , 1 ));
|
||||||
|
|
||||||
|
well_controls_iset_type( ctrls , 0 , SURFACE_RATE);
|
||||||
|
BOOST_CHECK_EQUAL( SURFACE_RATE , well_controls_iget_type( ctrls , 0 ));
|
||||||
|
well_controls_iset_type( ctrls , 1 , BHP);
|
||||||
|
BOOST_CHECK_EQUAL( BHP, well_controls_iget_type( ctrls , 1 ));
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
double newDist[3] = {77,78,79};
|
||||||
|
const double * tmp;
|
||||||
|
well_controls_iset_distr( ctrls , 0 , newDist );
|
||||||
|
tmp = well_controls_iget_distr( ctrls , 0);
|
||||||
|
BOOST_CHECK( memcmp(tmp , newDist , 3 * sizeof * tmp ) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
well_controls_destroy( ctrls );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
|||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
#include <opm/core/wells.h>
|
#include <opm/core/wells.h>
|
||||||
|
#include <opm/core/well_controls.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -104,20 +105,20 @@ BOOST_AUTO_TEST_CASE(Controls)
|
|||||||
if (ok1 && ok2) {
|
if (ok1 && ok2) {
|
||||||
WellControls* ctrls = W->ctrls[0];
|
WellControls* ctrls = W->ctrls[0];
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(ctrls->num , 2);
|
BOOST_CHECK_EQUAL(well_controls_get_num(ctrls) , 2);
|
||||||
BOOST_CHECK_EQUAL(ctrls->current, -1);
|
BOOST_CHECK_EQUAL(well_controls_get_current(ctrls), -1);
|
||||||
|
|
||||||
set_current_control(0, 0, W.get());
|
set_current_control(0, 0, W.get());
|
||||||
BOOST_CHECK_EQUAL(ctrls->current, 0);
|
BOOST_CHECK_EQUAL(well_controls_get_current(ctrls), 0);
|
||||||
|
|
||||||
set_current_control(0, 1, W.get());
|
set_current_control(0, 1, W.get());
|
||||||
BOOST_CHECK_EQUAL(ctrls->current, 1);
|
BOOST_CHECK_EQUAL(well_controls_get_current(ctrls), 1);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(ctrls->type[0], BHP);
|
BOOST_CHECK_EQUAL(well_controls_iget_type(ctrls , 0) , BHP);
|
||||||
BOOST_CHECK_EQUAL(ctrls->type[1], SURFACE_RATE);
|
BOOST_CHECK_EQUAL(well_controls_iget_type(ctrls , 1) , SURFACE_RATE);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(ctrls->target[0], 1.0);
|
BOOST_CHECK_EQUAL(well_controls_iget_target(ctrls , 0), 1.0);
|
||||||
BOOST_CHECK_EQUAL(ctrls->target[1], 1.0);
|
BOOST_CHECK_EQUAL(well_controls_iget_target(ctrls , 1), 1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -188,18 +189,48 @@ BOOST_AUTO_TEST_CASE(Copy)
|
|||||||
WellControls* c1 = W1->ctrls[w];
|
WellControls* c1 = W1->ctrls[w];
|
||||||
WellControls* c2 = W2->ctrls[w];
|
WellControls* c2 = W2->ctrls[w];
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(c2->num , c1->num );
|
BOOST_CHECK_EQUAL(well_controls_get_num(c2) , well_controls_get_num(c1));
|
||||||
BOOST_CHECK_EQUAL(c2->current, c1->current);
|
BOOST_CHECK_EQUAL(well_controls_get_current(c2) , well_controls_get_current(c1));
|
||||||
|
|
||||||
for (int c = 0; c < c1->num; ++c) {
|
for (int c = 0; c < well_controls_get_num(c1); ++c) {
|
||||||
BOOST_CHECK_EQUAL(c2->type [c], c1->type [c]);
|
BOOST_CHECK_EQUAL(well_controls_iget_type(c2, c) , well_controls_iget_type(c1 , c));
|
||||||
BOOST_CHECK_EQUAL(c2->target[c], c1->target[c]);
|
BOOST_CHECK_EQUAL(well_controls_iget_target(c2, c) , well_controls_iget_target(c1 , c));
|
||||||
|
|
||||||
for (int p = 0; p < W1->number_of_phases; ++p) {
|
{
|
||||||
BOOST_CHECK_EQUAL(c2->distr[c*W1->number_of_phases + p],
|
const double * dist1 = well_controls_iget_distr(c1 , c );
|
||||||
c1->distr[c*W1->number_of_phases + p]);
|
const double * dist2 = well_controls_iget_distr(c2 , c );
|
||||||
|
|
||||||
|
for (int p = 0; p < W1->number_of_phases; ++p)
|
||||||
|
BOOST_CHECK_EQUAL( dist1[p] , dist2[p]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_CHECK( well_controls_equal( c1 , c2 ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(Equals_WellsEqual_ReturnsTrue) {
|
||||||
|
const int nphases = 2;
|
||||||
|
const int nwells = 2;
|
||||||
|
const int nperfs = 2;
|
||||||
|
|
||||||
|
std::shared_ptr<Wells> W1(create_wells(nphases, nwells, nperfs),
|
||||||
|
destroy_wells);
|
||||||
|
std::shared_ptr<Wells> W2(create_wells(nphases, nwells, nperfs),
|
||||||
|
destroy_wells);
|
||||||
|
|
||||||
|
BOOST_CHECK(wells_equal(W1.get(), W2.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(Equals_WellsDiffer_ReturnsFalse) {
|
||||||
|
const int nphases = 2;
|
||||||
|
const int nperfs = 2;
|
||||||
|
|
||||||
|
std::shared_ptr<Wells> W1(create_wells(nphases, 2, nperfs),
|
||||||
|
destroy_wells);
|
||||||
|
std::shared_ptr<Wells> W2(create_wells(nphases, 3, nperfs),
|
||||||
|
destroy_wells);
|
||||||
|
|
||||||
|
BOOST_CHECK(!wells_equal(W1.get(), W2.get()));
|
||||||
}
|
}
|
||||||
|
236
tests/test_wellsmanager.cpp
Normal file
236
tests/test_wellsmanager.cpp
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2013 Statoil ASA.
|
||||||
|
|
||||||
|
This file is part of the Open Porous Media project (OPM).
|
||||||
|
|
||||||
|
OPM is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OPM is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#if HAVE_DYNAMIC_BOOST_TEST
|
||||||
|
#define BOOST_TEST_DYN_LINK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NVERBOSE // Suppress own messages when throw()ing
|
||||||
|
|
||||||
|
#define BOOST_TEST_MODULE WellsManagerTests
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <opm/core/wells/WellsManager.hpp>
|
||||||
|
#include <opm/core/wells.h>
|
||||||
|
#include <opm/core/well_controls.h>
|
||||||
|
|
||||||
|
#include <opm/core/io/eclipse/EclipseGridParser.hpp>
|
||||||
|
#include <opm/core/grid/GridManager.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
void wells_static_check(const Wells* wells) {
|
||||||
|
BOOST_CHECK_EQUAL(2 , wells->number_of_wells);
|
||||||
|
BOOST_CHECK_EQUAL(3 , wells->number_of_phases);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("INJ1" , wells->name[0]);
|
||||||
|
BOOST_CHECK_EQUAL("PROD1" , wells->name[1]);
|
||||||
|
|
||||||
|
/* The mapping from well number into the wells->WI and wells->well_cells arrays. */
|
||||||
|
BOOST_CHECK_EQUAL(0 , wells->well_connpos[0]);
|
||||||
|
BOOST_CHECK_EQUAL(1 , wells->well_connpos[1]);
|
||||||
|
BOOST_CHECK_EQUAL(2 , wells->well_connpos[2]);
|
||||||
|
|
||||||
|
/* Connection factor */
|
||||||
|
BOOST_CHECK_CLOSE(1.2279166666666664e-12 , wells->WI[0] , 0.001);
|
||||||
|
BOOST_CHECK_CLOSE(1.2279166666666664e-12 , wells->WI[1] , 0.001);
|
||||||
|
|
||||||
|
/* Completed cells */
|
||||||
|
BOOST_CHECK_EQUAL(0 , wells->well_cells[0]);
|
||||||
|
BOOST_CHECK_EQUAL(9 + 2*10 + 2*10*10 , wells->well_cells[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
The number of controls is determined by looking at which elements
|
||||||
|
have been given explicit - non-default - values in the WCONxxxx
|
||||||
|
keyword. Is that at all interesting?
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
void check_controls_epoch0( struct WellControls ** ctrls) {
|
||||||
|
// The injector
|
||||||
|
{
|
||||||
|
const struct WellControls * ctrls0 = ctrls[0];
|
||||||
|
BOOST_CHECK_EQUAL( 3 , well_controls_get_num(ctrls0)); // The number of controls for the injector == 3??
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL( SURFACE_RATE , well_controls_iget_type(ctrls0 , 0) );
|
||||||
|
BOOST_CHECK_EQUAL( RESERVOIR_RATE , well_controls_iget_type(ctrls0 , 1) );
|
||||||
|
BOOST_CHECK_EQUAL( BHP , well_controls_iget_type(ctrls0 , 2) );
|
||||||
|
|
||||||
|
// The different targets
|
||||||
|
BOOST_CHECK_EQUAL( 100.0 / 86400 , well_controls_iget_target(ctrls0,0));
|
||||||
|
BOOST_CHECK_EQUAL( 200.0 / 86400 , well_controls_iget_target(ctrls0,1));
|
||||||
|
BOOST_CHECK_EQUAL( 400 * 100000 , well_controls_iget_target(ctrls0,2));
|
||||||
|
|
||||||
|
// Which control is active
|
||||||
|
BOOST_CHECK_EQUAL( 0 , well_controls_get_current(ctrls0) );
|
||||||
|
|
||||||
|
// The phase distribution in the active target
|
||||||
|
{
|
||||||
|
const double * distr = well_controls_iget_distr( ctrls0 , 0 );
|
||||||
|
BOOST_CHECK_EQUAL( 0 , distr[0] ); // Water
|
||||||
|
BOOST_CHECK_EQUAL( 0 , distr[1] ); // Oil
|
||||||
|
BOOST_CHECK_EQUAL( 1 , distr[2] ); // Gas
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The producer
|
||||||
|
{
|
||||||
|
const struct WellControls * ctrls1 = ctrls[1];
|
||||||
|
BOOST_CHECK_EQUAL( 2 , well_controls_get_num( ctrls1 )); // The number of controls for the producer == 2??
|
||||||
|
BOOST_CHECK_EQUAL( SURFACE_RATE , well_controls_iget_type(ctrls1 , 0) );
|
||||||
|
BOOST_CHECK_EQUAL( BHP , well_controls_iget_type(ctrls1 , 1) );
|
||||||
|
|
||||||
|
// The different targets
|
||||||
|
BOOST_CHECK_EQUAL( -20000.0 / 86400 , well_controls_iget_target(ctrls1,0));
|
||||||
|
BOOST_CHECK_EQUAL( 1000 * 100000 , well_controls_iget_target(ctrls1,1));
|
||||||
|
|
||||||
|
// Which control is active
|
||||||
|
BOOST_CHECK_EQUAL( 0 , well_controls_get_current(ctrls1));
|
||||||
|
|
||||||
|
// The phase distribution in the active target
|
||||||
|
{
|
||||||
|
const double * distr = well_controls_iget_distr( ctrls1 , 0 );
|
||||||
|
BOOST_CHECK_EQUAL( 0 , distr[0] ); // Water
|
||||||
|
BOOST_CHECK_EQUAL( 1 , distr[1] ); // Oil
|
||||||
|
BOOST_CHECK_EQUAL( 0 , distr[2] ); // Gas
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void check_controls_epoch1( struct WellControls ** ctrls) {
|
||||||
|
// The injector
|
||||||
|
{
|
||||||
|
const struct WellControls * ctrls0 = ctrls[0];
|
||||||
|
BOOST_CHECK_EQUAL( 3 , well_controls_get_num(ctrls0)); // The number of controls for the injector == 3??
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL( SURFACE_RATE , well_controls_iget_type(ctrls0 , 0 ));
|
||||||
|
BOOST_CHECK_EQUAL( RESERVOIR_RATE , well_controls_iget_type(ctrls0 , 1 ));
|
||||||
|
BOOST_CHECK_EQUAL( BHP , well_controls_iget_type(ctrls0 , 2 ));
|
||||||
|
|
||||||
|
// The different targets
|
||||||
|
BOOST_CHECK_CLOSE( 10.0 / 86400 , well_controls_iget_target(ctrls0 , 0) , 0.001);
|
||||||
|
BOOST_CHECK_CLOSE( 20.0 / 86400 , well_controls_iget_target(ctrls0 , 1) , 0.001);
|
||||||
|
BOOST_CHECK_CLOSE( 40 * 100000 , well_controls_iget_target(ctrls0 , 2) , 0.001);
|
||||||
|
|
||||||
|
// Which control is active
|
||||||
|
BOOST_CHECK_EQUAL( 1 , well_controls_get_current(ctrls0));
|
||||||
|
|
||||||
|
{
|
||||||
|
const double * distr = well_controls_iget_distr( ctrls0 , 1 );
|
||||||
|
BOOST_CHECK_EQUAL( 1 , distr[0] ); // Water
|
||||||
|
BOOST_CHECK_EQUAL( 0 , distr[1] ); // Oil
|
||||||
|
BOOST_CHECK_EQUAL( 0 , distr[2] ); // Gas
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The producer
|
||||||
|
{
|
||||||
|
const struct WellControls * ctrls1 = ctrls[1];
|
||||||
|
BOOST_CHECK_EQUAL( 3 , well_controls_get_num(ctrls1)); // The number of controls for the producer - now 3.
|
||||||
|
BOOST_CHECK_EQUAL( SURFACE_RATE , well_controls_iget_type(ctrls1 , 0) );
|
||||||
|
BOOST_CHECK_EQUAL( RESERVOIR_RATE , well_controls_iget_type(ctrls1 , 1) );
|
||||||
|
BOOST_CHECK_EQUAL( BHP , well_controls_iget_type(ctrls1 , 2) );
|
||||||
|
|
||||||
|
// The different targets
|
||||||
|
BOOST_CHECK_CLOSE( -999.0 / 86400 , well_controls_iget_target(ctrls1 , 0), 0.001);
|
||||||
|
BOOST_CHECK_CLOSE( -123.0 / 86400 , well_controls_iget_target(ctrls1 , 1), 0.001);
|
||||||
|
BOOST_CHECK_CLOSE( 100 * 100000 , well_controls_iget_target(ctrls1 , 2), 0.001);
|
||||||
|
|
||||||
|
// Which control is active
|
||||||
|
BOOST_CHECK_EQUAL( 1 , well_controls_get_current(ctrls1) );
|
||||||
|
|
||||||
|
{
|
||||||
|
const double * distr = well_controls_iget_distr( ctrls1 , 1 );
|
||||||
|
BOOST_CHECK_EQUAL( 1 , distr[0] ); // Water
|
||||||
|
BOOST_CHECK_EQUAL( 1 , distr[1] ); // Oil
|
||||||
|
BOOST_CHECK_EQUAL( 1 , distr[2] ); // Gas
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(Constructor_Works) {
|
||||||
|
Opm::EclipseGridParser Deck("wells_manager_data.data");
|
||||||
|
Opm::GridManager gridManager(Deck);
|
||||||
|
|
||||||
|
Deck.setCurrentEpoch(0);
|
||||||
|
{
|
||||||
|
Opm::WellsManager wellsManager(Deck, *gridManager.c_grid(), NULL);
|
||||||
|
const Wells* wells = wellsManager.c_wells();
|
||||||
|
wells_static_check( wells );
|
||||||
|
check_controls_epoch0( wells->ctrls );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Deck.setCurrentEpoch(1);
|
||||||
|
{
|
||||||
|
Opm::WellsManager wellsManager(Deck, *gridManager.c_grid(), NULL);
|
||||||
|
const Wells* wells = wellsManager.c_wells();
|
||||||
|
|
||||||
|
wells_static_check( wells );
|
||||||
|
check_controls_epoch1( wells->ctrls );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(WellsEqual) {
|
||||||
|
Opm::EclipseGridParser Deck("wells_manager_data.data");
|
||||||
|
Opm::GridManager gridManager(Deck);
|
||||||
|
|
||||||
|
Deck.setCurrentEpoch(0);
|
||||||
|
Opm::WellsManager wellsManager0(Deck, *gridManager.c_grid(), NULL);
|
||||||
|
|
||||||
|
Deck.setCurrentEpoch(1);
|
||||||
|
Opm::WellsManager wellsManager1(Deck, *gridManager.c_grid(), NULL);
|
||||||
|
|
||||||
|
BOOST_CHECK( wells_equal( wellsManager0.c_wells() , wellsManager0.c_wells()) );
|
||||||
|
BOOST_CHECK( !wells_equal( wellsManager0.c_wells() , wellsManager1.c_wells()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(ControlsEqual) {
|
||||||
|
Opm::EclipseGridParser Deck("wells_manager_data.data");
|
||||||
|
Opm::GridManager gridManager(Deck);
|
||||||
|
|
||||||
|
Deck.setCurrentEpoch(0);
|
||||||
|
Opm::WellsManager wellsManager0(Deck, *gridManager.c_grid(), NULL);
|
||||||
|
|
||||||
|
Deck.setCurrentEpoch(1);
|
||||||
|
Opm::WellsManager wellsManager1(Deck, *gridManager.c_grid(), NULL);
|
||||||
|
|
||||||
|
BOOST_CHECK( well_controls_equal( wellsManager0.c_wells()->ctrls[0] , wellsManager0.c_wells()->ctrls[0]));
|
||||||
|
BOOST_CHECK( well_controls_equal( wellsManager0.c_wells()->ctrls[1] , wellsManager0.c_wells()->ctrls[1]));
|
||||||
|
BOOST_CHECK( well_controls_equal( wellsManager1.c_wells()->ctrls[0] , wellsManager1.c_wells()->ctrls[0]));
|
||||||
|
BOOST_CHECK( well_controls_equal( wellsManager1.c_wells()->ctrls[1] , wellsManager1.c_wells()->ctrls[1]));
|
||||||
|
|
||||||
|
BOOST_CHECK( !well_controls_equal( wellsManager0.c_wells()->ctrls[0] , wellsManager0.c_wells()->ctrls[1]));
|
||||||
|
BOOST_CHECK( !well_controls_equal( wellsManager0.c_wells()->ctrls[1] , wellsManager0.c_wells()->ctrls[0]));
|
||||||
|
BOOST_CHECK( !well_controls_equal( wellsManager1.c_wells()->ctrls[0] , wellsManager0.c_wells()->ctrls[0]));
|
||||||
|
BOOST_CHECK( !well_controls_equal( wellsManager1.c_wells()->ctrls[1] , wellsManager0.c_wells()->ctrls[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
58
tests/wells_manager_data.data
Executable file
58
tests/wells_manager_data.data
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
OIL
|
||||||
|
GAS
|
||||||
|
WATER
|
||||||
|
|
||||||
|
DIMENS
|
||||||
|
10 10 5 /
|
||||||
|
|
||||||
|
GRID
|
||||||
|
|
||||||
|
DXV
|
||||||
|
10*1000.0 /
|
||||||
|
|
||||||
|
DYV
|
||||||
|
10*1000.0 /
|
||||||
|
|
||||||
|
DZV
|
||||||
|
10.0 20.0 30.0 10.0 5.0 /
|
||||||
|
|
||||||
|
SCHEDULE
|
||||||
|
|
||||||
|
WELSPECS
|
||||||
|
'INJ1' 'G' 1 1 8335 'GAS' /
|
||||||
|
'PROD1' 'G' 10 10 8400 'OIL' /
|
||||||
|
/
|
||||||
|
|
||||||
|
COMPDAT
|
||||||
|
'INJ1' 1 1 1 1 'OPEN' 1 10.6092 0.5 /
|
||||||
|
'PROD1' 10 3 3 3 'OPEN' 0 10.6092 0.5 /
|
||||||
|
/
|
||||||
|
|
||||||
|
WCONPROD
|
||||||
|
'PROD1' 'OPEN' 'ORAT' 20000 4* 1000 /
|
||||||
|
/
|
||||||
|
|
||||||
|
WCONINJE
|
||||||
|
'INJ1' 'GAS' 'OPEN' 'RATE' 100 200 400 /
|
||||||
|
/
|
||||||
|
|
||||||
|
|
||||||
|
DATES
|
||||||
|
1 'FEB' 2000 /
|
||||||
|
/
|
||||||
|
|
||||||
|
WCONPROD
|
||||||
|
'PROD1' 'OPEN' 'RESV' 999 3* 123 100 /
|
||||||
|
/
|
||||||
|
|
||||||
|
WCONINJE
|
||||||
|
'INJ1' 'WATER' 'OPEN' 'RESV' 10 20 40 /
|
||||||
|
/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TSTEP
|
||||||
|
14.0
|
||||||
|
/
|
||||||
|
|
||||||
|
END
|
Loading…
Reference in New Issue
Block a user