Files
opm-simulators/opm/autodiff/WellHelpers.hpp
Andreas Lauser 44d3d5b536 Merge branch 'master' into frankenstein
* master: (42 commits)
  Let only one rank write to step_timing.txt
  Do not refer users to issue tracker if multiple procs log.
  Remove unused variable.
  Use vector instead of VLA, also add missing includes.
  changed: bundle eigen3 in the original tarball for debian
  update redhat6 packaging
  Bugfix parallel computation of weighted pressure etc.
  Fixed uninitialized bug, and added logging/comment
  Removed superfluous std::move
  Refactoring
  Initial version of summary data
  Do not store collective communication in the wells object.
  Make sure that updateWellControls is called on each process.
  Make WellSwitchingLogger work with DUNE 2.3
  Schedule::getGroup returns reference, not pointer
  Removed warning in WellSwitchLogger::calculateMessageSize
  Correctly initialize MPI for multisegment wells test
  Changed some names in WellSwitchingLogger
  Use speaking name for bool in getCellData
  Whitespace and other formatting changes
  ...
2016-10-14 19:31:56 +02:00

188 lines
6.4 KiB
C++

/*
Copyright 2016 SINTEF ICT, Applied Mathematics.
Copyright 2016 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/>.
*/
#ifndef OPM_WELLHELPERS_HEADER_INCLUDED
#define OPM_WELLHELPERS_HEADER_INCLUDED
#include <opm/core/wells.h>
#include <opm/autodiff/AutoDiffBlock.hpp>
// #include <opm/autodiff/AutoDiffHelpers.hpp>
#include <vector>
namespace Opm {
namespace wellhelpers
{
inline
double rateToCompare(const std::vector<double>& well_phase_flow_rate,
const int well,
const int num_phases,
const double* distr)
{
double rate = 0.0;
for (int phase = 0; phase < num_phases; ++phase) {
// Important: well_phase_flow_rate is ordered with all phase rates for first
// well first, then all phase rates for second well etc.
rate += well_phase_flow_rate[well*num_phases + phase] * distr[phase];
}
return rate;
}
inline
bool constraintBroken(const std::vector<double>& bhp,
const std::vector<double>& thp,
const std::vector<double>& well_phase_flow_rate,
const int well,
const int num_phases,
const WellType& well_type,
const WellControls* wc,
const int ctrl_index)
{
const WellControlType ctrl_type = well_controls_iget_type(wc, ctrl_index);
const double target = well_controls_iget_target(wc, ctrl_index);
const double* distr = well_controls_iget_distr(wc, ctrl_index);
bool broken = false;
switch (well_type) {
case INJECTOR:
{
switch (ctrl_type) {
case BHP:
broken = bhp[well] > target;
break;
case THP:
broken = thp[well] > target;
break;
case RESERVOIR_RATE: // Intentional fall-through
case SURFACE_RATE:
broken = rateToCompare(well_phase_flow_rate,
well, num_phases, distr) > target;
break;
}
}
break;
case PRODUCER:
{
switch (ctrl_type) {
case BHP:
broken = bhp[well] < target;
break;
case THP:
broken = thp[well] < target;
break;
case RESERVOIR_RATE: // Intentional fall-through
case SURFACE_RATE:
// Note that the rates compared below are negative,
// so breaking the constraints means: too high flow rate
// (as for injection).
broken = rateToCompare(well_phase_flow_rate,
well, num_phases, distr) < target;
break;
}
}
break;
default:
OPM_THROW(std::logic_error, "Can only handle INJECTOR and PRODUCER wells.");
}
return broken;
}
// --------- Types ---------
using Vector = AutoDiffBlock<double>::V;
/**
* Simple hydrostatic correction for VFP table
* @param wells - wells struct
* @param w Well number
* @param vfp_table VFP table
* @param well_perforation_densities Densities at well perforations
* @param gravity Gravitational constant (e.g., 9.81...)
*/
inline
double computeHydrostaticCorrection(const Wells& wells, const int w, double vfp_ref_depth,
const double& rho, const double gravity) {
if ( wells.well_connpos[w] == wells.well_connpos[w+1] )
{
// This is a well with no perforations.
// If this is the last well we would subscript over the
// bounds below.
// we assume well_perforation_densities to be 0
return 0;
}
const double well_ref_depth = wells.depth_ref[w];
const double dh = vfp_ref_depth - well_ref_depth;
const double dp = rho*gravity*dh;
return dp;
}
inline
Vector computeHydrostaticCorrection(const Wells& wells, const Vector vfp_ref_depth,
const Vector& well_perforation_densities, const double gravity) {
const int nw = wells.number_of_wells;
Vector retval = Vector::Zero(nw);
#pragma omp parallel for schedule(static)
for (int i=0; i<nw; ++i) {
const int perf = wells.well_connpos[i];
retval[i] = computeHydrostaticCorrection(wells, i, vfp_ref_depth[i], well_perforation_densities[perf], gravity);
}
return retval;
}
inline
std::vector<double> computeHydrostaticCorrection(const Wells& wells, const std::vector<double>& vfp_ref_depth,
const std::vector<double>& well_perforation_densities, const double gravity) {
const int nw = wells.number_of_wells;
std::vector<double> retval(nw,0.0);
#pragma omp parallel for schedule(static)
for (int i=0; i<nw; ++i) {
const int perf = wells.well_connpos[i];
retval[i] = computeHydrostaticCorrection(wells, i, vfp_ref_depth[i], well_perforation_densities[perf], gravity);
}
return retval;
}
} // namespace wellhelpers
}
#endif