Skip to content

Commit

Permalink
add Angle dimension
Browse files Browse the repository at this point in the history
  • Loading branch information
gertjanvanzwieten committed Sep 30, 2022
1 parent 28a0bef commit a38f302
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
11 changes: 11 additions & 0 deletions nutils/SI.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@ def _dispatch(op, *args, **kwargs):
args = [q.__value for q in stack_args],
elif name in ('shape', 'ndim', 'size', 'sign'):
Dim = Dimension.from_powers({})
elif name in ('sin', 'cos', 'tan'):
if not isinstance(args[0], Angle):
raise TypeError(f'trigonometric functions require angle [Φ], got {type(args[0]).__name__}')
Dim = Dimension.from_powers({})
elif name == 'arctan2':
if type(args[0]) != type(args[1]):
raise TypeError(f'arguments of arctan2 must have equal dimension, got {type(args[0]).__name__} and {type(args[1]).__name__}')
Dim = Angle
else:
return NotImplemented
assert isinstance(Dim, Dimension)
Expand Down Expand Up @@ -312,6 +320,7 @@ def _split_factors(s):
Temperature = Dimension.create('θ')
AmountOfSubstance = Dimension.create('N')
LuminousFlux = LuminousIntensity = Dimension.create('J')
Angle = Dimension.create('A')

Area = Length**2
Volume = Length**3
Expand Down Expand Up @@ -355,6 +364,7 @@ def _split_factors(s):
units.K = Temperature(1.)
units.mol = AmountOfSubstance(1.)
units.cd = LuminousIntensity(1.)
units.rad = Angle(1.)

units.N = 'kg*m/s2' # newton
units.Pa = 'N/m2' # pascal
Expand Down Expand Up @@ -385,3 +395,4 @@ def _split_factors(s):
units.t = '1000kg' # ton
units.Da = '1.66053904020yg' # dalton
units.eV = '.1602176634aJ' # electronvolt
units.deg = '0.017453292519943295rad' # degree
15 changes: 15 additions & 0 deletions tests/test_SI.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,18 @@ def test_type_error(self):
for F in SI.Force('2N'), numpy.array([1,2,3]) * SI.Force('N'):
with self.assertRaisesRegex(TypeError, r"unsupported operand type\(s\) for /: '\[M\*L/T2\]' and 'object'"):
F / object()

def test_angle(self):
φ = SI.Angle('30deg')
self.assertTrue(numpy.isclose(numpy.sin(φ), .5))
self.assertTrue(numpy.isclose(numpy.cos(φ), numpy.sqrt(3)/2))
self.assertTrue(numpy.isclose(numpy.tan(φ), 1/numpy.sqrt(3)))
with self.assertRaisesRegex(TypeError, r'trigonometric functions require angle \[Φ\], got \[L\]'):
numpy.sin(SI.parse('2m'))
a = SI.Length('1m')
b = SI.Length('-1m')
dim, val = numpy.arctan2(a, b).__unwrap_quantity__()
self.assertEqual(dim, SI.Angle)
self.assertTrue(numpy.isclose(val, .75*numpy.pi))
with self.assertRaisesRegex(TypeError, r'arguments of arctan2 must have equal dimension, got \[L\] and \[M\]'):
numpy.arctan2(SI.parse('2m'), SI.parse('1kg'))

0 comments on commit a38f302

Please sign in to comment.