module Circuit where
import Complex
import Maybe
import List
--------------------------------------------------------------------------------
data Device = Device
{ devtype :: DevType
, devname :: Int
, devnode :: [Int]
, devvalue :: Double
} deriving (Show, Eq)
data DevType = ADM | VSRC | ISRC | CCVS0 | CCVS1 | VCVS | CCCS | VCCS
deriving (Eq, Show, Read, Ord, Bounded, Enum)
data SimType = OP | TRANS
deriving (Eq, Show, Read, Ord, Bounded, Enum)
data ESim = ESim
{ simInfo :: SimInfo
, nrSteps :: Double
, trSteps :: Double
, nrData :: [Double]
, trData :: [Double]
} deriving (Show)
defaultESim = (ESim (SimInfo OP [] [] [] 0) 0 0 [] [])
data SimInfo = SimInfo
{ simType :: SimType
, nNODE :: [Int]
, nSRC :: [Int]
, simParam :: [Double]
, temp :: Double
} deriving (Show)
--- device models
--- level 0
-- N+ N- NC+ NC- value
-- 1 2 3 4
adm1 :: Int -> Int -> Int -> Double -> ESim
-> [Device]
adm1 name p1 p2 v z0 | (simType (simInfo z0)) == OP
= [(Device ADM name [p1,p2] v)]
| (simType (simInfo z0)) == TRANS
= [(Device ADM name [p1,p2] v)]
| otherwise
= error "adm : No internal model defined"
vsrc1 :: Int -> Int -> Int -> Double -> ESim
-> [Device]
vsrc1 name p1 p2 v z0 | (simType (simInfo z0)) == OP
= [(Device VSRC name [p1,p2] v)]
| (simType (simInfo z0)) == TRANS
= [(Device VSRC name [p1,p2] v)]
| otherwise
= error "vdc : No internal model defined"
-- ideal current source
-- p1 ---(<-)---p2
isrc1 :: Int -> Int -> Int -> Double -> ESim -> [Device]
isrc1 name p1 p2 v z0 | (simType (simInfo z0)) == OP
= [(Device ISRC name [p1,p2] v)]
| (simType (simInfo z0)) == TRANS
= [(Device ISRC name [p1,p2] v)]
| otherwise
= error "idc : No internal model defined"
vccs1 :: Int -> Int -> Int -> Int -> Int -> Double -> ESim -> [Device]
vccs1 name p1 p2 p3 p4 v z0 | (simType (simInfo z0)) == OP
= [(Device VCCS name [p1,p2,p3,p4] (1/v))]
| (simType (simInfo z0)) == TRANS
= [(Device VCCS name [p1,p2,p3,p4] (1/v))]
| otherwise
= error "vccs : No internal model defined"
vcvs1 :: Int -> Int -> Int -> Int -> Int -> Double -> ESim -> [Device]
vcvs1 name p1 p2 p3 p4 v z0 | (simType (simInfo z0)) == OP
= [(Device VCVS name [p1,p2,p3,p4] v)]
| (simType (simInfo z0)) == TRANS
= [(Device VCVS name [p1,p2,p3,p4] v)]
| otherwise
= error "vcvs : No internal model defined"
ccvs1 :: Int -> Int -> Int -> Int -> Int -> Double -> ESim -> [Device]
ccvs1 name p1 p2 p3 p4 v z0 | (simType (simInfo z0)) == OP
= [(Device CCVS0 name [p1,p2,p3,p4] v)] ++
[(Device CCVS1 (name * 100) [p1,p2,p3,p4] 0)]
| (simType (simInfo z0)) == TRANS
= [(Device CCVS0 name [p1,p2,p3,p4] v)] ++
[(Device CCVS1 (name * 100) [p1,p2,p3,p4] 0)]
| otherwise
= error "ccvs : No internal model defined"
cccs1 :: Int -> Int -> Int -> Int -> Int -> Double -> ESim -> [Device]
cccs1 name p1 p2 p3 p4 v z0 | (simType (simInfo z0)) == OP
= [(Device CCCS name [p1,p2,p3,p4] (1 / v))]
| (simType (simInfo z0)) == TRANS
= [(Device CCCS name [p1,p2,p3,p4] (1 / v))]
| otherwise
= error "cccs : No internal model defined"
--------------------------------------------------------------------------------
-- Level 1 Devices
res1 :: Int -> Int -> Int -> Double -> ESim
-> [Device]
res1 name p1 p2 v z0 | (simType (simInfo z0)) == OP
= (adm1 name p1 p2 (1 / v) z0)
| (simType (simInfo z0)) == TRANS
= (adm1 name p1 p2 (1 / v) z0)
| otherwise
= error "res: No internal model defined"
data Gmin = Gmin
{ gtlim :: Double --default 5
, gsteps :: Double --default 8
} deriving (Show)
defaultGmin = Gmin 5 8
-- resistor with Gmin support
res2 :: Int -> Int -> Int -> Double -> Gmin -> ESim -> [Device]
res2 name p1 p2 rp g0 z0 | (simType (simInfo z0)) == OP
= (res1 name p1 p2 r z0)
| (simType (simInfo z0)) == TRANS
= (res1 name p1 p2 r z0)
| otherwise
= error "res2 : No internal model defined"
--- Model Equations ------------------------------------------
where r = 1 / (1 / rp + gmin)
gmin | nrSteps z0 < gsteps g0
&& trSteps z0 < gtlim g0
= 1 / 10**(12 / gsteps g0 * nrSteps z0)
| otherwise = 1 / 10.0**12
--------------------------------------------------------
ind1 :: Int ->Int -> Int -> Double -> ESim -> [Device]
ind1 name p1 p2 v z0 | (simType (simInfo z0)) == OP
= (adm1 (nn!!0) p1 (ii!!0) 0 z0) ++
(vsrc1 (nn!!1) (ii!!0) p2 0 z0)
| (simType (simInfo z0)) == TRANS
= (adm1 (nn!!0) p1 (ii!!0) (1 / req) z0) ++
(vsrc1 (nn!!1) (ii!!0) p2 veq z0)
| otherwise
= error "ind: No internal model defined"
--- Model Equations ------------------------------------------
where req = v / (simParam (simInfo z0))!!0
veq = -1 * req * (ivsrc (nn!!1) (trData z0))
-- Helper Programs -------------------------------------
nn = [(name * 100)..]
ii = [(name * 100)..]
ivsrc src z = (z!!((idx src j)
+ ((length i) - 1)))
where idx n l = fromJust (elemIndex n l)
vnode node z | node == 0 = 0
| otherwise = z!!(nn' - 1)
where nn' = fromJust (elemIndex node i)
j = nSRC (simInfo z0)
i = nNODE (simInfo z0)
--------------------------------------------------------
cap1 :: Int -> Int -> Int -> Double -> ESim -> [Device]
cap1 name p1 p2 v z0 | (simType (simInfo z0)) == OP
= (adm1 (nn!!0) p1 p2 0 z0) ++
(isrc1 (nn!!1) p1 p2 0 z0)
| (simType (simInfo z0)) == TRANS
= (adm1 (nn!!0) p1 p2 geq z0) ++
(isrc1 (nn!!1) p1 p2 ieq z0)
| otherwise
= error "cap: No internal model defined"
--- Model Equations -----------------------------------------
where
geq = v / (simParam (simInfo z0))!!0
ieq = geq * (vp1 - vp2)
vp1 = vnode p1 (trData z0)
vp2 = vnode p2 (trData z0)
-- Helper Programs -------------------------------------
nn = [(name * 100)..]
ii = [(name * 100)..]
ivsrc src z = (z!!((idx src j) + ((length i) - 1)))
where idx n l = fromJust (elemIndex n l)
vnode node z | node == 0 = 0
| otherwise = z!!(nn' - 1)
where nn' = fromJust (elemIndex node i)
j = nSRC (simInfo z0)
i = nNODE (simInfo z0)
--------------------------------------------------------
-- intrinsic diode model
-- pin: (p1)--!<--(p2)
dio1 :: Int -> Int -> Int -> ESim -> [Device]
dio1 name p1 p2 z0 | (simType (simInfo z0)) == OP
= (adm1 (nn!!0) p1 p2 geq z0) ++
(isrc1 (nn!!1) p1 p2 ieq2 z0)
| (simType (simInfo z0)) == TRANS
= (adm1 (nn!!0) p1 p2 geq z0) ++
(isrc1 (nn!!1) p1 p2 ieq2 z0)
| otherwise = error "dio1: No internal model defined"
--- Model Equations ------------------------------------------
where geq = gd (vp2 - vp1)
ieq2 = 1 * (ieq (vp2 - vp1))
vp1 = vnode p1 (nrData z0)
vp2 = vnode p2 (nrData z0)
-- Diode Model
is = 1e-14
n = 1.0
isr = 0.0
nr = 2.0
ee = exp 1
vt = 0.025875
ieq vd = (idd vd) - (gd vd) * vd
idd vd = is * ((ee**(vd / (n * vt))) - 1)
+ isr * ((ee**(vd / (nr * vt))) - 1)
gd vd = (is / (n * vt)) * ee**(vd / (n * vt))
+ (is / (nr * vt)) * ee**(vd / (nr * vt))
-- Helper Programs -------------------------------------
nn = [(name * 100)..]
ii = [(name * 100)..]
ivsrc src z = (z!!((idx src j)
+ ((length i) - 1)))
where idx n l = fromJust (elemIndex n l)
vnode node z | node == 0 = 0
| otherwise = z!!(nn' - 1)
where nn' = fromJust (elemIndex node i)
j = nSRC (simInfo z0)
i = nNODE (simInfo z0)
--------------------------------------------------------
-- intrinsic (Ebers-Moll) bipolar junction transistor (NPN)
-- Pin C(p1) B(p2) E(p3)
npn1 :: Int -> Int -> Int -> Int -> ESim -> [Device]
npn1 name p1 p2 p3 z0 | (simType (simInfo z0)) == OP
= (dio1 (nn!!0) p1 p2 z0) ++
(dio1 (nn!!1) p3 p2 z0) ++
(isrc1 (nn!!2) p2 p1 icc z0) ++
(isrc1 (nn!!3) p2 p3 iee z0)
| (simType (simInfo z0)) == TRANS
= (dio1 (nn!!0) p1 p2 z0) ++
(dio1 (nn!!1) p3 p2 z0) ++
(isrc1 (nn!!2) p2 p1 icc z0) ++
(isrc1 (nn!!3) p2 p3 iee z0)
| otherwise = error "dio: No internal model defined"
--- Model Equations ------------------------------------------
where ar = 0.7
af = 0.995
icc = af * (idd (vp2 - vp3))
iee = ar * (idd (vp2 - vp1))
is = 1e-14
ee = exp 1
n = 1.0
vt = 0.02587
idd vd = is * ((ee**(vd / (n * vt))) - 1)
vp1 = vnode p1 (nrData z0)
vp2 = vnode p2 (nrData z0)
vp3 = vnode p3 (nrData z0)
-- Helper Programs -------------------------------------
nn = [(name * 100)..]
ii = [(name * 100)..]
ivsrc src z = (z!!((idx src j)
+ ((length i) - 1)))
where idx n l = fromJust (elemIndex n l)
vnode node z | node == 0 = 0
| otherwise = z!!(nn' - 1)
where nn' = fromJust (elemIndex node i)
j = nSRC (simInfo z0)
i = nNODE (simInfo z0)
--------------------------------------------------------
data VStep = VStep
{ vlim :: Double --default 40
, tlim :: Double --default 5
, steps :: Double --default 8
} deriving (Show)
defaultVStep = VStep 40 5 8
-- voltage source with voltage stepping support.
vsrc2 :: Int -> Int -> Int -> Double -> VStep -> ESim -> [Device]
vsrc2 name p1 p2 vp v0 z0 | (simType (simInfo z0)) == OP
= (vsrc1 name p1 p2 v z0)
| (simType (simInfo z0)) == TRANS
= (vsrc1 name p1 p2 v z0)
| otherwise
= error "vsrc2 : No internal model defined"
--- Model Equations ------------------------------------------
where v = vp * vstep
vstep | abs vp > vlim v0 && nrSteps z0 < steps v0
&& trSteps z0 < tlim v0 = nrSteps z0 / steps v0
| otherwise = 1.0
--vn = abs (abs (vp1 - vp2) - abs vp)
--vp1 = vnode p1 (trData z0)
--vp2 = vnode p2 (trData z0)
-- Helper Programs -------------------------------------
nn = [(name * 100)..]
ii = [(name * 100)..]
ivsrc src z = (z!!((idx src j) + ((length i) - 1)))
where idx n l = fromJust (elemIndex n l)
vnode node z | node == 0 = 0
| otherwise = z!!(nn' - 1)
where nn' = fromJust (elemIndex node i)
j = nSRC (simInfo z0)
i = nNODE (simInfo z0)
--------------------------------------------------------
-- sine wave no voltage stepping.
vsrc3 :: Int -> Int -> Int -> Double ->Double -> ESim -> [Device]
vsrc3 name p1 p2 vp f z0 | (simType (simInfo z0)) == OP
= (vsrc1 name p1 p2 0 z0)
| (simType (simInfo z0)) == TRANS
= (vsrc1 name p1 p2 v z0)
| otherwise
= error "vsrc2 : No internal model defined"
--- Model Equations ------------------------------------------
where v = vp * (sin trad)
trad = (2 * pi / t) * tt * (trSteps z0)
tt = (simParam (simInfo z0))!!0
t = 1 / f
--------------------------------------------------------
-- sinewave with voltage stepping
vsrc4 :: Int -> Int -> Int -> Double ->Double -> VStep -> ESim -> [Device]
vsrc4 name p1 p2 vp f v0 z0 | (simType (simInfo z0)) == OP
= (vsrc2 name p1 p2 0 v0 z0)
| (simType (simInfo z0)) == TRANS
= (vsrc2 name p1 p2 v v0 z0)
| otherwise
= error "vsrc2 : No internal model defined"
--- Model Equations ------------------------------------------
where v = vp * (sin trad)
trad = (2 * pi / t) * tt * (trSteps z0)
tt = (simParam (simInfo z0))!!0
t = 1 / f
--------------------------------------------------------
-- vsrc5 - piecewise voltage source without voltage stepping.
vsrc5 :: Int -> Int -> Int -> [(Double,Double)] -> ESim -> [Device]
vsrc5 name p1 p2 vl z0 | (simType (simInfo z0)) == OP
= (vsrc1 name p1 p2 0 z0)
| (simType (simInfo z0)) == TRANS
= (vsrc1 name p1 p2 v z0)
| otherwise
= error "vsrc5 : No internal model defined"
--- Model Equations ------------------------------------------
where v = vp (zl (trSteps z0)) vl
--vp _ [] = fst (last vl)
vp z (v:vs) | z == 0 = fst v
| length (v:vs) == 1 = fst (last vl)
| z < snd (head vs) / tt && slope > 0
= fst v + ((z - snd v / tt) * slope)
| z < snd (head vs) / tt && slope < 0
= fst v + ((z - snd v / tt) * slope)
| otherwise = vp z vs
where slope = (fst (head vs) - fst v) /
((snd (head vs) / tt) -
snd v / tt)
tt = (simParam (simInfo z0))!!0
end = truncate ((snd (last vl)) / tt)
zl tr = 0 + (fromInteger ((truncate tr) `rem` end))
--------------------------------------------------------
-- vsrc6 - piecewise voltage source with voltage stepping.
vsrc6 :: Int -> Int -> Int -> [(Double,Double)] -> VStep -> ESim -> [Device]
vsrc6 name p1 p2 vl v0 z0 | (simType (simInfo z0)) == OP
= (vsrc2 name p1 p2 0 v0 z0)
| (simType (simInfo z0)) == TRANS
= (vsrc2 name p1 p2 v v0 z0)
| otherwise
= error "vsrc6 : No internal model defined"
--- Model Equations ------------------------------------------
where v = vp (zl (trSteps z0)) vl
vp z (v:vs) | z <= (snd v / tt) = fst v
| length (v:vs) == 1 = fst (last vl)
| z < snd (head vs) / tt && slope > 0
= fst v + ((z - snd v / tt) * slope)
| z < snd (head vs) / tt && slope < 0
= fst v + ((z - snd v / tt) * slope)
| otherwise = vp z vs
where slope = (fst (head vs) - fst v) /
((snd (head vs) / tt) -
snd v / tt)
tt = (simParam (simInfo z0))!!0
end = truncate ((snd (last vl)) / tt)
zl tr = 0 + (fromInteger ((truncate tr) `rem` end))
--------------------------------------------------------
-- ideal transformer
trf1 :: Int -> Int -> Int -> Int -> Int -> Double -> ESim -> [Device]
trf1 name p1 p2 p3 p4 a z0 | (simType (simInfo z0)) == OP
= (vcvs1 (nn!!0) (ii!!0) p3 p2 p1 a z0) ++
(cccs1 (nn!!1) p1 p2 p4 (ii!!0) a z0)
| (simType (simInfo z0)) == TRANS
= (vcvs1 (nn!!0) (ii!!0) p3 p2 p1 a z0) ++
(cccs1 (nn!!1) p1 p2 p4 (ii!!0) a z0)
| otherwise
= error "trf1 : No internal model defined"
--- Model Equations ------------------------------------------
where
-- Helper Programs -------------------------------------
nn = [(name * 100)..]
ii = [(name * 100)..]
ivsrc src z = (z!!((idx src j)
+ ((length i) - 1)))
where idx n l = fromJust (elemIndex n l)
vnode node z | node == 0 = 0
| otherwise = z!!(nn' - 1)
where nn' = fromJust (elemIndex node i)
j = nSRC (simInfo z0)
i = nNODE (simInfo z0)
--------------------------------------------------------
|