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()
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()
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()
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"
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,