-- | Defines units for use in Drasil. Often used in a unital-related chunk that has an associated symbol.
module Data.Drasil.SI_Units where

import Language.Drasil
import Language.Drasil.Display
import Language.Drasil.ShortHands (cOmega)

-- * Lists of Units

fundamentals :: [UnitDefn]
fundamentals :: [UnitDefn]
fundamentals = [UnitDefn
metre, UnitDefn
kilogram, UnitDefn
second, UnitDefn
kelvin, UnitDefn
mole, UnitDefn
ampere, UnitDefn
candela]

derived :: [UnitDefn]
derived :: [UnitDefn]
derived = [UnitDefn
becquerel, UnitDefn
calorie, UnitDefn
centigrade, UnitDefn
coulomb, UnitDefn
farad, UnitDefn
gray, UnitDefn
henry, UnitDefn
hertz, UnitDefn
joule,
  UnitDefn
katal, UnitDefn
kilopascal, UnitDefn
kilowatt, UnitDefn
litre, UnitDefn
lumen, UnitDefn
lux,  UnitDefn
millimetre, UnitDefn
newton, UnitDefn
ohm,
  UnitDefn
pascal, UnitDefn
radian, UnitDefn
siemens, UnitDefn
sievert, UnitDefn
steradian, UnitDefn
tesla, UnitDefn
volt, UnitDefn
watt, UnitDefn
weber]

siUnits :: [UnitDefn]
siUnits :: [UnitDefn]
siUnits = forall a b. (a -> b) -> [a] -> [b]
map forall u. IsUnit u => u -> UnitDefn
unitWrapper [UnitDefn]
fundamentals forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map forall u. IsUnit u => u -> UnitDefn
unitWrapper [UnitDefn]
derived

-- * Fundamental SI Units

metre, kilogram, second, kelvin, mole, ampere, candela :: UnitDefn
metre :: UnitDefn
metre    = String -> String -> String -> UnitDefn
fund String
"metre"    String
"length"               String
"m"
kilogram :: UnitDefn
kilogram = String -> String -> String -> UnitDefn
fund String
"kilogram" String
"mass"                 String
"kg"
second :: UnitDefn
second   = String -> String -> String -> UnitDefn
fund String
"second"   String
"time"                 String
"s"
kelvin :: UnitDefn
kelvin   = String -> String -> String -> UnitDefn
fund String
"kelvin"   String
"temperature"          String
"K"
mole :: UnitDefn
mole     = String -> String -> String -> UnitDefn
fund String
"mole"     String
"amount of substance"  String
"mol"
ampere :: UnitDefn
ampere   = String -> String -> String -> UnitDefn
fund String
"ampere"   String
"electric current"     String
"A"
candela :: UnitDefn
candela  = String -> String -> String -> UnitDefn
fund String
"candela"  String
"luminous intensity"   String
"cd"

-- * Commonly Defined Units

