Exemplo n.º 1
0
    def test_check_empty_array(self) -> None:
        assert Array.FromScalars(scalars=[]) == Array.CreateEmptyArray()
        assert Array.FromScalars(scalars=[], unit="m") == Array([], "m")

        expected_msg = "If category and value are given, the unit must be specified too."
        with pytest.raises(AssertionError, match=expected_msg):
            Array.FromScalars(scalars=[], category="length")
Exemplo n.º 2
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
Exemplo n.º 3
0
def testArrayOperations(unit_database_len_time) -> None:
    unit_database = unit_database_len_time

    m = Quantity.CreateDerived(OrderedDict([("Table size", ["m", 1])]))
    km_city = Quantity.CreateDerived(OrderedDict([("City size", ["km", 1])]))

    s1: Array[List[float]] = Array.CreateWithQuantity(m, [1])
    s2: Array[List[float]] = Array.CreateWithQuantity(km_city, [0.01])
    initial1 = s1.GetQuantity().GetComposingUnits()
    initial2 = s2.GetQuantity().GetComposingUnits()
    # Check that they doesn't raise ComposedUnitError
    s1.GetValues()
    s2.GetValues()

    quantity, value = unit_database.Multiply(m, km_city, 1, 0.01)
    assert initial1 == s1.GetQuantity().GetComposingUnits()
    assert initial2 == s2.GetQuantity().GetComposingUnits()
    calculated1: Array[List[float]] = Array.CreateWithQuantity(quantity, [value])

    array = s1 * s2
    str(array)  # just to see if it works...
    assert calculated1 == s1 * s2

    quantity, value = unit_database.Sum(m, km_city, 1, 0.01)
    assert Array.CreateWithQuantity(quantity, [value]) == s1 + s2

    quantity, value = unit_database.Subtract(m, km_city, 1, 0.01)
    assert Array.CreateWithQuantity(quantity, [value]) == s1 - s2
Exemplo n.º 4
0
def testCopyPropertiesAndValidation(unit_database_len) -> None:
    # Not raises exception because by default validation is False on the copy operation
    array_source = Array("flow rate", values=[-1, -2, -3], unit="m3/s")
    assert not array_source.IsValid()

    array_dest = array_source.CreateCopy()
    assert array_dest.values == [-1, -2, -3]
Exemplo n.º 5
0
def default_well() -> case_description.WellDescription:
    """
    Minimum valid WellDescription
    """
    return case_description.WellDescription(
        name="Well 1",
        profile=case_description.ProfileDescription(
            length_and_elevation=case_description.LengthAndElevationDescription(
                length=Array([0.0] + [1000] * 2, "m"),
                elevation=Array([0.0] + [1.2] * 2, "m"),
            )
        ),
        stagnant_fluid="Lift Gas",
        top_node="Node 1",
        bottom_node="Node 2",
        annulus=case_description.AnnulusDescription(
            has_annulus_flow=False, top_node="Node 1"
        ),
        formation=case_description.FormationDescription(
            reference_y_coordinate=Scalar(0, "m")
        ),
        environment=case_description.EnvironmentDescription(
            thermal_model=constants.PipeThermalModelType.SteadyState
        ),
    )
Exemplo n.º 6
0
def build_compressor_pressure_table_description(
    speed_entries,
    corrected_mass_flow_rate_entries,
    pressure_ratio_table,
    isentropic_efficiency_table,
):
    """
    Helper to build a table for CompressorPressureTable from a parametrized input of `speed_entries`
    and `corrected_mass_flow_rate_entries`, correcting it so len(pressure_ratio_table) and
    len(isentropic_efficiency_table) have elements = len(speed_entries) * len(corrected_mass_flow_rate_entries),
    making it a explicit table with all combinations.
    """
    expected_size = len(speed_entries) * len(corrected_mass_flow_rate_entries)
    assert expected_size == len(
        pressure_ratio_table
    ), f"Missing pressure entries. Expected {expected_size} but got {len(pressure_ratio_table)}"
    assert expected_size == len(
        isentropic_efficiency_table
    ), f"Missing isentropic efficiency entries. Expected {expected_size} but got {len(isentropic_efficiency_table)}"

    adjusted_speeds = []
    adjusted_flow_rates = []
    for speed in speed_entries:
        for flow_rate in corrected_mass_flow_rate_entries:
            adjusted_speeds.append(speed)
            adjusted_flow_rates.append(flow_rate)

    return case_description.CompressorPressureTableDescription(
        speed_entries=Array(adjusted_speeds, speed_entries.unit),
        corrected_mass_flow_rate_entries=Array(
            adjusted_flow_rates, corrected_mass_flow_rate_entries.unit),
        pressure_ratio_table=pressure_ratio_table,
        isentropic_efficiency_table=isentropic_efficiency_table,
    )
