comparison sim.py @ 12:49939e179c86

Run 4 simulations at once. Since this requires the function arguments to be pickleable we pass the DB filename around.
author Daniel O'Connor <darius@dons.net.au>
date Sat, 18 Nov 2023 12:03:13 +1030
parents 8d34a9eec184
children ac2ff6be22f7
comparison
equal deleted inserted replaced
11:8d34a9eec184 12:49939e179c86
28 cmd = [simexe, '-b'] 28 cmd = [simexe, '-b']
29 cmd.extend(simflags) 29 cmd.extend(simflags)
30 cmd.append(runname.name) 30 cmd.append(runname.name)
31 #print(' '.join(map(shlex.quote, cmd))) 31 #print(' '.join(map(shlex.quote, cmd)))
32 then = datetime.datetime.now() 32 then = datetime.datetime.now()
33 print(f'Starting run {runname} at {then}')
33 p = subprocess.Popen(cmd, cwd = rundir) 34 p = subprocess.Popen(cmd, cwd = rundir)
34 p.communicate() 35 p.communicate()
35 now = datetime.datetime.now() 36 now = datetime.datetime.now()
36 taken = now - then 37 taken = now - then
37 38
78 if ipeak > imax: 79 if ipeak > imax:
79 cost += (ipeak - imax) * 5 80 cost += (ipeak - imax) * 5
80 81
81 return cost 82 return cost
82 83
83 def fn(v, cur, simexe, simflags, rundir, circ, ctr): 84 def fn(v, dsn, simexe, simflags, rundir, circ):
84 '''Called by differential_evolution, v contains the evolved parameters, the rest are passed in from the args parameter'. 85 '''Called by differential_evolution, v contains the evolved parameters, the rest are passed in from the args parameter'.
85 Returns the cost value which is being minimised''' 86 Returns the cost value which is being minimised'''
86 87
87 # Get parameters for run 88 # Get parameters for run
88 duty, c1, c2, l1, l2 = v 89 duty, c1, c2, l1, l2 = v
89 90
90 # Check if this combination has already been tried 91 # Check if this combination has already been tried
92 dbh = sqlite3.connect(dsn)
93 cur = dbh.cursor()
91 cur.execute('SELECT run, power, efficiency, thd, ipeak FROM GAN190 WHERE duty = ? AND c1 = ? AND c2 = ? AND l1 = ? AND l2 = ?', (duty, c1, c2, l1, l2)) 94 cur.execute('SELECT run, power, efficiency, thd, ipeak FROM GAN190 WHERE duty = ? AND c1 = ? AND c2 = ? AND l1 = ? AND l2 = ?', (duty, c1, c2, l1, l2))
92 tmp = cur.fetchone() 95 tmp = cur.fetchone()
93 if tmp is not None: 96 if tmp is not None:
94 run, power, eff, thd, ipeak = tmp 97 run, power, eff, thd, ipeak = tmp
95 # Recalculate the cost since it is cheap and might have been tweaked since the original run 98 # Recalculate the cost since it is cheap and might have been tweaked since the original run
96 cost = calccost(power, eff, thd, ipeak) 99 cost = calccost(power, eff, thd, ipeak)
97 print(f'Found run {run:3d}: Duty {duty:3.0f}%, C1 {c1:3.0f}pF, C2 {c2:3.0f}pF, L1 {l1:3.0f}uH, L2 {l2:4.0f}nH -> Power: {power:6.1f}W Efficiency: {eff:5.1f}% THD: {thd:5.1f}% IPeak: {ipeak:4.1f}A Cost: {cost:6.2f}') 100 print(f'Found run {run:3d}: Duty {duty:3.0f}%, C1 {c1:3.0f}pF, C2 {c2:3.0f}pF, L1 {l1:3.0f}uH, L2 {l2:4.0f}nH -> Power: {power:6.1f}W Efficiency: {eff:5.1f}% THD: {thd:5.1f}% IPeak: {ipeak:4.1f}A Cost: {cost:6.2f}')
98 return cost 101 return cost
99 102
100 # Get next run number 103 # Get next run number
101 run = next(ctr) 104 cur.execute('BEGIN DEFERRED')
105 cur.execute('INSERT INTO GAN190 DEFAULT VALUES RETURNING rowid')
106 run = cur.fetchone()[0]
107 cur.execute('COMMIT')
102 108
103 # Run the simulation 109 # Run the simulation
104 # Need to convert units to suit 110 # Need to convert units to suit
105 runname = pathlib.Path(circ).stem + '-' + str(run) + '.net' 111 runname = pathlib.Path(circ).stem + '-' + str(run) + '.net'
106 then, taken, power, eff, thd, ipeak = simulate(circ, simexe, simflags, rundir, runname, 112 then, taken, power, eff, thd, ipeak = simulate(circ, simexe, simflags, rundir, runname,
109 cost = calccost(power, eff, thd, ipeak) 115 cost = calccost(power, eff, thd, ipeak)
110 116
111 # Log & save the results 117 # Log & save the results
112 print(f'Run {run:3d}: Duty {duty:3.0f}%, C1 {c1:3.0f}pF, C2 {c2:3.0f}pF, L1 {l1:3.0f}uH, L2 {l2:4.0f}nH -> Power: {power:6.1f}W Efficiency: {eff:5.1f}% THD: {thd:5.1f}% IPeak: {ipeak:4.1f}A Cost: {cost:6.2f}') 118 print(f'Run {run:3d}: Duty {duty:3.0f}%, C1 {c1:3.0f}pF, C2 {c2:3.0f}pF, L1 {l1:3.0f}uH, L2 {l2:4.0f}nH -> Power: {power:6.1f}W Efficiency: {eff:5.1f}% THD: {thd:5.1f}% IPeak: {ipeak:4.1f}A Cost: {cost:6.2f}')
113 taken = taken.seconds + taken.microseconds / 1e6 119 taken = taken.seconds + taken.microseconds / 1e6
114 cur.execute('INSERT INTO GAN190 (name, run, start, duration, duty, c1, c2, l1, l2, power, efficiency, thd, ipeak, cost) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', 120 cur.execute('BEGIN DEFERRED')
121 cur.execute('REPLACE INTO GAN190 (name, run, start, duration, duty, c1, c2, l1, l2, power, efficiency, thd, ipeak, cost) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
115 (runname, run, then, taken, duty, c1, c2, l1, l2, power, eff, thd, ipeak, cost)) 122 (runname, run, then, taken, duty, c1, c2, l1, l2, power, eff, thd, ipeak, cost))
116 cur.execute('COMMIT') 123 cur.execute('COMMIT')
117 124
118 return cost 125 return cost
119 126
120 def ev(): 127 def ev():
121 # Bounds for parameters 128 # Bounds for parameters
129 # Note that the parameters are also constrained to be integral
122 bounds = [(10, 80), 130 bounds = [(10, 80),
123 (1, 20), 131 (1, 20),
124 (10, 300), 132 (10, 300),
125 (1, 20), 133 (1, 20),
126 (10, 500)] 134 (10, 500)]
135
127 # Initial solution 136 # Initial solution
128 x0 = [36, 10, 155, 5, 140] 137 x0 = [36, 10, 155, 5, 140]
129 dbh = sqlite3.connect('results.db') 138
139 # Where to save results
140 dsn = 'results.db'
141 dbh = sqlite3.connect(dsn)
130 cur = dbh.cursor() 142 cur = dbh.cursor()
131 cur.execute(''' 143 cur.execute('''
132 CREATE TABLE IF NOT EXISTS GAN190 ( 144 CREATE TABLE IF NOT EXISTS GAN190 (
133 name TEXT, -- Circuit name 145 name TEXT, -- Circuit name
134 run INTEGER, -- Run number 146 run INTEGER, -- Run number
143 efficiency REAL, -- Measured efficiency (%) 155 efficiency REAL, -- Measured efficiency (%)
144 thd REAL, -- Total harmonic distortion (%) 156 thd REAL, -- Total harmonic distortion (%)
145 ipeak REAL, -- Peak drain current (A) 157 ipeak REAL, -- Peak drain current (A)
146 cost REAL -- Calculated cost metric 158 cost REAL -- Calculated cost metric
147 );''') 159 );''')
148 def ctr(): 160
149 i = 0
150 while True:
151 yield i
152 i += 1
153 return differential_evolution(fn, bounds, x0 = x0, 161 return differential_evolution(fn, bounds, x0 = x0,
154 args = (cur, '/Users/oconnd1/bin/runltspice', ['-alt'], 'tmp', 'pa-GAN190-PP-nodriver.net', ctr()), 162 args = (dsn, '/Users/oconnd1/bin/runltspice', [], 'tmp', 'pa-GAN190-PP-nodriver.net'),
155 integrality = True, disp = True, seed = 12345) 163 integrality = True, disp = True, seed = 12345, updating = 'deferred', workers = 4)