File: unitsSI.py

package info (click to toggle)
python-escript 5.6-10
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 144,304 kB
  • sloc: python: 592,074; cpp: 136,909; ansic: 18,675; javascript: 9,411; xml: 3,384; sh: 738; makefile: 207
file content (387 lines) | stat: -rw-r--r-- 12,526 bytes parent folder | download | duplicates (3)
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
##############################################################################
#
# Copyright (c) 2003-2020 by The University of Queensland
# http://www.uq.edu.au
#
# Primary Business: Queensland, Australia
# Licensed under the Apache License, version 2.0
# http://www.apache.org/licenses/LICENSE-2.0
#
# Development until 2012 by Earth Systems Science Computational Center (ESSCC)
# Development 2012-2013 by School of Earth Sciences
# Development from 2014 by Centre for Geoscience Computing (GeoComp)
# Development from 2019 by School of Earth and Environmental Sciences
#
##############################################################################

from __future__ import print_function, division

"""

    :synopsis: some tools supporting physical units and conversion

    :var Yotta: prefix yotta, symbol:   Y
    :var Zetta: prefix zetta, symbol: Z
    :var Exa: prefix exa, symbol: E
    :var Peta: prefix peta, symbol: P
    :var Tera: prefix tera, symbol: T
    :var Giga: prefix giga, symbol: G
    :var Mega: prefix mega, symbol: M
    :var Kilo: prefix kilo, symbol: k
    :var Hecto: prefix hecto, symbol: h
    :var Deca:  prefix deca, symbol: da
    :var Deci:  prefix deci, symbol: d
    :var Centi: prefix centi, symbol: c
    :var Milli: prefix milli, symbol: m
    :var Micro: prefix micro, symbol: mu
    :var Nano:  prefix nano, symbol: n
    :var Pico:  prefix pico, symbol: p
    :var Femto: prefix femto, symbol: f
    :var Atto: prefix atto, symbol: a
    :var Zepto: prefix zepto, symbol: z
    :var Yocto: prefix yocto, symbol: y

    :var km: unit of kilo meter
    :var m: unit of meter
    :var cm: unit of centi meter
    :var mm: unit of milli meter
    :var sec: unit of second
    :var msec: unit of milli second
    :var minute: unit of minute
    :var h: unit of hour
    :var hour: unit of hour
    :var day: unit of day
    :var yr: unit of year
    :var Myr: unit of mega year
    :var Gyr: unit of giga year
    :var gram: unit of gram
    :var kg: unit of kilo gram
    :var lb: unit of pound
    :var ton: metric ton
    :var A: unit of Ampere
    :var Hz: unit of Hertz (frequenacy)
    :var N: unit of Newton (force)
    :var Pa: unit of Pascal (pressure, stress)
    :var bar: unit of bar (pressure)
    :var atm: unit of atmosphere (pressure)
    :var J: unit of Joule (energy, work)
    :var W: unit of Watt (power)
    :var C: unit of Coulomb (electric charge)
    :var V: unit of Volt (electric potential)
    :var F: unit of Farad (capacitance)
    :var Ohm: unit of Ohm (electric resistance)
    :var K: unit of Kelvin (temperature)
    :var Mol: unit of Mole (temperature)
    :var Celsius: unit of Celsius (temperature)
    :var Fahrenheit: unit of Fahrenheit (temperature)
    :var Poise: unit of Poise (dynamic viscosity)
    :var R_Earth_equator: Earth's equatorial radius
    :var R_Earth_poles: Earth's polar radius
    :var R_Earth: Earth's radius
    :var v_light: speed of light
    :var pi: value of pi accurate to 10 decimal places
    :var Gravitational_Constant: gravitational constant
"""


__copyright__="""Copyright (c) 2003-2020 by The University of Queensland
http://www.uq.edu.au
Primary Business: Queensland, Australia"""
__license__="""Licensed under the Apache License, version 2.0
http://www.apache.org/licenses/LICENSE-2.0"""
__url__="https://launchpad.net/escript-finley"
__author__="Lutz Gross, l.gross@uq.edu.au"

## :file unitsSI.py

