#6126 MSW AICDs: Fix computation of flow scaling factor

This commit is contained in:
Magne Sjaastad 2020-06-24 12:35:51 +02:00
parent 44b3cb76df
commit e935343fab
5 changed files with 80 additions and 25 deletions

View File

@ -246,6 +246,7 @@ RicMswPerforationAICD::RicMswPerforationAICD( const QString& label, const RimWel
, m_valid( false ) , m_valid( false )
, m_deviceOpen( false ) , m_deviceOpen( false )
, m_length( 0.0 ) , m_length( 0.0 )
, m_flowScalingFactor( 0.0 )
{ {
} }
@ -305,6 +306,22 @@ void RicMswPerforationAICD::setLength( double length )
m_length = length; m_length = length;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RicMswPerforationAICD::flowScalingFactor() const
{
return m_flowScalingFactor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswPerforationAICD::setflowScalingFactor( double scalingFactor )
{
m_flowScalingFactor = scalingFactor;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -170,6 +170,8 @@ public:
void setIsOpen( bool deviceOpen ); void setIsOpen( bool deviceOpen );
double length() const; double length() const;
void setLength( double length ); void setLength( double length );
double flowScalingFactor() const;
void setflowScalingFactor( double scalingFactor );
const std::array<double, AICD_NUM_PARAMS>& values() const; const std::array<double, AICD_NUM_PARAMS>& values() const;
std::array<double, AICD_NUM_PARAMS>& values(); std::array<double, AICD_NUM_PARAMS>& values();
@ -179,4 +181,5 @@ private:
bool m_deviceOpen; bool m_deviceOpen;
std::array<double, AICD_NUM_PARAMS> m_parameters; std::array<double, AICD_NUM_PARAMS> m_parameters;
double m_length; double m_length;
double m_flowScalingFactor;
}; };

View File

@ -38,7 +38,8 @@ RicMswICDAccumulator::RicMswICDAccumulator( RiaEclipseUnitTools::UnitSystem unit
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
bool RicMswICDAccumulator::accumulateValveParameters( const RimWellPathValve* wellPathValve, bool RicMswICDAccumulator::accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve, size_t subValve,
double contributionFraction ) double contributionFraction,
double totalValveLengthOpenForFlow )
{ {
CVF_ASSERT( wellPathValve ); CVF_ASSERT( wellPathValve );
if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::ICV || if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::ICV ||
@ -76,6 +77,7 @@ RicMswAICDAccumulator::RicMswAICDAccumulator( RiaEclipseUnitTools::UnitSystem un
, m_valid( false ) , m_valid( false )
, m_deviceOpen( false ) , m_deviceOpen( false )
, m_accumulatedLength( 0.0 ) , m_accumulatedLength( 0.0 )
, m_accumulatedFlowScalingFactorDivisor( 0.0 )
{ {
} }
@ -84,7 +86,8 @@ RicMswAICDAccumulator::RicMswAICDAccumulator( RiaEclipseUnitTools::UnitSystem un
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
bool RicMswAICDAccumulator::accumulateValveParameters( const RimWellPathValve* wellPathValve, bool RicMswAICDAccumulator::accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve, size_t subValve,
double contributionFraction ) double contributionFraction,
double totalValveLengthOpenForFlow )
{ {
CVF_ASSERT( wellPathValve ); CVF_ASSERT( wellPathValve );
if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::AICD ) if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::AICD )
@ -104,16 +107,26 @@ bool RicMswAICDAccumulator::accumulateValveParameters( const RimWellPathValve* w
m_meanCalculators[i].addValueAndWeight( values[i], contributionFraction ); m_meanCalculators[i].addValueAndWeight( values[i], contributionFraction );
} }
} }
std::pair<double, double> valveSegment = wellPathValve->valveSegments()[subValve]; std::pair<double, double> valveSegment = wellPathValve->valveSegments()[subValve];
double valveSegmentLength = std::fabs( valveSegment.second - valveSegment.first ); double valveSegmentLength = std::fabs( valveSegment.second - valveSegment.first );
const RimPerforationInterval* perfInterval = nullptr; double lengthFraction = 1.0;
wellPathValve->firstAncestorOrThisOfTypeAsserted( perfInterval ); if ( totalValveLengthOpenForFlow > 1.0e-8 )
double perfIntervalLength = std::fabs( perfInterval->endMD() - perfInterval->startMD() );
double lengthFraction = 1.0;
if ( perfIntervalLength > 1.0e-8 )
{ {
lengthFraction = valveSegmentLength / perfIntervalLength; lengthFraction = valveSegmentLength / totalValveLengthOpenForFlow;
} }
// https://github.com/OPM/ResInsight/issues/6126
//
// flowScalingFactor = 1 / (length_fraction * N_AICDs)
// where:
// length_fraction = length_COMPSEGS / Sum_lenght_COMPSEGS_for_valve
// N_AICDs = number of AICDs in perforation interval
double divisor = wellPathValve->valveLocations().size() * lengthFraction * contributionFraction;
m_accumulatedFlowScalingFactorDivisor += divisor;
m_accumulatedLength += lengthFraction * contributionFraction; m_accumulatedLength += lengthFraction * contributionFraction;
} }
} }
@ -148,6 +161,15 @@ void RicMswAICDAccumulator::applyToSuperValve( std::shared_ptr<RicMswValve> valv
aicd->setIsOpen( m_deviceOpen ); aicd->setIsOpen( m_deviceOpen );
aicd->setLength( m_accumulatedLength ); aicd->setLength( m_accumulatedLength );
// See https://github.com/OPM/ResInsight/issues/6126
double flowScalingFactor = 0.0;
if ( m_accumulatedFlowScalingFactorDivisor > 1.0e-8 )
{
flowScalingFactor = 1.0 / m_accumulatedFlowScalingFactorDivisor;
}
aicd->setflowScalingFactor( flowScalingFactor );
aicd->values() = values; aicd->values() = values;
} }
} }

