Esempio n. 1
0
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 default_case(tmp_path) -> case_description.CaseDescription:
    """
    Minimum valid CaseDescription with pvt configured
    """
    tab_file = tmp_path / "dummy.tab"
    file_content = [
        'PVTTABLE LABEL = "PVT1",PHASE = THREE,',
        'PVTTABLE LABEL = "PVT2", PHASE = THREE,',
    ]
    tab_file.write_text("\n".join(file_content))
    return case_description.CaseDescription(
        pvt_models=case_description.PvtModelsDescription(
            default_model="PVT2",
            tables={"PVT1": f"{tab_file}"},
            correlations={
                "PVT2": case_description.PvtModelCorrelationDescription()
            },
            compositions={
                "PVT3": case_description.PvtModelCompositionalDescription()
            },
            table_parameters={
                "PVT4":
                case_description.PvtModelTableParametersDescription.
                create_empty()
            },
        ))
def test_invalid_fluid_reference_on_wells(default_well):
    """
    Ensure that only declared Fluids can be used on WellDescription and AnnulusDescription.
    """
    case = case_description.CaseDescription(
        pvt_models=case_description.PvtModelsDescription(
            default_model="PVT",
            compositions={
                "PVT":
                case_description.PvtModelCompositionalDescription(
                    fluids={"Fluid 1": case_description.FluidDescription()})
            },
        ),
        wells=[
            attr.evolve(
                default_well,
                initial_conditions=attr.evolve(
                    default_well.initial_conditions,
                    fluid="acme",
                ),
                annulus=attr.evolve(
                    default_well.annulus,
                    initial_conditions=attr.evolve(
                        default_well.annulus.initial_conditions,
                        fluid="acme",
                    ),
                ),
            )
        ],
    )
    expected_error = "The following elements have an invalid fluid assigned: 'Annulus from Well 1', 'Well 1'."
    with pytest.raises(InvalidReferenceError, match=re.escape(expected_error)):
        case.ensure_valid_references()
def test_load_pvt_tables_with_pvt_model_selector(
    description_document_for_pvt_tables_test, tmp_path
):
    """
    PvtModelsDescription.tables should provide a way to the user select one of multiples pvt models that are inside the file
    This syntax can be used either for absolute path or relative path

    # Ex.: " <tab_file> | <pvt_model_name> "
    """
    document = description_document_for_pvt_tables_test

    document.content["tables"]["acme"] = YAML(
        str(document.file_path.parent / "acme.tab|SOMELABEL")
    )
    document.content["tables"]["acme_2"] = YAML("acme.tab|SOMELABEL")

    pvt_model_description = load_pvt_models_description(document=document)
    assert pvt_model_description.tables == {
        "acme": document.file_path.parent / "acme.tab|SOMELABEL",
        "acme_2": document.file_path.parent / "acme.tab|SOMELABEL",
    }

    # Ensure that the pvt file has the pvt_model GaveaDST
    case_description.CaseDescription(
        pvt_models=pvt_model_description
    ).ensure_valid_references()
