#6788 Fix MSW WSEGVALVE areas

This commit is contained in:
Gaute Lindkvist 2020-10-19 09:52:45 +02:00
parent 6a1f6ade49
commit 6f3af3c52f
4 changed files with 119 additions and 118 deletions

View File

@ -27,8 +27,8 @@
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RicMswICDAccumulator::RicMswICDAccumulator( RiaEclipseUnitTools::UnitSystem unitSystem ) RicMswICDAccumulator::RicMswICDAccumulator( std::shared_ptr<RicMswValve> valve, RiaEclipseUnitTools::UnitSystem unitSystem )
: RicMswValveAccumulator( unitSystem ) : RicMswValveAccumulator( valve, unitSystem )
, m_areaSum( 0.0 ) , m_areaSum( 0.0 )
{ {
} }
@ -37,34 +37,29 @@ RicMswICDAccumulator::RicMswICDAccumulator( RiaEclipseUnitTools::UnitSystem unit
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
bool RicMswICDAccumulator::accumulateValveParameters( const RimWellPathValve* wellPathValve, bool RicMswICDAccumulator::accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve, double overlapLength,
double contributionFraction, double perforationCompsegsLength )
double totalValveLengthOpenForFlow )
{ {
const double eps = 1.0e-8;
CVF_ASSERT( wellPathValve ); CVF_ASSERT( wellPathValve );
if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::ICV || if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::ICV ||
wellPathValve->componentType() == RiaDefines::WellPathComponentType::ICD ) wellPathValve->componentType() == RiaDefines::WellPathComponentType::ICD )
{ {
double lengthFraction = 1.0; size_t nICDs = wellPathValve->valveLocations().size();
if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::ICD )
{
std::pair<double, double> valveSegment = wellPathValve->valveSegments()[subValve];
double valveSegmentLength = std::fabs( valveSegment.second - valveSegment.first );
if ( totalValveLengthOpenForFlow > 1.0e-8 )
{
lengthFraction = valveSegmentLength / totalValveLengthOpenForFlow;
}
}
double combinedFraction = contributionFraction * lengthFraction;
double icdOrificeRadius = wellPathValve->orificeDiameter( m_unitSystem ) / 2; double icdOrificeRadius = wellPathValve->orificeDiameter( m_unitSystem ) / 2;
double icdArea = icdOrificeRadius * icdOrificeRadius * cvf::PI_D; double icdArea = icdOrificeRadius * icdOrificeRadius * cvf::PI_D;
double totalIcdArea = static_cast<double>( nICDs ) * icdArea;
m_areaSum += icdArea; double icdAreaFactor = totalIcdArea * overlapLength / perforationCompsegsLength;
m_coefficientCalculator.addValueAndWeight( wellPathValve->flowCoefficient(), icdArea * combinedFraction );
return true; m_areaSum += icdAreaFactor;
if ( icdAreaFactor > eps )
{
m_coefficientCalculator.addValueAndWeight( wellPathValve->flowCoefficient(), icdAreaFactor );
return true;
}
} }
return false; return false;
} }
@ -72,10 +67,11 @@ bool RicMswICDAccumulator::accumulateValveParameters( const RimWellPathValve* we
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RicMswICDAccumulator::applyToSuperValve( std::shared_ptr<RicMswValve> valve ) void RicMswICDAccumulator::applyToSuperValve()
{ {
std::shared_ptr<RicMswWsegValve> icd = std::dynamic_pointer_cast<RicMswWsegValve>( valve ); std::shared_ptr<RicMswWsegValve> icd = std::dynamic_pointer_cast<RicMswWsegValve>( m_valve );
CVF_ASSERT( icd ); CVF_ASSERT( icd );
icd->setArea( m_areaSum ); icd->setArea( m_areaSum );
if ( m_coefficientCalculator.validAggregatedWeight() ) if ( m_coefficientCalculator.validAggregatedWeight() )
{ {
@ -86,8 +82,8 @@ void RicMswICDAccumulator::applyToSuperValve( std::shared_ptr<RicMswValve> valve
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RicMswAICDAccumulator::RicMswAICDAccumulator( RiaEclipseUnitTools::UnitSystem unitSystem ) RicMswAICDAccumulator::RicMswAICDAccumulator( std::shared_ptr<RicMswValve> valve, RiaEclipseUnitTools::UnitSystem unitSystem )
: RicMswValveAccumulator( unitSystem ) : RicMswValveAccumulator( valve, unitSystem )
, m_valid( false ) , m_valid( false )
, m_deviceOpen( false ) , m_deviceOpen( false )
, m_accumulatedLength( 0.0 ) , m_accumulatedLength( 0.0 )
@ -99,12 +95,13 @@ RicMswAICDAccumulator::RicMswAICDAccumulator( RiaEclipseUnitTools::UnitSystem un
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
bool RicMswAICDAccumulator::accumulateValveParameters( const RimWellPathValve* wellPathValve, bool RicMswAICDAccumulator::accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve, double overlapLength,
double contributionFraction, double perforationCompsegsLength )
double totalValveCompsegsLength )
{ {
const double eps = 1.0e-8;
CVF_ASSERT( wellPathValve ); CVF_ASSERT( wellPathValve );
if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::AICD ) if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::AICD && overlapLength > eps )
{ {
const RimWellPathAicdParameters* params = wellPathValve->aicdParameters(); const RimWellPathAicdParameters* params = wellPathValve->aicdParameters();
if ( params->isValid() ) if ( params->isValid() )
@ -113,40 +110,31 @@ bool RicMswAICDAccumulator::accumulateValveParameters( const RimWellPathValve* w
m_deviceOpen = m_deviceOpen || params->isOpen(); m_deviceOpen = m_deviceOpen || params->isOpen();
if ( params->isOpen() ) if ( params->isOpen() )
{ {
std::pair<double, double> valveSegment = wellPathValve->valveSegments()[subValve];
double valveSegmentLength = std::fabs( valveSegment.second - valveSegment.first );
double lengthFraction = 1.0;
if ( totalValveCompsegsLength > 1.0e-8 )
{
lengthFraction = valveSegmentLength / totalValveCompsegsLength;
}
double combinedFraction = contributionFraction * lengthFraction;
std::array<double, AICD_NUM_PARAMS> values = params->doubleValues(); std::array<double, AICD_NUM_PARAMS> values = params->doubleValues();
for ( size_t i = 0; i < (size_t)AICD_NUM_PARAMS; ++i ) for ( size_t i = 0; i < (size_t)AICD_NUM_PARAMS; ++i )
{ {
if ( RiaStatisticsTools::isValidNumber( values[i] ) ) if ( RiaStatisticsTools::isValidNumber( values[i] ) )
{ {
m_meanCalculators[i].addValueAndWeight( values[i], combinedFraction ); m_meanCalculators[i].addValueAndWeight( values[i], overlapLength );
} }
} }
m_accumulatedLength += overlapLength / perforationCompsegsLength;
// https://github.com/OPM/ResInsight/issues/6126 // https://github.com/OPM/ResInsight/issues/6126
// //
// flowScalingFactor = 1 / (lengthFraction * aicdCount) // flowScalingFactor = 1 / (lengthFraction * aicdCount)
// where: // where:
// lengthFraction = length_COMPSEGS / Sum_length_COMPSEGS_for_valve // lengthFraction = length_COMPSEGS / Sum_length_COMPSEGS_for_valve
// N_AICDs = number of AICDs in perforation interval // N_AICDs = number of AICDs in perforation interval
size_t aicdCount = wellPathValve->valveLocations().size(); size_t aicdCount = wellPathValve->valveLocations().size();
double divisor = aicdCount * combinedFraction; double lengthFraction = overlapLength / perforationCompsegsLength;
double divisor = lengthFraction * aicdCount;
m_accumulatedFlowScalingFactorDivisor += divisor; m_accumulatedFlowScalingFactorDivisor += divisor;
m_accumulatedLength += combinedFraction; return true;
} }
} }
return true;
} }
return false; return false;
} }
@ -154,9 +142,9 @@ bool RicMswAICDAccumulator::accumulateValveParameters( const RimWellPathValve* w
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RicMswAICDAccumulator::applyToSuperValve( std::shared_ptr<RicMswValve> valve ) void RicMswAICDAccumulator::applyToSuperValve()
{ {
std::shared_ptr<RicMswPerforationAICD> aicd = std::dynamic_pointer_cast<RicMswPerforationAICD>( valve ); std::shared_ptr<RicMswPerforationAICD> aicd = std::dynamic_pointer_cast<RicMswPerforationAICD>( m_valve );
if ( aicd ) if ( aicd )
{ {

View File

@ -33,17 +33,20 @@ class RicMswValve;
class RicMswValveAccumulator class RicMswValveAccumulator
{ {
public: public:
RicMswValveAccumulator( RiaEclipseUnitTools::UnitSystem unitSystem ) RicMswValveAccumulator( std::shared_ptr<RicMswValve> valve, RiaEclipseUnitTools::UnitSystem unitSystem )
: m_unitSystem( unitSystem ) : m_valve( valve )
, m_unitSystem( unitSystem )
{ {
} }
virtual bool accumulateValveParameters( const RimWellPathValve* wellPathValve, virtual bool accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve, double overlapLength,
double contributionFraction, double perforationCompsegsLength ) = 0;
double totalValveLengthOpenForFlow ) = 0; virtual void applyToSuperValve() = 0;
virtual void applyToSuperValve( std::shared_ptr<RicMswValve> valve ) = 0;
std::shared_ptr<RicMswValve> superValve() const { return m_valve; }
protected: protected:
std::shared_ptr<RicMswValve> m_valve;
RiaEclipseUnitTools::UnitSystem m_unitSystem; RiaEclipseUnitTools::UnitSystem m_unitSystem;
}; };
@ -53,12 +56,11 @@ protected:
class RicMswICDAccumulator : public RicMswValveAccumulator class RicMswICDAccumulator : public RicMswValveAccumulator
{ {
public: public:
RicMswICDAccumulator( RiaEclipseUnitTools::UnitSystem unitSystem ); RicMswICDAccumulator( std::shared_ptr<RicMswValve> valve, RiaEclipseUnitTools::UnitSystem unitSystem );
bool accumulateValveParameters( const RimWellPathValve* wellPathValve, bool accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve, double overlapLength,
double contributionFraction, double perforationCompsegsLength ) override;
double totalValveCompsegsLength ) override; void applyToSuperValve() override;
void applyToSuperValve( std::shared_ptr<RicMswValve> valve ) override;
private: private:
RiaWeightedMeanCalculator<double> m_coefficientCalculator; RiaWeightedMeanCalculator<double> m_coefficientCalculator;
@ -71,12 +73,11 @@ private:
class RicMswAICDAccumulator : public RicMswValveAccumulator class RicMswAICDAccumulator : public RicMswValveAccumulator
{ {
public: public:
RicMswAICDAccumulator( RiaEclipseUnitTools::UnitSystem unitSystem ); RicMswAICDAccumulator( std::shared_ptr<RicMswValve> valve, RiaEclipseUnitTools::UnitSystem unitSystem );
bool accumulateValveParameters( const RimWellPathValve* wellPathValve, bool accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve, double overlapLength,
double contributionFraction, double perforationCompsegsLength ) override;
double totalValveCompsegsLength ) override; void applyToSuperValve() override;
void applyToSuperValve( std::shared_ptr<RicMswValve> valve ) override;
private: private:
bool m_valid; bool m_valid;

View File

@ -799,13 +799,12 @@ std::vector<std::pair<double, double>>
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
double RicWellPathExportMswCompletionsImpl::calculateLengthThroughActiveCells( std::pair<double, double> RicWellPathExportMswCompletionsImpl::calculateOverlapWithActiveCells(
double startMD, double startMD,
double endMD, double endMD,
const std::vector<WellPathCellIntersectionInfo>& wellPathIntersections, const std::vector<WellPathCellIntersectionInfo>& wellPathIntersections,
const RigActiveCellInfo* activeCellInfo ) const RigActiveCellInfo* activeCellInfo )
{ {
double totalOverlap = 0.0;
for ( const WellPathCellIntersectionInfo& intersection : wellPathIntersections ) for ( const WellPathCellIntersectionInfo& intersection : wellPathIntersections )
{ {
if ( intersection.globCellIndex < activeCellInfo->reservoirCellCount() && if ( intersection.globCellIndex < activeCellInfo->reservoirCellCount() &&
@ -813,11 +812,13 @@ double RicWellPathExportMswCompletionsImpl::calculateLengthThroughActiveCells(
{ {
double overlapStart = std::max( startMD, intersection.startMD ); double overlapStart = std::max( startMD, intersection.startMD );
double overlapEnd = std::min( endMD, intersection.endMD ); double overlapEnd = std::min( endMD, intersection.endMD );
double overlap = std::max( 0.0, overlapEnd - overlapStart ); if ( overlapEnd > overlapStart )
totalOverlap += overlap; {
return std::make_pair( overlapStart, overlapEnd );
}
} }
} }
return totalOverlap; return std::make_pair( 0.0, 0.0 );
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -1473,6 +1474,9 @@ void RicWellPathExportMswCompletionsImpl::assignValveContributionsToSuperICDsOrA
RiaEclipseUnitTools::UnitSystem unitSystem ) RiaEclipseUnitTools::UnitSystem unitSystem )
{ {
ValveContributionMap assignedRegularValves; ValveContributionMap assignedRegularValves;
std::map<std::shared_ptr<RicMswSegment>, std::shared_ptr<RicMswValveAccumulator>> accumulators;
for ( std::shared_ptr<RicMswSegment> segment : mainBoreSegments ) for ( std::shared_ptr<RicMswSegment> segment : mainBoreSegments )
{ {
std::shared_ptr<RicMswValve> superValve; std::shared_ptr<RicMswValve> superValve;
@ -1485,66 +1489,73 @@ void RicWellPathExportMswCompletionsImpl::assignValveContributionsToSuperICDsOrA
break; break;
} }
} }
std::shared_ptr<RicMswValveAccumulator> accumulator;
if ( std::dynamic_pointer_cast<const RicMswPerforationICD>( superValve ) ) if ( std::dynamic_pointer_cast<const RicMswPerforationICD>( superValve ) )
{ {
accumulator = std::make_shared<RicMswICDAccumulator>( unitSystem ); accumulators[segment] = std::make_shared<RicMswICDAccumulator>( superValve, unitSystem );
} }
else if ( std::dynamic_pointer_cast<const RicMswPerforationAICD>( superValve ) ) else if ( std::dynamic_pointer_cast<const RicMswPerforationAICD>( superValve ) )
{ {
accumulator = std::make_shared<RicMswAICDAccumulator>( unitSystem ); accumulators[segment] = std::make_shared<RicMswAICDAccumulator>( superValve, unitSystem );
}
}
for ( const RimPerforationInterval* interval : perforationIntervals )
{
if ( !interval->isChecked() ) continue;
std::vector<const RimWellPathValve*> perforationValves;
interval->descendantsIncludingThisOfType( perforationValves );
double totalPerforationLength = 0.0;
for ( const RimWellPathValve* valve : perforationValves )
{
if ( !valve->isChecked() ) continue;
for ( std::shared_ptr<RicMswSegment> segment : mainBoreSegments )
{
double intervalOverlapStart = std::max( interval->startMD(), segment->startMD() );
double intervalOverlapEnd = std::min( interval->endMD(), segment->endMD() );
auto intervalOverlapWithActiveCells = calculateOverlapWithActiveCells( intervalOverlapStart,
intervalOverlapEnd,
wellPathIntersections,
activeCellInfo );
totalPerforationLength += intervalOverlapWithActiveCells.second - intervalOverlapWithActiveCells.first;
}
} }
if ( !accumulator ) continue; for ( const RimWellPathValve* valve : perforationValves )
for ( const RimPerforationInterval* interval : perforationIntervals )
{ {
if ( !interval->isChecked() ) continue; if ( !valve->isChecked() ) continue;
std::vector<const RimWellPathValve*> perforationValves; for ( std::shared_ptr<RicMswSegment> segment : mainBoreSegments )
interval->descendantsIncludingThisOfType( perforationValves );
for ( const RimWellPathValve* valve : perforationValves )
{ {
if ( !valve->isChecked() ) continue; double intervalOverlapStart = std::max( interval->startMD(), segment->startMD() );
double intervalOverlapEnd = std::min( interval->endMD(), segment->endMD() );
double totalValveLength = calculateLengthThroughActiveCells( valve->startMD(), auto intervalOverlapWithActiveCells = calculateOverlapWithActiveCells( intervalOverlapStart,
valve->endMD(), intervalOverlapEnd,
wellPathIntersections, wellPathIntersections,
activeCellInfo ); activeCellInfo );
for ( size_t nSubValve = 0u; nSubValve < valve->valveSegments().size(); ++nSubValve ) double overlapLength = intervalOverlapWithActiveCells.second - intervalOverlapWithActiveCells.first;
if ( overlapLength > 0.0 )
{ {
std::pair<double, double> valveSegment = valve->valveSegments()[nSubValve]; auto it = accumulators.find( segment );
double valveSegmentLength = calculateLengthThroughActiveCells( valveSegment.first, if ( it != accumulators.end() )
valveSegment.second,
wellPathIntersections,
activeCellInfo );
double overlapStart = std::max( valveSegment.first, segment->startMD() );
double overlapEnd = std::min( valveSegment.second, segment->endMD() );
double overlapLength =
calculateLengthThroughActiveCells( overlapStart, overlapEnd, wellPathIntersections, activeCellInfo );
if ( overlapLength > 0.0 && valveSegmentLength > 0.0 && accumulator )
{ {
if ( accumulator->accumulateValveParameters( valve, it->second->accumulateValveParameters( valve, overlapLength, totalPerforationLength );
nSubValve, assignedRegularValves[it->second->superValve()].push_back( valve );
overlapLength / valveSegmentLength,
totalValveLength ) )
{
assignedRegularValves[superValve].insert( std::make_pair( valve, nSubValve ) );
}
} }
} }
} }
} }
if ( superValve && accumulator ) }
{
accumulator->applyToSuperValve( superValve ); for ( auto accumulator : accumulators )
} {
accumulator.second->applyToSuperValve();
} }
for ( auto regularValvePair : assignedRegularValves ) for ( auto regularValvePair : assignedRegularValves )
@ -1552,9 +1563,9 @@ void RicWellPathExportMswCompletionsImpl::assignValveContributionsToSuperICDsOrA
if ( !regularValvePair.second.empty() ) if ( !regularValvePair.second.empty() )
{ {
QStringList valveLabels; QStringList valveLabels;
for ( std::pair<const RimWellPathValve*, size_t> regularValve : regularValvePair.second ) for ( const RimWellPathValve* regularValve : regularValvePair.second )
{ {
QString valveLabel = QString( "%1 #%2" ).arg( regularValve.first->name() ).arg( regularValve.second + 1 ); QString valveLabel = QString( "%1" ).arg( regularValve->name() );
valveLabels.push_back( valveLabel ); valveLabels.push_back( valveLabel );
} }
QString valveContribLabel = QString( " with contribution from: %1" ).arg( valveLabels.join( ", " ) ); QString valveContribLabel = QString( " with contribution from: %1" ).arg( valveLabels.join( ", " ) );

View File

@ -128,14 +128,15 @@ private:
static void generateWsegvalvTable( RifTextDataTableFormatter& formatter, const RicMswExportInfo& exportInfo ); static void generateWsegvalvTable( RifTextDataTableFormatter& formatter, const RicMswExportInfo& exportInfo );
static void generateWsegAicdTable( RifTextDataTableFormatter& formatter, const RicMswExportInfo& exportInfo ); static void generateWsegAicdTable( RifTextDataTableFormatter& formatter, const RicMswExportInfo& exportInfo );
static double calculateLengthThroughActiveCells( double startMD, static std::pair<double, double>
double endMD, calculateOverlapWithActiveCells( double startMD,
const std::vector<WellPathCellIntersectionInfo>& wellPathIntersections, double endMD,
const RigActiveCellInfo* activeCellInfo ); const std::vector<WellPathCellIntersectionInfo>& wellPathIntersections,
const RigActiveCellInfo* activeCellInfo );
private: private:
typedef std::vector<std::shared_ptr<RicMswSegment>> MainBoreSegments; typedef std::vector<std::shared_ptr<RicMswSegment>> MainBoreSegments;
typedef std::map<std::shared_ptr<RicMswCompletion>, std::set<std::pair<const RimWellPathValve*, size_t>>> ValveContributionMap; typedef std::map<std::shared_ptr<RicMswCompletion>, std::vector<const RimWellPathValve*>> ValveContributionMap;
static std::vector<std::pair<double, double>> static std::vector<std::pair<double, double>>
createSubSegmentMDPairs( double startMD, double endMD, double maxSegmentLength ); createSubSegmentMDPairs( double startMD, double endMD, double maxSegmentLength );