def test_cv_table_description():
    expected_msg = "Opening and Flow Coefficient must have the same size, got 2 items for flow_coefficient and 1 for opening"
    with pytest.raises(ValueError, match=re.escape(expected_msg)):
        case_description.CvTableDescription(
            opening=Array([0.0], "-"),
            flow_coefficient=Array([0.0, 2], "(galUS/min)/(psi^0.5)"),
        )
Exemplo n.º 8
0
def build_constant_initial_tracers_mass_fractions_description(values, unit):
    return case_description.InitialTracersMassFractionsDescription(
        position_input_type=constants.TableInputType.length,
        table_length=case_description.TracersMassFractionsContainerDescription(
            positions=Array([0.0], "m"),
            tracers_mass_fractions=[Array(values, unit)]),
    )
Exemplo n.º 9
0
def testNumberOverArray() -> None:
    a = Array([2.0, 2.0], "m")
    b = Array([3.0, 3.0], "m")
    c = 1.0 / a

    assert approx(c.GetValues("1/m")) == [0.5, 0.5]
    assert approx((3.0 / a).GetValues("1/m")) == [1.5, 1.5]
    assert b / a == b * 1 / a == b * (1 / a)
Exemplo n.º 10
0
def testDivision(unit_database_len_time):
    unit_database = unit_database_len_time
    m = Quantity.CreateDerived(odict([("Table size", ["m", 1])]))
    km_city = Quantity.CreateDerived(odict([("City size", ["km", 1])]))
    quantity, value = unit_database.Divide(m, km_city, 1, 0.01)
    calculated1 = Array.CreateWithQuantity(quantity, [value])
    s1 = Array.CreateWithQuantity(m, [1])
    s2 = Array.CreateWithQuantity(km_city, [0.01])
    assert calculated1 == s1 / s2
Exemplo n.º 11
0
def test_build_compressor_pressure_table_description_invalid(
        pressure_ratios, isentropic_efficiencies, error_msg):
    with pytest.raises(AssertionError, match=error_msg):
        build_compressor_pressure_table_description(
            speed_entries=Array([0, 1000], "rpm"),
            corrected_mass_flow_rate_entries=Array([1, 2, 3], "kg/s"),
            pressure_ratio_table=Array(pressure_ratios, "-"),
            isentropic_efficiency_table=Array(isentropic_efficiencies, "-"),
        )
Exemplo n.º 12
0
def testDivision(unit_database_len_time) -> None:
    unit_database = unit_database_len_time
    m = Quantity.CreateDerived(OrderedDict([("Table size", ["m", 1])]))
    km_city = Quantity.CreateDerived(OrderedDict([("City size", ["km", 1])]))
    quantity, value = unit_database.Divide(m, km_city, 1, 0.01)
    calculated1: Array[List[float]] = Array.CreateWithQuantity(quantity, [value])
    s1: Array[List[float]] = Array.CreateWithQuantity(m, [1])
    s2: Array[List[float]] = Array.CreateWithQuantity(km_city, [0.01])
    assert calculated1 == s1 / s2
Exemplo n.º 13
0
def build_constant_initial_volume_fractions_description(values):
    return case_description.InitialVolumeFractionsDescription(
        position_input_type=constants.TableInputType.length,
        table_length=case_description.VolumeFractionsContainerDescription(
            positions=Array([0.0], "m"),
            fractions={k: Array([v.value], v.unit)
                       for k, v in values.items()},
        ),
    )
