Skip to content

Commit 3adc784

Browse files
committed
ENH: Allow RMS wellbores to share SMDA targets
1 parent 8358e5b commit 3adc784

2 files changed

Lines changed: 108 additions & 17 deletions

File tree

src/fmu/settings/models/mappings.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,22 @@ def _validate_identifier_mappings_collection(
307307
of a same-system primary. It is also invalid to add two ``rms -> smda``
308308
mappings for the same ``source_id``.
309309
310-
- A cross-system ``target_id`` can be used only once per target system.
310+
- A cross-system ``target_id`` can be used only once per target system, except
311+
for RMS to SMDA wellbore mappings. Different RMS wellbore names can map to
312+
the same SMDA wellbore.
311313
Example valid mappings::
312314
313315
rms -> rms, primary, source_id="TopVolantis", target_id="TopVolantis"
314316
rms -> rms, alias, source_id="TOP_VOLANTIS", target_id="TopVolantis"
315317
rms -> smda, primary, source_id="TopVolantis", target_id="VOLANTIS GP. Top"
316318
319+
Example valid RMS to SMDA wellbore mappings::
320+
321+
rms -> rms, primary, source_id="RFT_30_9-B-21_C", target_id="RFT_30_9-B-21_C"
322+
rms -> rms, primary, source_id="MLW_30_9-B-21_C", target_id="MLW_30_9-B-21_C"
323+
rms -> smda, primary, source_id="RFT_30_9-B-21_C", target_id="NO 30/9-B-21 C"
324+
rms -> smda, primary, source_id="MLW_30_9-B-21_C", target_id="NO 30/9-B-21 C"
325+
317326
Example invalid mappings::
318327
319328
rms -> rms, primary, source_id="TopVolantis", target_id="TopVolantis"
@@ -322,7 +331,9 @@ def _validate_identifier_mappings_collection(
322331
rms -> smda, primary, source_id="Volon", target_id="VOLANTIS GP. Top"
323332
324333
The second cross-system mapping is invalid because one cross-system
325-
``target_id`` cannot be mapped to more than one same-system primary.
334+
``target_id`` cannot be mapped to more than one same-system primary. The
335+
exception permits this relationship only for ``wellbore`` mappings from
336+
``rms`` to ``smda``.
326337
"""
327338
same_system_source_keys: set[tuple[DataSystem, MappingType, str]] = set()
328339
same_system_primary_source_keys: set[tuple[DataSystem, MappingType, str]] = set()
@@ -368,8 +379,14 @@ def _validate_identifier_mappings_collection(
368379
)
369380
cross_system_source_keys.add(cross_system_source_key)
370381

371-
# A cross-system target_id can only belong to one same-system primary.
372-
if mapping.target_id is not None:
382+
# RMS wellbore names can share an SMDA wellbore target. Other
383+
# cross-system target_ids can only belong to one same-system primary.
384+
allows_reused_target_id = (
385+
mapping.mapping_type == MappingType.wellbore
386+
and mapping.source_system == DataSystem.rms
387+
and mapping.target_system == DataSystem.smda
388+
)
389+
if mapping.target_id is not None and not allows_reused_target_id:
373390
cross_system_target_key = (
374391
mapping.mapping_type,
375392
mapping.source_system,

tests/test_mappings_model.py

Lines changed: 87 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -502,26 +502,62 @@ def test_validate_collection_rejects_multiple_cross_system_outcomes() -> None:
502502
)
503503

504504

505-
def test_validate_collection_rejects_reused_cross_system_target_id() -> None:
505+
@pytest.mark.parametrize(
506+
("mapping_type", "target_system", "source_ids", "shared_target_id"),
507+
[
508+
(
509+
MappingType.stratigraphy,
510+
DataSystem.smda,
511+
("TopVolantis", "Volon"),
512+
"VOLANTIS GP. Top",
513+
),
514+
(
515+
MappingType.wellbore,
516+
DataSystem.simulator,
517+
("RFT_30_9-B-21_C", "MLW_30_9-B-21_C"),
518+
"B21C",
519+
),
520+
],
521+
)
522+
def test_validate_collection_rejects_reused_cross_system_target_id(
523+
mapping_type: MappingType,
524+
target_system: DataSystem,
525+
source_ids: tuple[str, str],
526+
shared_target_id: str,
527+
) -> None:
506528
"""A cross-system target identifier can only belong to one primary source."""
507-
first_primary = create_stratigraphy_mapping()
508-
second_primary = create_stratigraphy_mapping(
509-
source_id="Volon",
510-
target_id="Volon",
529+
first_source_id, second_source_id = source_ids
530+
first_primary = InternalIdentifierMapping(
531+
source_system=DataSystem.rms,
532+
target_system=DataSystem.rms,
533+
mapping_type=mapping_type,
534+
relation_type=InternalRelationType.primary,
535+
source_id=first_source_id,
536+
target_id=first_source_id,
511537
)
512-
first_mapping = create_stratigraphy_mapping(
538+
second_primary = InternalIdentifierMapping(
513539
source_system=DataSystem.rms,
514-
target_system=DataSystem.smda,
540+
target_system=DataSystem.rms,
541+
mapping_type=mapping_type,
515542
relation_type=InternalRelationType.primary,
516-
source_id="TopVolantis",
517-
target_id="VOLANTIS GP. Top",
543+
source_id=second_source_id,
544+
target_id=second_source_id,
518545
)
519-
second_mapping = create_stratigraphy_mapping(
546+
first_mapping = InternalIdentifierMapping(
520547
source_system=DataSystem.rms,
521-
target_system=DataSystem.smda,
548+
target_system=target_system,
549+
mapping_type=mapping_type,
522550
relation_type=InternalRelationType.primary,
523-
source_id="Volon",
524-
target_id="VOLANTIS GP. Top",
551+
source_id=first_source_id,
552+
target_id=shared_target_id,
553+
)
554+
second_mapping = InternalIdentifierMapping(
555+
source_system=DataSystem.rms,
556+
target_system=target_system,
557+
mapping_type=mapping_type,
558+
relation_type=InternalRelationType.primary,
559+
source_id=second_source_id,
560+
target_id=shared_target_id,
525561
)
526562

527563
with pytest.raises(
@@ -535,6 +571,44 @@ def test_validate_collection_rejects_reused_cross_system_target_id() -> None:
535571
)
536572

537573

574+
def test_wellbore_mappings_allow_reused_rms_to_smda_target_id() -> None:
575+
"""Different RMS wellbore names can map to the same SMDA wellbore."""
576+
rft_primary = create_wellbore_mapping(
577+
source_system=DataSystem.rms,
578+
target_system=DataSystem.rms,
579+
source_id="RFT_30_9-B-21_C",
580+
target_id="RFT_30_9-B-21_C",
581+
)
582+
mlw_primary = create_wellbore_mapping(
583+
source_system=DataSystem.rms,
584+
target_system=DataSystem.rms,
585+
source_id="MLW_30_9-B-21_C",
586+
target_id="MLW_30_9-B-21_C",
587+
)
588+
rft_mapping = create_wellbore_mapping(
589+
source_system=DataSystem.rms,
590+
target_system=DataSystem.smda,
591+
source_id="RFT_30_9-B-21_C",
592+
target_id="NO 30/9-B-21 C",
593+
)
594+
mlw_mapping = create_wellbore_mapping(
595+
source_system=DataSystem.rms,
596+
target_system=DataSystem.smda,
597+
source_id="MLW_30_9-B-21_C",
598+
target_id="NO 30/9-B-21 C",
599+
)
600+
601+
mappings = InternalWellboreMappings(
602+
root=[rft_primary, mlw_primary, rft_mapping, mlw_mapping]
603+
)
604+
605+
converted = mappings.to_wellbore_mappings()
606+
assert [(mapping.source_id, mapping.target_id) for mapping in converted] == [
607+
("RFT_30_9-B-21_C", "NO 30/9-B-21 C"),
608+
("MLW_30_9-B-21_C", "NO 30/9-B-21 C"),
609+
]
610+
611+
538612
def test_validate_collection_rejects_reused_same_system_source_id() -> None:
539613
"""A source_id cannot be both a primary and an alias in the same collection."""
540614
primary = create_stratigraphy_mapping()

0 commit comments

Comments
 (0)