mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-12-18 21:43:27 -06:00
464b0c3d15
The 'cpty' field is for internal memory management purposes only. No client can know of its existence, let alone inspect or directly change the value, so it should not be used to adjudicate control set equality. This was useful during the refactoring work to introduce the opm-parser support, but its utility has since ceased. Okay'ed by: [at] atgeirr and [at] joakim-hove
347 lines
9.4 KiB
C
347 lines
9.4 KiB
C
/*===========================================================================
|
|
//
|
|
// 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;
|
|
|
|
bool well_is_open;
|
|
|
|
/*
|
|
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; the well is created open. */
|
|
ctrl->num = 0;
|
|
ctrl->number_of_phases = 0;
|
|
ctrl->type = NULL;
|
|
ctrl->target = NULL;
|
|
ctrl->distr = NULL;
|
|
ctrl->current = -1;
|
|
ctrl->cpty = 0;
|
|
ctrl->well_is_open = true;
|
|
}
|
|
|
|
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_current( const struct WellControls * ctrl) {
|
|
return ctrl->current;
|
|
}
|
|
|
|
void
|
|
well_controls_set_current( struct WellControls * ctrl, int current) {
|
|
ctrl->current = current;
|
|
}
|
|
|
|
bool well_controls_well_is_shut(const struct WellControls * ctrl) {
|
|
return !ctrl->well_is_open;
|
|
}
|
|
|
|
bool well_controls_well_is_open(const struct WellControls * ctrl) {
|
|
return ctrl->well_is_open;
|
|
}
|
|
|
|
void well_controls_open_well( struct WellControls * ctrl) {
|
|
ctrl->well_is_open = true;
|
|
}
|
|
|
|
void well_controls_shut_well( struct WellControls * ctrl) {
|
|
ctrl->well_is_open = false;
|
|
}
|
|
|
|
|
|
|
|
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 verbose)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
bool are_equal = true;
|
|
|
|
if (ctrls1->num != ctrls2->num) {
|
|
are_equal = false;
|
|
if (verbose)
|
|
printf("ctrls1->num:%d ctrls2->num:%d \n",ctrls1->num , ctrls2->num);
|
|
}
|
|
|
|
if (ctrls1->number_of_phases != ctrls2->number_of_phases) {
|
|
are_equal = false;
|
|
if (verbose)
|
|
printf("ctrls1->number_of_phases:%d ctrls2->number_of_phases:%d \n",ctrls1->number_of_phases , ctrls2->number_of_phases);
|
|
}
|
|
|
|
if (!are_equal) {
|
|
return are_equal;
|
|
}
|
|
|
|
if (memcmp(ctrls1->type, ctrls2->type, ctrls1->num * sizeof *ctrls1->type ) != 0) {
|
|
are_equal = false;
|
|
if (verbose)
|
|
printf("The ->type vectors are different \n");
|
|
}
|
|
|
|
if (memcmp(ctrls1->target, ctrls2->target, ctrls1->num * sizeof *ctrls1->target ) != 0) {
|
|
are_equal = false;
|
|
if (verbose)
|
|
printf("The ->target vectors are different \n");
|
|
}
|
|
|
|
return are_equal;
|
|
}
|
|
|