def test_pvt_model_are_valid(self, default_case):
     """
     Check that the validation for invalid references works for all types of PvtModel. (Composition, Correlation, Tables and TableParameters).
     """
     case = attr.evolve(
         default_case,
         pipes=[
             case_description.PipeDescription(
                 name="Pipe 1",
                 pvt_model="PVT1",
                 source="in",
                 target="out",
                 profile=_empty_profile(),
                 segments=build_simple_segment(),
             ),
             case_description.PipeDescription(
                 name="Pipe 2",
                 pvt_model="PVT2",
                 source="in",
                 target="out",
                 profile=_empty_profile(),
                 segments=build_simple_segment(),
             ),
             case_description.PipeDescription(
                 name="Pipe 3",
                 pvt_model="PVT3",
                 source="in",
                 target="out",
                 profile=_empty_profile(),
                 segments=build_simple_segment(),
             ),
             case_description.PipeDescription(
                 name="Pipe 4",
                 pvt_model="PVT4",
                 source="in",
                 target="out",
                 profile=_empty_profile(),
                 segments=build_simple_segment(),
             ),
             case_description.PipeDescription(
                 name="Pipe 5",
                 pvt_model="PVT5",
                 source="in",
                 target="out",
                 profile=_empty_profile(),
                 segments=build_simple_segment(),
             ),
         ],
     )
     expect_message = "PVT model 'PVT5' selected on 'Pipe 5' is not declared on 'pvt_models', available pvt_models are: PVT1, PVT2, PVT3, PVT4"
     with pytest.raises(
             InvalidReferenceError,
             match=re.escape(expect_message),
     ):
         case.ensure_valid_references()
def test_convert_description_to_alfacase_with_empty_dict(
        datadir: Path) -> None:
    """
    Ensure that the conversion from a description into a Alfacase it's not generating empty dict.
    Since it's not a valid syntax for strictyaml resulting in an InconsistentIndentationDisallowed error
    """

    simple_case = case_description.CaseDescription(
        name="Simple Case",
        pipes=[
            case_description.PipeDescription(
                name="pipe",
                source="mass_source_inlet",
                target="pressure_outlet",
                segments=build_simple_segment(),
                profile=case_description.ProfileDescription(
                    x_and_y=case_description.XAndYDescription(
                        x=Array([0], "m"), y=Array([0], "m"))),
            )
        ],
    )
    simple_case_alfacase_content = convert_description_to_alfacase(simple_case)
    assert "wall_description: {}" not in simple_case_alfacase_content
    assert "tables: {}" not in simple_case_alfacase_content
    # Smoke check, ensures that the alfacase is loaded correctly without errors
    simple_case_alfacase_file = datadir / "simple_case.alfacase"
    simple_case_alfacase_file.write_text(data=simple_case_alfacase_content,
                                         encoding="UTF-8")
    loaded_alfacase = DescriptionDocument.from_file(simple_case_alfacase_file)

    assert loaded_alfacase.content["name"].data == simple_case.name
 def test_pipe_pvt_model(self, default_case):
     """
     If a PipeDescription uses an invalid PvtModel, an InvalidReferenceError must be raised.
     """
     case = attr.evolve(
         default_case,
         pipes=[
             case_description.PipeDescription(
                 name="Pipe 1",
                 segments=build_simple_segment(),
                 pvt_model="Acme",
                 source="in",
                 target="out",
                 profile=_empty_profile(),
             )
         ],
     )
     expected_error = (
         "PVT model 'Acme' selected on 'Pipe 1' is not declared on 'pvt_models', "
         "available pvt_models are: PVT1, PVT2, PVT3")
     with pytest.raises(
             InvalidReferenceError,
             match=re.escape(expected_error),
     ):
         case.ensure_valid_references()