Exemplo n.º 14
0
def testNumpyConversion(unit_database_custom_conversion):
    unit_database = unit_database_custom_conversion

    from barril.units.posc import MakeBaseToCustomary, MakeCustomaryToBase

    f_unit_to_base = MakeCustomaryToBase(273.15, 1, 1, 0)
    f_base_to_unit = MakeBaseToCustomary(273.15, 1, 1, 0)
    unit_database.AddUnit(
        "My Temperature",
        "degrees Celsius",
        "degC",
        f_base_to_unit,
        f_unit_to_base,
        default_category=None,
    )
    f_unit_to_base = MakeCustomaryToBase(2298.35, 5, 9, 0)
    f_base_to_unit = MakeBaseToCustomary(2298.35, 5, 9, 0)
    unit_database.AddUnit(
        "My Temperature",
        "degree Fahrenheit",
        "degF",
        f_base_to_unit,
        f_unit_to_base,
        default_category=None,
    )
    f_unit_to_base = MakeCustomaryToBase(0, 1, 1, 0)
    f_base_to_unit = MakeBaseToCustomary(0, 1, 1, 0)
    unit_database.AddUnit(
        "My Temperature",
        "my Kelvin",
        "myK",
        f_base_to_unit,
        f_unit_to_base,
        default_category=None,
    )

    unit_database.AddCategory(
        "My Temperature",
        quantity_type="My Temperature",
        valid_units=["myK", "degC", "degF"],
        default_unit="myK",
        default_value=2,
        min_value=0,
        max_value=15,
        is_min_exclusive=False,
        is_max_exclusive=False,
        caption="My Temperature",
    )

    import numpy

    values = numpy.array(list(range(10, 13)), numpy.float32)
    arr = Array("My Temperature", values, "degC")
    obtained = arr.GetValues("degF")

    expected = [49.99995041, 51.79994965, 53.5999527]
    assert approx(obtained) == expected
Exemplo n.º 15
0
def testDefaultValues(unit_database_len):
    # Not raises exception because by default validation is False on the copy operation
    array = Array("flow rate")
    assert array.values == []

    array = Array(ObtainQuantity("m"))
    assert array.values == []

    with pytest.raises(AssertionError):
        Array(ObtainQuantity("m"), unit="m")
Exemplo n.º 16
0
def testDefaultValues(unit_database_len) -> None:
    # Not raises exception because by default validation is False on the copy operation
    array = Array[List[float]]("flow rate")
    assert array.values == []

    array = Array(ObtainQuantity("m"))
    assert array.values == []

    with pytest.raises(AssertionError):
        Array(ObtainQuantity("m"), unit="m")  # type:ignore[call-overload]
Exemplo n.º 17
0
def build_constant_initial_velocities_description(values):
    return case_description.InitialVelocitiesDescription(
        position_input_type=constants.TableInputType.length,
        table_length=case_description.VelocitiesContainerDescription(
            positions=Array([0.0], "m"),
            velocities={
                key: Array([v.value], v.unit)
                for key, v in values.items()
            },
        ),
    )
Exemplo n.º 18
0
def build_simple_segment():
    """
    Return an instance of PipeSegmentsDescription with a pre-populated value.

    The pre-filled value was the default value used by all tests before refactoring,
    which removed `diameter` and `absolute_roughness` from PipeDescription.
    """
    return case_description.PipeSegmentsDescription(
        start_positions=Array([0.0], "m"),
        diameters=Array([0.1], "m"),
        roughnesses=Array([1e-5], "m"),
    )
    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"))
Exemplo n.º 20
0
def test_to_array():
    type_error_msg = r"Expected pair \(values, unit\) or Array"

    assert to_array(None, is_optional=True) is None
    with pytest.raises(TypeError, match=type_error_msg):
        to_array(None)

    assert to_array(([1, 2, 3], "m")) == Array("length", [1, 2, 3], "m")
    with pytest.raises(TypeError, match=type_error_msg):
        to_array(("foo", [1, 2, 3], "m"))
    with pytest.raises(TypeError, match=type_error_msg):
        to_array("foo")

    array = Array("time", [0, 1.1, 2.2], "s")
    assert to_array(array) is array
Exemplo n.º 21
0
def to_array(value: ArrayLike,
             is_optional: bool = False,
             *,
             error_context: Optional[str] = None) -> Array:
    """
    Converter to be used with attr.ib, accepts tuples and Array as input.
    If `is_optional` is defined, the converter will also accept None, same as `to_scalar`.
    The `error_context` has the same behavior as in `to_scalar`.

    Ex.:
    @attr.s
    class Foo:
        bar = attr.id(converter=to_array)

    Foo(bar=Array([1,2,3],"m"))
    Foo(bar=([1,2,3],"m"))
    Foo(bar=((1,2,3),"m"))
    """
    if is_optional and value is None:
        return value
    if is_two_element_tuple(value):
        return Array(*value)
    elif isinstance(value, Array):
        return value

    message = prepare_error_message(
        f"Expected pair (values, unit) or Array, got {value!r} (type: {type(value)})",
        error_context,
    )
    raise TypeError(message)
