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

Prepare decline curve data for input to pFortran #11143

Closed
wants to merge 4 commits into from
Closed
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
24 changes: 24 additions & 0 deletions ApplicationLibCode/Application/Tools/RiaTextStringTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,30 @@ QString RiaTextStringTools::replaceTemplateTextWithValues( const QString& templa
return resolvedText;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaTextStringTools::createHtmlTable( const std::vector<std::vector<QString>>& tableCellContent )
{
QString htmlTable;

htmlTable += "<table border=\"0\" cellpadding=\"5\" cellspacing=\"0\">\n";

for ( const auto& row : tableCellContent )
{
htmlTable += "<tr>\n";
for ( const auto& cell : row )
{
htmlTable += "<td>" + cell + "</td>\n";
}
htmlTable += "</tr>\n";
}

htmlTable += "</table>\n";

return htmlTable;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions ApplicationLibCode/Application/Tools/RiaTextStringTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ QStringList splitSkipEmptyParts( const QString& text, const QRegExp& regExp );

QString replaceTemplateTextWithValues( const QString& templateText, const std::map<QString, QString>& valueMap );

QString createHtmlTable( const std::vector<std::vector<QString>>& tableCellContent );

} // namespace RiaTextStringTools

//--------------------------------------------------------------------------------------------------
Expand Down
159 changes: 159 additions & 0 deletions ApplicationLibCode/ProjectDataModel/Summary/RimSummaryDeclineCurve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,21 @@

#include "RiaQDateTimeTools.h"
#include "RiaSummaryTools.h"
#include "RiaTextStringTools.h"
#include "RiaTimeTTools.h"

#include "RifSummaryReaderInterface.h"

#include "RigDeclineCurveCalculator.h"

#include "RimSummaryCase.h"
#include "RimSummaryPlot.h"
#include "RimTimeAxisAnnotation.h"

#include "cafPdmUiDoubleSliderEditor.h"
#include "cafPdmUiLineEditor.h"
#include "cafPdmUiSliderEditor.h"
#include "cafPdmUiTextEditor.h"

#include <QDateTime>

Expand Down Expand Up @@ -68,6 +73,9 @@ RimSummaryDeclineCurve::RimSummaryDeclineCurve()
m_maxTimeSliderPosition.uiCapability()->setUiEditorTypeName( caf::PdmUiSliderEditor::uiEditorTypeName() );

CAF_PDM_InitField( &m_showTimeSelectionInPlot, "ShowTimeSelectionInPlot", true, "Show In Plot" );

CAF_PDM_InitField( &m_expressionText, "ExpressionText", QString(), "Expression" );
m_expressionText.uiCapability()->setUiEditorTypeName( caf::PdmUiTextEditor::uiEditorTypeName() );
}

