# HG changeset patch # User Daniel O'Connor # Date 1700227025 -37800 # Node ID 2832aefd442cdf451062d6277a76305f502b8bbc # Parent 66aa1acc90cd0073263482900d096791e980f764 Add 'no driver' version which can simulate in normal mode. Add Python code to optimise design. diff -r 66aa1acc90cd -r 2832aefd442c .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Fri Nov 17 23:47:05 2023 +1030 @@ -0,0 +1,3 @@ +tmp +__pycache__ +.*~ diff -r 66aa1acc90cd -r 2832aefd442c pa-GAN190-PP-nodriver.asc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pa-GAN190-PP-nodriver.asc Fri Nov 17 23:47:05 2023 +1030 @@ -0,0 +1,211 @@ +Version 4 +SHEET 1 2852 992 +WIRE 1040 144 944 144 +WIRE 1072 144 1040 144 +WIRE 1120 144 1072 144 +WIRE 1312 144 1200 144 +WIRE 1424 144 1312 144 +WIRE 1584 144 1424 144 +WIRE 1664 144 1648 144 +WIRE 1840 144 1744 144 +WIRE 240 192 224 192 +WIRE 288 192 240 192 +WIRE 576 192 288 192 +WIRE 656 192 576 192 +WIRE 1312 192 1312 144 +WIRE 224 240 224 192 +WIRE 288 240 288 192 +WIRE 576 240 288 240 +WIRE 944 240 944 224 +WIRE 1936 240 1904 240 +WIRE 1968 240 1936 240 +WIRE 656 272 656 192 +WIRE 704 272 656 272 +WIRE 1216 272 784 272 +WIRE 1584 272 1584 144 +WIRE 1424 304 1424 144 +WIRE 1840 304 1840 144 +WIRE 1904 304 1904 240 +WIRE 1968 304 1968 240 +WIRE 576 384 576 240 +WIRE 704 384 576 384 +WIRE 1328 384 784 384 +WIRE 1904 432 1904 384 +WIRE 1968 432 1968 384 +WIRE 1968 432 1904 432 +WIRE 1968 448 1968 432 +WIRE 224 480 224 320 +WIRE 448 480 224 480 +WIRE 1312 480 1312 352 +WIRE 1424 480 1424 464 +WIRE 1424 480 1312 480 +WIRE 1584 480 1584 336 +WIRE 1584 480 1424 480 +WIRE 448 512 448 480 +WIRE 1424 512 1424 480 +WIRE 1072 608 1072 144 +WIRE 1120 608 1072 608 +WIRE 1312 608 1200 608 +WIRE 1424 608 1312 608 +WIRE 1584 608 1424 608 +WIRE 1664 608 1648 608 +WIRE 1824 608 1744 608 +WIRE 1840 608 1840 384 +WIRE 1840 608 1824 608 +WIRE 368 656 224 656 +WIRE 576 656 368 656 +WIRE 656 656 576 656 +WIRE 1312 656 1312 608 +WIRE 224 704 224 656 +WIRE 368 704 368 656 +WIRE 576 704 368 704 +WIRE 384 736 352 736 +WIRE 656 736 656 656 +WIRE 704 736 656 736 +WIRE 1216 736 784 736 +WIRE 1584 736 1584 608 +WIRE 1424 768 1424 608 +WIRE 576 848 576 704 +WIRE 704 848 576 848 +WIRE 1328 848 784 848 +WIRE 224 928 224 784 +WIRE 448 928 224 928 +WIRE 1312 944 1312 816 +WIRE 1424 944 1424 928 +WIRE 1424 944 1312 944 +WIRE 1584 944 1584 800 +WIRE 1584 944 1424 944 +WIRE 448 976 448 928 +WIRE 1424 976 1424 944 +FLAG 448 512 0 +FLAG 576 192 D0 +FLAG 240 192 RFDrive +FLAG 1840 144 RFOutA +FLAG 1040 144 HV +FLAG 1312 144 SW0 +FLAG 816 240 0 +FLAG 944 240 0 +FLAG 1424 512 0 +FLAG 448 976 0 +FLAG 576 656 D1 +FLAG 1312 608 SW1 +FLAG 1424 976 0 +FLAG 224 656 nRFDrive +FLAG 1824 608 RFOutB +FLAG 1968 448 0 +FLAG 1936 240 RFOut +FLAG 1840 688 0 +SYMBOL Voltage 224 224 R0 +WINDOW 3 -185 128 Left 2 +SYMATTR Value PULSE(0 12 0 1.5n 1.5n {Ton} {Tperiod}) +SYMATTR InstName V3 +SYMBOL Voltage 944 128 R0 +WINDOW 0 -8 -4 Left 2 +SYMATTR InstName V4 +SYMATTR Value 100 +SYMATTR SpiceLine Rser=10m Cpar=1p +SYMBOL ind 1104 160 R270 +WINDOW 0 32 56 VTop 2 +WINDOW 3 5 56 VBottom 2 +SYMATTR InstName L1 +SYMATTR Value {L1} +SYMATTR SpiceLine Rser=35m +SYMBOL ind 1648 160 R270 +WINDOW 0 32 56 VTop 2 +WINDOW 3 -8 58 VBottom 2 +SYMATTR InstName L2 +SYMATTR Value {L2} +SYMATTR SpiceLine Rser=35m +SYMBOL cap 1648 128 R90 +WINDOW 0 0 32 VBottom 2 +WINDOW 3 40 27 VTop 2 +SYMATTR InstName C2 +SYMATTR Value {C2} +SYMBOL cap 1600 336 R180 +WINDOW 0 24 56 Left 2 +WINDOW 3 30 8 Left 2 +SYMATTR InstName C1 +SYMATTR Value {C1} +SYMBOL Res 1952 288 R0 +WINDOW 0 32 43 Left 2 +SYMATTR InstName R1 +SYMATTR Value {R1} +SYMBOL Res 800 256 R90 +WINDOW 0 0 56 VBottom 2 +WINDOW 3 35 59 VTop 2 +SYMATTR InstName R4 +SYMATTR Value 0 +SYMBOL Res 800 368 R90 +WINDOW 0 0 56 VBottom 2 +WINDOW 3 36 53 VTop 2 +SYMATTR InstName R2 +SYMATTR Value 0 +SYMBOL GAN190-650FBE 1296 272 R0 +WINDOW 3 -54 59 Left 1 +SYMATTR InstName U2 +SYMBOL GAN190-650FBE 1408 384 R0 +WINDOW 3 -62 66 Left 1 +SYMATTR InstName U3 +SYMBOL ind 1104 624 R270 +WINDOW 0 32 56 VTop 2 +WINDOW 3 5 56 VBottom 2 +SYMATTR InstName L4 +SYMATTR Value {L1} +SYMATTR SpiceLine Rser=35m +SYMBOL ind 1648 624 R270 +WINDOW 0 32 56 VTop 2 +WINDOW 3 -8 58 VBottom 2 +SYMATTR InstName L5 +SYMATTR Value {L2} +SYMATTR SpiceLine Rser=35m +SYMBOL cap 1648 592 R90 +WINDOW 0 0 32 VBottom 2 +WINDOW 3 40 27 VTop 2 +SYMATTR InstName C4 +SYMATTR Value {C2} +SYMBOL cap 1600 800 R180 +WINDOW 0 24 56 Left 2 +WINDOW 3 30 8 Left 2 +SYMATTR InstName C5 +SYMATTR Value {C1} +SYMBOL Res 800 720 R90 +WINDOW 0 0 56 VBottom 2 +WINDOW 3 35 59 VTop 2 +SYMATTR InstName R3 +SYMATTR Value 0 +SYMBOL Res 800 832 R90 +WINDOW 0 0 56 VBottom 2 +WINDOW 3 36 53 VTop 2 +SYMATTR InstName R5 +SYMATTR Value 0 +SYMBOL GAN190-650FBE 1296 736 R0 +WINDOW 3 -54 59 Left 1 +SYMATTR InstName U5 +SYMBOL GAN190-650FBE 1408 848 R0 +WINDOW 3 -62 66 Left 1 +SYMATTR InstName U6 +SYMBOL ind2 1824 288 R0 +WINDOW 0 20 1 Left 2 +WINDOW 3 -46 112 Left 2 +SYMATTR InstName L3 +SYMATTR Value 100n +SYMATTR Type ind +SYMBOL ind2 1888 288 R0 +WINDOW 0 26 2 Left 2 +WINDOW 3 14 112 Left 2 +SYMATTR InstName L6 +SYMATTR Value 100n +SYMATTR Type ind +SYMBOL Res 1824 592 R0 +SYMATTR InstName R6 +SYMATTR Value 10Meg +SYMBOL Voltage 224 688 R0 +WINDOW 3 -185 128 Left 2 +SYMATTR Value PULSE(0 12 {Tperiod / 2} 1.5n 1.5n {Ton} {TPeriod}) +SYMATTR InstName V5 +TEXT 112 -272 Left 2 !.param F0 = 35.24Meg\n.param Tperiod = 1 / {F0}\n.param dutypct = 20\n.param Ton = 1 / {F0} * {dutypct} / 100\n.param C1 = 10p\n.param C2 = 111p\n.param L1 = 4u\n.param L2 = 207n\n.param R1 = 12.5 +TEXT 600 -280 Left 2 !.meas PIN_HV AVG abs(V(HV)*I(V4))\n.meas POUT AVG abs(V(RFOut)*I(R1))\n.meas Efficiency Param 100*POUT/PIN_HV\n.meas IPEAK_U2 max(abs(Ix(U2:Drain)))\n.meas V_IPEAK_U2 FIND abs(V(SW0)) WHEN Ix(U2:Drain) = IPEAK_U2 * 0.999 cross=1\n.meas VPEAK_U2 max(abs(V(SW0)))\n.meas I_VPEAK_U2 FIND abs(Ix(U2:Drain)) WHEN V(SW0) = VPEAK_U2 * 0.999 cross=1\n.meas IPEAK_U5 max(abs(Ix(U5:Drain)))\n.meas VPEAK_U5 max(abs(V(SW1))) +TEXT 600 -16 Left 2 !*.tran 0 1.8u 1.7u\n.tran 0 5u 1.7u\n*.tran 0 2.5u 1.5u\n*.tran 0 5u +TEXT 120 56 Left 2 !.fourier {F0} 9 -1 V(rfout) +TEXT 104 -56 Left 2 !*.step param dutypct 20 60 4\n*.step param C1 10p 130p 10p\n*.step param C2 80p 195p 5p\n*.step param L2 80n 220n 10n +TEXT 1792 336 Left 2 !K1 L3 L6 1 diff -r 66aa1acc90cd -r 2832aefd442c pa-GAN190-PP-nodriver.log.plt Binary file pa-GAN190-PP-nodriver.log.plt has changed diff -r 66aa1acc90cd -r 2832aefd442c pa-GAN190-PP-nodriver.plt Binary file pa-GAN190-PP-nodriver.plt has changed diff -r 66aa1acc90cd -r 2832aefd442c pa-GAN190-PP.asc --- a/pa-GAN190-PP.asc Sat Oct 21 14:17:33 2023 +1030 +++ b/pa-GAN190-PP.asc Fri Nov 17 23:47:05 2023 +1030 @@ -14,7 +14,6 @@ WIRE 1584 144 1424 144 WIRE 1664 144 1648 144 WIRE 1840 144 1744 144 -WIRE 1936 144 1840 144 WIRE 240 192 224 192 WIRE 288 192 240 192 WIRE 384 192 288 192 @@ -28,8 +27,8 @@ WIRE 576 240 512 240 WIRE 816 240 816 224 WIRE 944 240 944 224 -WIRE 2032 240 2000 240 -WIRE 2064 240 2032 240 +WIRE 1936 240 1904 240 +WIRE 1968 240 1936 240 WIRE 384 272 352 272 WIRE 656 272 656 192 WIRE 704 272 656 272 @@ -38,19 +37,19 @@ WIRE 352 304 352 272 WIRE 384 304 352 304 WIRE 1424 304 1424 144 -WIRE 1936 304 1936 144 -WIRE 2000 304 2000 240 -WIRE 2064 304 2064 240 +WIRE 1840 304 1840 144 +WIRE 1904 304 1904 240 +WIRE 1968 304 1968 240 WIRE 352 384 352 304 WIRE 448 384 448 336 WIRE 448 384 352 384 WIRE 576 384 576 240 WIRE 704 384 576 384 WIRE 1328 384 784 384 -WIRE 2000 432 2000 384 -WIRE 2064 432 2064 384 -WIRE 2064 432 2000 432 -WIRE 2064 448 2064 432 +WIRE 1904 432 1904 384 +WIRE 1968 432 1968 384 +WIRE 1968 432 1904 432 +WIRE 1968 448 1968 432 WIRE 128 480 128 320 WIRE 224 480 224 320 WIRE 224 480 128 480 @@ -74,8 +73,8 @@ WIRE 1584 608 1424 608 WIRE 1664 608 1648 608 WIRE 1824 608 1744 608 -WIRE 1936 608 1936 384 -WIRE 1936 608 1824 608 +WIRE 1840 608 1840 384 +WIRE 1840 608 1824 608 WIRE 368 656 224 656 WIRE 384 656 368 656 WIRE 576 656 512 656 @@ -126,9 +125,9 @@ FLAG 1424 976 0 FLAG 224 656 nRFDrive FLAG 1824 608 RFOutB -FLAG 2064 448 0 -FLAG 2032 240 RFOut -FLAG 1936 688 0 +FLAG 1968 448 0 +FLAG 1936 240 RFOut +FLAG 1840 688 0 SYMBOL Voltage 128 224 R0 WINDOW 3 37 53 Left 2 SYMATTR Value 5 @@ -173,7 +172,7 @@ WINDOW 3 30 8 Left 2 SYMATTR InstName C1 SYMATTR Value {C1} -SYMBOL Res 2048 288 R0 +SYMBOL Res 1952 288 R0 WINDOW 0 32 43 Left 2 SYMATTR InstName R1 SYMATTR Value {R1} @@ -235,28 +234,28 @@ SYMBOL GAN190-650FBE 1408 848 R0 WINDOW 3 -62 66 Left 1 SYMATTR InstName U6 -SYMBOL ind2 1920 288 R0 +SYMBOL ind2 1824 288 R0 WINDOW 0 20 1 Left 2 WINDOW 3 -46 112 Left 2 SYMATTR InstName L3 SYMATTR Value 100n SYMATTR Type ind -SYMBOL ind2 1984 288 R0 +SYMBOL ind2 1888 288 R0 WINDOW 0 26 2 Left 2 WINDOW 3 14 112 Left 2 SYMATTR InstName L6 SYMATTR Value 100n SYMATTR Type ind -SYMBOL Res 1920 592 R0 +SYMBOL Res 1824 592 R0 SYMATTR InstName R6 SYMATTR Value 10Meg SYMBOL Voltage 224 688 R0 WINDOW 3 -185 128 Left 2 SYMATTR Value PULSE(0 5 {Tperiod / 2} 200p 200p {Ton} {TPeriod}) SYMATTR InstName V5 -TEXT 112 -272 Left 2 !.param F0 = 35.24Meg\n.param Tperiod = 1 / {F0}\n.param dutypct = 36\n.param Ton = 1 / {F0} * {dutypct} / 100\n.param C1 = 10p\n.param C2 = 155p\n.param L1 = 5u\n.param L2 = 140n\n.param R1 = 12.5 -TEXT 608 -280 Left 2 !.meas PIN_HV AVG abs(V(HV)*I(V4))\n.meas PIN_MOD AVG abs(V(MOD_RAIL)*I(V2))\n.meas PIN_LV AVG abs(V(VCC)*I(V1))\n.meas POUT AVG abs(V(RFOut)*I(R1))\n.meas Efficiency Param 100*POUT/(PIN_HV + PIN_LV + PIN_MOD) -TEXT 608 -152 Left 2 !*.tran 0 1.8u 1.7u\n*.tran 0 5u 1.7u\n*.tran 0 2.5u 1.5u\n.tran 0 5u -TEXT 608 -16 Left 2 !.fourier {F0} 9 -1 V(rfout) -TEXT 104 -8 Left 2 !*.step param dutypct 20 60 4\n*.step param C1 10p 130p 10p\n*.step param C2 80p 195p 5p\n*.step param L2 80n 220n 10n +TEXT 112 -272 Left 2 !.param F0 = 35.24Meg\n.param Tperiod = 1 / {F0}\n.param dutypct = 20\n.param Ton = 1 / {F0} * {dutypct} / 100\n.param C1 = 10p\n.param C2 = 111p\n.param L1 = 4u\n.param L2 = 207n\n.param R1 = 12.5 +TEXT 600 -280 Left 2 !.meas PIN_HV AVG abs(V(HV)*I(V4))\n.meas PIN_MOD AVG abs(V(MOD_RAIL)*I(V2))\n.meas PIN_LV AVG abs(V(VCC)*I(V1))\n.meas POUT AVG abs(V(RFOut)*I(R1))\n.meas Efficiency Param 100*POUT/(PIN_HV + PIN_LV + PIN_MOD)\n.meas IPEAK_U2 max(abs(Ix(U2:Drain)))\n.meas V_IPEAK_U2 FIND abs(V(SW0)) WHEN Ix(U2:Drain) = IPEAK_U2 * 0.999 cross=1\n.meas VPEAK_U2 max(abs(V(SW0)))\n.meas I_VPEAK_U2 FIND abs(Ix(U2:Drain)) WHEN V(SW0) = VPEAK_U2 * 0.999 cross=1\n.meas IPEAK_U5 max(abs(Ix(U5:Drain)))\n.meas VPEAK_U5 max(abs(V(SW1))) +TEXT 600 -16 Left 2 !*.tran 0 1.8u 1.7u\n.tran 0 5u 1.7u\n*.tran 0 2.5u 1.5u\n*.tran 0 5u +TEXT 120 56 Left 2 !.fourier {F0} 9 -1 V(rfout) +TEXT 104 -56 Left 2 !*.step param dutypct 20 60 4\n*.step param C1 10p 130p 10p\n*.step param C2 80p 195p 5p\n*.step param L2 80n 220n 10n TEXT 1792 336 Left 2 !K1 L3 L6 1 diff -r 66aa1acc90cd -r 2832aefd442c pa-GAN190-PP.plt Binary file pa-GAN190-PP.plt has changed diff -r 66aa1acc90cd -r 2832aefd442c pa-GAN190.asc Binary file pa-GAN190.asc has changed diff -r 66aa1acc90cd -r 2832aefd442c sim.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sim.py Fri Nov 17 23:47:05 2023 +1030 @@ -0,0 +1,148 @@ +import datetime +import pathlib +from scipy.optimize import differential_evolution +from spicelib.simulators.ltspice_simulator import LTspice +from spicelib.log.ltsteps import LTSpiceLogReader +from spicelib.editor.spice_editor import SpiceEditor +#from spicelib.sim.sim_runner import SimRunner +#import shlex +import sqlite3 +import subprocess + +def simulate(src, simexe, simflags, rundir, runname, params): + src = pathlib.Path(src) + runname = pathlib.Path(runname) + assert(runname.suffix == '.net') + rundir = pathlib.Path(rundir) + + e = SpiceEditor(src) + for k in params: + e.set_parameter(k, params[k]) + + #s = SimRunner(simulator = LTspice, output_folder = 'tmp', verbose = True) + #s.simulator.spice_exe = [simexe] + #raw_file, log_file = s.run_now(e, run_filename = runname) + + e.write_netlist(rundir / runname) + + cmd = [simexe, '-b'] + cmd.extend(simflags) + cmd.append(runname.name) + #print(' '.join(map(shlex.quote, cmd))) + then = datetime.datetime.now() + p = subprocess.Popen(cmd, cwd = rundir) + p.communicate() + now = datetime.datetime.now() + taken = now - then + + if p.returncode != 0: + raise Exception('failed') + + #rawpath = rundir / runname.with_suffix('.raw') + #raw = spicelib.RawRead(rawpath) + logpath = rundir / runname.with_suffix('.log') + log = LTSpiceLogReader(logpath) + + power = log.get_measure_value('pout') + eff = log.get_measure_value('efficiency') + thd = log.fourier['V(rfout)'][0].thd + ipeak_u2 = log.get_measure_value('ipeak_u2') + ipeak_u5 = log.get_measure_value('ipeak_u5') + ipeak = max(ipeak_u2, ipeak_u5) + + return then, taken, power, eff, thd, ipeak + + +def fn(v, cur, simexe, simflags, rundir, circ, ctr): + '''Called by differential_evolution, v contains the evolved parameters, the rest are passed in from the args parameter'. + Returns the cost value which is being minimised''' + + # Get parameters for run + duty, c1, c2, l1, l2 = v + + cur.execute('SELECT cost, run, power, efficiency, thd, ipeak FROM GAN190 WHERE duty = ? AND c1 = ? AND c2 = ? AND l1 = ? AND l2 = ?', (duty, c1, c2, l1, l2)) + tmp = cur.fetchone() + if tmp is not None: + cost, run, power, eff, thd, ipeak = tmp + 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}') + return cost + + # Get next run number + run = next(ctr) + + # Run the simulation + # Need to convert units to suit + runname = pathlib.Path(circ).stem + '-' + str(run) + '.net' + then, taken, power, eff, thd, ipeak = simulate(circ, simexe, simflags, rundir, runname, + {'dutypct' : duty, 'C1' : c1 * 1e-12, 'C2' : c2 * 1e-12, 'L1' : l1 * 1e-6, 'L2' : l2 * 1e-9}) + + # Calculate the cost + tpwr = 2000 + tthd = 2 + teff = 90 + imax = 11 + + cost = 0 + if power < tpwr / 2: + cost += 100 + elif power < tpwr: + cost += (tpwr - power) / tpwr / 100 + + if thd > 5 * tthd: + cost += 100 + else: + thdinv = 100 - thd + tthdinv = 100 - tthd + if thdinv < tthdinv: + cost += (tthdinv - thdinv) / tthdinv + if eff < teff: + cost += (teff - eff) / teff + + if ipeak > imax: + cost += (ipeak - imax) * 2 + + # Log & save the results + 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}') + taken = taken.seconds + taken.microseconds / 1e6 + cur.execute('INSERT INTO GAN190 (name, run, start, duration, duty, c1, c2, l1, l2, power, efficiency, thd, ipeak, cost) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + (runname, run, then, taken, duty, c1, c2, l1, l2, power, eff, thd, ipeak, cost)) + cur.execute('COMMIT') + + return cost + +def ev(): + # Bounds for parameters + bounds = [(10, 80), + (1, 20), + (10, 300), + (1, 20), + (10, 500)] + # Initial solution + x0 = [36, 10, 155, 5, 140] + dbh = sqlite3.connect('results.db') + cur = dbh.cursor() + cur.execute(''' +CREATE TABLE IF NOT EXISTS GAN190 ( + name TEXT, -- Circuit name + run INTEGER, -- Run number + start DATETIME, -- Datetime run started + duration REAL, -- Length of run (seconds) + duty REAL, -- Duty cyle (%) + c1 REAL, -- Value of C1 (pF) + c2 REAL, -- Value of C2 (pF) + l1 REAL, -- Value of L1 (uH) + l2 REAL, -- Value of L2 (nH) + power REAL, -- Measured power (Watts) + efficiency REAL, -- Measured efficiency (%) + thd REAL, -- Total harmonic distortion (%) + ipeak REAL, -- Peak drain current (A) + cost REAL -- Calculated cost metric +);''') + def ctr(): + i = 0 + while True: + yield i + i += 1 + return differential_evolution(fn, bounds, x0 = x0, + args = (cur, '/Users/oconnd1/bin/runltspice', ['-alt'], 'tmp', 'pa-GAN190-PP-nodriver.net', ctr()), + integrality = True, disp = True, seed = 12345)