Esempio n. 5
0
def test_convert_description_to_alfacase_with_nan_float():
    """
    Ensure that NaN is generated as `.nan` instead of `nan`, and '.inf' instead of `inf`
    because of YAML specification 1.2 that only accepts `.nan` and `.inf`, `+.inf`, `-.inf`.
    """

    simple_case = case_description.CaseDescription(
        numerical_options=NumericalOptionsDescription(
            tolerance=float("inf"), relaxed_tolerance=float("nan")))
    simple_case_alfacase_content = convert_description_to_alfacase(simple_case)
    assert "relaxed_tolerance: .nan" in simple_case_alfacase_content
    assert "tolerance: .inf" in simple_case_alfacase_content

    simple_case = case_description.CaseDescription(
        numerical_options=NumericalOptionsDescription(
            tolerance=float("+inf"), relaxed_tolerance=float("-inf")))
    simple_case_alfacase_content = convert_description_to_alfacase(simple_case)
    assert "tolerance: .inf" in simple_case_alfacase_content
    assert "relaxed_tolerance: -.inf" in simple_case_alfacase_content
 def test_remove_pvt_entry_from_pvt_models_when_file_is_invalid(self):
     """
     Remove the PVT entry from case.pvt_models.tables if the file is not a file when calling ResetInvalidReferences()
     """
     case = case_description.CaseDescription(
         pvt_models=case_description.PvtModelsDescription(
             default_model="PVT1", tables={"PVT1": "SomePath"}))
     case.reset_invalid_references()
     assert case.pvt_models.tables == {}
     assert case.pvt_models.default_model is None
 def test_pvt_models_with_invalid_pvtfile(self, tmp_path):
     """
     When a PVTModel assigned on case.pvt_models.tables doesn't exist,
     a InvalidReferenceError exception must be raised when case.EnsureValidReferences is called.
     """
     case = case_description.CaseDescription(
         pvt_models=case_description.PvtModelsDescription(
             default_model="PVT1", tables={"PVT1": "SomePath|PVT1"}))
     expect_message = "Error on 'PVT1', 'SomePath' is not a valid file"
     with pytest.raises(
             InvalidReferenceError,
             match=re.escape(expect_message),
     ):
         case.ensure_valid_references()
Esempio n. 8
0
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_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()
Esempio n. 10
0
def test_invalid_fluid_reference_on_nodes():
    """
    Ensure that only declared Fluids can be used on NodeDescription
    """
    case = case_description.CaseDescription(
        pvt_models=case_description.PvtModelsDescription(
            default_model="PVT",
            compositional={
                "PVT": case_description.PvtModelCompositionalDescription(
                    fluids={"Fluid 1": case_description.CompositionalFluidDescription()}
                )
            },
        ),
        nodes=[
            case_description.NodeDescription(
                name="Node 1",
                node_type=NodeCellType.Internal,
                internal_properties=case_description.InternalNodePropertiesDescription(
                    fluid="Acme2"
                ),
            ),
            case_description.NodeDescription(
                name="Node 2",
                node_type=NodeCellType.Pressure,
                pressure_properties=case_description.PressureNodePropertiesDescription(
                    fluid="Acme3"
                ),
            ),
            case_description.NodeDescription(
                name="Node 3",
                node_type=NodeCellType.MassSource,
                mass_source_properties=case_description.MassSourceNodePropertiesDescription(
                    fluid="Acme4"
                ),
            ),
        ],
    )

    expected_error = "The following elements have an invalid fluid assigned: 'Node 1', 'Node 2', 'Node 3'."
    with pytest.raises(InvalidReferenceError, match=re.escape(expected_error)):
        case.ensure_valid_references()
    def test_remove_pvt_entry_from_pvt_models_when_pvt_model_is_invalid(
            self, default_case, tmp_path):
        """
        Check if the PVTModel referred from case.pvt_models.tables is inside a pvt file,
        if invalid the entry must be removed, when calling case.ResetInvalidReferences()
        """

        case = attr.evolve(
            default_case,
            pvt_models=case_description.PvtModelsDescription(
                default_model="PVT1",
                tables={"PVT1": f"{tmp_path/'dummy.tab'}|INVALID"}),
        )
        case.reset_invalid_references()
        assert case.pvt_models.tables == {}
        assert case.pvt_models.default_model is None
        case = case_description.CaseDescription(
            pvt_models=case_description.PvtModelsDescription(
                default_model="PVT2",
                tables={"PVT2": f"{tmp_path/'dummy.tab'}|PVT2"}))
        case.reset_invalid_references()
        assert case.pvt_models.default_model == "PVT2"
