larsupilami73

chaos_circuit_high_res.py

Jul 10th, 2019
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.55 KB | None | 0 0
  1. #!/usr/bin/python3
  2. #high resolution attractor rendering of simple chaotic RC oscillator with ngspice
  3. #https://www.researchgate.net/publication/277939627_Simple_Two-Transistor_Single-Supply_Resistor-Capacitor_Chaotic_Oscillator
  4.  
  5. import os
  6. from scipy import  *
  7. import matplotlib.pyplot as plt
  8. import multiprocessing
  9.  
  10.  
  11. def do_sim(R4,n):
  12.     #random initial condition
  13.     random.seed(n)
  14.     v3,v4,v5,v6 = random.uniform(low=0,high=2,size=4)
  15.     outfilename = 'out_%i.dat' %n
  16.     circuitfilename = 'circuit_%i' %n
  17.     #prepare the circuit file
  18.     f=open(circuitfilename,'w')
  19.     f.write("""*** RC Chaos Generator ***
  20.  
  21. * Supply
  22. vcc 1 0 5.0V
  23.  
  24. * Circuit
  25. R1 1 2 5k
  26. R2 4 7 15k
  27. R3 2 6 30k
  28. R4 6 0 %f
  29. R6 2 3 5k
  30. R7 3 4 10k
  31. R8 4 5 10k
  32. C1 3 0 1nF ic=%f
  33. C3 4 0 1nF ic=%f
  34. C4 5 0 1nF ic=%f
  35. C2 6 0 360pF ic=%f
  36. Q1 2 5 0 BC547C
  37. Q2 7 6 0 BC547C
  38.  
  39. .model BC547C NPN(Is=32f Xti=3 Eg=1.11 Vaf=100 Bf=720
  40. + Xtb=1.5 Br=6.313 Isc=138f Nc=2.053 Rb=1.3k
  41. + Ikf=500m Ise=230f Ne=1.583
  42. + Ikr=.187 Rc=.4216 Cjc=5.25p Mjc=.3147 Vjc=.5697 Fc=.5 Cje=11.5p
  43. + Mje=.3333 Vje=.5 Tr=10n Tf=410.7p Itf=2.204 Xtf=66.65 Vtf=10)
  44.  
  45. * Other model
  46. .model BC547CV2   NPN(Is=7.049f Xti=3 Eg=1.11 Vaf=24.76 Bf=543.1 Ise=78.17f
  47. +               Ne=1.679 Ikf=94.96m Nk=.5381 Xtb=1.5 Br=1 Isc=27.51f Nc=1.775
  48. +               Ikr=3.321 Rc=.9706 Cjc=5.25p Mjc=.3147 Vjc=.5697 Fc=.5
  49. +               Cje=11.5p Mje=.6715 Vje=.5 Tr=10n Tf=410.7p Itf=1.12 Xtf=26.19
  50. +               Vtf=10)
  51. *       PHILIPS     pid=bc547c  case=TO92
  52. *       91-07-31 dsq
  53.  
  54. * Simulations
  55. .control
  56. tran 5ns 20ms uic
  57.  
  58. wrdata %s  v(2) v(3) v(4) v(5) v(6)
  59. exit
  60. .endc
  61. .end
  62.     """ %(R4,v3,v4,v5,v6,outfilename))
  63.     f.close()
  64.     #do simulation
  65.     os.system('ngspice %s' %circuitfilename)
  66.     x = genfromtxt(outfilename)
  67.     os.remove('%s' %outfilename)
  68.     os.remove('%s' %circuitfilename)
  69.     return x
  70.  
  71.  
  72. def do_map(V,_):
  73.     #throw away first transient
  74.     t=V[:,0]
  75.     t0=where(t>0.003)[0][0]
  76.     X=V[t0:,7] #1 3 5 7 9
  77.     Y=V[t0:,3]
  78.     Z=V[t0:,5]
  79.     Q=V[t0:,9]
  80.    
  81.     #rescale to figure same for all runs, rel to 1st run found limits
  82.     X = X - xmin
  83.     X = borderx + X * (xdim-2*borderx-1)/(xmax-xmin)
  84.     Y = Y - ymin
  85.     Y = bordery + Y  * (ydim-2*bordery-1)/(ymax-ymin)
  86.    
  87.     Z = (Z - zmin) / (zmax-zmin) #z-axis to 0..1
  88.     Q = (Q - zmin) / (zmax-zmin)
  89.    
  90.     X.clip(0,xdim-1,out=X)
  91.     Y.clip(0,ydim-1,out=Y)
  92.     Z.clip(0,1,out=Z)
  93.     Q.clip(0,1,out=Q)
  94.    
  95.     #change here how you map the values of the simulation to the image
  96.     #three channels are red, green, blue
  97.     #4th one (transparency) could be added too (but haven't tried)
  98.     m = zeros((ydim,xdim,3))
  99.     x0,y0,z0 = X[0],Y[0],Z[0]
  100.     for x,y,z,q in zip(X.round().astype(int),Y.round().astype(int),Z,Q):
  101.         m[y,x,0] += x
  102.         m[y,x,1] += y
  103.         s = sqrt(pow(x-x0,2)+ pow(y-y0,2) + (z-z0)**2)
  104.         x0,y0,z0 = x,y,z
  105.         m[y,x,2] += s
  106.        
  107.         #m[y,x,3]=
  108.    
  109.     return m
  110.    
  111.  
  112. if __name__=='__main__':
  113.     random.seed(42)
  114.     R4 = 44.0e3 #for this value of resistor R4, the circuit is in chaotic regime
  115.     numruns = 4
  116.     numthreads= 4 #8
  117.     borderx = 10
  118.     bordery = 10
  119.     xdim = 2000 #1584
  120.     ydim = 2000 #396
  121.     dpi=150
  122.     szx=xdim/dpi
  123.     szy=ydim/dpi
  124.     M = zeros((ydim,xdim,3))
  125.    
  126.     #do this once to get the extent of the attractor
  127.     V = do_sim(R4,0)
  128.     #throw away first transient
  129.     #throw away first transient
  130.     t=V[:,0]
  131.     t0=where(t>0.003)[0][0]
  132.     X=V[t0:,7]
  133.     Y=V[t0:,3]
  134.     Z=V[t0:,5]
  135.     Q=V[t0:,9]
  136.     xmin,xmax = X.min(),X.max()
  137.     ymin,ymax = Y.min(),Y.max()
  138.     zmin,zmax = Z.min(),Z.max()
  139.     qmin,qmax = Q.min(),Q.max()
  140.  
  141.     for k in range(numruns):
  142.         print('run {}:'.format(k))
  143.         print('simulating...')
  144.        
  145.         #simulate
  146.         tasks = [(R4,random.randint(1000000,9999999)) for _ in range(numthreads)]  
  147.         pool = multiprocessing.Pool(numthreads)
  148.         taskoutput = [pool.apply_async(do_sim, params) for params in tasks]
  149.         resultslist = [r.get() for r in taskoutput]
  150.         pool.close()
  151.         pool.join()
  152.  
  153.         #map
  154.         tasks = [(V,0) for V in resultslist]   
  155.         pool = multiprocessing.Pool(numthreads)
  156.         taskoutput = [pool.apply_async(do_map, params) for params in tasks]
  157.         resultslist = [r.get() for r in taskoutput]
  158.         pool.close()
  159.         pool.join()
  160.  
  161.         #add all results
  162.         for m in resultslist:
  163.             M += m
  164.        
  165.     #nonlinear mapping to enhance the trajectories
  166.     M[:,:,0] /= M[:,:,0].max()
  167.     M[:,:,1] /= M[:,:,1].max()
  168.     M[:,:,2] /= M[:,:,2].max()
  169.     M[:,:,0] = pow(M[:,:,0],1/3)
  170.     M[:,:,1] = pow(M[:,:,1],1/3)
  171.     M[:,:,2] = pow(M[:,:,2],1/3)
  172.    
  173.     #M[:,:,3] /= M[:,:,3].max()
  174.     #M[:,:,3] = pow(M[:,:,3],1/3)
  175.    
  176.     print('plotting...')
  177.     fig = plt.figure(frameon=False,figsize=(szx,szy),dpi=dpi)
  178.     ax = fig.add_axes([0, 0, 1, 1])
  179.     ax.axis('off')
  180.     ax.imshow(M)
  181.     plt.savefig('M.png') #,transparant=True
  182.     plt.close('all')
  183.     print('Done!')
Add Comment
Please, Sign In to add comment