def test_case_description_duplicate_names_between_elements(default_well):
    """
    Ensure Pipes and Wells has unique names (because of OutputDefinition)
    Ensure Nodes and Wells has unique names (because of Edge source/target)
    """
    well_1 = attr.evolve(default_well, name="ACME Node <-> Well")
    well_2 = attr.evolve(default_well, name="ACME Pipe <-> Well")

    case = case_description.CaseDescription(
        nodes=[
            case_description.NodeDescription(
                name="ACME Node <-> Well", node_type=NodeCellType.Pressure
            ),
            case_description.NodeDescription(
                name="Node1", node_type=NodeCellType.Pressure
            ),
        ],
        pipes=[
            case_description.PipeDescription(
                name="ACME Pipe <-> Well",
                source="ACME",
                target="ACME",
                segments=build_simple_segment(),
            ),
            case_description.PipeDescription(
                name="Pipe 1",
                source="ACME",
                target="ACME",
                segments=build_simple_segment(),
            ),
        ],
        wells=[well_1, well_2],
    )

    expected_msg = dedent(
        """\
        Some different type of elements needs to have unique name between them, found duplicated names for the following items:
        Nodes and Wells:
            - ACME Node <-> Well
        Pipes and Wells:
            - ACME Pipe <-> Well"""
    )

    with pytest.raises(InvalidReferenceError, match=re.escape(expected_msg)):
        case.ensure_unique_names()
    def test_pvt_model_default_behavior(self, default_case, default_well):
        """
        1) CaseDescription should accept components that uses PvtModel as None while default_model is configured.
        2) default_model must be a valid pvt_model defined on pvt_models
        3) If default_model is None, all components that uses pvt_model must be assigined.
        """
        from alfasim_sdk._internal.constants import NodeCellType

        case = attr.evolve(
            default_case,
            pvt_models=attr.evolve(default_case.pvt_models,
                                   default_model="PVT2"),
            nodes=[
                case_description.NodeDescription(
                    name="Node 1",
                    node_type=NodeCellType.Pressure,
                    pvt_model=None)
            ],
            pipes=[
                case_description.PipeDescription(
                    name="Pipe 1",
                    pvt_model=None,
                    source="in",
                    target="out",
                    segments=build_simple_segment(),
                    profile=case_description.ProfileDescription(
                        x_and_y=case_description.XAndYDescription(
                            x=Array([0], "m"), y=Array([0], "m"))),
                )
            ],
            wells=[
                attr.evolve(
                    default_well,
                    pvt_model=None,
                    annulus=attr.evolve(default_well.annulus, pvt_model=None),
                )
            ],
        )
        # Check 1) If default_model assigned, elements that uses pvt_model can be None
        case.ensure_valid_references()
        assert case.pvt_models.default_model == "PVT2"
        assert case.nodes[0].pvt_model is None
        assert case.pipes[0].pvt_model is None
        assert case.wells[0].pvt_model is None
        assert case.wells[0].annulus.pvt_model is None

        # Check 2) default_model must be filled with a valid pvt_model
        case_with_invalid_default_pvt_model = attr.evolve(
            case,
            pvt_models=attr.evolve(case.pvt_models, default_model="Acme"))
    def test_pipe_pvt_model(self, default_case, default_well):
        """
        If a Elements on case uses an invalid PvtModel, the pvt_model must reset to None when calling ResetInvalidReferences()
        """
        case = attr.evolve(
            default_case,
            nodes=[
                case_description.NodeDescription(
                    name="Node 1",
                    node_type=NodeCellType.Pressure,
                    pvt_model="InvalidPVT",
                )
            ],
            wells=[
                attr.evolve(
                    default_well,
                    pvt_model="InvalidPVT",
                    annulus=case_description.AnnulusDescription(
                        has_annulus_flow=False,
                        pvt_model="InvalidPVT",
                        top_node="Node 1",
                    ),
                )
            ],
            pipes=[
                case_description.PipeDescription(
                    name="Pipe 1",
                    pvt_model="InvalidPVT",
                    source="in",
                    target="out",
                    profile=_empty_profile(),
                    segments=build_simple_segment(),
                    equipment=case_description.EquipmentDescription(
                        mass_sources={
                            "Mass Equip. 1": case_description.MassSourceEquipmentDescription(
                                position=Scalar(0, "m")
                            )
                        }
                    ),
                )
            ],
        )

        case.reset_invalid_references()
        assert case.pipes[0].pvt_model is None
        assert case.nodes[0].pvt_model is None
        assert case.wells[0].pvt_model is None
        assert case.wells[0].annulus.pvt_model is None
def test_invalid_fluid_reference_on_pipes():
    """
    Ensure that only declared Fluids can be used on:
       PipeDescription, MassSourceEquipmentDescription, ReservoirInflowEquipmentDescription.
    """
    case = case_description.CaseDescription(
        pvt_models=case_description.PvtModelsDescription(
            default_model="PVT",
            compositions={
                "PVT":
                case_description.PvtModelCompositionalDescription(
                    fluids={"Fluid 1": case_description.FluidDescription()})
            },
        ),
        pipes=[
            case_description.PipeDescription(
                name="Pipe 1",
                source="",
                target="",
                segments=build_simple_segment(),
                initial_conditions=case_description.
                InitialConditionsDescription(fluid="acme5"),
                equipment=case_description.EquipmentDescription(
                    mass_sources={
                        "MassSource":
                        case_description.MassSourceEquipmentDescription(
                            position=Scalar(1, "m"), fluid="a6")
                    },
                    reservoir_inflows={
                        "Reservoir":
                        case_description.ReservoirInflowEquipmentDescription(
                            start=Scalar(1, "m"),
                            length=Scalar(10, "m"),
                            fluid="a7")
                    },
                ),
            )
        ],
    )
    expected_error = "The following elements have an invalid fluid assigned: 'MassSource from Pipe 1', 'Pipe 1', 'Reservoir from Pipe 1'."
    with pytest.raises(InvalidReferenceError, match=re.escape(expected_error)):
        case.ensure_valid_references()
)

