opm-simulators/opm/core/wells/well_controls.c
Bård Skaflestad 464b0c3d15 well_controls_equal(): Don't compare set capacities
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
2014-07-03 16:09:56 +02:00

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;
}