Store WELPI Scaling Eligibility as Per-Connection Flag

Greatly simplifies logic in container class (WellConnection).

Suggested by: [at]joakim-hove
This commit is contained in:
Bård Skaflestad
2020-10-08 00:38:13 +02:00
parent f384269133
commit 70ef0858f7
4 changed files with 29 additions and 122 deletions

View File

@@ -122,6 +122,8 @@ namespace RestartIO {
void setState(State state);
void setComplnum(int compnum);
void scaleWellPi(double wellPi);
bool prepareWellPIScaling();
void applyWellPIScaling(const double scaleFactor);
void updateSegmentRST(int segment_number_arg,
double center_depth_arg);
void updateSegment(int segment_number_arg,
@@ -161,6 +163,7 @@ namespace RestartIO {
serializer(m_perf_range);
serializer(m_defaultSatTabId);
serializer(segment_number);
serializer(m_subject_to_welpi);
}
private:
@@ -238,6 +241,9 @@ namespace RestartIO {
// 0 means the completion is not related to segment
int segment_number = 0;
// Whether or not this Connection is subject to WELPI scaling.
bool m_subject_to_welpi = false;
static std::string CTFKindToString(const CTFKind);
};
}

View File

@@ -121,8 +121,6 @@ namespace Opm {
serializer(headI);
serializer(headJ);
serializer.vector(m_connections);
serializer(m_hasWellPIAdjustment);
serializer(m_wellPIConnections);
}
private:
@@ -154,23 +152,9 @@ namespace Opm {
void orderTRACK();
void orderMSW();
// Exclude specific connection from WELPI CF scaling. No action unless
// this connection set has been prepared for WELPI.
void excludeFromWellPI(const std::size_t connID);
Connection::Order m_ordering = Connection::Order::TRACK;
int headI, headJ;
std::vector< Connection > m_connections;
// Backing data for 'WELPI'.
// 1. No adjustment if this set of connections has not been prepared
// for WELPI (m_hasWellPIAdjustment == false, default value).
//
// 2. Otherwise, scale Connection::CF() by supplied scaling factor
// for those connections that are marked in m_wellPIConnections.
// Apply scaling to all connections if m_wellPIConnections.empty().
bool m_hasWellPIAdjustment{false};
std::vector<bool> m_wellPIConnections{};
};
}

View File

