#13485: Export unique top-level well paths for completions and MSW

This commit is contained in:
Magne Sjaastad committed 2026-10-22 13:34:49 +02:00
1 parent 7b580694ed
commit 6a15c84463
5 files changed
+90 -2

No files matched your search

@@ -75,9 +75,12 @@
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeatureImpl::exportCompletions( const std::vector<RimWellPath*>& wellPaths,
void RicWellPathExportCompletionDataFeatureImpl::exportCompletions( const std::vector<RimWellPath*>& allWellPaths,
const RicExportCompletionDataSettingsUi& exportSettings )
{
// Laterals are exported together with their top level well path
const auto wellPaths = RicWellPathExportCompletionsFileTools::uniqueTopLevelWellPaths( allWellPaths );
if ( exportSettings.caseToApply() == nullptr )
{
RiaLogging::error( "Export Completions Data: Cannot export completions data a valid Eclipse case" );
@@ -29,6 +29,8 @@
#include "cafUtils.h"
#include <algorithm>
#include <QDateTime>
#include <QDir>
#include <QTextStream>
@@ -66,6 +68,23 @@ std::shared_ptr<QFile> RicWellPathExportCompletionsFileTools::openFile( const QS
return exportFile;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimWellPath*> RicWellPathExportCompletionsFileTools::uniqueTopLevelWellPaths( const std::vector<RimWellPath*>& wellPaths )
{
std::vector<RimWellPath*> result;
for ( auto* wellPath : wellPaths )
{
if ( !wellPath ) continue;
auto* topLevel = wellPath->topLevelWellPath();
if ( std::find( result.begin(), result.end(), topLevel ) == result.end() ) result.push_back( topLevel );
}
return result;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -22,12 +22,16 @@
#include <QString>
#include <memory>
#include <vector>
class RimWellPath;
class RicWellPathExportCompletionsFileTools
{
public:
// Replaces laterals by their top level well path and removes duplicates, keeping the original order
static std::vector<RimWellPath*> uniqueTopLevelWellPaths( const std::vector<RimWellPath*>& wellPaths );
static const RimWellPath* findWellPathFromExportName( const QString& wellNameForExport );
static std::shared_ptr<QFile>
@@ -198,8 +198,11 @@ void exportSplitMswData( const RicExportCompletionDataSettingsUi& exportSettings
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportMswCompletionsImpl::exportWellSegmentsForAllCompletions( const RicExportCompletionDataSettingsUi& exportSettings,
const std::vector<RimWellPath*>& wellPaths )
const std::vector<RimWellPath*>& allWellPaths )
{
// Laterals are exported together with their top level well path
const auto wellPaths = RicWellPathExportCompletionsFileTools::uniqueTopLevelWellPaths( allWellPaths );
if ( exportSettings.fileSplit() == RicExportCompletionDataSettingsUi::ExportSplit::SPLIT_ON_WELL )
{
internal::exportSplitMswData( exportSettings, exportSettings.folder(), wellPaths );
@@ -262,3 +262,62 @@ def test_msw_settings_read(rips_instance, initialize_test):
assert completion_settings.allow_well_cross_flow, (
"Allow well cross flow should be True"
)
def _export_msw_files(case, well_paths, export_function):
with tempfile.TemporaryDirectory(prefix="rips") as folder:
export_function(case, well_paths, folder)
files = {}
for name in os.listdir(folder):
if name.endswith("_MSW"):
with open(os.path.join(folder, name)) as f:
# Drop comment lines, they contain a timestamp
files[name] = [
line
for line in f.read().splitlines()
if not line.startswith("--")
]
return files
def _export_completions(case, well_paths, folder):
case.export_completions(
well_paths=well_paths,
time_step=0,
export_folder=folder,
file_split=rips.CompletionExportSplit.SPLIT_ON_WELL,
include_msw=True,
export_comments=False,
)
def _export_msw_completions(case, well_paths, folder):
case.export_msw_completions(
well_paths=well_paths,
export_folder=folder,
file_split=rips.CompletionExportSplit.SPLIT_ON_WELL,
)
@pytest.mark.parametrize(
"export_function", [_export_completions, _export_msw_completions]
)
def test_msw_export_main_and_lateral_exports_top_level_well(
rips_instance, initialize_test, export_function
):
"""Issue #13485: passing both a main well and its lateral must export the
main well (including all laterals), not only the lateral."""
project_path = dataroot.PATH + "/msw-export/project-files/perf_lateral.rsp"
project = rips_instance.project.open(path=project_path)
case = project.cases()[0]
well_y1 = project.well_path_by_name("Well-1 Y1")
well_y2 = project.well_path_by_name("Well-1 Y2")
assert well_y1 is not None and well_y2 is not None
reference = _export_msw_files(case, [well_y1], export_function)
assert len(reference) == 1
for well_paths in ([well_y1, well_y2], [well_y2, well_y1], [well_y2]):
exported = _export_msw_files(case, well_paths, export_function)
assert exported == reference