mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-11 07:56:08 -06:00
#6788 Fix MSW WSEGVALVE areas
This commit is contained in:
parent
6a1f6ade49
commit
6f3af3c52f
@ -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 )
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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( ", " ) );
|
||||
|
@ -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 );
|
||||
|
Loading…
Reference in New Issue
Block a user