1 |
|
2 |
######################################################## |
3 |
# |
4 |
# Copyright (c) 2003-2010 by University of Queensland |
5 |
# Earth Systems Science Computational Center (ESSCC) |
6 |
# http://www.uq.edu.au/esscc |
7 |
# |
8 |
# Primary Business: Queensland, Australia |
9 |
# Licensed under the Open Software License version 3.0 |
10 |
# http://www.opensource.org/licenses/osl-3.0.php |
11 |
# |
12 |
######################################################## |
13 |
|
14 |
__copyright__="""Copyright (c) 2003-2010 by University of Queensland |
15 |
Earth Systems Science Computational Center (ESSCC) |
16 |
http://www.uq.edu.au/esscc |
17 |
Primary Business: Queensland, Australia""" |
18 |
__license__="""Licensed under the Open Software License version 3.0 |
19 |
http://www.opensource.org/licenses/osl-3.0.php""" |
20 |
__url__="https://launchpad.net/escript-finley" |
21 |
__author__="Lutz Gross, l.gross@uq.edu.au" |
22 |
|
23 |
## :file unitsSI.py |
24 |
|
25 |
""" |
26 |
some tools supporting physical units and conversion |
27 |
|
28 |
:var __author__: name of author |
29 |
:var __copyright__: copyrights |
30 |
:var __license__: licence agreement |
31 |
:var __url__: url entry point on documentation |
32 |
:var __version__: version |
33 |
:var __date__: date of the version |
34 |
|
35 |
:var Yotta : prefix yotta, symbol: Y |
36 |
:var Zetta : prefix zetta, symbol: Z |
37 |
:var Exa : prefix exa, symbol: E |
38 |
:var Peta : prefix peta, symbol: P |
39 |
:var Tera : prefix tera, symbol: T |
40 |
:var Giga : prefix giga, symbol: G |
41 |
:var Mega : prefix mega, symbol: M |
42 |
:var Kilo : prefix kilo, symbol: k |
43 |
:var Hecto : prefix hecto, symbol: h |
44 |
:var Deca : prefix deca, symbol: da |
45 |
:var Deci : prefix deci, symbol: d |
46 |
:var Centi : prefix centi, symbol: c |
47 |
:var Milli : prefix milli, symbol: m |
48 |
:var Micro : prefix micro, symbol: mu |
49 |
:var Nano : prefix nano, symbol: n |
50 |
:var Pico : prefix pico, symbol: p |
51 |
:var Femto : prefix femto, symbol: f |
52 |
:var Atto : prefix atto, symbol: a |
53 |
:var Zepto : prefix zepto, symbol: z |
54 |
:var Yocto : prefix yocto, symbol: y |
55 |
|
56 |
:var km : unit of kilo meter |
57 |
:var m : unit of meter |
58 |
:var cm : unit of centi meter |
59 |
:var mm : unit of milli meter |
60 |
:var sec: unit of second |
61 |
:var minute : unit of minute |
62 |
:var h : unit of hour |
63 |
:var hour : unit of hour |
64 |
:var day : unit of day |
65 |
:var yr : unit of year |
66 |
:var Myr : unit of mega year |
67 |
:var Gyr : unit of giga year |
68 |
:var gram : unit of gram |
69 |
:var kg : unit of kilo gram |
70 |
:var lb : unit of pound |
71 |
:var ton : metric ton |
72 |
:var A : unit of Ampere |
73 |
:var Hz: unit of Hertz (frequenacy) |
74 |
:var N: unit of Newton (force) |
75 |
:var Pa: unit of Pascal (pressure, stress) |
76 |
:var bar: unit of bar (pressure) |
77 |
:var atm: unit of atmosphere (pressure) |
78 |
:var J: unit of Joule (energy, work) |
79 |
:var W: unit of Watt (power) |
80 |
:var C: unit of Coulomb (electric charge) |
81 |
:var V: unit of Volt (electric potential) |
82 |
:var F: unit of Farad (capacitance) |
83 |
:var Ohm: unit of Ohm (electric resistance) |
84 |
:var K : unit of Kelvin (temperature) |
85 |
:var Mol : unit of Mole (temperature) |
86 |
:var Celsius: unit of Celsius (temperature) |
87 |
:var Fahrenheit : unit of Fahrenheit (temperature) |
88 |
:var Poise : unit of Poise (dynamic viscosity) |
89 |
:var R_Earth_equator: Earth's equatorial radius |
90 |
:var R_Earth_poles: Earth's polar radius |
91 |
:var R_Earth: Earth's radius |
92 |
:var v_light: speed of light |
93 |
:var pi: value of pi accurate to 10 decimal places |
94 |
""" |
95 |
from math import pi |
96 |
class Unit(object): |
97 |
""" |
98 |
a general class to define a physical unit and convert from this unit to an appropriate SI unit. |
99 |
|
100 |
`Unit` object have a dual purpose: Firstly physical units can be combined through *,/ and ** to form new physical units or to add prefixes such as |
101 |
Milli to m to form mm=Milli*m. Moreover, a given floating point number x (or any other arithmetic object) can be converted from the physical unit to |
102 |
the SI system, eg. 10*mm to create the value for 10mm which is the float number 0.01 in the SI system. In addition, a value in the SI unit can be |
103 |
converted back to the given unit, eg. to express 0.01m in physical units of mm use 0.01/mm which will return 10. |
104 |
""" |
105 |
def __init__(self, name, longname,a ,b ): |
106 |
""" |
107 |
initializes the physical unit |
108 |
|
109 |
:param name: short name of the physical unit or prefix |
110 |
:type name: ``str`` |
111 |
:param longname: long name of the physical unit or prefix |
112 |
:type longname: ``str`` |
113 |
:param a: absolute value in transformation |
114 |
:type a: ``float`` |
115 |
:param b: slop in translation |
116 |
:type b: ``float`` |
117 |
""" |
118 |
self.setName(name) |
119 |
self.setLongName(longname) |
120 |
self.__a=a |
121 |
self.__b=b |
122 |
|
123 |
def __str__(self): |
124 |
return self.getName() |
125 |
|
126 |
def getName(self): |
127 |
""" |
128 |
Returns the name of the physical unit |
129 |
|
130 |
:return: name of the physical unit |
131 |
:rtype: ``str`` |
132 |
""" |
133 |
return self.__name |
134 |
|
135 |
def setName(self, name): |
136 |
""" |
137 |
Sets the name of the physical unit |
138 |
|
139 |
:param name: new name of the physical unit |
140 |
:type name: ``str`` |
141 |
""" |
142 |
self.__name=name |
143 |
|
144 |
def getLongName(self): |
145 |
""" |
146 |
Returns the long name of the physical unit |
147 |
|
148 |
:return: name of the physical unit |
149 |
:rtype: ``str`` |
150 |
""" |
151 |
return self.__longname |
152 |
|
153 |
def setLongName(self, name): |
154 |
""" |
155 |
Sets the long name of the physical unit |
156 |
|
157 |
:param name: new long name of the physical unit |
158 |
:type name: ``str`` |
159 |
""" |
160 |
self.__longname=name |
161 |
|
162 |
def __call__(self,x): |
163 |
""" |
164 |
Converts a value x in the physical unit self to SI |
165 |
|
166 |
:param x: value to convert |
167 |
:type x: an arithmetic object |
168 |
""" |
169 |
return self.__b*x+self.__a |
170 |
|
171 |
def __mul__(self,other): |
172 |
""" |
173 |
Performs self*other operation for two `Unit` objects |
174 |
|
175 |
:param other: an other physical unit |
176 |
:type other: `Unit` |
177 |
:rtype: `Unit` or ``NotImplemented`` |
178 |
""" |
179 |
if isinstance(other, Unit): |
180 |
a=self(other(0.)) |
181 |
b=(self(other(1.))-a) |
182 |
if isinstance(other, _PowUnit) or isinstance(self,_DivUnit) or isinstance(self, _PowUnit): |
183 |
return _ProdUnit(self.getName()+" "+other.getName(),self.getLongName()+"*"+other.getLongName(),a ,b) |
184 |
else: |
185 |
return _ProdUnit(self.getName()+other.getName(),self.getLongName()+"*"+other.getLongName(),a ,b) |
186 |
else: |
187 |
return NotImplemented |
188 |
|
189 |
def __rmul__(self,other): |
190 |
""" |
191 |
Performs other*self operation |
192 |
|
193 |
:param other: an other `Unit` or an arithmetic object. if other is a arithmetic object such as ``float`` other is assumed to be given in the physical unit ``self`` and is converted into the corresponding SI unit. |
194 |
:type other: `Unit` or |
195 |
:rtype: `Unit` of or an arithmetic object |
196 |
""" |
197 |
if isinstance(other, Unit): |
198 |
a=other(self(0.)) |
199 |
b=(other(self(1.))-a) |
200 |
if isinstance(other, _PowUnit) or isinstance(self, _PowUnit) or isinstance(other, _DivUnit): |
201 |
return _ProdUnit(other.getName()+" "+self.getName(),other.getLongName()+"*"+self.getLongName(),a ,b) |
202 |
else: |
203 |
return _ProdUnit(other.getName()+self.getName(),other.getLongName()+"*"+self.getLongName(),a ,b) |
204 |
else: |
205 |
return self(other) |
206 |
|
207 |
def __div__(self,other): |
208 |
""" |
209 |
Performs self*other operation for two `Unit` objects |
210 |
|
211 |
:param other: an other physical unit |
212 |
:type other: `Unit` |
213 |
:rtype: `Unit` or ``NotImplemented`` |
214 |
""" |
215 |
if isinstance(other, Unit): |
216 |
if abs(self(0.))+abs(other(0.))>0: |
217 |
raise ValueError,"Division of physical units requires 0 absolute values" |
218 |
if isinstance(other, (_ProdUnit, _DivUnit)): |
219 |
# X/(c*d) or X/(c/d) requires brackets: |
220 |
return _DivUnit(self.getName()+"/("+other.getName()+")",self.getLongName()+"/("+other.getLongName()+")",0 , self(1.)/other(1.)) |
221 |
else: |
222 |
return _DivUnit(self.getName()+"/"+other.getName(),self.getLongName()+"/"+other.getLongName(),0 , self(1.)/other(1.)) |
223 |
else: |
224 |
return NotImplemented |
225 |
def __rdiv__(self,other): |
226 |
""" |
227 |
Performs other/self operation |
228 |
|
229 |
:param other: an other `Unit` or an arithmetic object |
230 |
:type other: `Unit` or an arithmetic object |
231 |
:rtype: `Unit` or an arithmetic object |
232 |
""" |
233 |
if isinstance(other, Unit): |
234 |
if abs(self(0.))+abs(other(0.))>0: |
235 |
raise ValueError,"Division of physical units requires 0 absolute values" |
236 |
if isinstance(self, (_ProdUnit, _DivUnit)): |
237 |
# X/(a*b) or X/(a/b) requires brackets: |
238 |
return _DivUnit(other.getName()+"/("+self.getName()+")",other.getLongName()+"/("+self.getLongName()+")",0 , other(1.)/self(1.)) |
239 |
else: |
240 |
return _DivUnit(other.getName()+"/"+self.getName(),other.getLongName()+"/"+self.getLongName(),0 , other(1.)/self(1.)) |
241 |
else: |
242 |
return (other-self(0.))/(self(1.)-self(0.)) |
243 |
def __pow__(self,other): |
244 |
""" |
245 |
Performs self**other operation |
246 |
|
247 |
:param other: an exponent |
248 |
:type other: ``int`` or ``float`` |
249 |
:rtype: `Unit` |
250 |
""" |
251 |
if isinstance(other, float) or isinstance(other, int): |
252 |
if abs(self(0.))>0: |
253 |
raise ValueError,"Power of physical unit requires 0 absolute values" |
254 |
if isinstance(self, (_ProdUnit, _DivUnit, _PowUnit)): |
255 |
return _PowUnit("("+self.getName()+")^%s"%other, "("+self.getLongName()+")^%s"%other, 0., self(1.)**other) |
256 |
else: |
257 |
return _PowUnit(self.getName()+"^%s"%other, self.getLongName()+"^%s"%other, 0., self(1.)**other) |
258 |
else: |
259 |
return NotImplemented |
260 |
|
261 |
class _ProdUnit(Unit): |
262 |
pass |
263 |
class _DivUnit(Unit): |
264 |
pass |
265 |
class _PowUnit(Unit): |
266 |
pass |
267 |
|
268 |
# |
269 |
# prefixes: |
270 |
# |
271 |
Yotta=Unit("Y","Yotta",0.,1.e24) |
272 |
Zetta=Unit("Z","Zetta",0.,1.e21) |
273 |
Exa=Unit("E","Exa",0.,1.e18) |
274 |
Peta=Unit("P","Peta",0.,1.e15) |
275 |
Tera=Unit("T","Tera",0.,1.e12) |
276 |
Giga=Unit("G","Giga",0.,1.e9) |
277 |
Mega=Unit("M","Mega",0.,1.e6) |
278 |
Kilo=Unit("k","Kilo",0.,1.e3) |
279 |
Hecto=Unit("h","Hecto",0.,1.e2) |
280 |
Deca=Unit("da","Deca",0.,1.e1) |
281 |
one=Unit("1","1",0.,1.) |
282 |
Deci=Unit("d","Deci",0.,1.e-1) |
283 |
Centi=Unit("c","Centi",0.,1.e-2) |
284 |
Milli=Unit("m","Milli",0.,1.e-3) |
285 |
Micro=Unit("mu","Micro",0.,1.e-6) |
286 |
Nano=Unit("n","Nano",0.,1.e-9) |
287 |
Pico=Unit("p","Pico",0.,1.e-12) |
288 |
Femto=Unit("f","Femto",0.,1.e-15) |
289 |
Atto=Unit("a","Atto",0.,1.e-18) |
290 |
Zepto=Unit("z","Zepto",0.,1.e-21) |
291 |
Yocto=Unit("y","Yocto",0.,1.e-24) |
292 |
# |
293 |
# length |
294 |
# |
295 |
m=Unit("m","meter",0.,1.) |
296 |
km=Kilo*m |
297 |
cm=Centi*m |
298 |
mm=Milli*m |
299 |
# |
300 |
# time |
301 |
# |
302 |
sec=Unit("sec","second",0.,1.) |
303 |
minute=Unit("min","minute",0.,60.) |
304 |
hour=Unit("h","hour",0.,60.*60.) |
305 |
h=hour |
306 |
day=Unit("d","day",0.,60.*60.*24.) |
307 |
yr=Unit("yr","year",0.,60.*60.*24.*365.2425) |
308 |
year=yr |
309 |
Myr=Mega*yr |
310 |
Gyr=Giga*yr |
311 |
# |
312 |
# mass |
313 |
# |
314 |
kg=Unit("kg","kg",0.,1.) |
315 |
gram=Milli*kg |
316 |
lb=Unit("lb","pound",0.,0.45359237) |
317 |
ton=Kilo*kg |
318 |
# |
319 |
# electric current |
320 |
# |
321 |
A=Unit("A","Ampere",0.,1.) |
322 |
# |
323 |
# Temperature |
324 |
# |
325 |
K=Unit("K","Kelvin",0.,1.) |
326 |
Celsius=Unit("C","Celsius",273.15,1.) |
327 |
Fahrenheit=Unit("F","Fahrenheit",459.67*5./9.,5./9.) |
328 |
# |
329 |
# others |
330 |
# |
331 |
Mol=Unit("mole","Mole",0.,1.) |
332 |
Hz=one/sec |
333 |
N = Unit("N","Newton",0.,1.) |
334 |
Pa = Unit("Pa","Pascal",0.,1.) |
335 |
bar=100*Kilo*Pa |
336 |
atm= Unit("atm","atmosphere",0.,101325.024) |
337 |
J = Unit("J","Joule",0.,1.) |
338 |
W= Unit("W","Watt",0.,1.) |
339 |
C=Unit("C","Coulomb",0.,1.) |
340 |
V = Unit("V","Volt",0.,1.) |
341 |
F = Unit("F","Farad",0.,1.) |
342 |
Ohm=Unit("Ohm","Ohm",0.,1.) |
343 |
RAD=Unit("RAD","rad",0.,1.) |
344 |
DEG=Unit("Ohm","Ohm",0.,pi/180.) |
345 |
# |
346 |
# Derived |
347 |
# |
348 |
Poise= gram/cm/sec |
349 |
Darcy= 9.869233e-13*m**2 |
350 |
# |
351 |
# some constants |
352 |
# |
353 |
R_Earth_equator=6378.1370*km |
354 |
R_Earth_poles=6356.7523*km |
355 |
R_Earth=(R_Earth_equator+R_Earth_poles)/2 |
356 |
v_light=299792458.*m/sec |