Exemplo n.º 22
0
 def test_create_array_informing_category(self) -> None:
     array_molar_fraction = Array.FromScalars(
         scalars=[Scalar(1, "-"), Scalar(2, "-")], category="percentage"
     )
     assert array_molar_fraction.values == [1, 2]
     assert array_molar_fraction.unit == "-"
     assert array_molar_fraction.category == "percentage"
def test_compressor_pressure_table_description_length():
    expected_msg = dedent("""\
    speed_entries, corrected_mass_flow_rate_entries, pressure_ratio_table and isentropic_efficiency_table must have the same size, got:
        - 2 items for speed_entries
        - 2 items for corrected_mass_flow_rate_entries
        - 2 items for pressure_ratio_table
        - 1 items for isentropic_efficiency_table
    """)
    with pytest.raises(ValueError, match=re.escape(expected_msg)):
        case_description.CompressorPressureTableDescription(
            speed_entries=Array([1, 2], "rpm"),
            corrected_mass_flow_rate_entries=Array([1, 2], "kg/s"),
            pressure_ratio_table=Array([1, 2], "-"),
            isentropic_efficiency_table=Array([1], "-"),
        )

    # Check if the defaults values works well
    case_description.CompressorPressureTableDescription()
def test_table_pump_description_length():
    expected_msg = dedent("""\
    speeds, void_fractions, flow_rates and pressure_boosts must have the same size, got:
        - 2 items for speeds
        - 2 items for void_fractions
        - 2 items for flow_rates
        - 1 items for pressure_boosts
    """)
    with pytest.raises(ValueError, match=re.escape(expected_msg)):
        case_description.TablePumpDescription(
            speeds=Array([1, 2], "rpm"),
            void_fractions=Array([1, 2], "-"),
            flow_rates=Array([1, 2], "m3/s"),
            pressure_boosts=Array([1], "bar"),
        )

    # Check if the defaults values works well
    case_description.TablePumpDescription()
def test_get_value_and_unit_from_length_and_elevation_description_and_xand_ydescription(
):
    """
    Ensure that GetValueAndUnit returns a pair of values along with their units.
    """
    length_and_elevation = case_description.LengthAndElevationDescription(
        length=Array([0.0, 5.0, 7.0], "m"), elevation=Array([1.0] * 3, "m"))
    assert list(length_and_elevation.iter_values_and_unit()) == [
        ((0.0, "m"), (1.0, "m")),
        ((5.0, "m"), (1.0, "m")),
        ((7.0, "m"), (1.0, "m")),
    ]
    x_and_y = case_description.XAndYDescription(x=Array([1.0, 10.0, 100.0],
                                                        "m"),
                                                y=Array([42.0] * 3, "m"))
    assert list(x_and_y.iter_values_and_unit()) == [
        ((1.0, "m"), (42.0, "m")),
        ((10.0, "m"), (42.0, "m")),
        ((100.0, "m"), (42.0, "m")),
    ]
Exemplo n.º 26
0
def testNumberInteractions(unit_database_len_time):
    import numpy

    m = Quantity.CreateDerived(odict([("Table size", ["m", 1])]))
    s1 = Array.CreateWithQuantity(m, list(range(10)))
    s2 = Array.CreateWithQuantity(m, [x + x for x in range(10)])
    assert s1 == 0 + s1
    assert s1 == s1 + 0
    assert s2 == s1 + s1

    num_arr = Array.CreateWithQuantity(m, numpy.array([x for x in range(10)]))
    sum_array = num_arr + s1
    assert isinstance(sum_array.values, numpy.ndarray)

    sum_array2 = num_arr + numpy.array([x for x in range(10)])
    assert isinstance(sum_array2.values, numpy.ndarray)

    tup_arr = Array.CreateWithQuantity(m, tuple([x for x in range(10)]))
    tup_arr = tup_arr + 1
    assert isinstance(tup_arr.values, tuple)