from math import pi
class Unit(object):
   """
   a general class to define a physical unit and convert from this unit to an appropriate SI unit.

   `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
   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 
   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 
   converted back to the given unit, eg. to express 0.01m in physical units of mm use 0.01/mm which will return 10.
   """
   def __init__(self, name, longname,a ,b ):
       """
       initializes the physical unit
       
       :param name: short name of the physical unit or prefix
       :type name: ``str``
       :param longname: long name of the physical unit or prefix
       :type longname: ``str``
       :param a: absolute value in transformation
       :type a: ``float``
       :param b: slop in translation
       :type b: ``float``
       """
       self.setName(name)
       self.setLongName(longname)
       self.__a=a
       self.__b=b

   def __str__(self):
       return self.getName()

   def getName(self):
       """
       Returns the name of the physical unit
 
       :return: name of the physical unit
       :rtype: ``str``
       """
       return self.__name

   def setName(self, name):
       """
       Sets the name of the physical unit
 
       :param name: new name of the physical unit
       :type name: ``str``
       """
       self.__name=name

   def getLongName(self):
       """
       Returns the long name of the physical unit
 
       :return: name of the physical unit
       :rtype: ``str``
       """
       return self.__longname

   def setLongName(self, name):
       """
       Sets the long name of the physical unit
 
       :param name: new long name of the physical unit
       :type name: ``str``
       """
       self.__longname=name

   def __call__(self,x):
       """
       Converts a value x in the physical unit self to SI 

       :param x: value to convert
       :type x: an arithmetic object
       """
       return self.__b*x+self.__a

   def __mul__(self,other):
       """
       Performs self*other operation for two `Unit` objects

       :param other: an other physical unit
       :type other: `Unit`
       :rtype: `Unit` or ``NotImplemented``
       """
       if isinstance(other, Unit):
          a=self(other(0.))
          b=(self(other(1.))-a)
          if isinstance(other, _PowUnit) or isinstance(self,_DivUnit) or  isinstance(self, _PowUnit):
            return _ProdUnit(self.getName()+" "+other.getName(),self.getLongName()+"*"+other.getLongName(),a ,b)
          else:
            return _ProdUnit(self.getName()+other.getName(),self.getLongName()+"*"+other.getLongName(),a ,b)
       else:
          return NotImplemented

   def __rmul__(self,other):
       """
       Performs other*self operation

       :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.
       :type other: `Unit` or
       :rtype: `Unit` of or an arithmetic object
       """
       if isinstance(other, Unit):
          a=other(self(0.))
          b=(other(self(1.))-a)
          if isinstance(other, _PowUnit) or  isinstance(self, _PowUnit) or isinstance(other, _DivUnit):
             return _ProdUnit(other.getName()+" "+self.getName(),other.getLongName()+"*"+self.getLongName(),a ,b)
          else:
             return _ProdUnit(other.getName()+self.getName(),other.getLongName()+"*"+self.getLongName(),a ,b)
       else:
          return self(other)

   #Need this for python2       
   def __div__(self, other):
       return self.__truediv__(other)

   def __truediv__(self,other):
       """
       Performs self*other operation for two `Unit` objects

       :param other: an other physical unit
       :type other: `Unit`
       :rtype: `Unit` or ``NotImplemented``
       """
       if isinstance(other, Unit):
          if abs(self(0.))+abs(other(0.))>0:
              raise ValueError("Division of physical units requires 0 absolute values")
          if  isinstance(other, (_ProdUnit, _DivUnit)):
              # X/(c*d) or X/(c/d) requires brackets:
              return _DivUnit(self.getName()+"/("+other.getName()+")",self.getLongName()+"/("+other.getLongName()+")",0 , self(1.)/other(1.))
          else:
              return _DivUnit(self.getName()+"/"+other.getName(),self.getLongName()+"/"+other.getLongName(),0 , self(1.)/other(1.))
       else:
          return NotImplemented

   #Need this for python2       
   def __rdiv__(self, other):
       return self.__rtruediv__(other)          
          
   def __rtruediv__(self,other):
       """
       Performs other/self operation

       :param other: an other `Unit` or an arithmetic object
       :type other: `Unit` or an arithmetic object
       :rtype: `Unit` or an arithmetic object
       """
       if isinstance(other, Unit):
          if abs(self(0.))+abs(other(0.))>0:
              raise ValueError("Division of physical units requires 0 absolute values")
          if  isinstance(self, (_ProdUnit, _DivUnit)):
              # X/(a*b) or X/(a/b) requires brackets:
              return _DivUnit(other.getName()+"/("+self.getName()+")",other.getLongName()+"/("+self.getLongName()+")",0 , other(1.)/self(1.))
          else:
              return _DivUnit(other.getName()+"/"+self.getName(),other.getLongName()+"/"+self.getLongName(),0 , other(1.)/self(1.))
       else:
          return (other-self(0.))/(self(1.)-self(0.))
   def __pow__(self,other):
       """
       Performs self**other operation

       :param other: an exponent
       :type other: ``int`` or ``float``
       :rtype: `Unit` 
       """
       if isinstance(other, float) or isinstance(other, int):
          if abs(self(0.))>0:
              raise ValueError("Power of physical unit requires 0 absolute values")
          if  isinstance(self, (_ProdUnit, _DivUnit, _PowUnit)):
              return _PowUnit("("+self.getName()+")^%s"%other, "("+self.getLongName()+")^%s"%other, 0., self(1.)**other)
          else:
              return _PowUnit(self.getName()+"^%s"%other, self.getLongName()+"^%s"%other, 0., self(1.)**other)
       else:
          return NotImplemented

