mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Significant modification of well data structures and related functions.
The following changes are made: - The SurfaceComponent enum has been removed. - Added new member Wells::number_of_phases. - The Wells::zfrac member has been replaced with comp_frac. The old zfrac always had 3 components per well (accessed according to the canonical ordering given by SurfaceComponent), the new one has number_of_phases components per well. - Changed add_well() accordingly to accept comp_frac. - Added new member WellControls::distr, giving distributions for rate controls. - All functions dealing with well controls now take Wells* and a well index instead of directly taking WellControls*. - Now append_well_controls() also takes a rate distribution argument. - Added new public function set_current_control().
This commit is contained in:
parent
743085bd16
commit
597a2cc7af
@ -35,26 +35,29 @@ extern "C" {
|
||||
|
||||
/** Well type indicates desired/expected well behaviour. */
|
||||
enum WellType { INJECTOR, PRODUCER };
|
||||
/** Type of well control equation or inequality constraint.
|
||||
* BHP -> Well constrained by bottom-hole pressure target.
|
||||
* RATE -> Well constrained by total reservoir volume flow rate.
|
||||
*/
|
||||
enum WellControlType { BHP , RATE };
|
||||
/** Canonical component names and ordering. */
|
||||
enum SurfaceComponent { WATER = 0, OIL = 1, GAS = 2 };
|
||||
|
||||
/** Type of well control equation or inequality constraint.
|
||||
* BHP -> Well constrained by bottom-hole pressure target.
|
||||
* RESERVOIR_RATE -> Well constrained by reservoir volume flow rates.
|
||||
* SURFACE_RATE -> Well constrained by surface volume flow rates.
|
||||
*/
|
||||
enum WellControlType { BHP, RESERVOIR_RATE, SURFACE_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, for BHP controls it is a pressure in Pascal, for RATE
|
||||
* controls it is a volumetric rate in cubic(meter)/second. The sign
|
||||
* convention for RATE targets is as follows:
|
||||
* 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.
|
||||
* The active control as an equality constraint, whereas the
|
||||
* 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
|
||||
@ -63,8 +66,10 @@ enum SurfaceComponent { WATER = 0, OIL = 1, GAS = 2 };
|
||||
struct WellControls
|
||||
{
|
||||
int num; /** Number of controls. */
|
||||
enum WellControlType *type; /** Array of control types. */
|
||||
double *target; /** Array of control targets. */
|
||||
enum WellControlType *type; /** Array of control types.*/
|
||||
double *target; /** Array of control targets */
|
||||
double *distr; /** Array of rate control distributions,
|
||||
Wells::number_of_phases numbers per well */
|
||||
int current; /** Index of current active control. */
|
||||
|
||||
void *data; /** Internal management structure. */
|
||||
@ -75,19 +80,20 @@ struct WellControls
|
||||
/** Data structure aggregating static information about all wells in a scenario. */
|
||||
struct Wells
|
||||
{
|
||||
int number_of_wells; /** Number of wells. */
|
||||
int number_of_wells; /** Number of wells. */
|
||||
int number_of_phases; /** Number of phases. */
|
||||
|
||||
enum WellType *type; /** Array of well types. */
|
||||
double *depth_ref; /** Array of well bhp reference depths. */
|
||||
double *zfrac; /** Component volume fractions for each well, size is (3*number_of_wells).
|
||||
double *comp_frac; /** Component fractions for each well, size is (number_of_wells*number_of_phases).
|
||||
* This is intended to be used for injection wells. For production wells
|
||||
* the component fractions will vary and cannot be specified a priori.
|
||||
*/
|
||||
int *well_connpos; /** Array of indices into well_cells (and WI).
|
||||
* For a well w, well_connpos[w] and well_connpos[w+1] yield
|
||||
* start and one-beyond-end indices into the well_cells array
|
||||
* for accessing w's perforation cell indices.
|
||||
*/
|
||||
* For a well w, well_connpos[w] and well_connpos[w+1] yield
|
||||
* start and one-beyond-end indices into the well_cells array
|
||||
* for accessing w's perforation cell indices.
|
||||
*/
|
||||
int *well_cells; /** Array of perforation cell indices.
|
||||
* Size is number of perforations (== well_connpos[number_of_wells]).
|
||||
*/
|
||||
@ -130,19 +136,21 @@ struct CompletionData
|
||||
* destroy_wells() to dispose of the Wells object and its allocated
|
||||
* memory resources.
|
||||
*
|
||||
* \param[in] nwells Expected number of wells in simulation scenario.
|
||||
* Pass zero if the total number of wells is unknown.
|
||||
* \param[in] nphases Number of active phases in simulation scenario.
|
||||
*
|
||||
* \param[in] nperf Expected total number of well connections
|
||||
* (perforations) for all wells in simulation
|
||||
* scenario. Pass zero if the total number of well
|
||||
* connections is unknown.
|
||||
* \param[in] nwells Expected number of wells in simulation scenario.
|
||||
* Pass zero if the total number of wells is unknown.
|
||||
*
|
||||
* \param[in] nperf Expected total number of well connections
|
||||
* (perforations) for all wells in simulation
|
||||
* scenario. Pass zero if the total number of well
|
||||
* connections is unknown.
|
||||
*
|
||||
* \return A valid Wells object with no wells if successful, and NULL
|
||||
* otherwise.
|
||||
*/
|
||||
struct Wells *
|
||||
create_wells(int nwells, int nperf);
|
||||
create_wells(int nphases, int nwells, int nperf);
|
||||
|
||||
|
||||
/**
|
||||
@ -156,7 +164,7 @@ create_wells(int nwells, int nperf);
|
||||
* \param[in] type Type of well.
|
||||
* \param[in] depth_ref Reference depth for well's BHP.
|
||||
* \param[in] nperf Number of perforations.
|
||||
* \param[in] zfrac Injection fraction (three components) or NULL.
|
||||
* \param[in] comp_frac Injection fraction array (size equal to W->number_of_phases) or NULL.
|
||||
* \param[in] cells Grid cells in which well is perforated. Should
|
||||
* ideally be track ordered.
|
||||
* \param[in] WI Well production index per perforation, or NULL.
|
||||
@ -169,7 +177,7 @@ int
|
||||
add_well(enum WellType type ,
|
||||
double depth_ref,
|
||||
int nperf ,
|
||||
const double *zfrac ,
|
||||
const double *comp_frac,
|
||||
const int *cells ,
|
||||
const double *WI ,
|
||||
struct Wells *W );
|
||||
@ -181,23 +189,35 @@ add_well(enum WellType type ,
|
||||
* Increments ctrl->num by one if successful. Introducing a new
|
||||
* operational constraint does not affect the well's notion of the
|
||||
* currently active constraint represented by ctrl->current.
|
||||
* Note that *_RATE controls now require a phase distribution array
|
||||
* to be associated with the control, see WellControls.
|
||||
*
|
||||
* \param[in] type Control type.
|
||||
* \param[in] target Target value for the control.
|
||||
* \param[inout] ctrl Existing set of well controls.
|
||||
* \param[in] type Control type.
|
||||
* \param[in] target Target value for the control.
|
||||
* \param[in] distr Array of size W->number_of_phases or NULL.
|
||||
* \param[in] well_index Index of well to receive additional control.
|
||||
* \param[in,out] W Existing set of well controls.
|
||||
* \return Non-zero (true) if successful and zero (false) otherwise.
|
||||
*/
|
||||
int
|
||||
append_well_controls(enum WellControlType type ,
|
||||
double target,
|
||||
struct WellControls *ctrl );
|
||||
const double *distr,
|
||||
int well_index,
|
||||
struct Wells *W);
|
||||
|
||||
/**
|
||||
* Clear all controls from a well.
|
||||
* Set the current control for a single well.
|
||||
*/
|
||||
void
|
||||
set_current_control(int well_index, int current_control, struct Wells *W);
|
||||
|
||||
/**
|
||||
* Clear all controls from a single well.
|
||||
*
|
||||
* Does not affect the control set capacity. */
|
||||
void
|
||||
clear_well_controls(struct WellControls *ctrl);
|
||||
clear_well_controls(int well_index, struct Wells *W);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -103,6 +103,7 @@ well_controls_destroy(struct WellControls *ctrl)
|
||||
{
|
||||
if (ctrl != NULL) {
|
||||
destroy_ctrl_mgmt(ctrl->data);
|
||||
free (ctrl->distr);
|
||||
free (ctrl->target);
|
||||
free (ctrl->type);
|
||||
}
|
||||
@ -125,6 +126,7 @@ well_controls_create(void)
|
||||
ctrl->num = 0;
|
||||
ctrl->type = NULL;
|
||||
ctrl->target = NULL;
|
||||
ctrl->distr = NULL;
|
||||
ctrl->current = -1;
|
||||
|
||||
ctrl->data = create_ctrl_mgmt();
|
||||
@ -141,26 +143,31 @@ well_controls_create(void)
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
static int
|
||||
well_controls_reserve(int nctrl, struct WellControls *ctrl)
|
||||
well_controls_reserve(int nctrl, int nphases, struct WellControls *ctrl)
|
||||
/* ---------------------------------------------------------------------- */
|
||||
{
|
||||
int c, ok;
|
||||
void *type, *target;
|
||||
int c, p, ok;
|
||||
void *type, *target, *distr;
|
||||
|
||||
struct WellControlMgmt *m;
|
||||
|
||||
type = realloc(ctrl->type , nctrl * sizeof *ctrl->type );
|
||||
target = realloc(ctrl->target, nctrl * sizeof *ctrl->target);
|
||||
distr = realloc(ctrl->distr , nphases * nctrl * 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 == 2) {
|
||||
m = ctrl->data;
|
||||
for (c = m->cpty; c < nctrl; c++) {
|
||||
ctrl->type [c] = BHP;
|
||||
ctrl->target[c] = -1.0;
|
||||
for (p = 0; p < nphases; ++p) {
|
||||
ctrl->distr [nphases*c + p] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
m->cpty = nctrl;
|
||||
@ -175,15 +182,17 @@ static int
|
||||
wells_allocate(int nwells, struct Wells *W)
|
||||
/* ---------------------------------------------------------------------- */
|
||||
{
|
||||
int ok;
|
||||
void *type, *depth_ref, *zfrac;
|
||||
int ok, np;
|
||||
void *type, *depth_ref, *comp_frac;
|
||||
void *well_connpos;
|
||||
void *ctrls;
|
||||
|
||||
type = realloc(W->type , 1 * nwells * sizeof *W->type);
|
||||
depth_ref = realloc(W->depth_ref, 1 * nwells * sizeof *W->depth_ref);
|
||||
zfrac = realloc(W->zfrac , 3 * nwells * sizeof *W->zfrac);
|
||||
ctrls = realloc(W->ctrls , 1 * nwells * sizeof *W->ctrls);
|
||||
np = W->number_of_phases;
|
||||
|
||||
type = realloc(W->type , 1 * nwells * sizeof *W->type);
|
||||
depth_ref = realloc(W->depth_ref, 1 * nwells * sizeof *W->depth_ref);
|
||||
comp_frac = realloc(W->comp_frac, np * nwells * sizeof *W->comp_frac);
|
||||
ctrls = realloc(W->ctrls , 1 * nwells * sizeof *W->ctrls);
|
||||
|
||||
well_connpos = realloc(W->well_connpos,
|
||||
(nwells + 1) * sizeof *W->well_connpos);
|
||||
@ -191,7 +200,7 @@ wells_allocate(int nwells, struct Wells *W)
|
||||
ok = 0;
|
||||
if (type != NULL) { W->type = type ; ok++; }
|
||||
if (depth_ref != NULL) { W->depth_ref = depth_ref ; ok++; }
|
||||
if (zfrac != NULL) { W->zfrac = zfrac ; ok++; }
|
||||
if (comp_frac != NULL) { W->comp_frac = comp_frac ; ok++; }
|
||||
if (well_connpos != NULL) { W->well_connpos = well_connpos; ok++; }
|
||||
if (ctrls != NULL) { W->ctrls = ctrls ; ok++; }
|
||||
|
||||
@ -223,7 +232,7 @@ static int
|
||||
initialise_new_wells(int nwells, struct Wells *W)
|
||||
/* ---------------------------------------------------------------------- */
|
||||
{
|
||||
int ok, w;
|
||||
int ok, w, p;
|
||||
|
||||
struct WellMgmt *m;
|
||||
|
||||
@ -233,9 +242,9 @@ initialise_new_wells(int nwells, struct Wells *W)
|
||||
W->type [w] = PRODUCER;
|
||||
W->depth_ref[w] = -1.0;
|
||||
|
||||
W->zfrac[3*w + WATER] = 0.0;
|
||||
W->zfrac[3*w + OIL ] = 0.0;
|
||||
W->zfrac[3*w + GAS ] = 0.0;
|
||||
for (p = 0; p < W->number_of_phases; ++p) {
|
||||
W->comp_frac[W->number_of_phases*w + p] = 0.0;
|
||||
}
|
||||
|
||||
W->well_connpos[w + 1] = W->well_connpos[w];
|
||||
}
|
||||
@ -322,7 +331,7 @@ wells_reserve(int nwells, int nperf, struct Wells *W)
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
struct Wells *
|
||||
create_wells(int nwells, int nperf)
|
||||
create_wells(int nphases, int nwells, int nperf)
|
||||
/* ---------------------------------------------------------------------- */
|
||||
{
|
||||
int ok;
|
||||
@ -332,10 +341,11 @@ create_wells(int nwells, int nperf)
|
||||
|
||||
if (W != NULL) {
|
||||
W->number_of_wells = 0;
|
||||
W->number_of_phases = nphases;
|
||||
|
||||
W->type = NULL;
|
||||
W->depth_ref = NULL;
|
||||
W->zfrac = NULL;
|
||||
W->comp_frac = NULL;
|
||||
|
||||
W->well_connpos = malloc(1 * sizeof *W->well_connpos);
|
||||
W->well_cells = NULL;
|
||||
@ -386,7 +396,7 @@ destroy_wells(struct Wells *W)
|
||||
free(W->WI);
|
||||
free(W->well_cells);
|
||||
free(W->well_connpos);
|
||||
free(W->zfrac);
|
||||
free(W->comp_frac);
|
||||
free(W->depth_ref);
|
||||
free(W->type);
|
||||
}
|
||||
@ -417,13 +427,13 @@ int
|
||||
add_well(enum WellType type ,
|
||||
double depth_ref,
|
||||
int nperf ,
|
||||
const double *zfrac , /* Injection fraction or NULL */
|
||||
const double *comp_frac, /* Injection fraction or NULL */
|
||||
const int *cells ,
|
||||
const double *WI , /* Well index per perf (or NULL) */
|
||||
struct Wells *W )
|
||||
/* ---------------------------------------------------------------------- */
|
||||
{
|
||||
int ok, nw, nperf_tot, off;
|
||||
int ok, nw, np, nperf_tot, off;
|
||||
int nwalloc, nperfalloc;
|
||||
|
||||
struct WellMgmt *m;
|
||||
@ -459,8 +469,9 @@ add_well(enum WellType type ,
|
||||
W->type [nw] = type ;
|
||||
W->depth_ref[nw] = depth_ref;
|
||||
|
||||
if (zfrac != NULL) {
|
||||
memcpy(W->zfrac + 3*nw, zfrac, 3 * sizeof *W->zfrac);
|
||||
np = W->number_of_phases;
|
||||
if (comp_frac != NULL) {
|
||||
memcpy(W->comp_frac + np*nw, comp_frac, np * sizeof *W->comp_frac);
|
||||
}
|
||||
|
||||
W->well_connpos[nw + 1] = off + nperf;
|
||||
@ -473,15 +484,22 @@ add_well(enum WellType type ,
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
int
|
||||
append_well_controls(enum WellControlType type ,
|
||||
append_well_controls(enum WellControlType type,
|
||||
double target,
|
||||
struct WellControls *ctrl )
|
||||
const double *distr,
|
||||
int well_index,
|
||||
struct Wells *W)
|
||||
/* ---------------------------------------------------------------------- */
|
||||
{
|
||||
int ok, alloc;
|
||||
|
||||
int ok, alloc, p, np;
|
||||
struct WellControls *ctrl;
|
||||
struct WellControlMgmt *m;
|
||||
|
||||
assert (W != NULL);
|
||||
|
||||
ctrl = W->ctrls[well_index];
|
||||
np = W->number_of_phases;
|
||||
|
||||
assert (ctrl != NULL);
|
||||
|
||||
m = ctrl->data;
|
||||
@ -489,13 +507,17 @@ append_well_controls(enum WellControlType type ,
|
||||
|
||||
if (! ok) {
|
||||
alloc = alloc_size(ctrl->num, 1, m->cpty);
|
||||
ok = well_controls_reserve(alloc, ctrl);
|
||||
ok = well_controls_reserve(alloc, np, ctrl);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
ctrl->type [ctrl->num] = type ;
|
||||
ctrl->target[ctrl->num] = target;
|
||||
|
||||
if (distr != NULL) {
|
||||
for (p = 0; p < np; ++p) {
|
||||
ctrl->distr[ctrl->num * np + p] = distr[p];
|
||||
}
|
||||
}
|
||||
ctrl->num += 1;
|
||||
}
|
||||
|
||||
@ -505,10 +527,21 @@ append_well_controls(enum WellControlType type ,
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
void
|
||||
clear_well_controls(struct WellControls *ctrl)
|
||||
set_current_control(int well_index, int current_control, struct Wells *W)
|
||||
/* ---------------------------------------------------------------------- */
|
||||
{
|
||||
if (ctrl != NULL) {
|
||||
ctrl->num = 0;
|
||||
assert (W->ctrls[well_index] != NULL);
|
||||
|
||||
W->ctrls[well_index]->current = current_control;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
void
|
||||
clear_well_controls(int well_index, struct Wells *W)
|
||||
/* ---------------------------------------------------------------------- */
|
||||
{
|
||||
if (W->ctrls[well_index] != NULL) {
|
||||
W->ctrls[well_index]->num = 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user