degree :: UnitDefn --FIXME: define degree in terms of radians and pi
-- degree = UD (dcc "degree" (cn' "degree") "angle") (BaseSI (US [(Special Circle,1)])) ["degree"]
degree :: UnitDefn
degree = String -> String -> Symbol -> UnitDefn
fund' String
"degree" String
"angle" (Special -> Symbol
Special Special
Circle)

-- Some of these units are easiest to define via others less common names, 
-- which we define first.
s_2 :: UnitDefn
s_2 :: UnitDefn
s_2 = String -> UnitEquation -> UnitDefn
newUnit String
"seconds squared" forall a b. (a -> b) -> a -> b
$ UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: Integer
2

m_2, m_3 :: UnitDefn
m_2 :: UnitDefn
m_2 = String -> UnitEquation -> UnitDefn
newUnit String
"square metres"   forall a b. (a -> b) -> a -> b
$ UnitDefn
metre UnitDefn -> Integer -> UnitEquation
^: Integer
2
m_3 :: UnitDefn
m_3 = String -> UnitEquation -> UnitDefn
newUnit String
"cubic metres"    forall a b. (a -> b) -> a -> b
$ UnitDefn
metre UnitDefn -> Integer -> UnitEquation
^: Integer
3

-- And now for the ones with 'common' names

becquerel, calorie, centigrade, coulomb, farad, gray, henry, hertz, joule,
  katal, kilopascal, kilowatt, litre, lumen, lux,  millimetre, newton, ohm,
  pascal, radian, siemens, sievert, steradian, tesla, volt, watt, weber :: UnitDefn

becquerel :: UnitDefn
becquerel = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"becquerel" 
  String
"becquerel" String
"activity" (String -> Symbol
label String
"Bq") --of a Radionuclide
  (UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: (-Integer
1))
  
calorie :: UnitDefn
calorie = String -> String -> String -> Symbol -> UDefn -> UnitDefn
derUC String
"calorie" 
  String
"calorie" String
"energy" (String -> Symbol
label String
"cal") (forall s. IsUnit s => Double -> s -> UDefn
scale Double
4.184 UnitDefn
joule)

centigrade :: UnitDefn
centigrade = String -> String -> String -> Symbol -> UDefn -> UnitDefn
derUC String
"centigrade" 
  String
"centigrade" String
"temperature" ([Symbol] -> Symbol
Concat [Special -> Symbol
Special Special
Circle, String -> Symbol
label String
"C"])
  (forall s. IsUnit s => Double -> s -> UDefn
shift Double
273.15 UnitDefn
kelvin)

coulomb :: UnitDefn
coulomb = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"coulomb" 
  String
"coulomb" String
"electric charge" (String -> Symbol
label String
"C") (UnitDefn
ampere UnitDefn -> UnitDefn -> UnitEquation
*: UnitDefn
second)

farad :: UnitDefn
farad = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"farad" 
  String
"farad" String
"capacitance" (String -> Symbol
label String
"F") (UnitDefn
coulomb UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
volt)

gray :: UnitDefn
gray = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"gray" 
  String
"gray" String
"absorbed dose" (String -> Symbol
label String
"Gy") (UnitDefn
joule UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
kilogram)
  
henry :: UnitDefn
henry = String -> NP -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC'' String
"henry" 
  (String -> NP
cnIES String
"henry") String
"inductance" (String -> Symbol
label String
"H") (UnitDefn
weber UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
ampere)
  
hertz :: UnitDefn
hertz = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC String
"hertz" 
  String
"hertz" String
"frequency" (String -> Symbol
label String
"Hz") (UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: (-Integer
1))

joule :: UnitDefn
joule = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"joule" 
  String
"joule" String
"energy" (String -> Symbol
label String
"J") 
 (UnitDefn
kilogram UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
m_2 UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: (-Integer
2))))

katal :: UnitDefn
katal = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"katal" 
  String
"katal" String
"catalytic activity" (String -> Symbol
label String
"kat") (UnitDefn
mole UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
second)

kilopascal :: UnitDefn
kilopascal = String -> String -> String -> Symbol -> UDefn -> UnitDefn
derUC' String
"kilopascal" 
  String
"kilopascal" String
"pressure"
  ([Symbol] -> Symbol
Concat [String -> Symbol
label String
"k", String -> Symbol
label String
"Pa"]) (forall s. IsUnit s => Double -> s -> UDefn
scale Double
1000 UnitDefn
pascal)

kilowatt :: UnitDefn
kilowatt = String -> String -> String -> Symbol -> UDefn -> UnitDefn
derUC' String
"kilowatt" 
  String
"kilowatt" String
"power" ([Symbol] -> Symbol
Concat [String -> Symbol
label String
"k", String -> Symbol
label String
"W"]) (forall s. IsUnit s => Double -> s -> UDefn
scale Double
1000 UnitDefn
watt)
  
litre :: UnitDefn
litre = String -> String -> String -> Symbol -> UDefn -> UnitDefn
derUC' String
"litre"
  String
"litre" String
"volume" (String -> Symbol
label String
"L") (forall s. IsUnit s => Double -> s -> UDefn
scale (Double
1forall a. Fractional a => a -> a -> a
/Double
1000) UnitDefn
m_3)