View File

@ -39,8 +39,9 @@ public:
} }
virtual bool accumulateValveParameters( const RimWellPathValve* wellPathValve, virtual bool accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve, size_t subValve,
double contributionFraction ) = 0; double contributionFraction,
virtual void applyToSuperValve( std::shared_ptr<RicMswValve> valve ) = 0; double totalValveLengthOpenForFlow ) = 0;
virtual void applyToSuperValve( std::shared_ptr<RicMswValve> valve ) = 0;
protected: protected:
RiaEclipseUnitTools::UnitSystem m_unitSystem; RiaEclipseUnitTools::UnitSystem m_unitSystem;
@ -55,7 +56,8 @@ public:
RicMswICDAccumulator( RiaEclipseUnitTools::UnitSystem unitSystem ); RicMswICDAccumulator( RiaEclipseUnitTools::UnitSystem unitSystem );
bool accumulateValveParameters( const RimWellPathValve* wellPathValve, bool accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve, size_t subValve,
double contributionFraction ) override; double contributionFraction,
double totalValveLengthOpenForFlow ) override;
void applyToSuperValve( std::shared_ptr<RicMswValve> valve ) override; void applyToSuperValve( std::shared_ptr<RicMswValve> valve ) override;
private: private:
@ -72,7 +74,8 @@ public:
RicMswAICDAccumulator( RiaEclipseUnitTools::UnitSystem unitSystem ); RicMswAICDAccumulator( RiaEclipseUnitTools::UnitSystem unitSystem );
bool accumulateValveParameters( const RimWellPathValve* wellPathValve, bool accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve, size_t subValve,
double contributionFraction ) override; double contributionFraction,
double totalValveLengthOpenForFlow ) override;
void applyToSuperValve( std::shared_ptr<RicMswValve> valve ) override; void applyToSuperValve( std::shared_ptr<RicMswValve> valve ) override;
private: private:
@ -80,4 +83,5 @@ private:
bool m_deviceOpen; bool m_deviceOpen;
std::array<RiaWeightedMeanCalculator<double>, AICD_NUM_PARAMS> m_meanCalculators; std::array<RiaWeightedMeanCalculator<double>, AICD_NUM_PARAMS> m_meanCalculators;
double m_accumulatedLength; double m_accumulatedLength;
}; double m_accumulatedFlowScalingFactorDivisor;
};

