mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
one version of the class WellMultiSegment.
This commit is contained in:
parent
60dd7743c3
commit
62bdd301d3
@ -140,16 +140,21 @@ namespace Opm
|
||||
|
||||
const std::vector<WellConstPtr>& wells_ecl = eclipse_state_->getSchedule()->getWells(timer.currentStepNum());
|
||||
|
||||
std::vector<WellMutliSegmentPtr> wells_multisegment;
|
||||
std::vector<WellMutliSegmentPtr> wells_multisegment(wells_ecl.size());
|
||||
|
||||
wells_multisegment.reserve(wells_ecl.size());
|
||||
// wells_multisegment.resize(wells_ecl.size());
|
||||
|
||||
/* std::cout << " the number of the wells from EclipseState " << wells_ecl.size() << std::endl;
|
||||
for (size_t i = 0; i < wells_multisegment.size(); ++i) {
|
||||
wells_multisegment[i].reset(new WellMultiSegment(wells_ecl[i], timer.currentStepNum(), wells));
|
||||
}
|
||||
|
||||
// for DEBUGGING OUTPUT
|
||||
std::cout << " the number of the wells from EclipseState " << wells_ecl.size() << std::endl;
|
||||
for (size_t i = 0; i < wells_ecl.size(); ++i) {
|
||||
std::cout << " well name " << wells_ecl[i]->name() << std::endl;
|
||||
std::cout << " segment wells " << wells_ecl[i]->isMultiSegment() << std::endl;
|
||||
}
|
||||
std::cin.ignore(); */
|
||||
std::cin.ignore();
|
||||
|
||||
// give the polymer and surfactant simulators the chance to do their stuff
|
||||
asImpl().handleAdditionalWellInflow(timer, wells_manager, well_state, wells);
|
||||
|
@ -25,15 +25,21 @@
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
WellMultiSegment::WellMultiSegment(WellConstPtr well, size_t time_step, const Wells* wells) {
|
||||
init(well, time_step, wells);
|
||||
}
|
||||
|
||||
|
||||
// how to find the order of the well?
|
||||
void WellMultiSegment::init(WellConstPtr well, size_t time_step, const Wells* wells) {
|
||||
m_well_name_ = well->name();
|
||||
CompletionSetConstPtr completion_set = well->getCompletions(time_step);
|
||||
|
||||
if (well->isMultiSegment()) {
|
||||
m_is_multi_segment_ = true;
|
||||
SegmentSetConstPtr segment_set = well->getSegmentSet(time_step);
|
||||
m_number_of_segments_ = segment_set->numberSegment();
|
||||
|
||||
m_number_of_perforations_ = completion_set->size();
|
||||
m_comp_pressure_drop_ = segment_set->compPressureDrop();
|
||||
m_multiphase_model_ = segment_set->multiPhaseModel();
|
||||
|
||||
@ -41,9 +47,11 @@ namespace Opm
|
||||
// m_well_index_ from wells
|
||||
m_outlet_segment_.resize(m_number_of_segments_);
|
||||
m_segment_length_.resize(m_number_of_segments_);
|
||||
m_segment_depth_.resize(m_number_of_segments_);
|
||||
m_segment_internal_diameter_.resize(m_number_of_segments_);
|
||||
m_segment_roughness_.resize(m_number_of_segments_);
|
||||
m_segment_volume_.resize(m_number_of_segments_);
|
||||
m_segment_perforations_.resize(m_number_of_segments_);
|
||||
// what is the point to do this?
|
||||
|
||||
// we change the ID to location now for easier use later.
|
||||
@ -60,16 +68,156 @@ namespace Opm
|
||||
// update the completion related information
|
||||
// find the location of the well in wells first
|
||||
// through well names?
|
||||
for (size_t i = 0; i < completion_set->size(); ++i) {
|
||||
|
||||
int index_well;
|
||||
for (index_well = 0; index_well < wells->number_of_wells; ++index_well) {
|
||||
if (m_well_name_ == std::string(wells->name[index_well])) {
|
||||
break;
|
||||
}
|
||||
// std::cout << std::string(wells->name[i]) << "1" << std::endl;
|
||||
}
|
||||
|
||||
std::vector<int> temp_well_cell;
|
||||
std::vector<double> temp_well_index;
|
||||
|
||||
if (index_well == wells->number_of_wells) {
|
||||
throw std::runtime_error(" did not find the well " + m_well_name_ + "\n");
|
||||
} else {
|
||||
|
||||
m_well_type_ = wells->type[index_well];
|
||||
m_well_controls_ = wells->ctrls[index_well];
|
||||
m_number_of_phases_ = wells->number_of_phases;
|
||||
m_comp_frac_.resize(m_number_of_phases_);
|
||||
std::copy(wells->comp_frac + index_well * m_number_of_phases_,
|
||||
wells->comp_frac + (index_well + 1) * m_number_of_phases_, m_comp_frac_.begin());
|
||||
|
||||
int index_begin = wells->well_connpos[index_well];
|
||||
int index_end = wells->well_connpos[index_well + 1];
|
||||
// m_number_of_perforations_ = index_end - index_begin;
|
||||
|
||||
|
||||
for(int i = index_begin; i < index_end; ++i) {
|
||||
temp_well_cell.push_back(wells->well_cells[i]);
|
||||
temp_well_index.push_back(wells->WI[i]);
|
||||
// copy the WI and well_cell_ informatin to m_well_index_ and m_well_cell_
|
||||
// maybe also the depth of the perforations.
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<double> temp_perf_depth;
|
||||
temp_perf_depth.resize(m_number_of_perforations_);
|
||||
|
||||
for (size_t i = 0; i < completion_set->size(); ++i) {
|
||||
int i_segment = completion_set->get(i)->getSegmentNumber();
|
||||
// convert the original segment id to be the current segment id,
|
||||
// which is the location in the array.
|
||||
i_segment = segment_set->numberToLocation(i_segment);
|
||||
m_segment_perforations_[i_segment].push_back(i);
|
||||
temp_perf_depth[i] = completion_set->get(i)->getCenterDepth();
|
||||
// TODO: how to handle the center depth of the perforation from the COMPSEGS
|
||||
}
|
||||
|
||||
// reordering the perforation related informations
|
||||
// so that the perforations belong to the same segment will be continuous
|
||||
m_well_cell_.resize(m_number_of_perforations_);
|
||||
m_well_index_.resize(m_number_of_perforations_);
|
||||
m_perf_depth_.resize(m_number_of_perforations_);
|
||||
|
||||
int perf_count = 0;
|
||||
for (size_t is = 0; is < m_number_of_segments_; ++is) {
|
||||
for (size_t iperf = 0; iperf < m_segment_perforations_[is].size(); ++iperf) {
|
||||
int perf_number = m_segment_perforations_[is][iperf];
|
||||
m_well_cell_[perf_count] = temp_well_cell[perf_number];
|
||||
m_well_index_[perf_count] = temp_well_index[perf_number];
|
||||
m_perf_depth_[perf_count] = temp_perf_depth[perf_number];
|
||||
m_segment_perforations_[is][iperf] = perf_count;
|
||||
++perf_count;
|
||||
}
|
||||
}
|
||||
|
||||
assert(perf_count == m_number_of_perforations_);
|
||||
// std::cin.ignore();
|
||||
|
||||
// how to build the relation between segments and completions
|
||||
// the completion should be in a global array (all the wells) or local scope (this well)?
|
||||
// As the first version, probably it should be OK to handle the wells seperately.
|
||||
// Even it will be easier to genrate the matrix in an interleaved way.
|
||||
// For each segment, a 4X4 block.
|
||||
// we handle with in the local scope first
|
||||
// need to change the related segments to the new segment ID (location in the arrary)
|
||||
|
||||
} else {
|
||||
m_is_multi_segment_ = false;
|
||||
m_number_of_segments_ = 1;
|
||||
m_comp_pressure_drop_ = WellSegment::H__;
|
||||
m_multiphase_model_ = WellSegment::HO;
|
||||
|
||||
m_outlet_segment_.resize(m_number_of_segments_);
|
||||
m_segment_length_.resize(m_number_of_segments_);
|
||||
m_segment_depth_.resize(m_number_of_segments_);
|
||||
m_segment_internal_diameter_.resize(m_number_of_segments_);
|
||||
m_segment_roughness_.resize(m_number_of_segments_);
|
||||
m_segment_volume_.resize(m_number_of_segments_);
|
||||
m_segment_perforations_.resize(m_number_of_segments_);
|
||||
|
||||
// now the segment for top segment is 0, then its outlet segment will be -1
|
||||
// it is also the flag to indicate the top segment
|
||||
m_outlet_segment_[0] = -1;
|
||||
// TODO: decide the following quantities later.
|
||||
// m_segment_length_[i] = (*segment_set)[i]->length();
|
||||
// m_segment_depth_[i] = (*segment_set)[i]->depth();
|
||||
// m_segment_internal_diameter_[i] = (*segment_set)[i]->internalDiameter();
|
||||
// m_segment_roughness_[i] = (*segment_set)[i]->roughness();
|
||||
// m_segment_volume_[i] = (*segment_set)[i]->volume();
|
||||
|
||||
// update the completion related information
|
||||
// find the location of the well in wells first
|
||||
// through well names?
|
||||
int index_well;
|
||||
for (index_well = 0; index_well < wells->number_of_wells; ++index_well) {
|
||||
if (m_well_name_ == std::string(wells->name[index_well])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index_well == wells->number_of_wells) {
|
||||
throw std::runtime_error(" did not find the well " + m_well_name_ + "\n");
|
||||
} else {
|
||||
m_well_type_ = wells->type[index_well];
|
||||
m_well_controls_ = wells->ctrls[index_well];
|
||||
m_number_of_phases_ = wells->number_of_phases;
|
||||
m_comp_frac_.resize(m_number_of_phases_);
|
||||
std::copy(wells->comp_frac + index_well * m_number_of_phases_,
|
||||
wells->comp_frac + (index_well + 1) * m_number_of_phases_, m_comp_frac_.begin());
|
||||
|
||||
int index_begin = wells->well_connpos[index_well];
|
||||
int index_end = wells->well_connpos[index_well + 1];
|
||||
m_number_of_perforations_ = index_end - index_begin;
|
||||
|
||||
for(int i = index_begin; i < index_end; ++i) {
|
||||
m_well_cell_.push_back(wells->well_cells[i]);
|
||||
m_well_index_.push_back(wells->WI[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: not sure if we need the perf_depth_.
|
||||
// m_perf_depth_.resize(m_number_of_perforations_);
|
||||
m_segment_perforations_[0].resize(m_number_of_perforations_);
|
||||
|
||||
for (size_t i = 0; i < m_number_of_perforations_; ++i) {
|
||||
m_segment_perforations_[0][i] = i;
|
||||
}
|
||||
|
||||
// std::cin.ignore();
|
||||
|
||||
// how to build the relation between segments and completions
|
||||
// the completion should be in a global array (all the wells) or local scope (this well)?
|
||||
// As the first version, probably it should be OK to handle the wells seperately.
|
||||
// Even it will be easier to genrate the matrix in an interleaved way.
|
||||
// For each segment, a 4X4 block.
|
||||
// we handle with in the local scope first
|
||||
// need to change the related segments to the new segment ID (location in the arrary)
|
||||
|
||||
|
||||
// building a segment structure for the non-segmented well
|
||||
// basically, for each well, only one segment, which means the top segment
|
||||
// and all the completions will contribute to the top segment.
|
||||
@ -81,18 +229,37 @@ namespace Opm
|
||||
// The major point will be if the pressure difference between the
|
||||
// location of bhp reference point is exactly same with the current
|
||||
// way to compute the connection pressure difference.
|
||||
|
||||
// And also, with Multisegment well, the way to calculate the density of
|
||||
// mixture for wellbore hydrostatic head is always AVG.
|
||||
// while for usual wells, it is typically SEG.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
size_t WellMultiSegment::numberOfPerforations() const {
|
||||
const enum WellType WellMultiSegment::wellType() const {
|
||||
return m_well_type_;
|
||||
}
|
||||
|
||||
const struct WellControls* WellMultiSegment::wellControls() const {
|
||||
return m_well_controls_;
|
||||
}
|
||||
|
||||
const size_t WellMultiSegment::numberOfPerforations() const {
|
||||
return m_number_of_perforations_;
|
||||
}
|
||||
|
||||
size_t WellMultiSegment::numberOfSegment() const {
|
||||
const size_t WellMultiSegment::numberOfSegment() const {
|
||||
return m_number_of_segments_;
|
||||
}
|
||||
|
||||
const std::vector<double>& WellMultiSegment::compFrac() const {
|
||||
return m_comp_frac_;
|
||||
}
|
||||
|
||||
const size_t WellMultiSegment::numberOfPhases() const {
|
||||
return m_number_of_phases_;
|
||||
}
|
||||
|
||||
const std::vector<double>& WellMultiSegment::wellIndex() const {
|
||||
return m_well_index_;
|
||||
}
|
||||
|
@ -43,10 +43,17 @@ namespace Opm
|
||||
{
|
||||
public:
|
||||
|
||||
WellMultiSegment(WellConstPtr well, size_t time_step, const Wells* wells);
|
||||
|
||||
size_t numberOfPerforations() const;
|
||||
size_t numberOfSegment() const;
|
||||
const size_t numberOfPerforations() const;
|
||||
const size_t numberOfSegment() const;
|
||||
|
||||
const struct WellControls* wellControls() const;
|
||||
const std::vector<double>& compFrac() const;
|
||||
|
||||
const size_t numberOfPhases() const;
|
||||
|
||||
const enum WellType wellType() const;
|
||||
const std::vector<double>& wellIndex() const;
|
||||
const std::vector<double>& perfDepth() const;
|
||||
const std::vector<int>& wellCell() const;
|
||||
@ -65,10 +72,21 @@ namespace Opm
|
||||
|
||||
private:
|
||||
// name of the well
|
||||
std::string m_well_name;
|
||||
std::string m_well_name_;
|
||||
// flag to indicate if this well is a
|
||||
// multi-segmented well
|
||||
bool m_is_multi_segment_;
|
||||
// well type
|
||||
// INJECTOR or PRODUCER
|
||||
enum WellType m_well_type_;
|
||||
// number of phases
|
||||
size_t m_number_of_phases_;
|
||||
// component fractions for each well
|
||||
std::vector<double> m_comp_frac_;
|
||||
// controls for this well
|
||||
// using pointer for temporary
|
||||
// changing it when figuring out how to using it
|
||||
struct WellControls *m_well_controls_;
|
||||
// components of the pressure drop to be included
|
||||
WellSegment::CompPresureDropEnum m_comp_pressure_drop_;
|
||||
// multi-phase flow model
|
||||
@ -79,7 +97,7 @@ namespace Opm
|
||||
size_t m_number_of_segments_;
|
||||
// well index for each completion
|
||||
std::vector<double> m_well_index_;
|
||||
// depth for each completion
|
||||
// depth for each completion // form the keyword COMPSEGS?
|
||||
std::vector<double> m_perf_depth_;
|
||||
// well cell for each completion
|
||||
std::vector<int> m_well_cell_;
|
||||
@ -107,6 +125,8 @@ namespace Opm
|
||||
// the completions that is related to each segment
|
||||
// the completions's ids are their location in the vector m_well_index_
|
||||
// m_well_cell_
|
||||
// This is also assuming the order of the completions in Well is the same with
|
||||
// the order of the completions in wells.
|
||||
std::vector<std::vector<int>> m_segment_perforations_;
|
||||
};
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <opm/core/well_controls.h>
|
||||
#include <opm/core/simulator/WellState.hpp>
|
||||
#include <opm/core/utility/ErrorMacros.hpp>
|
||||
#include <opm/autodiff/WellMultiSegment.hpp>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
@ -41,27 +42,71 @@ namespace Opm
|
||||
: public WellState
|
||||
{
|
||||
public:
|
||||
|
||||
// typedef std::array< int, 3 > mapentry_t;
|
||||
// typedef std::map< std::string, mapentry_t > WellMapType;
|
||||
// this map needs to change a little bit?
|
||||
/* struct mapentry {
|
||||
int well_number;
|
||||
int number_of_segments;
|
||||
std::vector<int> number_of_performations;
|
||||
} */
|
||||
// MAYNOT NEED THIS
|
||||
|
||||
/// Allocate and initialize if wells is non-null. Also tries
|
||||
/// to give useful initial values to the bhp(), wellRates()
|
||||
/// and perfPhaseRates() fields, depending on controls
|
||||
template <class State, class PrevState>
|
||||
void init(const Wells* wells, const State& state, const PrevState& prevState)
|
||||
void init(const std::vector<WellMultiSegment>& wells, const State& state, const PrevState& prevState)
|
||||
{
|
||||
const int nw = wells.size();
|
||||
if (nw == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int np = wells[0].numberOfPhases(); // number of the phases
|
||||
|
||||
int nperf = 0; // the number of the perforations
|
||||
int nseg = 0; // the nubmer of the segments
|
||||
|
||||
for (int iw = 0; iw < nw; ++iw) {
|
||||
nperf += wells[i].numberOfPerforations();
|
||||
nseg += wells[i].numberOfSegment();
|
||||
}
|
||||
|
||||
bhp_.resize(nw);
|
||||
thp_.resize(nw);
|
||||
wellrates_.resize(nw * np, 0.0);
|
||||
|
||||
current_controls_.resize(nw);
|
||||
for(int iw = 0; iw < nw; ++iw) {
|
||||
current_controls_[iw] = well_controls_get_current(wells[iw].wellControls());
|
||||
}
|
||||
|
||||
for (int iw = 0; iw < nw; ++iw) {
|
||||
assert((wells[i].wellType() == INJECTOR) || (wells[i].wellType() == PRODUCER));
|
||||
const WellControls* ctrl = wells[iw]->wellControls();
|
||||
}
|
||||
|
||||
|
||||
// Map is used to map the value from the previous state to the current state as the initial values
|
||||
// TODO: handle this later.
|
||||
// Trying to figure out the work flow first.
|
||||
}
|
||||
|
||||
private:
|
||||
// pressure for the segment nodes
|
||||
// pressure for the top segment nodes are the bhp
|
||||
std::vector<double> segpressure_;
|
||||
std::vector<double> seg_pressure_;
|
||||
// phase rates for the segments
|
||||
std::vector<double> segphaserates_;
|
||||
std::vector<double> seg_phaserates_;
|
||||
// phase rates for the completions
|
||||
std::vector<double> perfphaserates_;
|
||||
std::vector<double> perf_phaserates_;
|
||||
// fractions for each segments (W, O, G)
|
||||
std::vector<double> seg_phasefrac_;
|
||||
// total flow rates for each segments, G_T
|
||||
std::vector<double> seg_totalrate_;
|
||||
std::vector<int> current_controls_;
|
||||
// WellMapType wellMap_;
|
||||
WellMapType wellMap_;
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
Loading…
Reference in New Issue
Block a user