diff --git a/ApplicationLibCode/Commands/CompletionExportCommands/MswExport/RicMswBranchBuilder.cpp b/ApplicationLibCode/Commands/CompletionExportCommands/MswExport/RicMswBranchBuilder.cpp index 65f1f7f648..b9f4ee7c75 100644 --- a/ApplicationLibCode/Commands/CompletionExportCommands/MswExport/RicMswBranchBuilder.cpp +++ b/ApplicationLibCode/Commands/CompletionExportCommands/MswExport/RicMswBranchBuilder.cpp @@ -101,22 +101,13 @@ void applyIcdAreaPerCell( const FishbonesExportContext& context, RigMswWellExpor { if ( context.icdSegments.empty() ) return; - std::map> icdSegmentsPerCell; - for ( const auto& icdSegment : context.icdSegments ) - { - for ( auto globalCellIndex : icdSegment.globalCellIndices ) - { - icdSegmentsPerCell[globalCellIndex].insert( icdSegment.segmentNumber ); - } - } - std::set icdSegmentNumbers; for ( const auto& icdSegment : context.icdSegments ) { icdSegmentNumbers.insert( icdSegment.segmentNumber ); } - std::map areaPerSegment; + std::map originalAreaPerSegment; for ( const auto& branch : exportData.branches ) { for ( const auto& segment : branch.segments ) @@ -124,26 +115,36 @@ void applyIcdAreaPerCell( const FishbonesExportContext& context, RigMswWellExpor if ( !segment.wsegvalvData.has_value() ) continue; if ( !icdSegmentNumbers.count( segment.segmentNumber ) ) continue; - areaPerSegment[segment.segmentNumber] = segment.wsegvalvData->area; + originalAreaPerSegment[segment.segmentNumber] = segment.wsegvalvData->area; } } - // An ICD sub connected to several cells is summed once per cell, in ascending cell order, and - // ends up with the sum of the last cell it takes part in. This matches the tree implementation. - for ( const auto& [globalCellIndex, segmentNumbers] : icdSegmentsPerCell ) + // Every sum is computed from the original areas, so the result does not depend on the order the + // cells are visited in. + std::map areaSumPerCell; + for ( const auto& icdSegment : context.icdSegments ) { - double areaSum = 0.0; - for ( auto segmentNumber : segmentNumbers ) + auto it = originalAreaPerSegment.find( icdSegment.segmentNumber ); + if ( it == originalAreaPerSegment.end() ) continue; + + for ( auto globalCellIndex : icdSegment.globalCellIndices ) { - auto it = areaPerSegment.find( segmentNumber ); - if ( it != areaPerSegment.end() ) areaSum += it->second; + areaSumPerCell[globalCellIndex] += it->second; + } + } + + // An ICD sub spans a 0.1 m valve segment and normally connects to a single cell. When it reaches + // into more than one, it reports the largest of the sums it takes part in. + std::map areaPerSegment; + for ( const auto& icdSegment : context.icdSegments ) + { + double area = 0.0; + for ( auto globalCellIndex : icdSegment.globalCellIndices ) + { + area = std::max( area, areaSumPerCell[globalCellIndex] ); } - for ( auto segmentNumber : segmentNumbers ) - { - auto it = areaPerSegment.find( segmentNumber ); - if ( it != areaPerSegment.end() ) it->second = areaSum; - } + if ( area > 0.0 ) areaPerSegment[icdSegment.segmentNumber] = area; } for ( auto& branch : exportData.branches ) diff --git a/ApplicationLibCode/Commands/CompletionExportCommands/MswExport/RicMswBranchBuilder.h b/ApplicationLibCode/Commands/CompletionExportCommands/MswExport/RicMswBranchBuilder.h index 044053f95f..6f14a15a05 100644 --- a/ApplicationLibCode/Commands/CompletionExportCommands/MswExport/RicMswBranchBuilder.h +++ b/ApplicationLibCode/Commands/CompletionExportCommands/MswExport/RicMswBranchBuilder.h @@ -108,6 +108,9 @@ void applyEffectiveDiameters( const FishbonesExportContext& context, RigMswWellE //-------------------------------------------------------------------------------------------------- /// Replace the WSEGVALV area of fishbones ICD subs connected to the same grid cell with the sum of /// their areas, so that the cell sees the total flow area of the ICDs completing it. +/// +/// The sums are computed from the original areas only. An ICD sub reaching into more than one cell +/// reports the largest of the sums it takes part in. //-------------------------------------------------------------------------------------------------- void applyIcdAreaPerCell( const FishbonesExportContext& context, RigMswWellExportData& exportData ); diff --git a/ApplicationLibCode/UnitTests/RicMswBranchBuilder-Test.cpp b/ApplicationLibCode/UnitTests/RicMswBranchBuilder-Test.cpp index 7d1c09b2ef..3fadfb068d 100644 --- a/ApplicationLibCode/UnitTests/RicMswBranchBuilder-Test.cpp +++ b/ApplicationLibCode/UnitTests/RicMswBranchBuilder-Test.cpp @@ -354,6 +354,56 @@ TEST( RicMswBranchBuilder, IcdAreaPerCell_SeparateCellsAreIndependent ) EXPECT_DOUBLE_EQ( 0.003, areaOfSegment( exportData, 20 ) ); } +//-------------------------------------------------------------------------------------------------- +/// An ICD sub reaching into two cells reports the largest sum, computed from the original areas. +//-------------------------------------------------------------------------------------------------- +TEST( RicMswBranchBuilder, IcdAreaPerCell_MultipleCellsUseLargestSum ) +{ + FishbonesExportContext context; + context.icdSegments.push_back( { 10, { 100, 200 } } ); + context.icdSegments.push_back( { 20, { 100 } } ); + context.icdSegments.push_back( { 30, { 200 } } ); + context.icdSegments.push_back( { 40, { 200 } } ); + + auto exportData = makeExportData( { { 10, 0.001 }, { 20, 0.002 }, { 30, 0.003 }, { 40, 0.004 } } ); + applyIcdAreaPerCell( context, exportData ); + + // Cell 100 sums to 0.003, cell 200 to 0.008. Segment 10 takes part in both and reports the larger. + EXPECT_DOUBLE_EQ( 0.008, areaOfSegment( exportData, 10 ) ); + EXPECT_DOUBLE_EQ( 0.003, areaOfSegment( exportData, 20 ) ); + EXPECT_DOUBLE_EQ( 0.008, areaOfSegment( exportData, 30 ) ); + EXPECT_DOUBLE_EQ( 0.008, areaOfSegment( exportData, 40 ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// The result does not depend on the order the ICD subs are recorded in. +//-------------------------------------------------------------------------------------------------- +TEST( RicMswBranchBuilder, IcdAreaPerCell_IsIndependentOfRecordingOrder ) +{ + FishbonesExportContext forward; + forward.icdSegments.push_back( { 10, { 100, 200 } } ); + forward.icdSegments.push_back( { 20, { 100 } } ); + forward.icdSegments.push_back( { 30, { 200 } } ); + + FishbonesExportContext reversed; + reversed.icdSegments.push_back( { 30, { 200 } } ); + reversed.icdSegments.push_back( { 20, { 100 } } ); + reversed.icdSegments.push_back( { 10, { 200, 100 } } ); + + const std::vector> segments = { { 10, 0.001 }, { 20, 0.002 }, { 30, 0.003 } }; + + auto forwardData = makeExportData( segments ); + applyIcdAreaPerCell( forward, forwardData ); + + auto reversedData = makeExportData( segments ); + applyIcdAreaPerCell( reversed, reversedData ); + + for ( int segmentNumber : { 10, 20, 30 } ) + { + EXPECT_DOUBLE_EQ( areaOfSegment( forwardData, segmentNumber ), areaOfSegment( reversedData, segmentNumber ) ); + } +} + //-------------------------------------------------------------------------------------------------- /// Valve segments that are not fishbones ICD subs are left alone. //--------------------------------------------------------------------------------------------------