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:
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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{};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user