def test_scalar_attribute(): @attr.s(kw_only=True) class Foo: position = attrib_scalar(default=Scalar(1, "m")) position_2 = attrib_scalar(default=None) # Check position instance_with_scalar = Foo(position=Scalar(1, "m")) assert isinstance(instance_with_scalar.position, Scalar) instance_with_tuple = Foo(position=(1, "m")) assert isinstance(instance_with_tuple.position, Scalar) expected_msg = ( "Expected pair (value, unit) or Scalar, got None (type: <class 'NoneType'>)" ) with pytest.raises(TypeError, match=re.escape(expected_msg)): Foo(position=None) # Check position_1 (accepts None) instance_with_scalar = Foo(position_2=Scalar(1, "m")) assert isinstance(instance_with_scalar.position, Scalar) instance_with_tuple = Foo(position_2=(1, "m")) assert isinstance(instance_with_tuple.position, Scalar) assert Foo(position_2=None).position_2 is None
def testHertzPerSecond(): from barril.units import Scalar assert approx(Scalar(1, "rpm").GetValue("Hz")) == 1 / 60.0 assert approx(Scalar(1, "Hz").GetValue("rpm")) == 60.0 assert approx(Scalar(1, "Hz/s").GetValue("rpm/s")) == 60.0 assert approx(Scalar(1, "rpm/s").GetValue("Hz/s")) == 1 / 60.0
def testFormatFloat(): """ Convert unit of scalar where value is "0.0". """ assert FormatFloat("%g", 0.0) == "0" assert FormatFloat("%g", -0.0) == "0" scalar = Scalar("length", 0.0, "m") assert FormatFloat("%g", scalar.GetValue()) == "0" assert locale.format_string("%g", scalar.GetValue("ft")) == "-0" assert FormatFloat("%g", scalar.GetValue("ft")) == "0" # Large float numbers on integer format. large_float_number = 1e010 * 1.0 assert FormatFloat("%d", large_float_number) == "10000000000" # Infinity assert FormatFloat("%.3g", PLUS_INFINITY) == "+INF" assert FormatFloat("%.3g", MINUS_INFINITY) == "-INF" assert FormatFloat("%.3g", NAN) == "-1.#IND" # Digit grouping assert FormatFloat("%.2f", 1234567, False) == "1234567.00" assert FormatFloat("%.2f", 1234567, True) == "1234567.00"
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 testFixedArrayIndexAsScalar() -> None: from barril.units import Scalar fixed_array = units.FixedArray(3, "length of path", [1, 2, 3], "m") assert fixed_array.IndexAsScalar(0).GetCategory() == "length of path" assert fixed_array.IndexAsScalar(0) == Scalar("length of path", 1, "m") assert fixed_array.IndexAsScalar(1) == Scalar("length of path", 2, "m")
def test_get_scalar_loader(): alfacase_content = YAML( value={"foo": { "value": YAML(value=1), "unit": YAML(value="m") }}) description_document = DescriptionDocument(content=alfacase_content, file_path=Path()) # Loading Scalar passing ``category`` scalar_loader = get_scalar_loader(category="length") assert scalar_loader(key="foo", alfacase_content=description_document) == Scalar( 1.0, "m", "length") # Load Scalar passing ``from_unit`` scalar_loader = get_scalar_loader(from_unit="m") assert scalar_loader(key="foo", alfacase_content=description_document) == Scalar( 1.0, "m", "length") # Passing None expected_msg = "Either 'category' or 'from_unit' parameter must be defined" with pytest.raises(ValueError, match=expected_msg): get_scalar_loader() # Informing both parameter expected_msg = "Both parameters 'category' and 'from_unit' were provided, only one must be informed" with pytest.raises(ValueError, match=expected_msg): get_scalar_loader(category="length", from_unit="m")
def testScalarCreationModes(): base = Scalar(10, "m") assert Scalar("length", 10, "m") == base assert Scalar((10.0, "m")) == base with pytest.raises(AssertionError): Scalar("length", 1.0) # missing unit
def testGetValueInvalidUnitError() -> None: from barril.units.unit_database import InvalidUnitError with raises( InvalidUnitError, match="Invalid unit for quantity_type volume flow rate: 1000ft3/foo" ): q = Scalar(1.0, "1000ft3/d") q.GetValue("1000ft3/foo")
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 = Scalar.CreateWithQuantity(quantity, value) s1 = Scalar.CreateWithQuantity(m, 1) s2 = Scalar.CreateWithQuantity(km_city, 0.01) assert calculated1 == s1 / s2
def testScalarPickle(unit_database_posc): import pickle simple_scalar = Scalar("length", 10, "m") simple_scalar2 = pickle.loads(pickle.dumps(simple_scalar)) assert simple_scalar == simple_scalar2 complex_scalar = Scalar("length", 10, "m") * Scalar("time", 5, "s") complex_scalar2 = pickle.loads(pickle.dumps(complex_scalar)) assert complex_scalar == complex_scalar2
def testCopyPropertiesAndValidation(unit_database_well_length): category = "well-length-with-min-and-max" # the minimum value is zero unit = "m" value = -1 # Not raises exception because validation is False on the copy operation scalar_source = Scalar(category, value, unit) assert not scalar_source.IsValid() # Raises exception because validation is True and the value -1 is invalid accordingly to # the category 'well-length-with-min-and-max' another = scalar_source.CreateCopy() assert not another.IsValid()
def testCreationWithDerivedQuantity(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.Multiply(m, km_city, 1, 0.01) calculated1 = Scalar.CreateWithQuantity(quantity, value) assert six.text_type(calculated1) s1 = Scalar.CreateWithQuantity(m, 1) s2 = Scalar.CreateWithQuantity(km_city, 0.01) assert calculated1 == s1 * s2
def testScalarValidUnits(unit_database_empty): db = unit_database_empty db.AddUnit("length", "milimeters", "mm", "%f * 1000.0", "%f / 1000.0") db.AddUnitBase("length", "meters", "m") db.AddUnit("length", "centimeters", "cm", "%f * 100.0", "%f / 100.0") db.AddUnit("length", "kilometers", "km", "%f / 1000.0", "%f * 1000.0") db.AddCategory("len1", "length", valid_units=["mm", "cm"]) db.AddCategory("len2", "length", valid_units=["m", "km"]) s1 = Scalar("len1", 1, "mm") assert s1 is not None s2 = Scalar("len2", 1, "mm") assert s2 is not None
def testCopyProperties(unit_database_well_length): """ Test if the mehod SetValue is not called when copying the Scalar's properties. """ category = "well-length" unit = "m" value = 10.0 scalar_source = Scalar(category, value, unit) scalar_dest = scalar_source.CreateCopyInstance() assert scalar_dest.GetCategory() == category assert scalar_dest.GetUnit() == unit assert scalar_dest.GetValue() == value
def testSort(unit_database_empty): db = unit_database_empty db.AddUnitBase("length", "meters", "m") db.AddUnit("length", "centimeters", "cm", "x * 100.0", "x / 100.0") db.AddCategory("length", "length") s1 = Scalar("length", 10.0, "cm") s2 = Scalar("length", 1.0, "m") s3 = Scalar("length", 500.0, "cm") s4 = Scalar("length", 10.0, "m") x = [s2, s1, s4, s3] x.sort() assert x == [s1, s2, s3, s4]
def test_pipeline_info(): pipeline_segment_info = PipelineSegmentInfo( inner_diameter=Scalar("diameter", 0.15, "m"), start_position=Scalar(0.0, "m"), is_custom=True, roughness=Scalar(0.0, "m"), ) pipeline_info = PipelineInfo( name="Foo", edge_name="Foo 2", segments=[pipeline_segment_info], total_length=Scalar(0.0, "m"), ) assert pipeline_info
def to_scalar(value: Union[Tuple[Number, str], Scalar], is_optional: bool = False) -> Scalar: """ Converter to be used with attr.ib, accepts tuples and Scalar as input If `is_optional` is defined, the converter will also accept None. Ex.: @attr.s class TrendOutputDescription: pos = attrib_scalar() temperature = attrib_scalar(converter=partial(ToScalar, is_optional=True)) TrendOutputDescription(position=Scalar(1,"m") TrendOutputDescription(position=(1,"m") TrendOutputDescription(temperature=None) """ if is_optional and value is None: return value if isinstance(value, tuple) and (len(value) == 2): return Scalar(value) elif isinstance(value, Scalar): return value raise TypeError( f"Expected pair (value, unit) or Scalar, got {value!r} (type: {type(value)})" )
def to_scalar(value: ScalarLike, is_optional: bool = False, *, error_context: Optional[str] = None) -> Scalar: """ Converter to be used with attr.ib, accepts tuples and Scalar as input, is used by `attrib_scalar`. If `is_optional` is defined, the converter will also accept None. If `error_context` is not `None` it is prepended to the type error message when `value` type is not respected. Ex.: @attr.s class PositionalOutputDescription: pos = attrib_scalar() temperature = attrib_scalar(is_optional=True)) PositionalOutputDescription(position=Scalar(1,"m")) PositionalOutputDescription(position=(1,"m")) PositionalOutputDescription(temperature=None) """ if is_optional and value is None: return value if is_two_element_tuple(value): return Scalar(value) elif isinstance(value, Scalar): return value message = prepare_error_message( f"Expected pair (value, unit) or Scalar, got {value!r} (type: {type(value)})", error_context, ) raise TypeError(message)
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 ), )
def _ScalarCheckMsgPredicate(cls, scalar: Scalar) -> Optional[str]: """ :param Scalar scalar: The scalar to be checked against its limits :returns str: The built message saying if the scalar is less or greater than its limits """ try: quantity = ObtainQuantity(scalar.GetUnit(), scalar.GetCategory()) quantity.CheckValue(scalar.GetValue(), use_literals=True) except ValueError as error: return str(error) return None
def testConversionToFullScalar() -> None: y = _LightweightScalar(value=1.0, unit="kg/m3", category="density") x = Scalar(value=y.GetValue(), unit=y.GetUnit(), category=y.GetCategory()) assert x.GetValue() == 1.0 assert x.GetUnit() == "kg/m3" assert x.GetCategory() == "density" assert x.GetQuantityType() == "density" assert x.GetQuantity().GetUnit() == "kg/m3" assert x.GetQuantity().GetCategory() == "density" assert x.GetQuantity().GetQuantityType() == "density" # Full Scalar supports conversion assert x.GetValue(unit="g/cm3") == 0.001
def test_remove_redundant_input_type_data_option( remove: bool, input_type: MultiInputType) -> None: mass_source_equipment_description = case_description.MassSourceEquipmentDescription( position=Scalar(0, "m"), temperature_input_type=input_type) yaml = convert_description_to_alfacase( mass_source_equipment_description, remove_redundant_input_type_data=remove) def has_key_in_yaml(key: str) -> bool: pattern = rf"^\s*{re.escape(key)}\s*:" return bool(re.search(pattern, yaml, re.MULTILINE)) if remove: assert not has_key_in_yaml("temperature_input_type") if input_type == MultiInputType.Constant: assert has_key_in_yaml("temperature") assert not has_key_in_yaml("temperature_curve") elif input_type == MultiInputType.Curve: assert not has_key_in_yaml("temperature") assert has_key_in_yaml("temperature_curve") else: assert has_key_in_yaml("temperature_input_type") assert has_key_in_yaml("temperature") assert has_key_in_yaml("temperature_curve")
def ConvertScalarToCurrent( self, scalar: "Scalar", unit_database: Optional[UnitDatabase] = None) -> "Scalar": """ Same as ConvertToCurrent but receives and returns a scalar instead of category, unit and value :param Scalar scalar: The scalar to be converted :param UnitDatabase unit_database: The unit database to perform the conversion. If not given, use the singleton. :rtype: Scalar :returns: A Scalar containing the converted value and target unit. Note that if there is no current unit system, the returned value and unit are the same as the input. """ from barril.units import Scalar ret_tuple = self.ConvertToCurrent(scalar.GetCategory(), scalar.GetUnit(), scalar.GetValue(), unit_database) return Scalar(*ret_tuple)
def testNumberInteractions(unit_database_len_time): scalar = Scalar("Table size", 1, "m") scalar2 = Scalar.CreateWithQuantity(Quantity.CreateDerived(odict()), 0) assert scalar == scalar + scalar2 assert scalar == scalar + 0 assert scalar == 0 + scalar assert 9 == (10 - scalar).value assert -9 == (scalar - 10).value assert 10 == (10 * scalar).value assert 10 == (scalar * 10).value assert 10 == (10.0 / scalar).value assert 1 / 10.0 == (scalar / 10.0).value
def testScalarCopyAndRepresentation(unit_database_empty): unit_database = unit_database_empty unit_database.AddUnitBase("length", "meters", "m") unit_database.AddUnit("length", "milimeters", "mm", "x * 1000.0", "x / 1000.0") unit_database.AddUnit("length", "centimeters", "cm", "x * 100.0", "x / 100.0") unit_database.AddCategory("well-diameter", "length") s = Scalar("well-diameter", 10, "m") assert "Scalar(10.0, 'm', 'well-diameter')" == repr(s) assert "10.0" == six.text_type(s.value) assert "m" == s.unit assert "well-diameter" == s.GetCategory() assert "length" == s.GetQuantityType() s = s.CreateCopy(unit="cm") assert "Scalar(1000.0, 'cm', 'well-diameter')" == repr(s) assert "1000 [cm]" == six.text_type(s)
def testInvalidUnit(unit_database_empty): unit_database = unit_database_empty unit_database.AddUnitBase("length", "meters", "m") unit_database.AddUnit("length", "milimeters", "mm", "x * 1000.0", "x / 1000.0") unit_database.AddUnit("length", "centimeters", "cm", "x * 100.0", "x / 100.0") unit_database.AddCategory("well-diameter", "length") with pytest.raises(InvalidUnitError): Scalar("well-diameter", 10, "days")
def testEmptyScalar(): """ ScalarMultiData exception when some of its scalars don't have a quantity_type """ # An empty scalar doesn't have a category defined scalar_1 = Scalar.CreateEmptyScalar(20.0) # When try to retrieve scalar value or unit a exception was being raised assert scalar_1.GetValue("m") == 20. assert scalar_1.GetUnit() == ""
def testEmptyScalar(): scalar = Scalar.CreateEmptyScalar() assert not scalar.HasCategory() assert scalar == scalar.Copy() scalar = scalar.CreateCopy(category="pressure", unit="psi") assert scalar.HasCategory() assert scalar.GetValue() == 0.0 assert scalar == scalar.Copy()
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 testScalarValidationMsgs(unit_database) -> None: def _Check(scalar, value, unit, expected_msg): some_scalar = scalar.CreateCopy(value=value, unit=unit) obtained_msg = ScalarMinMaxValidator.CreateScalarCheckErrorMsg( some_scalar, "Some Property") assert obtained_msg == expected_msg _CreateTestCategories(unit_database) some_scalar = Scalar("test category", 10.0, "-") # Test value below minimum ----------------------------------------------------------------- expected_error_msg = "Error in Some Property. Invalid value for Test Category: 0. Must be greater or equal to 1.0." _Check(some_scalar, 0.0, "-", expected_error_msg) # Test value above maximum ----------------------------------------------------------------- expected_error_msg = "Error in Some Property. Invalid value for Test Category: 51. Must be less or equal to 50.0." _Check(some_scalar, 51.0, "-", expected_error_msg) # Test no error without exclusive ---------------------------------------------------------- _Check(some_scalar, 1.0, "-", None) _Check(some_scalar, 50.0, "-", None) # Test using min and max exclusive --------------------------------------------------------- some_scalar = Scalar("category exclusive", 10.0, "-") # Test value below minimum ----------------------------------------------------------------- expected_error_msg = ( "Error in Some Property. Invalid value for Category Exclusive: 1. Must be greater than 1.0." ) _Check(some_scalar, 1.0, "-", expected_error_msg) # Test value above maximum ----------------------------------------------------------------- expected_error_msg = ( "Error in Some Property. Invalid value for Category Exclusive: 50. Must be less than 50.0." ) _Check(some_scalar, 50.0, "-", expected_error_msg) # Test no error with exclusive ------------------------------------------------------------- _Check(some_scalar, 49.0, "-", None) _Check(some_scalar, 2.0, "-", None)