@@ -127,6 +127,7 @@ Connection::Connection(const RestartIO::RstConnection& rst_connection, const Ecl
result.m_sort_value = 14;
result.m_defaultSatTabId = true;
result.segment_number = 16;
result.m_subject_to_welpi = true;
return result;
}
@@ -247,7 +248,20 @@ const std::optional<std::pair<double, double>>& Connection::perf_range() const {
this->m_CF *= wellPi;
}
bool Connection::prepareWellPIScaling() {
const auto update = !this->m_subject_to_welpi;
this->m_subject_to_welpi = true;
return update;
}
void Connection::applyWellPIScaling(const double scaleFactor) {
if (! this->m_subject_to_welpi)
return;
this->scaleWellPi(scaleFactor);
}
std::string Connection::str() const {
std::stringstream ss;
@@ -283,7 +297,8 @@ const std::optional<std::pair<double, double>>& Connection::perf_range() const {
&& this->direction == rhs.direction
&& this->segment_number == rhs.segment_number
&& this->center_depth == rhs.center_depth
&& this->m_sort_value == rhs.m_sort_value;
&& this->m_sort_value == rhs.m_sort_value
&& this->m_subject_to_welpi == rhs.m_subject_to_welpi;
}
bool Connection::operator!=( const Connection& rhs ) const {

View File

@@ -22,7 +22,6 @@
#include <cmath>
#include <cstddef>
#include <iostream>
#include <initializer_list>
#include <limits>
#include <stdexcept>
#include <string>
@@ -153,8 +152,6 @@ inline std::array< size_t, 3> directionIndices(const Opm::Connection::Direction
result.headI = 1;
result.headJ = 2;
result.m_connections = {Connection::serializeObject()};
result.m_hasWellPIAdjustment = true;
result.m_wellPIConnections.assign({true, true, false, true, false, false});
return result;
}
@@ -191,33 +188,17 @@ inline std::array< size_t, 3> directionIndices(const Opm::Connection::Direction
bool WellConnections::prepareWellPIScaling()
{
// New WELPI adjustment applies to all connections.
auto update = ! (this->m_hasWellPIAdjustment && this->m_wellPIConnections.empty());
this->m_hasWellPIAdjustment = true;
this->m_wellPIConnections.clear();
auto update = false;
for (auto& conn : this->m_connections)
update = conn.prepareWellPIScaling() || update;
return update;
}
void WellConnections::applyWellPIScaling(const double scaleFactor)
{
if (! this->m_hasWellPIAdjustment)
return;
if (this->m_wellPIConnections.empty())
// Apply to all connections
for (auto& conn : this->m_connections)
conn.scaleWellPi(scaleFactor);
else {
// Apply to active subset
const auto nConn = std::min(this->m_wellPIConnections.size(),
this->m_connections.size());
for (auto conn = 0*nConn; conn < nConn; ++conn)
if (this->m_wellPIConnections[conn])
this->m_connections[conn].scaleWellPi(scaleFactor);
}
for (auto& conn : this->m_connections)
conn.applyWellPIScaling(scaleFactor);
}
void WellConnections::addConnection(int i, int j , int k ,
@@ -446,8 +427,6 @@ inline std::array< size_t, 3> directionIndices(const Opm::Connection::Direction
depth,
css_ind,
*perf_range);
this->excludeFromWellPI(std::distance(this->m_connections.begin(), prev));
}
}
}
@@ -507,7 +486,6 @@ inline std::array< size_t, 3> directionIndices(const Opm::Connection::Direction
void WellConnections::add( Connection connection ) {
m_connections.emplace_back( connection );
this->excludeFromWellPI(this->m_connections.size() - 1);
}
bool WellConnections::allConnectionsShut( ) const {
@@ -569,33 +547,6 @@ inline std::array< size_t, 3> directionIndices(const Opm::Connection::Direction
}
}
void WellConnections::excludeFromWellPI(const std::size_t connID) {
assert (!this->m_connections.empty() &&
"Connection set must be non-empty before calling excludeFromWellPI");
if (!this->m_hasWellPIAdjustment)
// Connection set not prepared for WELPI. Common case. Nothing to do.
return;
if (connID >= this->m_connections.size())
throw std::invalid_argument {
"Cannot exclude connection ID outside known range. "
"Expected 0.." + std::to_string(this->m_connections.size() - 1)
+ ", but got " + std::to_string(connID)
};
if (this->m_wellPIConnections.empty())
// WELPI applies to all connections. Prepare to exclude 'connID'.
this->m_wellPIConnections.assign(this->m_connections.size(), true);
if (this->m_wellPIConnections.size() < this->m_connections.size())
// WELPI applies to subset of connections. Must also exclude those
// that are not already in set of explicitly included connections.
this->m_wellPIConnections.resize(this->m_connections.size(), false);
this->m_wellPIConnections[connID] = false;
}
size_t WellConnections::findClosestConnection(int oi, int oj, double oz, size_t start_pos)
{
size_t closest = std::numeric_limits<size_t>::max();
@@ -628,8 +579,6 @@ inline std::array< size_t, 3> directionIndices(const Opm::Connection::Direction
bool WellConnections::operator==( const WellConnections& rhs ) const {
return this->size() == rhs.size() &&
this->m_ordering == rhs.m_ordering &&
this->m_hasWellPIAdjustment == rhs.m_hasWellPIAdjustment &&
this->m_wellPIConnections == rhs.m_wellPIConnections &&
std::equal( this->begin(), this->end(), rhs.begin() );
}
@@ -637,60 +586,13 @@ inline std::array< size_t, 3> directionIndices(const Opm::Connection::Direction
return !( *this == rhs );
}
namespace {
template <typename S1FwdIter, typename S2FwdIter, typename Predicate>
std::pair<S1FwdIter, S2FwdIter>
remove_if(S1FwdIter s1begin, S1FwdIter s1end, S2FwdIter s2begin, Predicate&& predicate)
{
auto ret = std::make_pair(s1begin, s2begin);
for (; s1begin != s1end; ++s1begin, ++s2begin) {
if (predicate(*s1begin))
// Skip those elements that match the predicate.
continue;
if (ret.first != s1begin) {
// Do nothing if src == dest, i.e. if we've not
// skipped any sequence elements. Otherwise, move
// down.
*ret.first = std::move(*s1begin);
*ret.second = *s2begin;
}
++ret.first;
++ret.second;
}
return ret;
}
}
void WellConnections::filter(const ActiveGridCells& grid) {
auto isInactive = [&grid](const Connection& c) {
return !grid.cellActive(c.getI(), c.getJ(), c.getK());
};
if (!this->m_hasWellPIAdjustment || this->m_wellPIConnections.empty()) {
// Common case. Either no WELPI or WELPI applies to all connections.
// Don't need to take WELPI scaling subset into account.
auto new_end = std::remove_if(m_connections.begin(), m_connections.end(), isInactive);
m_connections.erase(new_end, m_connections.end());
}
else {
// Special case. Subset of connections subject to WELPI scaling.
// Preserve those too.
if (this->m_wellPIConnections.size() < this->m_connections.size())
this->m_wellPIConnections.resize(this->m_connections.size(), false);
auto new_end = remove_if(this->m_connections.begin(), this->m_connections.end(),
this->m_wellPIConnections.begin(), isInactive);
if (new_end.first != this->m_connections.end()) {
// Prune moved from sequence elements.
this->m_connections.erase(new_end.first, this->m_connections.end());
this->m_wellPIConnections.erase(new_end.second, this->m_wellPIConnections.end());
}
}
auto new_end = std::remove_if(m_connections.begin(), m_connections.end(), isInactive);
m_connections.erase(new_end, m_connections.end());
}