X_AND_Y_DESCRIPTION = case_description.XAndYDescription(
    x=Array([1, 2, 3], "m"), y=Array([4, 5, 6], "m")
)


PROFILE_DESCRIPTION_WITH_XY = case_description.ProfileDescription(
    x_and_y=X_AND_Y_DESCRIPTION
)
PIPE_DESCRIPTION = case_description.PipeDescription(
    environment=ENVIRONMENT_DESCRIPTION,
    equipment=EQUIPMENT_DESCRIPTION,
    initial_conditions=INITIAL_CONDITIONS_DESCRIPTION,
    name="pipe 1",
    profile=PROFILE_DESCRIPTION_WITH_XY,
    pvt_model="gavea",
    segments=PIPE_WALL_DESCRIPTION,
    source="mass_source_node",
    target="pressure_node",
)
FORMATION_LAYER_DESCRIPTION = case_description.FormationLayerDescription(
    name="f", start=Scalar(1, "m"), material="Carbon Steel"
)
FORMATION_DESCRIPTION = case_description.FormationDescription(
    reference_y_coordinate=Scalar(1, "m"),
    layers=[FORMATION_LAYER_DESCRIPTION, FORMATION_LAYER_DESCRIPTION],
)

LENGTH_AND_ELEVATION_DESCRIPTION = case_description.LengthAndElevationDescription(
    length=Array([0, 1, 2], "m"), elevation=Array([0, 0.5, 1], "m")
def test_case_description_duplicate_names(default_well):
    """
    Pipes because they are reference by OutputDescription
    Nodes because they are referenced by PipeDescription, WellDescription and OutputDescription
    PVTs names, because of default_model
    Wall Names because of PipeSegmentsDescription
    Material because of WellDescription(stagnant_fluid), CasingSectionDescription, TubingDescription
    """
    well_1 = attr.evolve(default_well, name="Well 1")
    well_2 = attr.evolve(default_well, name="Well 1")

    case = case_description.CaseDescription(
        materials=[
            case_description.MaterialDescription(name="Material"),
            case_description.MaterialDescription(name="Material"),
        ],
        walls=[
            case_description.WallDescription(name="Wall A"),
            case_description.WallDescription(name="Wall A"),
        ],
        pvt_models=case_description.PvtModelsDescription(
            default_model="PVT",
            correlations={
                "PVT1": case_description.PvtModelCorrelationDescription(),
            },
            compositions={
                "PVT1":
                case_description.PvtModelCompositionalDescription(fluids={
                    "Fluid 0":
                    case_description.FluidDescription(),
                    "Fluid 1":
                    case_description.FluidDescription(),
                }, ),
                "PVT2":
                case_description.PvtModelCompositionalDescription(
                    fluids={
                        "Fluid 0": case_description.FluidDescription(),
                        "Fluid 1": case_description.FluidDescription(),
                    }),
            },
        ),
        nodes=[
            case_description.NodeDescription(name="ACME",
                                             node_type=NodeCellType.Pressure),
            case_description.NodeDescription(name="ACME",
                                             node_type=NodeCellType.Pressure),
            case_description.NodeDescription(name="Node1",
                                             node_type=NodeCellType.Pressure),
            case_description.NodeDescription(name="FOO",
                                             node_type=NodeCellType.Pressure),
            case_description.NodeDescription(name="FOO",
                                             node_type=NodeCellType.Pressure),
        ],
        pipes=[
            case_description.PipeDescription(
                name="Pipe 1",
                source="ACME",
                target="ACME",
                segments=build_simple_segment(),
            ),
            case_description.PipeDescription(
                name="Pipe 1",
                source="ACME",
                target="ACME",
                segments=build_simple_segment(),
            ),
        ],
        wells=[well_1, well_2],
    )

    expected_msg = dedent("""\
        Elements that can be referenced must have a unique name, found multiples definitions of the following items:
        Fluids:
            - Fluid 0
            - Fluid 1
        Materials:
            - Material
        Nodes:
            - ACME
            - FOO
        PVT:
            - PVT1
        Pipes:
            - Pipe 1
        Walls:
            - Wall A
        Wells:
            - Well 1""")

    with pytest.raises(InvalidReferenceError, match=re.escape(expected_msg)):
        case.ensure_unique_names()