Skip to content

Commit

Permalink
Add Connection Fracturing Statistics Summary Vectors
Browse files Browse the repository at this point in the history
This commit adds support for collecting and reporting the following
set of connection level fracturing statistics measures

  - CFR<Q>MAX -- Maximum value of connection level fracturing
    quantity <Q>
  - CFR<Q>MIN -- Minimum value of connection level fracturing
    quantity <Q>
  - CFR<Q>AVG -- Arithmetic average of connection level fracturing
    quantity <Q>
  - CFR<Q>STD -- Unbiased standard deviation of connection level
    fracturing quantity <Q>

The currently supported quantities (<Q>) are

  - 'P'  -- Fracture pressure
  - 'IR' -- Injection flow rate
  - 'WD' -- Fracture width

These vectors adhere to the common connection level summary vector
specification whence

    CFRPMAX
      'I1' 16 16 6 /
    /

    CFRIRAVG
      'I1' * /
    /

    CFRWDSTD
      * * /
    /

will report the maximum pressure across all cells intersected by a
fracture originating in connection (16,16,6) of well 'I1', one
average value for each connection of well 'I1' with the average
being taken over all cells intersected by the fraction originating
at that connection and, finally, the standard deviation of the
fracture width for each connection of each well with each standard
deviation being calculated over all cells intersected by the fracture
originating at that connection.
  • Loading branch information
