mirror of
https://github.com/OPM/opm-simulators.git
synced 2026-07-29 18:37:55 -05:00
Merge pull request #5746 from lisajulia/feature/ms-wells-solving
Feature/ms wells - part 2: Solving, straightforward option
This commit is contained in:
@@ -322,14 +322,13 @@ void FlowGenericVanguard::init()
|
||||
if (comm.rank() == 0)
|
||||
{
|
||||
std::string message =
|
||||
std::string("Option --allow-distributed-wells=true is only allowed if model\n")
|
||||
+ "only has only standard wells. You need to provide option \n"
|
||||
+ " with --enable-multisegement-wells=false to treat existing \n"
|
||||
std::string("Option --allow-distributed-wells=true in a model with\n")
|
||||
+ "multisegment wells. This feature is still experimental. You can\n"
|
||||
+ "set --enable-multisegment-wells=false to treat the existing \n"
|
||||
+ "multisegment wells as standard wells.";
|
||||
OpmLog::error(message);
|
||||
OpmLog::info(message);
|
||||
}
|
||||
comm.barrier();
|
||||
OPM_THROW(std::invalid_argument, "All wells need to be standard wells!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -887,7 +887,7 @@ namespace Opm {
|
||||
this->wellState().init(cellPressures, cellTemperatures, this->schedule(), this->wells_ecl_,
|
||||
this->local_parallel_well_info_, timeStepIdx,
|
||||
&this->prevWellState(), this->well_perf_data_,
|
||||
this->summaryState());
|
||||
this->summaryState(), simulator_.vanguard().enableDistributedWells());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -152,6 +152,14 @@ apply(const BVector& x, BVector& Ax) const
|
||||
|
||||
duneB_.mv(x, Bx);
|
||||
|
||||
if (this->pw_info_.communication().size() == 1) {
|
||||
// We need to communicate here to get the contributions from all segments
|
||||
this->pw_info_.communication().sum(Bx.data(), Bx.size());
|
||||
}
|
||||
|
||||
// It is ok to do this on each process instead of only on one,
|
||||
// because the other processes would remain idle while waiting for
|
||||
// the single process to complete the computation.
|
||||
// invDBx = duneD^-1 * Bx_
|
||||
const BVectorWell invDBx = mswellhelpers::applyUMFPack(*duneDSolver_, Bx);
|
||||
|
||||
@@ -163,6 +171,9 @@ template<class Scalar, int numWellEq, int numEq>
|
||||
void MultisegmentWellEquations<Scalar,numWellEq,numEq>::
|
||||
apply(BVector& r) const
|
||||
{
|
||||
// It is ok to do this on each process instead of only on one,
|
||||
// because the other processes would remain idle while waiting for
|
||||
// the single process to complete the computation.
|
||||
// invDrw_ = duneD^-1 * resWell_
|
||||
const BVectorWell invDrw = mswellhelpers::applyUMFPack(*duneDSolver_, resWell_);
|
||||
// r = r - duneC_^T * invDrw
|
||||
@@ -193,6 +204,9 @@ template<class Scalar, int numWellEq, int numEq>
|
||||
typename MultisegmentWellEquations<Scalar,numWellEq,numEq>::BVectorWell
|
||||
MultisegmentWellEquations<Scalar,numWellEq,numEq>::solve() const
|
||||
{
|
||||
// It is ok to do this on each process instead of only on one,
|
||||
// because the other processes would remain idle while waiting for
|
||||
// the single process to complete the computation.
|
||||
return mswellhelpers::applyUMFPack(*duneDSolver_, resWell_);
|
||||
}
|
||||
|
||||
@@ -200,6 +214,9 @@ template<class Scalar, int numWellEq, int numEq>
|
||||
typename MultisegmentWellEquations<Scalar,numWellEq,numEq>::BVectorWell
|
||||
MultisegmentWellEquations<Scalar,numWellEq,numEq>::solve(const BVectorWell& rhs) const
|
||||
{
|
||||
// It is ok to do this on each process instead of only on one,
|
||||
// because the other processes would remain idle while waiting for
|
||||
// the single process to complete the computation.
|
||||
return mswellhelpers::applyUMFPack(*duneDSolver_, rhs);
|
||||
}
|
||||
|
||||
@@ -207,10 +224,24 @@ template<class Scalar, int numWellEq, int numEq>
|
||||
void MultisegmentWellEquations<Scalar,numWellEq,numEq>::
|
||||
recoverSolutionWell(const BVector& x, BVectorWell& xw) const
|
||||
{
|
||||
BVectorWell resWell = resWell_;
|
||||
// resWell = resWell - B * x
|
||||
duneB_.mmv(x, resWell);
|
||||
BVectorWell resWell = resWell_;
|
||||
if (this->pw_info_.communication().size() == 1) {
|
||||
duneB_.mmv(x, resWell);
|
||||
} else {
|
||||
BVectorWell Bx(duneB_.N());
|
||||
duneB_.mv(x, Bx);
|
||||
|
||||
// We need to communicate here to get the contributions from all segments
|
||||
this->pw_info_.communication().sum(Bx.data(), Bx.size());
|
||||
|
||||
resWell -= Bx;
|
||||
}
|
||||
|
||||
// xw = D^-1 * resWell
|
||||
// It is ok to do this on each process instead of only on one,
|
||||
// because the other processes would remain idle while waiting for
|
||||
// the single process to complete the computation.
|
||||
xw = mswellhelpers::applyUMFPack(*duneDSolver_, resWell);
|
||||
}
|
||||
|
||||
|
||||
@@ -264,11 +264,13 @@ void WellState<Scalar>::init(const std::vector<Scalar>& cellPressures,
|
||||
const int report_step,
|
||||
const WellState* prevState,
|
||||
const std::vector<std::vector<PerforationData<Scalar>>>& well_perf_data,
|
||||
const SummaryState& summary_state)
|
||||
const SummaryState& summary_state,
|
||||
const bool enableDistributedWells)
|
||||
{
|
||||
// call init on base class
|
||||
this->base_init(cellPressures, cellTemperatures, wells_ecl, parallel_well_info,
|
||||
well_perf_data, summary_state);
|
||||
this->enableDistributedWells_ = enableDistributedWells;
|
||||
this->global_well_info = std::make_optional<GlobalWellInfo>(schedule,
|
||||
report_step,
|
||||
wells_ecl);
|
||||
@@ -439,7 +441,7 @@ void WellState<Scalar>::resize(const std::vector<Well>& wells_ecl,
|
||||
const SummaryState& summary_state)
|
||||
{
|
||||
const std::vector<Scalar> tmp(numCells, 0.0); // <- UGLY HACK to pass the size
|
||||
init(tmp, tmp, schedule, wells_ecl, parallel_well_info, 0, nullptr, well_perf_data, summary_state);
|
||||
init(tmp, tmp, schedule, wells_ecl, parallel_well_info, 0, nullptr, well_perf_data, summary_state, this->enableDistributedWells_);
|
||||
|
||||
if (handle_ms_well) {
|
||||
initWellStateMSWell(wells_ecl, nullptr);
|
||||
@@ -728,8 +730,8 @@ void WellState<Scalar>::initWellStateMSWell(const std::vector<Well>& wells_ecl,
|
||||
n_activeperf++;
|
||||
}
|
||||
}
|
||||
|
||||
if (static_cast<int>(ws.perf_data.size()) != n_activeperf)
|
||||
|
||||
if (!this->enableDistributedWells_ && static_cast<int>(ws.perf_data.size()) != n_activeperf)
|
||||
throw std::logic_error("Distributed multi-segment wells cannot be initialized properly yet.");
|
||||
|
||||
|
||||
|
||||
@@ -104,7 +104,8 @@ public:
|
||||
const int report_step,
|
||||
const WellState* prevState,
|
||||
const std::vector<std::vector<PerforationData<Scalar>>>& well_perf_data,
|
||||
const SummaryState& summary_state);
|
||||
const SummaryState& summary_state,
|
||||
const bool enableDistributedWells);
|
||||
|
||||
void resize(const std::vector<Well>& wells_ecl,
|
||||
const std::vector<std::reference_wrapper<ParallelWellInfo<Scalar>>>& parallel_well_info,
|
||||
@@ -353,6 +354,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
bool enableDistributedWells_ = false;
|
||||
|
||||
bool is_permanently_inactive_well(const std::string& wname) const {
|
||||
return std::find(this->permanently_inactive_well_names_.begin(), this->permanently_inactive_well_names_.end(), wname) != this->permanently_inactive_well_names_.end();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user