Plan 9 from Bell Labs’s /usr/web/sources/contrib/fernan/escomma/Circuit.hs

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


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)    
                        --------------------------------------------------------




Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.