-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathunit_converter.py
More file actions
88 lines (70 loc) · 3.33 KB
/
unit_converter.py
File metadata and controls
88 lines (70 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#!/usr/bin/env python3
import numpy as np
class UnitConverter:
# SI values in l.u.
m: float
s: float
kg: float
# m s kg
param_dimensions = {'distance': [ 1, 0, 0],
'time': [ 0, 1, 0],
'weight': [ 0, 0, 1],
'viscosity': [-1, -1, 1],
'pressure': [-1, -2, 1],
'energy': [ 2, -2, 1],
'density': [-3, 0, 1],
'concentration': [-3, 0, 0],
'surface_tension': [ 0, -2, 1],
'diffusivity': [ 2, -1, 0]}
def __init__(self, verbose=True, dx=None, dt=None, kg=None, **kwargs):
# This can be extended to use other units too
# Set up the unit matrix and the vector of ratios of the lattice and physical values
dimensions = [] # Powers of dimensions for each unit: meters, seconds, kilograms
value_ratios = []
if (dx is not None):
dimensions.append([1, 0, 0])
value_ratios.append(dx)
if (dt is not None):
dimensions.append([0, 1, 0])
value_ratios.append(dt)
if (kg is not None):
dimensions.append([0, 0, 1])
value_ratios.append(1/kg)
for arg in kwargs:
values = kwargs[arg]
if (not hasattr(values, "__len__") or len(values) != 2):
raise Exception(arg + " requires a 2-tuple containing the physical value and the lattice value.")
dimensions.append(self.param_dimensions[arg])
value_ratios.append(values[0]/values[1])
if (len(dimensions)!=3) or (len(value_ratios)!=3):
raise Exception("Three values are needed to initialise the unit converter.")
# Invert the unit matrix to find the values for m, s, kg
inv_dimensions = np.linalg.inv(dimensions)
units = np.ones(3)
for i in range(3):
for j in range(3):
units[i] = units[i] * value_ratios[j]**inv_dimensions[i,j] # Matrix multiplication with linear operators of multiplication and raising to a power
self.m, self.s, self.kg = units
if (verbose): print(self)
def __str__(self):
return "Unit Converter:\n" + \
f"1 l.u. = {self.m} metre\n" + \
f"1 l.u. = {self.s} second\n" + \
f"1 l.u. = {self.kg} kilogram"
def toLattice(self, value, param=None, m=0, s=0, kg=0):
if (param is not None):
m = self.param_dimensions[param][0]
s = self.param_dimensions[param][1]
kg = self.param_dimensions[param][2]
return value / self.m**m / self.s**s / self.kg**kg
def toSI(self, value, param=None, m=0, s=0, kg=0):
if (param is not None):
m = self.param_dimensions[param][0]
s = self.param_dimensions[param][1]
kg = self.param_dimensions[param][2]
return value * self.m**m * self.s**s * self.kg**kg
if (__name__ == "__main__"):
units = UnitConverter(dx=0.1, dt=1, viscosity=[1e-3,10])
print()
print("10 meters in lattice units:", units.toLattice(10, m=1))
print("10 lattice units of energy in Joules:", units.toSI(10, m=2, s=-2, kg=1))