def test_conversion_factor_to(self): #conversion_factor_to should errror for units with different base #power, should error for units with incompativle offset w = PhysicalQuantity('1cm') x = PhysicalQuantity('1m') y = PhysicalQuantity('1degF') z1 = PhysicalQuantity('1degC') z2 = PhysicalQuantity('1degK') self.assertEqual(w.unit.conversion_factor_to(x.unit), 1/100.0) try: #incompatible units w.unit.conversion_factor_to(y.unit) except TypeError as err: self.assertEqual(str(err),"Incompatible units") else: self.fail("Expecting TypeError") #compatible offset units self.assertEqual(z1.unit.conversion_factor_to(z2.unit), 1.0) try: #incompatible offset units y.unit.conversion_factor_to(z2.unit) except TypeError as err: msg = "Unit conversion (degF to degK) cannot be expressed as a simple multiplicative factor" self.assertEqual(str(err), msg) else: self.fail("Expecting TypeError")
def test_pow(self): #power should error for offest units and for non-integer powers x = PhysicalQuantity('1m') y = PhysicalQuantity('1degF') z = x**3 self.assertEqual(z.unit, PhysicalQuantity('1m**3').unit) x = z**(1.0/3.0) #checks inverse integer units self.assertEqual(x.unit, PhysicalQuantity('1m').unit) #test offset units: try: y**17 except TypeError as err: self.assertEqual(str(err), 'cannot exponentiate units with non-zero offset') else: self.fail('Expecting TypeError') #test non-integer powers try: x**1.2 except TypeError as err: self.assertEqual(str(err), 'Only integer and inverse integer exponents allowed') else: self.fail('Expecting TypeError') try: x**(5.0/2.0) except TypeError as err: self.assertEqual(str(err), 'Only integer and inverse integer exponents allowed') else: self.fail('Expecting TypeError')
def test_neg_known_Values(self): #__neg__ should flip sign of value for physical quantity x = PhysicalQuantity('5V') self.assertEqual((-x).value, -5) x = PhysicalQuantity('-9.8m') self.assertEqual((-x).value, 9.8)
def test_sin_cos_tan_known_Values(self): #__sin__ should give known result with known input x = PhysicalQuantity('0 rad') x.sin() self.assertEqual(x.sin(), math.sin(x.value)) self.assertEqual(x.cos(), math.cos(x.value)) self.assertEqual(x.tan(), math.tan(x.value)) x = PhysicalQuantity('1m') try: x.sin() except TypeError as err: self.assertEqual(str(err),"Argument of sin must be an angle") else: self.fail("TypeError expected") try: x.cos() except TypeError as err: self.assertEqual(str(err),"Argument of cos must be an angle") else: self.fail("TypeError expected") try: x.tan() except TypeError as err: self.assertEqual(str(err),"Argument of tan must be an angle") else: self.fail("TypeError expected")
def test_pi(self): # Fixes issue 786 x = PhysicalQuantity('1rpm') x.convert_to_unit('rad/min') self.assertAlmostEqual(x.value, PhysicalQuantity('6.283185rad/min').value, places=3)
def test_pos_known_Values(self): #should retain sign for value of physical quantity x = PhysicalQuantity('5V') self.assertEqual((+x).value, 5) x = PhysicalQuantity('-9.8m') self.assertEqual((+x).value, -9.8)
def _needs_pseudo(self, parent, srcexpr, destexpr): """Return a non-None pseudo_type if srcexpr and destexpr require a pseudocomp to be created. """ srcrefs = list(srcexpr.refs()) if srcrefs and srcrefs[0] != srcexpr.text: # expression is more than just a simple variable reference, # so we need a pseudocomp return 'multi_var_expr' destmeta = destexpr.get_metadata('units') srcmeta = srcexpr.get_metadata('units') # compare using get_unit_name() to account for unit aliases if srcmeta: srcunit = srcmeta[0][1] if srcunit: srcunit = PhysicalQuantity(1., srcunit).unit else: srcunit = None if destmeta: destunit = destmeta[0][1] if destunit: destunit = PhysicalQuantity(1., destunit).unit else: destunit = None if destunit and srcunit: if destunit.powers != srcunit.powers or \ destunit.factor != srcunit.factor or \ destunit.offset != srcunit.offset: return 'units' return None
def test_division(self): #division should error when working with offset units w = PhysicalQuantity('2kg') x = PhysicalQuantity('1g') y = PhysicalQuantity('2s') z = PhysicalQuantity('1 degC') quo = w.unit/x.unit quo2 = x.unit/y.unit self.assertEqual(quo, PhysicalUnit({'kg': 1, 'g': -1}, 1000.0, _get_powers(),0)) self.assertEqual(quo2, PhysicalUnit({'s': -1, 'g': 1}, 0.001, _get_powers(mass=1, time=-1),0)) quo = y.unit/2.0 self.assertEqual(quo, PhysicalUnit({'s': 1, "2.0":-1}, .5, _get_powers(time=1), 0)) quo = 2.0/y.unit self.assertEqual(quo, PhysicalUnit({'s': -1,"2.0":1},2, _get_powers(time=-1),0)) try: x.unit / z.unit except TypeError as err: self.assertEqual(str(err),"cannot divide units with non-zero offset") else: self.fail("Expecting TypeError")
def test_abs_known_Values(self): #__abs__ should give known result with known input x = PhysicalQuantity('-5V') self.assertEqual(abs(x).unit, x.unit) self.assertEqual(abs(x).value, 5) x = PhysicalQuantity('5V') self.assertEqual(abs(x).unit, x.unit) self.assertEqual(abs(x).value, 5)
def test_prefix_plus_math(self): # From an issue: m**2 converts fine, but cm**2 does not. x1 = convert_units(1.0, 'm**2', 'cm**2') self.assertEqual(x1, 10000.0) # Let's make sure we can dclare some complicated units x = PhysicalQuantity('7200nm**3/kPa*dL') #from issue 825, make sure you can handle single characters before a / x = PhysicalQuantity('1 g/kW')
def test_name(self): #name should return a mathematically correct representation of the unit x1 = PhysicalQuantity('1m') x2 = PhysicalQuantity('1kg') y = 1/x1 self.assertEqual(y.unit.name(), '1/m') y = 1/x1/x1 self.assertEqual(y.unit.name(), '1/m**2') y = x1**2 self.assertEqual(y.unit.name(), 'm**2') y = x2/(x1**2) self.assertEqual(y.unit.name(), 'kg/m**2')
def test_lt(self): x = PhysicalQuantity('1 d') y = PhysicalQuantity('2 d') self.assertTrue(x < y) self.assertTrue(y > x) self.assertEqual(x, x) try: x < 2 except TypeError as err: self.assertEqual("Incompatible types", str(err)) else: self.fail('Expecting TypeError')
def test_div_known_Values(self): #__div__ should give known result with known input #the unit of the product should be the product of the units #scalar division x = PhysicalQuantity('1cm') y = 12.3 z = 1/12.3 self.assertAlmostEqual((x/y).value, PhysicalQuantity('%f cm'%z).value, 4) self.assertEqual((x/y).unit, PhysicalQuantity('%f cm'%z).unit) self.assertEqual(y/x, PhysicalQuantity('12.3cm**-1')) #unitless result x = PhysicalQuantity('1.0m') y = PhysicalQuantity('5m') quo = 1.0/5 # if quotient is unit-less (that is, x and y are additively compatible) # re-arranges x & y in terms of the known quotient and __rdiv__ and checks for consistency self.assertEqual((x/y), quo) self.assertEqual(x.__rdiv__(y), 1/quo) self.assertEqual(type(x/y), float) x = PhysicalQuantity('3cm') y = PhysicalQuantity('5s') quo = 3.0/5 # if quotient has a unit (x and y are additively incompatible) # re-arranges x & y in terms of the known quotient and __rdiv__ and checks for consistency self.assertEqual((x/y).value, quo) self.assertEqual(x.__rdiv__(y).value, 1/quo) self.assertEqual((x/y).unit, x.unit/y.unit) self.assertEqual(x.__rdiv__(y).unit, y.unit/x.unit) self.assertEqual(str(x/y), '0.6 cm/s')
def test_in_units_of(self): #in_units_of should return a new PhysicalQuantity with the requested #unit, leaving the old unit as it was x = PhysicalQuantity('5cm') y = x.in_units_of('m') self.assertEqual(y, PhysicalQuantity('0.05m')) self.assertEqual(x, PhysicalQuantity('5cm')) x = PhysicalQuantity('5cm') try: y = x.in_units_of('degC') except TypeError as err: self.assertEqual(str(err), 'Incompatible units') else: self.fail("TypeError expected")
def _validate_with_metadata(self, obj, name, value, src_units): """Perform validation and unit conversion using metadata from the source trait. """ # pylint: disable=E1101 dst_units = self.units if isinstance(value, UncertainDistribution): value = value.getvalue() # FIXME: The try blocks testing whether the unit is bogus or undefined # are generally redundant because that test is done at creation. HOWEVER # you might have a case where it wasn't tested because it's technically # not a float. NPSS wrapper may be such a case. A test needs to be # constructed to test these lines. try: pq = PhysicalQuantity(value, src_units) except NameError: raise NameError("while setting value of %s: undefined unit '%s'" % (src_units, name)) try: pq.convert_to_unit(dst_units) except NameError: raise NameError("undefined unit '%s' for variable '%s'" % (dst_units, name)) except TypeError: msg = "%s: units '%s' are incompatible " % (name, src_units) + \ "with assigning units of '%s'" % (dst_units) raise TypeError(msg) return pq.value
def _validate_with_metadata(self, obj, name, value, src_units): """Perform validation and unit conversion using metadata from the source trait. """ # pylint: disable=E1101 dst_units = self.units try: pq = PhysicalQuantity(1.0, src_units) except NameError: raise NameError("while setting value of %s: undefined unit '%s'" % (src_units, name)) try: pq.convert_to_unit(dst_units) except NameError: raise NameError("undefined unit '%s' for variable '%s'" % (dst_units, name)) except TypeError: msg = "%s: units '%s' are incompatible " % (name, src_units) + \ "with assigning units of '%s'" % (dst_units) raise TypeError(msg) value *= pq.value return value
def create_cube(shape, width, height, depth): """ Creates a cube-shaped single-zone structured domain. """ imax, jmax, kmax = shape delta_x = float(width) / (imax - 1) delta_y = float(height) / (jmax - 1) delta_z = float(depth) / (kmax - 1) dtype = numpy.float32 # Default single-precision. x = numpy.zeros(shape, dtype=dtype) y = numpy.zeros(shape, dtype=dtype) z = numpy.zeros(shape, dtype=dtype) q1 = numpy.zeros(shape, dtype=dtype) q2 = numpy.zeros(shape, dtype=dtype) q3 = numpy.zeros(shape, dtype=dtype) q4 = numpy.zeros(shape, dtype=dtype) q5 = numpy.zeros(shape, dtype=dtype) for i in range(imax): for j in range(jmax): for k in range(kmax): x.itemset(i, j, k, delta_x * i) y.itemset(i, j, k, delta_y * j) z.itemset(i, j, k, delta_z * k) q1.itemset(i, j, k, delta_x * i) q2.itemset(i, j, k, delta_x * i) q3.itemset(i, j, k, delta_y * j) q4.itemset(i, j, k, delta_z * k) q5.itemset(i, j, k, delta_z * k) momentum = Vector() momentum.x = q2 momentum.y = q3 momentum.z = q4 zone = Zone() zone.grid_coordinates.x = x zone.grid_coordinates.y = y zone.grid_coordinates.z = z zone.flow_solution.mach = 0.5 zone.flow_solution.alpha = 0. zone.flow_solution.reynolds = 100000. zone.flow_solution.time = 42. zone.flow_solution.add_array('density', q1) zone.flow_solution.add_vector('momentum', momentum) zone.flow_solution.add_array('energy_stagnation_density', q5) domain = DomainObj() domain.reference_state = dict(length_reference=PhysicalQuantity(1., 'ft')) domain.add_zone('xyzzy', zone) return domain
def test__is_compatible__known__Values(self): #is_compatible should return True for compatible units and False for #incompatible ones testvals=(('5m', 'cm',True), ('1s', 'ms',True), ('1m', 'ms',False)) for q1, q2, bool in testvals: x = PhysicalQuantity(q1) self.assertEqual(x.is_compatible(q2), bool)
def test_pow_known_Values(self): #__pow__ should give known result with known input #the unit of the power should be the power of the input units #test integer exponent x = PhysicalQuantity('5V') self.assertEqual((x**2).value,5**2) self.assertEqual((x**2).unit,x.unit**2) #test for inverse integer exponent x = PhysicalQuantity('1m**2') y = PhysicalQuantity('1m') self.assertEqual(x**(1.0/2.0), y) self.assertEqual(x/y, y) #test for error from non integer exponent try: x**2.5 except TypeError as err: self.assertEqual(str(err),"Only integer and inverse integer exponents allowed") else: self.fail("Expecting TypeError") #test for error on offset units x = PhysicalQuantity('1degC') try: x**2 except TypeError as err: self.assertEqual(str(err), 'cannot exponentiate units with non-zero offset') else: self.fail("expected TypeError") #test for error if exponent is a PhysicalQuantity try: x**x except TypeError as err: self.assertEqual(str(err), 'Exponents must be dimensionless') else: self.fail("expected TypeError") try: #__rpow__ 2**x except TypeError as err: self.assertEqual(str(err), 'Exponents must be dimensionless') else: self.fail("expected TypeError")
def test_repr_str(self): #__repr__should return a string which could be used to contruct the #unit instance, __str__ should return a string with just the unit #name for str u = PhysicalQuantity('1 d') self.assertEqual(repr(u.unit), "PhysicalUnit({'d': 1},86400.0,%s,0.0)" % _get_powers(time=1)) self.assertEqual(str(u.unit), "<PhysicalUnit d>")
def test_new_units(self): # Hour added to test problem in Classic OpenMDAO Ticket 466 # knot, rev, month added to test problem in Issue 804 x = PhysicalQuantity('7200s') x.convert_to_unit('h') self.assertEqual(x, PhysicalQuantity('2h')) x = PhysicalQuantity('5knot') x.convert_to_unit('nm/h') self.assertEqual(x, PhysicalQuantity('5nmi/h')) x = PhysicalQuantity('33rev/min') x.convert_to_unit('rpm') self.assertEqual(x, PhysicalQuantity('33rpm')) x = PhysicalQuantity('12mo') x.convert_to_unit('yr') self.assertEqual(x, PhysicalQuantity('1yr')) x = PhysicalQuantity('1Mibyte') x.convert_to_unit('Kibyte') self.assertEqual(x, PhysicalQuantity('1024Kibyte'))
def test_convert_to_unit(self): #convert_to_unit should change the unit of the calling instance to the requested new unit x = PhysicalQuantity('5cm') x.convert_to_unit('m') self.assertEqual(x, PhysicalQuantity('0.05m')) #Test for no compatible units x = PhysicalQuantity('5cm') try: x.convert_to_unit('kg') except TypeError as err: self.assertEqual(str(err), 'Incompatible units') else: self.fail("TypeError expected") x = PhysicalQuantity('1.0psi') x.convert_to_unit('psf') self.assertEqual(x, PhysicalQuantity('144.0psf'))
def test_cmp(self): #should error for incompatible units, if they are compatible then it #should cmp on their factors x = PhysicalQuantity('1 d') y = PhysicalQuantity('1 s') z = PhysicalQuantity('1 ft') self.assertTrue(x > y) self.assertEqual(x, x) self.assertTrue(y < x) try: x < z except TypeError as err: self.assertEqual(str(err),"Incompatible units") else: self.fail("Expecting TypeError")
def test_multiply(self): #multiplication should error for units with offsets x = PhysicalQuantity('1g') y = PhysicalQuantity('2s') z = PhysicalQuantity('1 degC') self.assertEqual(x.unit*y.unit, PhysicalUnit({'s': 1, 'kg': 1}, .001, _get_powers(mass=1,time=1), 0)) self.assertEqual(y.unit*x.unit, PhysicalUnit({'s': 1, 'kg': 1}, .001, _get_powers(mass=1,time=1), 0)) try: x.unit * z.unit except TypeError as err: self.assertEqual(str(err),"cannot multiply units with non-zero offset") else: self.fail("Expecting TypeError")
def create_wedge_2d(shape, inner, outer, angle): """ Creates a 2D wedge-shaped single-zone structured domain. """ imax, jmax = shape delta_radius = float(outer - inner) / (imax - 1) if imax > 1 else 1. delta_theta = float(angle * _DEG2RAD) / (jmax - 1) if jmax > 1 else 1. dtype = numpy.float32 # Default single-precision. x = numpy.zeros(shape, dtype=dtype) y = numpy.zeros(shape, dtype=dtype) q1 = numpy.zeros(shape, dtype=dtype) q2 = numpy.zeros(shape, dtype=dtype) q3 = numpy.zeros(shape, dtype=dtype) q4 = numpy.zeros(shape, dtype=dtype) for i in range(imax): radial = inner + delta_radius * i for j in range(jmax): tangential = delta_theta * j x.itemset(i, j, radial * cos(tangential)) y.itemset(i, j, radial * sin(tangential)) q1.itemset(i, j, radial) q2.itemset(i, j, radial) q3.itemset(i, j, tangential) q4.itemset(i, j, tangential) momentum = Vector() momentum.x = q2 momentum.y = q3 zone = Zone() zone.grid_coordinates.x = x zone.grid_coordinates.y = y zone.flow_solution.mach = 0.5 zone.flow_solution.alpha = 0. zone.flow_solution.reynolds = 100000. zone.flow_solution.time = 42. zone.flow_solution.add_array('density', q1) zone.flow_solution.add_vector('momentum', momentum) zone.flow_solution.add_array('energy_stagnation_density', q4) domain = DomainObj() domain.reference_state = dict(length_reference=PhysicalQuantity(1., 'ft')) domain.add_zone('xyzzy', zone) return domain
def __init__(self, default_value=None, dtype = None, shape = None, iotype=None, desc=None, units=None, **metadata): # Determine default_value if unspecified if default_value is None: if shape is None or len(shape) == 1: default_value = array([]) elif len(shape) == 2: default_value = array([[]]) elif len(shape) == 3: default_value = array([[[]]]) elif isinstance(default_value, ndarray): pass elif isinstance(default_value, list): default_value = array(default_value) else: raise TypeError("Default value should be an array-like object, " "not a %s." % type(default_value)) # Put iotype in the metadata dictionary if iotype is not None: metadata['iotype'] = iotype # Put desc in the metadata dictionary if desc is not None: metadata['desc'] = desc # Put units in the metadata dictionary if units is not None: metadata['units'] = units # Since there are units, test them by creating a physical quantity try: pq = PhysicalQuantity(0., metadata['units']) except: raise ValueError("Units of '%s' are invalid" % metadata['units']) # Put shape in the metadata dictionary if shape is not None: metadata['shape'] = shape # Make sure default matches the shape. if len(shape) != len(default_value.shape): raise ValueError("Shape of the default value does not match " "the shape attribute.") for i, sh in enumerate(shape): if sh is not None and sh != default_value.shape[i]: raise ValueError("Shape of the default value does not " "match the shape attribute.") super(Array, self).__init__(dtype=dtype, value=default_value, **metadata)
def test_init(self): #__init__ should have the same result regardless of the #constructor calling pattern x = PhysicalQuantity('1m') y = PhysicalQuantity(1, 'm') self.assertEqual(x.value, y.value) self.assertEqual(x.unit, y.unit) z = PhysicalQuantity('1dam') #check for two letter prefixes #error for improper init argument try: x = PhysicalQuantity('m') except TypeError as err: self.assertEqual(str(err), "No number found in input argument: 'm'") else: self.fail("Expecting TypeError") try: x = PhysicalQuantity('1in') except ValueError as err: self.assertEqual(str(err), "no unit named 'in' is defined") else: self.fail("Expecting ValueError") try: x = PhysicalQuantity(1, None) except TypeError as err: self.assertEqual(str(err), "None is not a unit") else: self.fail("Expecting TypeError")
def test_in_base_units(self): #in_base_units() should return a new PhysicalQuantity instance #using the base units, leaving the original instance intact x = PhysicalQuantity(1, '1/h') y = x.in_base_units() self.assertEqual(y, PhysicalQuantity(1/3600.0, '1/s')) self.assertEqual(x, PhysicalQuantity(1, '1/h')) x = PhysicalQuantity(1, 'ft**-3') y = x.in_base_units() self.assertEqual(y, PhysicalQuantity(35.314666721488585, '1/m**3')) x = PhysicalQuantity(1, 'ft**3') y = x.in_base_units() self.assertEqual(y, PhysicalQuantity(0.028316846592000004, 'm**3')) x = PhysicalQuantity('5cm') y = x.in_base_units() self.assertEqual(y, PhysicalQuantity('0.05m')) self.assertEqual(x, PhysicalQuantity('5cm'))
def create_curve_2d(npoints, radius, angle): """ Creates a curve (arc) of `npoints` at `radius` through `angle`. """ delta_theta = float(angle * _DEG2RAD) / (npoints - 1) dtype = numpy.float32 # Default single-precision. shape = (npoints, ) x = numpy.zeros(shape, dtype=dtype) y = numpy.zeros(shape, dtype=dtype) q1 = numpy.zeros(shape, dtype=dtype) q2 = numpy.zeros(shape, dtype=dtype) q3 = numpy.zeros(shape, dtype=dtype) q4 = numpy.zeros(shape, dtype=dtype) for i in range(npoints): tangential = delta_theta * i x.itemset(i, radius * cos(tangential)) y.itemset(i, radius * sin(tangential)) q1.itemset(i, radius) q2.itemset(i, radius) q3.itemset(i, tangential) q4.itemset(i, tangential) momentum = Vector() momentum.x = q2 momentum.y = q3 zone = Zone() zone.grid_coordinates.x = x zone.grid_coordinates.y = y zone.flow_solution.mach = 0.5 zone.flow_solution.alpha = 0. zone.flow_solution.reynolds = 100000. zone.flow_solution.time = 42. zone.flow_solution.add_array('density', q1) zone.flow_solution.add_vector('momentum', momentum) zone.flow_solution.add_array('energy_stagnation_density', q4) domain = DomainObj() domain.reference_state = dict(length_reference=PhysicalQuantity(1., 'ft')) domain.add_zone('xyzzy', zone) return domain
def test_conversion_tuple_to(self): #test_conversion_tuple_to shoudl error when units have different power lists w = PhysicalQuantity('1cm') x = PhysicalQuantity('1m') y = PhysicalQuantity('1degF') z1 = PhysicalQuantity('1degC') z2 = PhysicalQuantity('1degK') #check for non offset units self.assertEqual(w.unit.conversion_tuple_to(x.unit), (1/100.0,0)) #check for offset units result = y.unit.conversion_tuple_to(z1.unit) self.assertAlmostEqual(result[0], 0.556,3) self.assertAlmostEqual(result[1], -32.0,3) #check for incompatible units try: x.unit.conversion_tuple_to(z1.unit) except TypeError as err: self.assertEqual(str(err), "Incompatible units") else: self.fail("Expecting TypeError")