bska committed Dec 20, 2024
1 parent 8f04827 commit 7b35fba
Show file tree
Hide file tree
Showing 3 changed files with 252 additions and 3 deletions.
14 changes: 13 additions & 1 deletion opm/input/eclipse/share/keywords/900_OPM/C/CONNECTION_PROBE_OPM
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,19 @@
"CINJFVR",
"CINJFVT",
"CFCRAD",
"CFCAOF"
"CFCAOF",
"CFRPMAX",
"CFRPMIN",
"CFRPAVG",
"CFRPSTD",
"CFRIRMAX",
"CFRIRMIN",
"CFRIRAVG",
"CFRIRSTD",
"CFRWDMAX",
"CFRWDMIN",
"CFRWDAVG",
"CFRWDSTD"
],
"items": [
{
Expand Down
169 changes: 167 additions & 2 deletions opm/output/data/Wells.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,163 @@ namespace Opm { namespace data {
void read(MessageBufferType& buffer);
};

/// Connection Level Fracturing Statistics
struct ConnectionFracturing
{
/// Statistics collection for a single quantity
struct Statistics
{
/// Arithmetic average.
double avg{};

/// Maximum value.
double max{};

/// Minimum value.
double min{};

/// Unbiased sample standard deviation.
///
/// Usable only if sample size is at least two.
double stdev{};

/// Create a serialization test object.
static Statistics serializationTestObject()
{
return {
12.34, 56.78, 9.10, 11.12
};
}

/// Convert between byte array and object representation.
///
/// \tparam Serializer Byte array conversion protocol.
///
/// \param[in,out] serializer Byte array conversion object.
template <class Serializer>
void serializeOp(Serializer& serializer)
{
serializer(this->avg);
serializer(this->max);
serializer(this->min);
serializer(this->stdev);
}

/// Equality predicate.
///
/// \param[in] that Object against which \code *this \endcode
/// will be tested for equality.
///
/// \return Whether or not \code *this \endcode is the same as
/// \p that.
bool operator==(const Statistics& that) const
{
return (this->avg == that.avg)
&& (this->max == that.max)
&& (this->min == that.min)
&& (this->stdev == that.stdev)
;
}

/// MPI communication protocol--serialisation operation
template <class MessageBufferType>
void write(MessageBufferType& buffer) const
{
buffer.write(this->avg);
buffer.write(this->max);
buffer.write(this->min);
buffer.write(this->stdev);
}

/// MPI communication protocol--deserialisation operation
template <class MessageBufferType>
void read(MessageBufferType& buffer)
{
buffer.read(this->avg);
buffer.read(this->max);
buffer.read(this->min);
buffer.read(this->stdev);
}
};

/// Sample size.
///
/// Expected to be the same for each quantiy.
std::size_t numCells{};

/// Statistical measures for connection's fracture pressures.
Statistics press{};

/// Statistical measures for connection's fracture fracture flow rate.
Statistics rate{};

/// Statistical measures for connection's fracture fracture width.
Statistics width{};

/// Create a serialisation test object.
static ConnectionFracturing serializationTestObject()
{
auto fract = ConnectionFracturing{};

fract.numCells = 123;
fract.press = Statistics::serializationTestObject();
fract.rate = Statistics::serializationTestObject();
fract.width = Statistics::serializationTestObject();

return fract;
}

/// Convert between byte array and object representation.
///
/// \tparam Serializer Byte array conversion protocol.
///
/// \param[in,out] serializer Byte array conversion object.
template <class Serializer>
void serializeOp(Serializer& serializer)
{
serializer(this->numCells);
serializer(this->press);
serializer(this->rate);
serializer(this->width);
}

/// Equality predicate.
///
/// \param[in] that Object against which \code *this \endcode will
/// be tested for equality.
///
/// \return Whether or not \code *this \endcode is the same as \p
/// that.
bool operator==(const ConnectionFracturing& that) const
{
return (this->numCells == that.numCells)
&& (this->press == that.press)
&& (this->rate == that.rate)
&& (this->width == that.width)
;
}

/// MPI communication protocol--serialisation operation
template <class MessageBufferType>
void write(MessageBufferType& buffer) const
{
buffer.write(this->numCells);
buffer.write(this->press);
buffer.write(this->rate);
buffer.write(this->width);
}

/// MPI communication protocol--deserialisation operation
template <class MessageBufferType>
void read(MessageBufferType& buffer)
{
buffer.read(this->numCells);
buffer.read(this->press);
buffer.read(this->rate);
buffer.read(this->width);
}
};

struct Connection
{
using global_index = std::size_t;
Expand All @@ -263,7 +420,10 @@ namespace Opm { namespace data {
double d_factor{};
double compact_mult{1.0}; // Rock compaction transmissibility multiplier (ROCKTAB)

ConnectionFiltrate filtrate;
ConnectionFiltrate filtrate{};

/// Connection level fracturing statistics.
ConnectionFracturing fract{};

bool operator==(const Connection& conn2) const
{
Expand All @@ -279,6 +439,7 @@ namespace Opm { namespace data {
&& (d_factor == conn2.d_factor)
&& (compact_mult == conn2.compact_mult)
&& (filtrate == conn2.filtrate)
&& (this->fract == conn2.fract)
;
}

Expand All @@ -304,6 +465,7 @@ namespace Opm { namespace data {
serializer(d_factor);
serializer(compact_mult);
serializer(filtrate);
serializer(this->fract);
}

static Connection serializationTestObject()
Expand All @@ -312,7 +474,8 @@ namespace Opm { namespace data {
1, Rates::serializationTestObject(),
2.0, 3.0, 4.0, 5.0,
6.0, 7.0, 8.0, 9.0, 0.987,
ConnectionFiltrate::serializationTestObject()
ConnectionFiltrate::serializationTestObject(),
ConnectionFracturing::serializationTestObject()
};
}
};
Expand Down Expand Up @@ -1268,6 +1431,7 @@ namespace Opm { namespace data {
buffer.write(this->d_factor);
buffer.write(this->compact_mult);
this->filtrate.write(buffer);
this->fract.write(buffer);
}

void Connection::init_json(Json::JsonObject& json_data) const {
Expand Down Expand Up @@ -1444,6 +1608,7 @@ namespace Opm { namespace data {
buffer.read(this->d_factor);
buffer.read(this->compact_mult);
this->filtrate.read(buffer);
this->fract.read(buffer);
}

template <class MessageBufferType>
Expand Down
72 changes: 72 additions & 0 deletions opm/output/eclipse/Summary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,45 @@ inline quantity cratel( const fn_args& args ) {
return { sum, unit };
}

template <Opm::data::ConnectionFracturing::Statistics Opm::data::ConnectionFracturing::* q,
double Opm::data::ConnectionFracturing::Statistics::* stat,
measure unit>
quantity connFracStatistics(const fn_args& args)
{
const auto zero = quantity { 0.0, unit };

if (args.schedule_wells.empty()) {
return zero;
}

const auto& name = args.schedule_wells.front()->name();
auto xwPos = args.wells.find(name);
if ((xwPos == args.wells.end()) ||
(xwPos->second.dynamicStatus == Opm::Well::Status::SHUT))
{
return zero;
}

const auto global_index = static_cast<std::size_t>(args.num - 1);

const auto& well_data = xwPos->second;
const auto connPos =
std::find_if(well_data.connections.begin(),
well_data.connections.end(),
[global_index](const Opm::data::Connection& c)
{
return c.index == global_index;
});

if ((connPos == well_data.connections.end()) ||
(connPos->fract.numCells == 0))
{
return zero;
}

return { connPos->fract.*q.*stat, unit };
}

template< bool injection >
inline quantity flowing( const fn_args& args ) {
const auto& wells = args.wells;
Expand Down Expand Up @@ -2481,6 +2520,39 @@ static const auto funs = std::unordered_map<std::string, ofun> {
{ "CFCPORO", filtrate_connection_quantities<injector> },
{ "CFCRAD", filtrate_connection_quantities<injector> },
{ "CFCAOF", filtrate_connection_quantities<injector> },

// Hydraulic fracturing (OPM extension)
//
// Fracture pressure
{ "CFRPMAX", connFracStatistics<&Opm::data::ConnectionFracturing::press,
&Opm::data::ConnectionFracturing::Statistics::max, measure::pressure> },
{ "CFRPMIN", connFracStatistics<&Opm::data::ConnectionFracturing::press,
&Opm::data::ConnectionFracturing::Statistics::min, measure::pressure> },
{ "CFRPAVG", connFracStatistics<&Opm::data::ConnectionFracturing::press,
&Opm::data::ConnectionFracturing::Statistics::avg, measure::pressure> },
{ "CFRPSTD", connFracStatistics<&Opm::data::ConnectionFracturing::press,
&Opm::data::ConnectionFracturing::Statistics::stdev, measure::pressure> },

// Fracture injection rate
{ "CFRIRMAX", connFracStatistics<&Opm::data::ConnectionFracturing::rate,
&Opm::data::ConnectionFracturing::Statistics::max, measure::rate> },
{ "CFRIRMIN", connFracStatistics<&Opm::data::ConnectionFracturing::rate,
&Opm::data::ConnectionFracturing::Statistics::min, measure::rate> },
{ "CFRIRAVG", connFracStatistics<&Opm::data::ConnectionFracturing::rate,
&Opm::data::ConnectionFracturing::Statistics::avg, measure::rate> },
{ "CFRIRSTD", connFracStatistics<&Opm::data::ConnectionFracturing::rate,
&Opm::data::ConnectionFracturing::Statistics::stdev, measure::rate> },

// Fracture width
{ "CFRWDMAX", connFracStatistics<&Opm::data::ConnectionFracturing::width,
&Opm::data::ConnectionFracturing::Statistics::max, measure::length> },
{ "CFRWDMIN", connFracStatistics<&Opm::data::ConnectionFracturing::width,
&Opm::data::ConnectionFracturing::Statistics::min, measure::length> },
{ "CFRWDAVG", connFracStatistics<&Opm::data::ConnectionFracturing::width,
&Opm::data::ConnectionFracturing::Statistics::avg, measure::length> },
{ "CFRWDSTD", connFracStatistics<&Opm::data::ConnectionFracturing::width,
&Opm::data::ConnectionFracturing::Statistics::stdev, measure::length> },

{ "COIT", mul( crate< rt::oil, injector >, duration ) },
{ "CWIT", mul( crate< rt::wat, injector >, duration ) },
{ "CGIT", mul( crate< rt::gas, injector >, duration ) },
Expand Down

0 comments on commit 7b35fba

Please sign in to comment.