Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Connection Fracturing Statistics Summary Vectors #4388

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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