when encountering a multisegment well

we create a multisegment well instead of treating all the wells as
StandardWell. Making it compile.
This commit is contained in:
Kai Bao 2017-09-01 17:37:51 +02:00
parent d694a72b53
commit 16ecbddefb
4 changed files with 41 additions and 21 deletions

View File

@ -36,6 +36,8 @@ namespace Opm
// TODO: the WellState does not have any information related to segments
using typename Base::WellState;
using typename Base::Simulator;
using typename Base::ModelParameters;
// TODO: for now, not considering the polymer, solvent and so on to simplify the development process.
// TODO: should I begin with the old primary variable or the new fraction based variable systems?
@ -157,6 +159,7 @@ namespace Opm
using Base::well_ecl_;
using Base::number_of_perforations_; // TODO: can use well_ecl_?
using Base::current_step_;
using Base::well_cells_; // TODO: are the perforation orders same with StandardWell or Wells?
using Base::well_index_;
@ -173,6 +176,8 @@ namespace Opm
// As the current temporary solution, the grid cell related to a segment determined by the
// first perforation cell related to the segment.
// when no perforation is related to the segment, use it outlet segment's cell.
// TODO: it can be a source of error
std::vector<int> segment_cell_;
// the completions that is related to each segment
@ -181,7 +186,11 @@ namespace Opm
// the order of the completions in wells.
// it is for convinience reason. we can just calcuate the inforation for segment once then using it for all the perofrations
// belonging to this segment
std::vector<std::vector<int>> segment_perforations_;
std::vector<std::vector<int> > segment_perforations_;
// the inlet segments for each segment. It is for convinience and efficiency reason
// the original segment structure is defined as a gathering tree structure based on outlet_segment
std::vector<std::vector<int> > segment_inlets_;
// Things are easy to get from SegmentSet
// segment_volume_, segment_cross_area_, segment_length_(total length), segment_depth_
@ -206,7 +215,7 @@ namespace Opm
mutable BVector scaleAddRes_;
// residuals of the well equations
BVectorWell resWell_;
mutable BVectorWell resWell_;
// the values for the primary varibles
// based on different solutioin strategies, the wells can have different primary variables
@ -217,6 +226,8 @@ namespace Opm
// the Evaluation for the well primary variables, which contain derivativles and are used in AD calculation
mutable std::vector<std::array<EvalWell, numWellEq> > primary_variables_evaluation_;
void initMatrixAndVectors(const int num_cells) const;
// protected functions
// EvalWell getBhp(); this one should be something similar to getSegmentPressure();
// EvalWell getQs(); this one should be something similar to getSegmentRates()

View File

