test_quantities.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. import warnings
  2. from sympy.core.add import Add
  3. from sympy.core.function import (Function, diff)
  4. from sympy.core.numbers import (Number, Rational)
  5. from sympy.core.singleton import S
  6. from sympy.core.symbol import (Symbol, symbols)
  7. from sympy.functions.elementary.complexes import Abs
  8. from sympy.functions.elementary.exponential import (exp, log)
  9. from sympy.functions.elementary.miscellaneous import sqrt
  10. from sympy.functions.elementary.trigonometric import sin
  11. from sympy.integrals.integrals import integrate
  12. from sympy.physics.units import (amount_of_substance, area, convert_to, find_unit,
  13. volume, kilometer, joule, molar_gas_constant,
  14. vacuum_permittivity, elementary_charge, volt,
  15. ohm)
  16. from sympy.physics.units.definitions import (amu, au, centimeter, coulomb,
  17. day, foot, grams, hour, inch, kg, km, m, meter, millimeter,
  18. minute, quart, s, second, speed_of_light, bit,
  19. byte, kibibyte, mebibyte, gibibyte, tebibyte, pebibyte, exbibyte,
  20. kilogram, gravitational_constant, electron_rest_mass)
  21. from sympy.physics.units.definitions.dimension_definitions import (
  22. Dimension, charge, length, time, temperature, pressure,
  23. energy, mass
  24. )
  25. from sympy.physics.units.prefixes import PREFIXES, kilo
  26. from sympy.physics.units.quantities import PhysicalConstant, Quantity
  27. from sympy.physics.units.systems import SI
  28. from sympy.testing.pytest import raises
  29. k = PREFIXES["k"]
  30. def test_str_repr():
  31. assert str(kg) == "kilogram"
  32. def test_eq():
  33. # simple test
  34. assert 10*m == 10*m
  35. assert 10*m != 10*s
  36. def test_convert_to():
  37. q = Quantity("q1")
  38. q.set_global_relative_scale_factor(S(5000), meter)
  39. assert q.convert_to(m) == 5000*m
  40. assert speed_of_light.convert_to(m / s) == 299792458 * m / s
  41. assert day.convert_to(s) == 86400*s
  42. # Wrong dimension to convert:
  43. assert q.convert_to(s) == q
  44. assert speed_of_light.convert_to(m) == speed_of_light
  45. expr = joule*second
  46. conv = convert_to(expr, joule)
  47. assert conv == joule*second
  48. def test_Quantity_definition():
  49. q = Quantity("s10", abbrev="sabbr")
  50. q.set_global_relative_scale_factor(10, second)
  51. u = Quantity("u", abbrev="dam")
  52. u.set_global_relative_scale_factor(10, meter)
  53. km = Quantity("km")
  54. km.set_global_relative_scale_factor(kilo, meter)
  55. v = Quantity("u")
  56. v.set_global_relative_scale_factor(5*kilo, meter)
  57. assert q.scale_factor == 10
  58. assert q.dimension == time
  59. assert q.abbrev == Symbol("sabbr")
  60. assert u.dimension == length
  61. assert u.scale_factor == 10
  62. assert u.abbrev == Symbol("dam")
  63. assert km.scale_factor == 1000
  64. assert km.func(*km.args) == km
  65. assert km.func(*km.args).args == km.args
  66. assert v.dimension == length
  67. assert v.scale_factor == 5000
  68. def test_abbrev():
  69. u = Quantity("u")
  70. u.set_global_relative_scale_factor(S.One, meter)
  71. assert u.name == Symbol("u")
  72. assert u.abbrev == Symbol("u")
  73. u = Quantity("u", abbrev="om")
  74. u.set_global_relative_scale_factor(S(2), meter)
  75. assert u.name == Symbol("u")
  76. assert u.abbrev == Symbol("om")
  77. assert u.scale_factor == 2
  78. assert isinstance(u.scale_factor, Number)
  79. u = Quantity("u", abbrev="ikm")
  80. u.set_global_relative_scale_factor(3*kilo, meter)
  81. assert u.abbrev == Symbol("ikm")
  82. assert u.scale_factor == 3000
  83. def test_print():
  84. u = Quantity("unitname", abbrev="dam")
  85. assert repr(u) == "unitname"
  86. assert str(u) == "unitname"
  87. def test_Quantity_eq():
  88. u = Quantity("u", abbrev="dam")
  89. v = Quantity("v1")
  90. assert u != v
  91. v = Quantity("v2", abbrev="ds")
  92. assert u != v
  93. v = Quantity("v3", abbrev="dm")
  94. assert u != v
  95. def test_add_sub():
  96. u = Quantity("u")
  97. v = Quantity("v")
  98. w = Quantity("w")
  99. u.set_global_relative_scale_factor(S(10), meter)
  100. v.set_global_relative_scale_factor(S(5), meter)
  101. w.set_global_relative_scale_factor(S(2), second)
  102. assert isinstance(u + v, Add)
  103. assert (u + v.convert_to(u)) == (1 + S.Half)*u
  104. assert isinstance(u - v, Add)
  105. assert (u - v.convert_to(u)) == S.Half*u
  106. def test_quantity_abs():
  107. v_w1 = Quantity('v_w1')
  108. v_w2 = Quantity('v_w2')
  109. v_w3 = Quantity('v_w3')
  110. v_w1.set_global_relative_scale_factor(1, meter/second)
  111. v_w2.set_global_relative_scale_factor(1, meter/second)
  112. v_w3.set_global_relative_scale_factor(1, meter/second)
  113. expr = v_w3 - Abs(v_w1 - v_w2)
  114. assert SI.get_dimensional_expr(v_w1) == (length/time).name
  115. Dq = Dimension(SI.get_dimensional_expr(expr))
  116. assert SI.get_dimension_system().get_dimensional_dependencies(Dq) == {
  117. length: 1,
  118. time: -1,
  119. }
  120. assert meter == sqrt(meter**2)
  121. def test_check_unit_consistency():
  122. u = Quantity("u")
  123. v = Quantity("v")
  124. w = Quantity("w")
  125. u.set_global_relative_scale_factor(S(10), meter)
  126. v.set_global_relative_scale_factor(S(5), meter)
  127. w.set_global_relative_scale_factor(S(2), second)
  128. def check_unit_consistency(expr):
  129. SI._collect_factor_and_dimension(expr)
  130. raises(ValueError, lambda: check_unit_consistency(u + w))
  131. raises(ValueError, lambda: check_unit_consistency(u - w))
  132. raises(ValueError, lambda: check_unit_consistency(u + 1))
  133. raises(ValueError, lambda: check_unit_consistency(u - 1))
  134. raises(ValueError, lambda: check_unit_consistency(1 - exp(u / w)))
  135. def test_mul_div():
  136. u = Quantity("u")
  137. v = Quantity("v")
  138. t = Quantity("t")
  139. ut = Quantity("ut")
  140. v2 = Quantity("v")
  141. u.set_global_relative_scale_factor(S(10), meter)
  142. v.set_global_relative_scale_factor(S(5), meter)
  143. t.set_global_relative_scale_factor(S(2), second)
  144. ut.set_global_relative_scale_factor(S(20), meter*second)
  145. v2.set_global_relative_scale_factor(S(5), meter/second)
  146. assert 1 / u == u**(-1)
  147. assert u / 1 == u
  148. v1 = u / t
  149. v2 = v
  150. # Pow only supports structural equality:
  151. assert v1 != v2
  152. assert v1 == v2.convert_to(v1)
  153. # TODO: decide whether to allow such expression in the future
  154. # (requires somehow manipulating the core).
  155. # assert u / Quantity('l2', dimension=length, scale_factor=2) == 5
  156. assert u * 1 == u
  157. ut1 = u * t
  158. ut2 = ut
  159. # Mul only supports structural equality:
  160. assert ut1 != ut2
  161. assert ut1 == ut2.convert_to(ut1)
  162. # Mul only supports structural equality:
  163. lp1 = Quantity("lp1")
  164. lp1.set_global_relative_scale_factor(S(2), 1/meter)
  165. assert u * lp1 != 20
  166. assert u**0 == 1
  167. assert u**1 == u
  168. # TODO: Pow only support structural equality:
  169. u2 = Quantity("u2")
  170. u3 = Quantity("u3")
  171. u2.set_global_relative_scale_factor(S(100), meter**2)
  172. u3.set_global_relative_scale_factor(Rational(1, 10), 1/meter)
  173. assert u ** 2 != u2
  174. assert u ** -1 != u3
  175. assert u ** 2 == u2.convert_to(u)
  176. assert u ** -1 == u3.convert_to(u)
  177. def test_units():
  178. assert convert_to((5*m/s * day) / km, 1) == 432
  179. assert convert_to(foot / meter, meter) == Rational(3048, 10000)
  180. # amu is a pure mass so mass/mass gives a number, not an amount (mol)
  181. # TODO: need better simplification routine:
  182. assert str(convert_to(grams/amu, grams).n(2)) == '6.0e+23'
  183. # Light from the sun needs about 8.3 minutes to reach earth
  184. t = (1*au / speed_of_light) / minute
  185. # TODO: need a better way to simplify expressions containing units:
  186. t = convert_to(convert_to(t, meter / minute), meter)
  187. assert t.simplify() == Rational(49865956897, 5995849160)
  188. # TODO: fix this, it should give `m` without `Abs`
  189. assert sqrt(m**2) == m
  190. assert (sqrt(m))**2 == m
  191. t = Symbol('t')
  192. assert integrate(t*m/s, (t, 1*s, 5*s)) == 12*m*s
  193. assert (t * m/s).integrate((t, 1*s, 5*s)) == 12*m*s
  194. def test_issue_quart():
  195. assert convert_to(4 * quart / inch ** 3, meter) == 231
  196. assert convert_to(4 * quart / inch ** 3, millimeter) == 231
  197. def test_electron_rest_mass():
  198. assert convert_to(electron_rest_mass, kilogram) == 9.1093837015e-31*kilogram
  199. assert convert_to(electron_rest_mass, grams) == 9.1093837015e-28*grams
  200. def test_issue_5565():
  201. assert (m < s).is_Relational
  202. def test_find_unit():
  203. assert find_unit('coulomb') == ['coulomb', 'coulombs', 'coulomb_constant']
  204. assert find_unit(coulomb) == ['C', 'coulomb', 'coulombs', 'planck_charge', 'elementary_charge']
  205. assert find_unit(charge) == ['C', 'coulomb', 'coulombs', 'planck_charge', 'elementary_charge']
  206. assert find_unit(inch) == [
  207. 'm', 'au', 'cm', 'dm', 'ft', 'km', 'ly', 'mi', 'mm', 'nm', 'pm', 'um', 'yd',
  208. 'nmi', 'feet', 'foot', 'inch', 'mile', 'yard', 'meter', 'miles', 'yards',
  209. 'inches', 'meters', 'micron', 'microns', 'angstrom', 'angstroms', 'decimeter',
  210. 'kilometer', 'lightyear', 'nanometer', 'picometer', 'centimeter', 'decimeters',
  211. 'kilometers', 'lightyears', 'micrometer', 'millimeter', 'nanometers', 'picometers',
  212. 'centimeters', 'micrometers', 'millimeters', 'nautical_mile', 'planck_length',
  213. 'nautical_miles', 'astronomical_unit', 'astronomical_units']
  214. assert find_unit(inch**-1) == ['D', 'dioptre', 'optical_power']
  215. assert find_unit(length**-1) == ['D', 'dioptre', 'optical_power']
  216. assert find_unit(inch ** 2) == ['ha', 'hectare', 'planck_area']
  217. assert find_unit(inch ** 3) == [
  218. 'L', 'l', 'cL', 'cl', 'dL', 'dl', 'mL', 'ml', 'liter', 'quart', 'liters', 'quarts',
  219. 'deciliter', 'centiliter', 'deciliters', 'milliliter',
  220. 'centiliters', 'milliliters', 'planck_volume']
  221. assert find_unit('voltage') == ['V', 'v', 'volt', 'volts', 'planck_voltage']
  222. assert find_unit(grams) == ['g', 't', 'Da', 'kg', 'me', 'mg', 'ug', 'amu', 'mmu', 'amus',
  223. 'gram', 'mmus', 'grams', 'pound', 'tonne', 'dalton', 'pounds',
  224. 'kilogram', 'kilograms', 'microgram', 'milligram', 'metric_ton',
  225. 'micrograms', 'milligrams', 'planck_mass', 'milli_mass_unit', 'atomic_mass_unit',
  226. 'electron_rest_mass', 'atomic_mass_constant']
  227. def test_Quantity_derivative():
  228. x = symbols("x")
  229. assert diff(x*meter, x) == meter
  230. assert diff(x**3*meter**2, x) == 3*x**2*meter**2
  231. assert diff(meter, meter) == 1
  232. assert diff(meter**2, meter) == 2*meter
  233. def test_quantity_postprocessing():
  234. q1 = Quantity('q1')
  235. q2 = Quantity('q2')
  236. SI.set_quantity_dimension(q1, length*pressure**2*temperature/time)
  237. SI.set_quantity_dimension(q2, energy*pressure*temperature/(length**2*time))
  238. assert q1 + q2
  239. q = q1 + q2
  240. Dq = Dimension(SI.get_dimensional_expr(q))
  241. assert SI.get_dimension_system().get_dimensional_dependencies(Dq) == {
  242. length: -1,
  243. mass: 2,
  244. temperature: 1,
  245. time: -5,
  246. }
  247. def test_factor_and_dimension():
  248. assert (3000, Dimension(1)) == SI._collect_factor_and_dimension(3000)
  249. assert (1001, length) == SI._collect_factor_and_dimension(meter + km)
  250. assert (2, length/time) == SI._collect_factor_and_dimension(
  251. meter/second + 36*km/(10*hour))
  252. x, y = symbols('x y')
  253. assert (x + y/100, length) == SI._collect_factor_and_dimension(
  254. x*m + y*centimeter)
  255. cH = Quantity('cH')
  256. SI.set_quantity_dimension(cH, amount_of_substance/volume)
  257. pH = -log(cH)
  258. assert (1, volume/amount_of_substance) == SI._collect_factor_and_dimension(
  259. exp(pH))
  260. v_w1 = Quantity('v_w1')
  261. v_w2 = Quantity('v_w2')
  262. v_w1.set_global_relative_scale_factor(Rational(3, 2), meter/second)
  263. v_w2.set_global_relative_scale_factor(2, meter/second)
  264. expr = Abs(v_w1/2 - v_w2)
  265. assert (Rational(5, 4), length/time) == \
  266. SI._collect_factor_and_dimension(expr)
  267. expr = Rational(5, 2)*second/meter*v_w1 - 3000
  268. assert (-(2996 + Rational(1, 4)), Dimension(1)) == \
  269. SI._collect_factor_and_dimension(expr)
  270. expr = v_w1**(v_w2/v_w1)
  271. assert ((Rational(3, 2))**Rational(4, 3), (length/time)**Rational(4, 3)) == \
  272. SI._collect_factor_and_dimension(expr)
  273. def test_dimensional_expr_of_derivative():
  274. l = Quantity('l')
  275. t = Quantity('t')
  276. t1 = Quantity('t1')
  277. l.set_global_relative_scale_factor(36, km)
  278. t.set_global_relative_scale_factor(1, hour)
  279. t1.set_global_relative_scale_factor(1, second)
  280. x = Symbol('x')
  281. y = Symbol('y')
  282. f = Function('f')
  283. dfdx = f(x, y).diff(x, y)
  284. dl_dt = dfdx.subs({f(x, y): l, x: t, y: t1})
  285. assert SI.get_dimensional_expr(dl_dt) ==\
  286. SI.get_dimensional_expr(l / t / t1) ==\
  287. Symbol("length")/Symbol("time")**2
  288. assert SI._collect_factor_and_dimension(dl_dt) ==\
  289. SI._collect_factor_and_dimension(l / t / t1) ==\
  290. (10, length/time**2)
  291. def test_get_dimensional_expr_with_function():
  292. v_w1 = Quantity('v_w1')
  293. v_w2 = Quantity('v_w2')
  294. v_w1.set_global_relative_scale_factor(1, meter/second)
  295. v_w2.set_global_relative_scale_factor(1, meter/second)
  296. assert SI.get_dimensional_expr(sin(v_w1)) == \
  297. sin(SI.get_dimensional_expr(v_w1))
  298. assert SI.get_dimensional_expr(sin(v_w1/v_w2)) == 1
  299. def test_binary_information():
  300. assert convert_to(kibibyte, byte) == 1024*byte
  301. assert convert_to(mebibyte, byte) == 1024**2*byte
  302. assert convert_to(gibibyte, byte) == 1024**3*byte
  303. assert convert_to(tebibyte, byte) == 1024**4*byte
  304. assert convert_to(pebibyte, byte) == 1024**5*byte
  305. assert convert_to(exbibyte, byte) == 1024**6*byte
  306. assert kibibyte.convert_to(bit) == 8*1024*bit
  307. assert byte.convert_to(bit) == 8*bit
  308. a = 10*kibibyte*hour
  309. assert convert_to(a, byte) == 10240*byte*hour
  310. assert convert_to(a, minute) == 600*kibibyte*minute
  311. assert convert_to(a, [byte, minute]) == 614400*byte*minute
  312. def test_conversion_with_2_nonstandard_dimensions():
  313. good_grade = Quantity("good_grade")
  314. kilo_good_grade = Quantity("kilo_good_grade")
  315. centi_good_grade = Quantity("centi_good_grade")
  316. kilo_good_grade.set_global_relative_scale_factor(1000, good_grade)
  317. centi_good_grade.set_global_relative_scale_factor(S.One/10**5, kilo_good_grade)
  318. charity_points = Quantity("charity_points")
  319. milli_charity_points = Quantity("milli_charity_points")
  320. missions = Quantity("missions")
  321. milli_charity_points.set_global_relative_scale_factor(S.One/1000, charity_points)
  322. missions.set_global_relative_scale_factor(251, charity_points)
  323. assert convert_to(
  324. kilo_good_grade*milli_charity_points*millimeter,
  325. [centi_good_grade, missions, centimeter]
  326. ) == S.One * 10**5 / (251*1000) / 10 * centi_good_grade*missions*centimeter
  327. def test_eval_subs():
  328. energy, mass, force = symbols('energy mass force')
  329. expr1 = energy/mass
  330. units = {energy: kilogram*meter**2/second**2, mass: kilogram}
  331. assert expr1.subs(units) == meter**2/second**2
  332. expr2 = force/mass
  333. units = {force:gravitational_constant*kilogram**2/meter**2, mass:kilogram}
  334. assert expr2.subs(units) == gravitational_constant*kilogram/meter**2
  335. def test_issue_14932():
  336. assert (log(inch) - log(2)).simplify() == log(inch/2)
  337. assert (log(inch) - log(foot)).simplify() == -log(12)
  338. p = symbols('p', positive=True)
  339. assert (log(inch) - log(p)).simplify() == log(inch/p)
  340. def test_issue_14547():
  341. # the root issue is that an argument with dimensions should
  342. # not raise an error when the `arg - 1` calculation is
  343. # performed in the assumptions system
  344. from sympy.physics.units import foot, inch
  345. from sympy.core.relational import Eq
  346. assert log(foot).is_zero is None
  347. assert log(foot).is_positive is None
  348. assert log(foot).is_nonnegative is None
  349. assert log(foot).is_negative is None
  350. assert log(foot).is_algebraic is None
  351. assert log(foot).is_rational is None
  352. # doesn't raise error
  353. assert Eq(log(foot), log(inch)) is not None # might be False or unevaluated
  354. x = Symbol('x')
  355. e = foot + x
  356. assert e.is_Add and set(e.args) == {foot, x}
  357. e = foot + 1
  358. assert e.is_Add and set(e.args) == {foot, 1}
  359. def test_issue_22164():
  360. warnings.simplefilter("error")
  361. dm = Quantity("dm")
  362. SI.set_quantity_dimension(dm, length)
  363. SI.set_quantity_scale_factor(dm, 1)
  364. bad_exp = Quantity("bad_exp")
  365. SI.set_quantity_dimension(bad_exp, length)
  366. SI.set_quantity_scale_factor(bad_exp, 1)
  367. expr = dm ** bad_exp
  368. # deprecation warning is not expected here
  369. SI._collect_factor_and_dimension(expr)
  370. def test_issue_22819():
  371. from sympy.physics.units import tonne, gram, Da
  372. from sympy.physics.units.systems.si import dimsys_SI
  373. assert tonne.convert_to(gram) == 1000000*gram
  374. assert dimsys_SI.get_dimensional_dependencies(area) == {length: 2}
  375. assert Da.scale_factor == 1.66053906660000e-24
  376. def test_issue_20288():
  377. from sympy.core.numbers import E
  378. from sympy.physics.units import energy
  379. u = Quantity('u')
  380. v = Quantity('v')
  381. SI.set_quantity_dimension(u, energy)
  382. SI.set_quantity_dimension(v, energy)
  383. u.set_global_relative_scale_factor(1, joule)
  384. v.set_global_relative_scale_factor(1, joule)
  385. expr = 1 + exp(u**2/v**2)
  386. assert SI._collect_factor_and_dimension(expr) == (1 + E, Dimension(1))
  387. def test_issue_24062():
  388. from sympy.core.numbers import E
  389. from sympy.physics.units import impedance, capacitance, time, ohm, farad, second
  390. R = Quantity('R')
  391. C = Quantity('C')
  392. T = Quantity('T')
  393. SI.set_quantity_dimension(R, impedance)
  394. SI.set_quantity_dimension(C, capacitance)
  395. SI.set_quantity_dimension(T, time)
  396. R.set_global_relative_scale_factor(1, ohm)
  397. C.set_global_relative_scale_factor(1, farad)
  398. T.set_global_relative_scale_factor(1, second)
  399. expr = T / (R * C)
  400. dim = SI._collect_factor_and_dimension(expr)[1]
  401. assert SI.get_dimension_system().is_dimensionless(dim)
  402. exp_expr = 1 + exp(expr)
  403. assert SI._collect_factor_and_dimension(exp_expr) == (1 + E, Dimension(1))
  404. def test_issue_24211():
  405. from sympy.physics.units import time, velocity, acceleration, second, meter
  406. V1 = Quantity('V1')
  407. SI.set_quantity_dimension(V1, velocity)
  408. SI.set_quantity_scale_factor(V1, 1 * meter / second)
  409. A1 = Quantity('A1')
  410. SI.set_quantity_dimension(A1, acceleration)
  411. SI.set_quantity_scale_factor(A1, 1 * meter / second**2)
  412. T1 = Quantity('T1')
  413. SI.set_quantity_dimension(T1, time)
  414. SI.set_quantity_scale_factor(T1, 1 * second)
  415. expr = A1*T1 + V1
  416. # should not throw ValueError here
  417. SI._collect_factor_and_dimension(expr)
  418. def test_prefixed_property():
  419. assert not meter.is_prefixed
  420. assert not joule.is_prefixed
  421. assert not day.is_prefixed
  422. assert not second.is_prefixed
  423. assert not volt.is_prefixed
  424. assert not ohm.is_prefixed
  425. assert centimeter.is_prefixed
  426. assert kilometer.is_prefixed
  427. assert kilogram.is_prefixed
  428. assert pebibyte.is_prefixed
  429. def test_physics_constant():
  430. from sympy.physics.units import definitions
  431. for name in dir(definitions):
  432. quantity = getattr(definitions, name)
  433. if not isinstance(quantity, Quantity):
  434. continue
  435. if name.endswith('_constant'):
  436. assert isinstance(quantity, PhysicalConstant), f"{quantity} must be PhysicalConstant, but is {type(quantity)}"
  437. assert quantity.is_physical_constant, f"{name} is not marked as physics constant when it should be"
  438. for const in [gravitational_constant, molar_gas_constant, vacuum_permittivity, speed_of_light, elementary_charge]:
  439. assert isinstance(const, PhysicalConstant), f"{const} must be PhysicalConstant, but is {type(const)}"
  440. assert const.is_physical_constant, f"{const} is not marked as physics constant when it should be"
  441. assert not meter.is_physical_constant
  442. assert not joule.is_physical_constant