//--------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -305,6 +313,137 @@ std::pair<time_t, time_t> RimSummaryDeclineCurve::selectedTimeStepRange() const
return { selectedMin, selectedMax };
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryDeclineCurve::updateExpressionText()
{
auto [minTimeStep, maxTimeStep] = selectedTimeStepRange();

auto parameters = curveParameters( RimSummaryCurve::valuesY(),
RimSummaryCurve::timeStepsY(),
minTimeStep,
maxTimeStep,
RiaSummaryTools::hasAccumulatedData( summaryAddressY() ) );

std::vector<std::vector<QString>> text;

for ( auto [key, unit, value] : parameters )
{
auto keyString = QString::fromStdString( key );
auto unitString = QString::fromStdString( unit );
auto valueString = QString::number( value );

text.push_back( { keyString, unitString, valueString } );
}

QString htmlTable = RiaTextStringTools::createHtmlTable( text );

m_expressionText = htmlTable;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::tuple<std::string, std::string, double>> RimSummaryDeclineCurve::curveParameters( const std::vector<double>& values,
const std::vector<time_t>& timeSteps,
time_t minTimeStep,
time_t maxTimeStep,
bool isAccumulatedResult ) const
{
if ( values.empty() || timeSteps.empty() ) return {};

// Use only the values inside the range specified
auto [timeStepsInRange, valuesInRange] = getInRangeValues( timeSteps, values, minTimeStep, maxTimeStep );

if ( timeStepsInRange.empty() || valuesInRange.empty() ) return {};

auto [initialProductionRate, initialDeclineRatePerSecond] =
computeInitialProductionAndDeclineRate( valuesInRange, timeStepsInRange, isAccumulatedResult );
if ( std::isinf( initialProductionRate ) || std::isnan( initialProductionRate ) || std::isinf( initialDeclineRatePerSecond ) ||
std::isnan( initialDeclineRatePerSecond ) )
{
return {};
}

auto initialDeclineRatePerYear = initialDeclineRatePerSecond * 60 * 24 * 365;

std::vector<std::tuple<std::string, std::string, double>> parameters;
parameters.push_back( { "Initial Production Rate", "SM3/STREAM DAY", initialProductionRate } );
parameters.push_back( { "Initial Decline Rate", "FRACTION 1/YEAR", initialDeclineRatePerYear } );
parameters.push_back( { "B Factor", "UNITLESS", m_hyperbolicDeclineConstant } );

auto timeToExtractValues = timeStepsInRange.back();

auto computeValue = []( const RifSummaryReaderInterface* reader,
const RifEclipseSummaryAddress& curveAddress,
time_t timeToExtractValues,
const std::string& vectorPostFix ) -> std::pair<std::string, double>
{
auto invalidReturnValue = std::make_pair( "", 0.0 );

if ( !reader ) return invalidReturnValue;

auto vectorName = curveAddress.vectorName();
if ( !vectorName.empty() )
{
auto otherVectorName = vectorName.substr( 0, 1 ) + vectorPostFix;
auto otherAdr = curveAddress;
otherAdr.setVectorName( otherVectorName );

if ( reader->hasAddress( otherAdr ) )
{
auto timeSteps = reader->timeSteps( otherAdr );

size_t stepIndex = std::numeric_limits<size_t>::max();
for ( size_t i = 0; i < timeSteps.size(); ++i )
{
if ( timeSteps[i] == timeToExtractValues )
{
stepIndex = i;
break;
}
}

if ( stepIndex != std::numeric_limits<size_t>::max() )
{
auto [isOk, values] = reader->values( otherAdr );
if ( isOk )
{
if ( stepIndex < values.size() )
{
return { otherVectorName, values[stepIndex] };
}
}
}
}
}

return invalidReturnValue;
};

if ( summaryCaseY() )
{
RifSummaryReaderInterface* reader = summaryCaseY()->summaryReader();

auto adr = summaryAddressY();

auto [liquidVectorName, liquidRateValue] = computeValue( reader, adr, timeToExtractValues, "LPR" );
if ( !liquidVectorName.empty() )
{
parameters.push_back( { "LiquidRate (" + liquidVectorName + ")", "SM3/STREAM DAY", liquidRateValue } );
}

auto [gorVectorName, gorValue] = computeValue( reader, adr, timeToExtractValues, "GOR" );
if ( !gorVectorName.empty() )
{
parameters.push_back( { "Gas-Oil-Ratio (" + gorVectorName + ")", "SM3/SM3", gorValue } );
}
}

return parameters;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -357,6 +496,8 @@ void RimSummaryDeclineCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiO
declineCurveGroup->add( &m_hyperbolicDeclineConstant );
}

declineCurveGroup->add( &m_expressionText );

caf::PdmUiGroup* timeSelectionGroup = uiOrdering.addNewGroup( "Time Selection" );
timeSelectionGroup->add( &m_minTimeSliderPosition );
timeSelectionGroup->add( &m_maxTimeSliderPosition );
Expand Down Expand Up @@ -425,6 +566,14 @@ void RimSummaryDeclineCurve::defineEditorAttribute( const caf::PdmFieldHandle* f
myAttr->m_showSpinBox = false;
}
}

if ( field == &m_expressionText )
{
if ( auto* attr = dynamic_cast<caf::PdmUiTextEditorAttribute*>( attribute ) )
{
attr->textMode = caf::PdmUiTextEditorAttribute::HTML;
}
}
}

//--------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -469,6 +618,16 @@ void RimSummaryDeclineCurve::updateTimeAnnotations()
}
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryDeclineCurve::onLoadDataAndUpdate( bool updateParentPlot )
{
RimSummaryCurve::onLoadDataAndUpdate( updateParentPlot );

updateExpressionText();
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class RimSummaryDeclineCurve : public RimSummaryCurve

protected:
void updateTimeAnnotations() override;
void onLoadDataAndUpdate( bool updateParentPlot ) override;

private:
QString createCurveAutoName() override;
Expand Down Expand Up @@ -94,11 +95,20 @@ class RimSummaryDeclineCurve : public RimSummaryCurve
std::pair<time_t, time_t> fullTimeStepRange() const;
std::pair<time_t, time_t> selectedTimeStepRange() const;

void updateExpressionText();
std::vector<std::tuple<std::string, std::string, double>> curveParameters( const std::vector<double>& values,
const std::vector<time_t>& timeSteps,
time_t minTimeStep,
time_t maxTimeStep,
bool isAccumulatedResult ) const;

private:
caf::PdmField<caf::AppEnum<DeclineCurveType>> m_declineCurveType;
caf::PdmField<int> m_predictionYears;
caf::PdmField<double> m_hyperbolicDeclineConstant;

caf::PdmField<QString> m_expressionText;

// Time step range defined in the range [0..100] as time_t can hold values that do not fit into int used by QSpinBox
caf::PdmField<int> m_minTimeSliderPosition;
caf::PdmField<int> m_maxTimeSliderPosition;
Expand Down
Loading