Esempio n. 12
0
def test_alfacase_file_export(tmp_path):
    """
    Check that GenerateAlfacaseFile creates a alfatable file with the content from PvtModelsDescription.table_parameters
    When exporting this alfatable should be placed on PvtModelDescription.tables
    """

    alfacase_file = tmp_path / "mycase.alfacase"
    alfatable_file = tmp_path / "mycase.fluid_a_1.alfatable"

    pvt_model_table_parameter = {
        "FLUID-A 1": PvtModelTableParametersDescription.create_constant()
    }
    from alfasim_sdk._internal.alfacase import case_description

    case_description = case_description.CaseDescription(
        pvt_models=case_description.PvtModelsDescription(
            table_parameters=pvt_model_table_parameter))

    generate_alfacase_file(case_description, alfacase_file)
    assert alfacase_file.is_file()
    assert alfatable_file.is_file()
    # Load
    case = convert_alfacase_to_description(alfacase_file)
    assert case.pvt_models.tables == {"FLUID-A 1": alfatable_file}
TRACERS_DESCRIPTION = case_description.TracersDescription(
    constant_coefficients={
        "Tracer 0": TRACER_MODEL_CONSTANT_COEFFICIENTS_DESCRIPTION,
        "Tracer 1": TRACER_MODEL_CONSTANT_COEFFICIENTS_DESCRIPTION,
    }
)
CASE = case_description.CaseDescription(
    name="divergent_pipes",
    time_options=TIME_OPTIONS_DESCRIPTION,
    physics=PHYSICS_DESCRIPTION,
    numerical_options=NUMERICAL_OPTIONS_DESCRIPTION,
    ipr_models=IPR_MODELS_DESCRIPTION,
    pvt_models=PVT_MODELS_DEFINITION,
    tracers=TRACERS_DESCRIPTION,
    outputs=CASE_OUTPUT_DEFINITION,
    pipes=[PIPE_DESCRIPTION],
    nodes=[
        NODE_MASS_SOURCE_DESCRIPTION,
        NODE_PRESSURE_DESCRIPTION,
        NODE_SEPARATOR_DESCRIPTION,
        NODE_INTERNAL_DESCRIPTION,
    ],
    wells=[WELL_DESCRIPTION],
    materials=[MATERIAL_DESCRIPTION],
    walls=[WALL_DESCRIPTION],
)
REFERENCED_VOLUME_FRACTIONS_CONTAINER_DESCRIPTION = (
    case_description.ReferencedVolumeFractionsContainerDescription(
        reference_coordinate=Scalar(1.0, "m"),
        positions=Array([1.0, 2.0, 3.0], "m"),
        fractions={
            constants.FLUID_GAS: Array([0.5, 0.5], "-"),
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()
        case = attr.evolve(
            default_case,
            pvt_models=case_description.PvtModelsDescription(
                default_model="PVT1",
                tables={"PVT1": f"{tmp_path/'dummy.tab'}|INVALID"}),
        )
        expect_message = "'INVALID' could not be found on 'dummy.tab', available models are: 'PVT1, PVT2'"
        with pytest.raises(
                InvalidReferenceError,
                match=re.escape(expect_message),
        ):
            case.ensure_valid_references()

        # Ensure the test finishes in a valid state
        case = case_description.CaseDescription(
            pvt_models=case_description.PvtModelsDescription(
                default_model="PVT2",
                tables={"PVT2": f"{tmp_path/'dummy.tab'}|PVT2"}))
        case.ensure_valid_references()
        assert case.pvt_models.default_model == "PVT2"

    def test_pvt_models_with_invalid_pvtfile(self, tmp_path):
        """
        When a PVTModel assigned on case.pvt_models.tables doesn't exist,
        a InvalidReferenceError exception must be raised when case.EnsureValidReferences is called.
        """
        case = case_description.CaseDescription(
            pvt_models=case_description.PvtModelsDescription(
                default_model="PVT1", tables={"PVT1": "SomePath|PVT1"}))
        expect_message = "Error on 'PVT1', 'SomePath' is not a valid file"
        with pytest.raises(
                InvalidReferenceError,