lumen :: UnitDefn
lumen = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"lumen" 
  String
"lumen" String
"luminous flux" (String -> Symbol
label String
"lm") (UnitDefn
candela UnitDefn -> UnitDefn -> UnitEquation
*: UnitDefn
steradian)

lux :: UnitDefn
lux = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC String
"lux" 
  String
"lux" String
"illuminance" (String -> Symbol
label String
"lx") (UnitDefn
lumen UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
m_2)

millimetre :: UnitDefn
millimetre = String -> String -> String -> Symbol -> UDefn -> UnitDefn
derUC' String
"millimetre"
  String
"millimetre" String
"length" (String -> Symbol
label String
"mm") (forall s. IsUnit s => Double -> s -> UDefn
scale Double
0.0001 UnitDefn
metre)

newton :: UnitDefn
newton = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"newton"
  String
"newton" String
"force" (String -> Symbol
label String
"N") (UnitDefn
kilogram UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: (-Integer
2)))
  
ohm :: UnitDefn
ohm = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"ohm"
  String
"ohm" String
"resistance" Symbol
cOmega (UnitDefn
volt UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
ampere)
  
pascal :: UnitDefn
pascal = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"pascal" 
  String
"pascal" String
"pressure" (String -> Symbol
label String
"Pa")
  (UnitDefn
kilogram UnitDefn -> UnitEquation -> UnitEquation
/$ (UnitDefn
metre UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: Integer
2)))
  
radian :: UnitDefn
radian = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"radian" 
  String
"radian" String
"angle" (String -> Symbol
label String
"rad") (UnitDefn
metre UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
metre)
            
siemens :: UnitDefn
siemens = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC String
"siemens" 
  String
"siemens" String
"conductance" (String -> Symbol
label String
"S") (UnitDefn
ohm UnitDefn -> Integer -> UnitEquation
^: (-Integer
1))
  
sievert :: UnitDefn
sievert = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"sievert" 
  String
"sievert" String
"dose equivalent" (String -> Symbol
label String
"Sv")
  (UnitDefn
joule UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
kilogram)
            
steradian :: UnitDefn
steradian = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"steradian" 
  String
"steradian" String
"solid angle" (String -> Symbol
label String
"sr") (UnitDefn
m_2 UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
m_2 )
  
tesla :: UnitDefn
tesla = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC String
"tesla"
  String
"tesla" String
"magnetic flux density" (String -> Symbol
label String
"T") (UnitDefn
weber UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
m_2)

volt :: UnitDefn
volt = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"volt" 
  String
"volt" String
"voltage" (String -> Symbol
label String
"V") (UnitDefn
watt UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
ampere)

watt :: UnitDefn
watt = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"watt" String
"watt" String
"power" (String -> Symbol
label String
"W")
  (UnitDefn
kilogram UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
m_2 UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: (-Integer
3))))
          
weber :: UnitDefn
weber = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' String
"weber"
  String
"weber" String
"magnetic flux" (String -> Symbol
label String
"Wb") (UnitDefn
volt UnitDefn -> UnitDefn -> UnitEquation
*: UnitDefn
second)
  
specificE :: UnitDefn
specificE :: UnitDefn
specificE = ConceptChunk -> UnitEquation -> UnitDefn
makeDerU (String -> NP -> String -> ConceptChunk
dcc String
"specificE" (String -> NP
cnIES String
"specific energy") 
  String
"energy per unit mass") (UnitDefn
joule UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
kilogram)

specificWeight :: UnitDefn
specificWeight :: UnitDefn
specificWeight = ConceptChunk -> UnitEquation -> UnitDefn
makeDerU (String -> NP -> String -> ConceptChunk
dcc String
"specificWeight" (String -> NP
cn' String
"specific weight")
  String
"weight per unit volume") (UnitDefn
newton UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
metre UnitDefn -> Integer -> UnitEquation
^: (-Integer
3)))
  
-- FIXME: Need to add pi 
--degrees = DUC
  --  (UD (dcc "Degrees" "angle") (UName (Special Circle)))
  --  Equiv to pi/180 rad.