#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 )
: RicMswValveAccumulator( unitSystem )
RicMswICDAccumulator::RicMswICDAccumulator( std::shared_ptr<RicMswValve> valve, RiaEclipseUnitTools::UnitSystem unitSystem )
: RicMswValveAccumulator( valve, unitSystem )
, m_areaSum( 0.0 )
{
}
@ -37,34 +37,29 @@ RicMswICDAccumulator::RicMswICDAccumulator( RiaEclipseUnitTools::UnitSystem unit
///
//--------------------------------------------------------------------------------------------------
bool RicMswICDAccumulator::accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve,
double contributionFraction,
double totalValveLengthOpenForFlow )
double overlapLength,
double perforationCompsegsLength )
{
const double eps = 1.0e-8;
CVF_ASSERT( wellPathValve );
if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::ICV ||
wellPathValve->componentType() == RiaDefines::WellPathComponentType::ICD )
{
double lengthFraction = 1.0;
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;
size_t nICDs = wellPathValve->valveLocations().size();
double icdOrificeRadius = wellPathValve->orificeDiameter( m_unitSystem ) / 2;
double icdArea = icdOrificeRadius * icdOrificeRadius * cvf::PI_D;
double totalIcdArea = static_cast<double>( nICDs ) * icdArea;
m_areaSum += icdArea;
m_coefficientCalculator.addValueAndWeight( wellPathValve->flowCoefficient(), icdArea * combinedFraction );
return true;
double icdAreaFactor = totalIcdArea * overlapLength / perforationCompsegsLength;
m_areaSum += icdAreaFactor;
if ( icdAreaFactor > eps )
{
m_coefficientCalculator.addValueAndWeight( wellPathValve->flowCoefficient(), icdAreaFactor );
return true;
}
}
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 );
icd->setArea( m_areaSum );
if ( m_coefficientCalculator.validAggregatedWeight() )
{
@ -86,8 +82,8 @@ void RicMswICDAccumulator::applyToSuperValve( std::shared_ptr<RicMswValve> valve
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicMswAICDAccumulator::RicMswAICDAccumulator( RiaEclipseUnitTools::UnitSystem unitSystem )
: RicMswValveAccumulator( unitSystem )
RicMswAICDAccumulator::RicMswAICDAccumulator( std::shared_ptr<RicMswValve> valve, RiaEclipseUnitTools::UnitSystem unitSystem )
: RicMswValveAccumulator( valve, unitSystem )
, m_valid( false )
, m_deviceOpen( false )
, m_accumulatedLength( 0.0 )
@ -99,12 +95,13 @@ RicMswAICDAccumulator::RicMswAICDAccumulator( RiaEclipseUnitTools::UnitSystem un
///
//--------------------------------------------------------------------------------------------------
bool RicMswAICDAccumulator::accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve,
double contributionFraction,
double totalValveCompsegsLength )
double overlapLength,
double perforationCompsegsLength )
{
const double eps = 1.0e-8;
CVF_ASSERT( wellPathValve );
if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::AICD )
if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::AICD && overlapLength > eps )
{
const RimWellPathAicdParameters* params = wellPathValve->aicdParameters();
if ( params->isValid() )
@ -113,40 +110,31 @@ bool RicMswAICDAccumulator::accumulateValveParameters( const RimWellPathValve* w
m_deviceOpen = m_deviceOpen || 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();
for ( size_t i = 0; i < (size_t)AICD_NUM_PARAMS; ++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
//
// flowScalingFactor = 1 / (lengthFraction * aicdCount)
// where:
// lengthFraction = length_COMPSEGS / Sum_length_COMPSEGS_for_valve
// N_AICDs = number of AICDs in perforation interval
size_t aicdCount = wellPathValve->valveLocations().size();
double divisor = aicdCount * combinedFraction;
size_t aicdCount = wellPathValve->valveLocations().size();
double lengthFraction = overlapLength / perforationCompsegsLength;
double divisor = lengthFraction * aicdCount;
m_accumulatedFlowScalingFactorDivisor += divisor;
m_accumulatedLength += combinedFraction;
return true;
}
}
return true;
}
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 )
{

View File

@ -33,17 +33,20 @@ class RicMswValve;
class RicMswValveAccumulator
{
public:
RicMswValveAccumulator( RiaEclipseUnitTools::UnitSystem unitSystem )
: m_unitSystem( unitSystem )
RicMswValveAccumulator( std::shared_ptr<RicMswValve> valve, RiaEclipseUnitTools::UnitSystem unitSystem )
: m_valve( valve )
, m_unitSystem( unitSystem )
{
}
virtual bool accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve,
double contributionFraction,
double totalValveLengthOpenForFlow ) = 0;
virtual void applyToSuperValve( std::shared_ptr<RicMswValve> valve ) = 0;
double overlapLength,
double perforationCompsegsLength ) = 0;
virtual void applyToSuperValve() = 0;
std::shared_ptr<RicMswValve> superValve() const { return m_valve; }
protected:
std::shared_ptr<RicMswValve> m_valve;
RiaEclipseUnitTools::UnitSystem m_unitSystem;
};
@ -53,12 +56,11 @@ protected:
class RicMswICDAccumulator : public RicMswValveAccumulator
{
public:
RicMswICDAccumulator( RiaEclipseUnitTools::UnitSystem unitSystem );
RicMswICDAccumulator( std::shared_ptr<RicMswValve> valve, RiaEclipseUnitTools::UnitSystem unitSystem );
bool accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve,
double contributionFraction,
double totalValveCompsegsLength ) override;
void applyToSuperValve( std::shared_ptr<RicMswValve> valve ) override;
double overlapLength,
double perforationCompsegsLength ) override;
void applyToSuperValve() override;
private:
RiaWeightedMeanCalculator<double> m_coefficientCalculator;
@ -71,12 +73,11 @@ private:
class RicMswAICDAccumulator : public RicMswValveAccumulator
{
public:
RicMswAICDAccumulator( RiaEclipseUnitTools::UnitSystem unitSystem );
RicMswAICDAccumulator( std::shared_ptr<RicMswValve> valve, RiaEclipseUnitTools::UnitSystem unitSystem );
bool accumulateValveParameters( const RimWellPathValve* wellPathValve,
size_t subValve,
double contributionFraction,
double totalValveCompsegsLength ) override;
void applyToSuperValve( std::shared_ptr<RicMswValve> valve ) override;
double overlapLength,
double perforationCompsegsLength ) override;
void applyToSuperValve() override;
private:
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 endMD,
const std::vector<WellPathCellIntersectionInfo>& wellPathIntersections,
const RigActiveCellInfo* activeCellInfo )
{
double totalOverlap = 0.0;
for ( const WellPathCellIntersectionInfo& intersection : wellPathIntersections )
{
if ( intersection.globCellIndex < activeCellInfo->reservoirCellCount() &&
@ -813,11 +812,13 @@ double RicWellPathExportMswCompletionsImpl::calculateLengthThroughActiveCells(
{
double overlapStart = std::max( startMD, intersection.startMD );
double overlapEnd = std::min( endMD, intersection.endMD );
double overlap = std::max( 0.0, overlapEnd - overlapStart );
totalOverlap += overlap;
if ( overlapEnd > overlapStart )
{
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 )
{
ValveContributionMap assignedRegularValves;
std::map<std::shared_ptr<RicMswSegment>, std::shared_ptr<RicMswValveAccumulator>> accumulators;
for ( std::shared_ptr<RicMswSegment> segment : mainBoreSegments )
{
std::shared_ptr<RicMswValve> superValve;
@ -1485,66 +1489,73 @@ void RicWellPathExportMswCompletionsImpl::assignValveContributionsToSuperICDsOrA
break;
}
}
std::shared_ptr<RicMswValveAccumulator> accumulator;
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 ) )
{
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 RimPerforationInterval* interval : perforationIntervals )
for ( const RimWellPathValve* valve : perforationValves )
{
if ( !interval->isChecked() ) continue;
if ( !valve->isChecked() ) continue;
std::vector<const RimWellPathValve*> perforationValves;
interval->descendantsIncludingThisOfType( perforationValves );
for ( const RimWellPathValve* valve : perforationValves )
for ( std::shared_ptr<RicMswSegment> segment : mainBoreSegments )
{
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(),
valve->endMD(),
wellPathIntersections,
activeCellInfo );
auto intervalOverlapWithActiveCells = calculateOverlapWithActiveCells( intervalOverlapStart,
intervalOverlapEnd,
wellPathIntersections,
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,
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 ( it != accumulators.end() )
{
if ( accumulator->accumulateValveParameters( valve,
nSubValve,
overlapLength / valveSegmentLength,
totalValveLength ) )
{
assignedRegularValves[superValve].insert( std::make_pair( valve, nSubValve ) );
}
it->second->accumulateValveParameters( valve, overlapLength, totalPerforationLength );
assignedRegularValves[it->second->superValve()].push_back( valve );
}
}
}
}
if ( superValve && accumulator )
{
accumulator->applyToSuperValve( superValve );
}
}
for ( auto accumulator : accumulators )
{
accumulator.second->applyToSuperValve();
}
for ( auto regularValvePair : assignedRegularValves )
@ -1552,9 +1563,9 @@ void RicWellPathExportMswCompletionsImpl::assignValveContributionsToSuperICDsOrA
if ( !regularValvePair.second.empty() )
{
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 );
}
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 generateWsegAicdTable( RifTextDataTableFormatter& formatter, const RicMswExportInfo& exportInfo );
static double calculateLengthThroughActiveCells( double startMD,
double endMD,
const std::vector<WellPathCellIntersectionInfo>& wellPathIntersections,
const RigActiveCellInfo* activeCellInfo );
static std::pair<double, double>
calculateOverlapWithActiveCells( double startMD,
double endMD,
const std::vector<WellPathCellIntersectionInfo>& wellPathIntersections,
const RigActiveCellInfo* activeCellInfo );
private:
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::vector<std::shared_ptr<RicMswSegment>> MainBoreSegments;
typedef std::map<std::shared_ptr<RicMswCompletion>, std::vector<const RimWellPathValve*>> ValveContributionMap;
static std::vector<std::pair<double, double>>
createSubSegmentMDPairs( double startMD, double endMD, double maxSegmentLength );