class _ProdUnit(Unit):
    pass
class _DivUnit(Unit):
    pass
class _PowUnit(Unit):
    pass

#
#  prefixes:
#
Yotta=Unit("Y","Yotta",0.,1.e24)
Zetta=Unit("Z","Zetta",0.,1.e21)
Exa=Unit("E","Exa",0.,1.e18)
Peta=Unit("P","Peta",0.,1.e15)
Tera=Unit("T","Tera",0.,1.e12)
Giga=Unit("G","Giga",0.,1.e9)
Mega=Unit("M","Mega",0.,1.e6)
Kilo=Unit("k","Kilo",0.,1.e3)
Hecto=Unit("h","Hecto",0.,1.e2)
Deca=Unit("da","Deca",0.,1.e1)
one=Unit("1","1",0.,1.)
Deci=Unit("d","Deci",0.,1.e-1)
Centi=Unit("c","Centi",0.,1.e-2)
Milli=Unit("m","Milli",0.,1.e-3)
Micro=Unit("mu","Micro",0.,1.e-6)
Nano=Unit("n","Nano",0.,1.e-9)
Pico=Unit("p","Pico",0.,1.e-12)
Femto=Unit("f","Femto",0.,1.e-15)
Atto=Unit("a","Atto",0.,1.e-18)
Zepto=Unit("z","Zepto",0.,1.e-21)
Yocto=Unit("y","Yocto",0.,1.e-24)
#
#   length
#
m=Unit("m","meter",0.,1.)
km=Kilo*m
cm=Centi*m
mm=Milli*m
liter=(Deci*m)**3
ft=Unit("ft", "feet", 0., 0.3048 * m)
Barrel=Unit("bbl","barrel", 0., 0.158987294928 * m**3)
Mscf=Unit("MSCF", "thousand standard cubic feet", 0., 28.31685 * m**3)
Mcf=1000. * ft**3
ccm=cm**3
#
#  time
#
sec=Unit("sec","second",0.,1.)
msec=Unit("msec","milli-second",0.,1e-3)
minute=Unit("min","minute",0.,60.)
hour=Unit("h","hour",0.,60.* minute)
h=hour
day=Unit("d","day",0., 24. * h)
yr=Unit("yr","year",0.,365.2425 * day)
year=yr
Myr=Mega*yr
Gyr=Giga*yr
#
#  mass
#
kg=Unit("kg","kg",0.,1.)
gram=Milli*kg
lb=Unit("lb","pound",0.,0.45359237 * kg)
ton=Kilo*kg
#
#   electric current
#
A=Unit("A","Ampere",0.,1.)
#
#   Temperature
#
K=Unit("K","Kelvin",0.,1.)
Celsius=Unit("C","Celsius",273.15,1.)
Fahrenheit=Unit("F","Fahrenheit",459.67*5./9.,5./9.)
#
#  others
#
Mol=Unit("mole","Mole",0.,1.)
Hz=one/sec
N = Unit("N","Newton",0.,1.)
Pa = Unit("Pa","Pascal",0.,1.)
bar=100*Kilo*Pa
atm= Unit("atm","atmosphere",0.,101325.024 * Pa)
psi= Unit("psi","Psi",0.,6894.75728034 * Pa)
J = Unit("J","Joule",0.,1.)
W= Unit("W","Watt",0.,1.)
C=Unit("C","Coulomb",0.,1.)
V = Unit("V","Volt",0.,1.)
F = Unit("F","Farad",0.,1.)
Ohm=Unit("Ohm","Ohm",0.,1.)
RAD=Unit("RAD","rad",0.,1.)
DEG=Unit("Ohm","Ohm",0.,pi/180.)
gal=Unit("gal","galileo",0.,0.01)
mgal=gal*Milli
Tesla=V*sec/(m**2)
T=Tesla
#
#  Derived 
#
Poise= gram/cm/sec
cPoise=Poise*Centi
mPoise=Poise*Milli
Darcy= 9.869233e-13*m**2
mDarcy=Darcy*Milli
#
#  some constants
#
R_Earth_equator=6378.1370*km
R_Earth_poles=6356.7523*km
R_Earth=(R_Earth_equator+R_Earth_poles)/2
v_light=299792458.*m/sec
Mu_0 = 4 * pi * 10**(-7)*V*sec/A/m 
Magnetic_Dipole_Moment_Earth = 8.22 * 10**22*A*m**2 
Gravitational_Constant=6.6742e-11*m**3/(kg*sec**2)