@ -27,7 +27,10 @@ namespace Opm
template<typename TypeTag>
MultisegmentWell<TypeTag>::
MultisegmentWell(const Well* well, const int time_step, const Wells* wells)
:Basse(well, time_step, wells)
: Base(well, time_step, wells)
, segment_cell_(numberOfSegments())
, segment_perforations_(numberOfSegments())
, segment_inlets_(numberOfSegments())
{
// TODO: to see what information we need to process here later.
// const auto& completion_set = well->getCompletions(time_step);
@ -61,6 +64,10 @@ namespace Opm
// For the last case, should we update the depth with the depth_arg? For the
// future, it can be a source of wrong result with Multisegment well.
// An indicator from the opm-parser should indicate what kind of depth we should use here.
// \Note: we do not update the depth here. And it looks like for now, we only have the option to use
// specified perforation depth
initMatrixAndVectors(num_cells);
}
@ -81,9 +88,9 @@ namespace Opm
// B D] x_well] res_well]
// the number of the nnz should be numSegment() + numberOfOutlet()
invDuneD_.setSize(numSegment(), numSegment(), 100000);
duneB_.setSize(numSegment(), num_cells, number_of_perforations_);
duneC_.setSize(numSegment(), num_cells, number_of_perforations_);
invDuneD_.setSize(numberOfSegments(), numberOfSegments(), 100000);
duneB_.setSize(numberOfSegments(), num_cells, number_of_perforations_);
duneC_.setSize(numberOfSegments(), num_cells, number_of_perforations_);
// we need to add the off diagonal ones
for (auto row=invDuneD_.createbegin(), end = invDuneD_.createend(); row!=end; ++row) {
@ -93,8 +100,8 @@ namespace Opm
for (auto row = duneC_.createbegin(), end = duneC_.createend(); row!=end; ++row) {
// the number of the row corresponds to the segment number now.
for (int perf = 0 ; perf < ]; ++perf) { // the segments hold some perforations
const int cell_idx = wells().well_cells[perf];
for (int perf = 0 ; perf < number_of_perforations_; ++perf) { // the segments hold some perforations
const int cell_idx = well_cells_[perf];
row.insert(cell_idx);
}
}
@ -102,16 +109,16 @@ namespace Opm
// make the B^T matrix
for (auto row = duneB_.createbegin(), end = duneB_.createend(); row!=end; ++row) {
// the number of the row corresponds to the segment number now.
for (int perf = wells().well_connpos[row.index()] ; perf < wells().well_connpos[row.index()+1]; ++perf) {
const int cell_idx = wells().well_cells[perf];
for (int perf = 0; perf < number_of_perforations_; ++perf) {
const int cell_idx = well_cells_[perf];
row.insert(cell_idx);
}
}
resWell_.resize( nw );
resWell_.resize( numberOfSegments() );
// resize temporary class variables
Cx_.resize( duneC_.N() );
Bx_.resize( duneC_.N() );
invDrw_.resize( invDuneD_.N() );
}
@ -124,7 +131,7 @@ namespace Opm
MultisegmentWell<TypeTag>::
initPrimaryVariablesEvaluation() const
{
for (int seg = 0; seg < numSegment(); ++seg) {
for (int seg = 0; seg < numberOfSegments(); ++seg) {
for (int eq_idx = 0; eq_idx < numWellEq; ++eq_idx) {
primary_variables_evaluation_[seg][eq_idx] = 0.0;
primary_variables_evaluation_[seg][eq_idx].setValue(primary_variables_[seg][eq_idx]);
@ -186,6 +193,8 @@ namespace Opm
const ModelParameters& param) const
{
// TODO: it will be very similar
ConvergenceReport report;
return report;
}
@ -222,7 +231,7 @@ namespace Opm
template<typename TypeTag>
void
MultisegmentWell<TypeTag>::
void apply(const BVector& x, BVector& Ax) const
apply(const BVector& x, BVector& Ax) const
{
@ -309,7 +318,7 @@ namespace Opm
MultisegmentWell<TypeTag>::
segmentSet() const
{
return well_ecl_->getSegmentSet(time_step);
return well_ecl_->getSegmentSet(current_step_);
}

View File

@ -49,6 +49,7 @@
#include <opm/autodiff/RateConverter.hpp>
#include <opm/autodiff/WellInterface.hpp>
#include <opm/autodiff/StandardWell.hpp>
#include <opm/autodiff/MultisegmentWell.hpp>
#include<dune/common/fmatrix.hh>
#include<dune/istl/bcrsmatrix.hh>
#include<dune/istl/matrixmatrix.hh>

View File

@ -146,13 +146,12 @@ namespace Opm {
}
const Well* well_ecl = wells_ecl[index_well];
// TODO: stopping throwing when encoutnering MS wells for now.
/* if (well_ecl->isMultiSegment(time_step)) {
OPM_THROW(Opm::NumericalProblem, "Not handling Multisegment Wells for now");
} */
// Basically, we are handling all the wells as StandardWell for the moment
well_container.emplace_back(new StandardWell<TypeTag>(well_ecl, time_step, wells) );
if ( !well_ecl->isMultiSegment(time_step) ) {
well_container.emplace_back(new StandardWell<TypeTag>(well_ecl, time_step, wells) );
} else {
well_container.emplace_back(new MultisegmentWell<TypeTag>(well_ecl, time_step, wells) );
}
}
}
return well_container;