Skip to content

Commit

Permalink
Fix conversion of molar units
Browse files Browse the repository at this point in the history
  • Loading branch information
xnx committed May 19, 2024
1 parent 80cf56b commit 2bb2680
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 16 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

setup(
name="pyqn",
version="1.4",
version="1.4.1",
description="A package for managing physical units and quantities",
long_description=long_description,
long_description_content_type="text/x-rst",
Expand Down
3 changes: 1 addition & 2 deletions src/pyqn/dimensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ def __init__(self, dims=None, **kwargs):
if not kwargs:
self.dims = dims
else:
print("bad initialisation of Dimensions object")
sys.exit(1)
raise ValueError("Bad initialisation of Dimensions object")
else:
# initialize by keyword arguments
for dim_name in kwargs:
Expand Down
28 changes: 16 additions & 12 deletions src/pyqn/units.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
h, NA, c, kB = (6.62607015e-34, 6.02214076e23, 299792458.0, 1.380649e-23)


class UnitsConversionError(UnitsError):
pass


class Units:
"""
A class to represent the units of a physical quantity.
Expand Down Expand Up @@ -327,25 +331,25 @@ def kBT_conversion(self, other):
else:
raise UnitsError(
"Failure in conversion of units: was expecting to "
"covert between energy and temperature"
"convert between energy and temperature"
)
return fac / other.to_si()

def mol_conversion(self, other):
from_dims = self.get_dims() # original unit dimensions
to_dims = other.get_dims() # desired unit dimensions
fac = self.to_si() # factor needed to conver to SI units
from_dims_Q = self.get_dims().dims[4]
to_dims_Q = other.get_dims().dims[4]

if from_dims.dims[4] == to_dims.dims[4]:
raise UnitsError(
"Failure in conversion of units: no "
"different in quantity dimensions between %s and %s" % from_dims,
to_dims,
# We can only remove or add the amount dimension in its entirity.
if from_dims_Q and to_dims_Q:
raise UnitsConversionError(
f"Cannot force molar conversion between {self} and {other}"
)
elif from_dims.dims[4] > to_dims.dims[4]:
fac = fac / (NA ** (from_dims.dims[4] - to_dims.dims[4]))

fac = self.to_si()
if from_dims_Q:
fac = fac * NA**from_dims_Q
else:
fac = fac * (NA ** (to_dims.dims[4] - from_dims.dims[4]))
fac = fac * NA**to_dims_Q
return fac / other.to_si()

def spec_conversion(self, other):
Expand Down
40 changes: 39 additions & 1 deletion tests/test_conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,51 @@ def test_litres(self):
self.assertEqual(u1.to_si(), 1.0e-3)

def test_molar_units_conversion(self):

u1 = Units("mol")
u2 = Units("1")
self.assertAlmostEqual(u1.conversion(u2, force="mol"), 6.02214076e23)

u1 = Units("mol-1")
u2 = Units("1")
self.assertAlmostEqual(u1.conversion(u2, force="mol"), 1 / 6.02214076e23)
print(u1.dims.dims)

u1 = Units("mol2")
u2 = Units("1")
self.assertAlmostEqual(u1.conversion(u2, force="mol"), 6.02214076e23**2)

u1 = Units("mol-2")
u2 = Units("1")
self.assertAlmostEqual(u1.conversion(u2, force="mol"), 6.02214076e23**-2)

u1 = Units("kJ")
u2 = Units("J/mol")
u2 = Units("kJ.mol-1")

with self.assertRaises(UnitsError) as cm:
u1.conversion(u2, strict=True)
self.assertAlmostEqual(u1.conversion(u2, force="mol"), 1.660e-21)

u3 = Units("cal.mol-1")
u4 = Units("eV")
self.assertAlmostEqual(u3.conversion(u4, force="mol"), 4.3364104350063916e-05)

u9 = Units("nmol2.L-1")
u10 = Units("L-1")
self.assertAlmostEqual(u9.conversion(u10, force="mol"), 3.626617933325338e29)

u5 = Units("J.mmol-1")
u6 = Units("J")
self.assertAlmostEqual(u5.conversion(u6, force="mol"), 1.6605390671738467e-21)

u7 = Units("1")
u8 = Units("mol-2")
self.assertAlmostEqual(u7.conversion(u8, force="mol"), 2.757389993610589e-48)

u9 = Units("nmol2.L-1")
u10 = Units("L-1")
self.assertAlmostEqual(u9.conversion(u10, force="mol"), 3.626617933325338e29)

def test_kBT_units_conversion(self):
u1 = Units("K")
u2 = Units("J")
Expand Down

0 comments on commit 2bb2680

Please sign in to comment.