View File

@ -737,7 +737,7 @@ void RicWellPathExportMswCompletionsImpl::generateWsegAicdTable( RifTextDataTabl
"Segment Number", "Segment Number",
"Segment Number", "Segment Number",
"Strength of AICD", "Strength of AICD",
"Length of AICD", "Flow Scaling Factor for AICD",
"Density of Calibration Fluid", "Density of Calibration Fluid",
"Viscosity of Calibration Fluid", "Viscosity of Calibration Fluid",
"Critical water in liquid fraction for emulsions viscosity model", "Critical water in liquid fraction for emulsions viscosity model",
@ -781,13 +781,16 @@ void RicWellPathExportMswCompletionsImpl::generateWsegAicdTable( RifTextDataTabl
{ {
CVF_ASSERT( aicd->subSegments().size() == 1u ); CVF_ASSERT( aicd->subSegments().size() == 1u );
tighterFormatter.comment( aicd->label() ); tighterFormatter.comment( aicd->label() );
tighterFormatter.add( exportInfo.wellPath()->completions()->wellNameForExport() ); // 1 tighterFormatter.add( exportInfo.wellPath()->completions()->wellNameForExport() ); // #1
tighterFormatter.add( aicd->subSegments().front()->segmentNumber() ); tighterFormatter.add( aicd->subSegments().front()->segmentNumber() );
tighterFormatter.add( aicd->subSegments().front()->segmentNumber() ); tighterFormatter.add( aicd->subSegments().front()->segmentNumber() );
std::array<double, AICD_NUM_PARAMS> values = aicd->values(); std::array<double, AICD_NUM_PARAMS> values = aicd->values();
tighterFormatter.add( values[AICD_STRENGTH] ); tighterFormatter.add( values[AICD_STRENGTH] );
tighterFormatter.add( aicd->length() ); // 5
tighterFormatter.add( aicd->flowScalingFactor() ); // #5 Flow scaling factor used when item #11 is
// set to '1'
tighterFormatter.add( values[AICD_DENSITY_CALIB_FLUID] ); tighterFormatter.add( values[AICD_DENSITY_CALIB_FLUID] );
tighterFormatter.add( values[AICD_VISCOSITY_CALIB_FLUID] ); tighterFormatter.add( values[AICD_VISCOSITY_CALIB_FLUID] );
tighterFormatter.addValueOrDefaultMarker( values[AICD_CRITICAL_WATER_IN_LIQUID_FRAC], tighterFormatter.addValueOrDefaultMarker( values[AICD_CRITICAL_WATER_IN_LIQUID_FRAC],
@ -795,13 +798,16 @@ void RicWellPathExportMswCompletionsImpl::generateWsegAicdTable( RifTextDataTabl
tighterFormatter.addValueOrDefaultMarker( values[AICD_EMULSION_VISC_TRANS_REGION], tighterFormatter.addValueOrDefaultMarker( values[AICD_EMULSION_VISC_TRANS_REGION],
RicMswExportInfo::defaultDoubleValue() ); RicMswExportInfo::defaultDoubleValue() );
tighterFormatter.addValueOrDefaultMarker( values[AICD_MAX_RATIO_EMULSION_VISC], tighterFormatter.addValueOrDefaultMarker( values[AICD_MAX_RATIO_EMULSION_VISC],
RicMswExportInfo::defaultDoubleValue() ); // 10 RicMswExportInfo::defaultDoubleValue() ); // #10
tighterFormatter.add( 1 );
tighterFormatter.add( 1 ); // #11 : Always use method "b. Scale factor". The value of the scale
// factor is given in item #5
tighterFormatter.addValueOrDefaultMarker( values[AICD_MAX_FLOW_RATE], tighterFormatter.addValueOrDefaultMarker( values[AICD_MAX_FLOW_RATE],
RicMswExportInfo::defaultDoubleValue() ); RicMswExportInfo::defaultDoubleValue() );
tighterFormatter.add( values[AICD_VOL_FLOW_EXP] ); tighterFormatter.add( values[AICD_VOL_FLOW_EXP] );
tighterFormatter.add( values[AICD_VISOSITY_FUNC_EXP] ); tighterFormatter.add( values[AICD_VISOSITY_FUNC_EXP] );
tighterFormatter.add( aicd->isOpen() ? "OPEN" : "SHUT" ); // 15 tighterFormatter.add( aicd->isOpen() ? "OPEN" : "SHUT" ); // #15
tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_OIL_FRAC_DENSITY], tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_OIL_FRAC_DENSITY],
RicMswExportInfo::defaultDoubleValue() ); RicMswExportInfo::defaultDoubleValue() );
tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_WATER_FRAC_DENSITY], tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_WATER_FRAC_DENSITY],
@ -811,7 +817,7 @@ void RicWellPathExportMswCompletionsImpl::generateWsegAicdTable( RifTextDataTabl
tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_OIL_FRAC_VISCOSITY], tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_OIL_FRAC_VISCOSITY],
RicMswExportInfo::defaultDoubleValue() ); RicMswExportInfo::defaultDoubleValue() );
tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_WATER_FRAC_VISCOSITY], tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_WATER_FRAC_VISCOSITY],
RicMswExportInfo::defaultDoubleValue() ); // 20 RicMswExportInfo::defaultDoubleValue() ); // #20
tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_GAS_FRAC_VISCOSITY], tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_GAS_FRAC_VISCOSITY],
RicMswExportInfo::defaultDoubleValue() ); RicMswExportInfo::defaultDoubleValue() );
tighterFormatter.rowCompleted(); tighterFormatter.rowCompleted();
@ -1276,9 +1282,9 @@ RicWellPathExportMswCompletionsImpl::MainBoreSegments
{ {
MainBoreSegments mainBoreSegments; MainBoreSegments mainBoreSegments;
// Intersections along the well path with grid geometry is handled by well log extraction tools. The threshold in // Intersections along the well path with grid geometry is handled by well log extraction tools.
// RigWellLogExtractionTools::isEqualDepth is currently set to 0.1m, and this is a pretty large threshold based on // The threshold in RigWellLogExtractionTools::isEqualDepth is currently set to 0.1m, and this
// the indicated threshold of 0.001m for MSW segments // is a pretty large threshold based on the indicated threshold of 0.001m for MSW segments
const double segmentLengthThreshold = 1.0e-3; const double segmentLengthThreshold = 1.0e-3;
for ( const auto& cellIntInfo : subSegIntersections ) for ( const auto& cellIntInfo : subSegIntersections )
@ -1515,7 +1521,6 @@ void RicWellPathExportMswCompletionsImpl::assignValveContributionsToSuperICDsOrA
std::vector<const RimWellPathValve*> perforationValves; std::vector<const RimWellPathValve*> perforationValves;
interval->descendantsIncludingThisOfType( perforationValves ); interval->descendantsIncludingThisOfType( perforationValves );
for ( const RimWellPathValve* valve : perforationValves ) for ( const RimWellPathValve* valve : perforationValves )
{ {
if ( !valve->isChecked() ) continue; if ( !valve->isChecked() ) continue;
@ -1530,7 +1535,11 @@ void RicWellPathExportMswCompletionsImpl::assignValveContributionsToSuperICDsOrA
if ( overlap > 0.0 && accumulator ) if ( overlap > 0.0 && accumulator )
{ {
if ( accumulator->accumulateValveParameters( valve, nSubValve, overlap / valveSegmentLength ) ) double lengthOpenForFlow = std::fabs( valve->endMD() - valve->startMD() );
if ( accumulator->accumulateValveParameters( valve,
nSubValve,
overlap / valveSegmentLength,
lengthOpenForFlow ) )
{ {
assignedRegularValves[superValve].insert( std::make_pair( valve, nSubValve ) ); assignedRegularValves[superValve].insert( std::make_pair( valve, nSubValve ) );
} }