Exemplo n.º 27
0
def build_linear_initial_temperatures_description(
    from_temperature,
    to_temperature,
    unit,
    final_position,
    position_unit,
    start_position=0.0,
):
    return case_description.InitialTemperaturesDescription(
        position_input_type=constants.TableInputType.length,
        table_length=case_description.TemperaturesContainerDescription(
            positions=Array(
                [
                    Scalar(start_position, position_unit).GetValue("m"),
                    Scalar(final_position, position_unit).GetValue("m"),
                ],
                "m",
            ),
            temperatures=Array([from_temperature, to_temperature], unit),
        ),
    )
Exemplo n.º 28
0
def test_to_curve():
    type_error_msg = r"Expected pair \(image_array, domain_array\) or Curve"

    assert to_curve(None, is_optional=True) is None
    with pytest.raises(TypeError, match=type_error_msg):
        to_curve(None)

    image = Array("length", [1, 2, 3], "m")
    domain = Array("time", [0, 1.1, 2.2], "s")
    curve = Curve(image, domain)
    assert to_curve((([1, 2, 3], "m"), domain)) == curve
    with pytest.raises(
        TypeError, match=r"Curve image: Expected pair \(values, unit\) or Array"
    ):
        to_curve((("foo", [1, 2, 3], "m"), domain))
    with pytest.raises(TypeError, match=type_error_msg):
        to_curve(("foo", [1, 2, 3], "m"))
    with pytest.raises(TypeError, match=type_error_msg):
        to_curve("foo")

    assert to_curve(curve) is curve
def test_check_profile_description(default_case):
    """
    Ensures that the ProfileDescription only accepts either XAndYDescription or a LengthAndElevationDescription

    Check 1: length_and_elevation and x_and_y are mutually exclusive
    """
    msg = (
        "length_and_elevation and x_and_y are mutually exclusive and you must configure only one of them, got "
        "length_and_elevation=LengthAndElevationDescription(length=Array(length, [0.0, 5.0, 7.0], m), elevation=Array(length, [1.0, 1.0, 1.0], m)) "
        "and x_and_y=XAndYDescription(x=Array(length, [1.0, 10.0, 100.0], m), y=Array(length, [42.0, 42.0, 42.0], m))"
    )
    with pytest.raises(ValueError, match=re.escape(msg)):
        case_description.ProfileDescription(
            length_and_elevation=case_description.
            LengthAndElevationDescription(length=Array([0.0, 5.0, 7.0], "m"),
                                          elevation=Array([1.0] * 3, "m")),
            x_and_y=case_description.XAndYDescription(
                x=Array([1.0, 10.0, 100.0], "m"), y=Array([42.0] * 3, "m")),
        )

    # Empty Profile is allowed.
    profile = case_description.ProfileDescription(length_and_elevation=None,
                                                  x_and_y=None)
    assert profile.length_and_elevation is None
    assert profile.x_and_y is None

    # Empty Array is allowed
    profile_2 = case_description.ProfileDescription(
        length_and_elevation=case_description.LengthAndElevationDescription(
            length=Array([], "m"), elevation=Array([], "m")),
        x_and_y=None,
    )
    assert profile_2.x_and_y is None
    assert profile_2.length_and_elevation.length.GetValues("m") == []
    assert profile_2.length_and_elevation.elevation.GetValues("m") == []
Exemplo n.º 30
0
def test_build_compressor_pressure_table_description_valid():
    description = build_compressor_pressure_table_description(
        speed_entries=Array([0, 1000], "rpm"),
        corrected_mass_flow_rate_entries=Array([1, 2, 3], "kg/s"),
        pressure_ratio_table=Array([1, 2, 3, 4, 5, 6], "-"),
        isentropic_efficiency_table=Array([0.4, 0.5, 0.6, 0.7, 0.8, 0.9], "-"),
    )
    assert description.speed_entries == Array([0, 0, 0, 1000, 1000, 1000],
                                              "rpm")
    assert description.corrected_mass_flow_rate_entries == Array(
        [1, 2, 3, 1, 2, 3], "kg/s")
    assert description.pressure_ratio_table == Array([1, 2, 3, 4, 5, 6], "-")
    assert description.isentropic_efficiency_table == Array(
        [0.4, 0.5, 0.6, 0.7, 0.8, 0.9], "-")