def enforce_minimum_piezo_dimensions(x0): c = cantilever_divingboard(*x0) min_pr_thickness = 30e-9 min_pr_length = 1e-6 min_pr_width = 500e-9 return min(c.l_pr - min_pr_length, c.w_pr - min_pr_width, c.t_pr - min_pr_thickness)
def enforce_minimum_dimensions(x0): c = cantilever_divingboard(*x0) min_thickness = 1e-6 min_length = 20e-6 min_width = 500e-9 return min(c.l - min_length, c.w - min_width, c.t - min_thickness)
def enforce_positive_dimensions(x0): c = cantilever_divingboard(*x0) return min(c.l, c.w, c.t, c.l_pr, c.w_pr, c.w_gap, c.t_pr)
def optimize_cantilever(x0): c = cantilever_divingboard(*x0) return c.force_resolution()
c = cantilever_divingboard(*x0) min_pr_thickness = 30e-9 min_pr_length = 1e-6 min_pr_width = 500e-9 return min(c.l_pr - min_pr_length, c.w_pr - min_pr_width, c.t_pr - min_pr_thickness) def enforce_positive_resolution(x0): c = cantilever_divingboard(*x0) return c.force_resolution() def enforce_minimum_natural_frequency(x0): c = cantilever_divingboard(*x0) min_natural_frequency_hz = 50e3 print 'Force resolution: %f' % c.force_resolution() return (c.omega_vacuum_hz() - min_natural_frequency_hz) c1 = cantilever_divingboard(*x) print 'Cantilever L/W/T: %f %f %f' % (c1.l * 1e6, c1.w * 1e6, c1.t * 1e6) print 'Piezo L/W/T: %f %f %f' % (c1.l_pr * 1e6, c1.w_pr * 1e6, c1.t_pr * 1e6) print 'Resistance: %f' % log10(c1.resistance()) print 'Doping Concentration: %f' % c1.N print 'Force resolution: %f' % c1.force_resolution() print 'Natural freq: %f' % c1.omega_vacuum_hz() # fmin_tnc and blfs won't work, because they don't provide enough constraint flexibility
w = 1e-6 l = 400e-6 l_pr = 1 # estimated from SEM in paper w_pr = 1 t_pr = 1 w_gap = 1 freq_min = 1e1 freq_max = 1e5 V_bias = 5 N = 4e19 beta = 0.7 c = cantilever_divingboard(freq_min, freq_max, l, w, t, l_pr, w_pr, w_gap, t_pr, V_bias, N) # For L = 400e-6 c.l = 400e-6 c.w = 0.1e-6 print c.omega_damped_hz() c.w = 0.5e-6 print c.omega_damped_hz() c.w = 1e-6 print c.omega_damped_hz() c.w = 5e-6 print c.omega_damped_hz()
def enforce_minimum_natural_frequency(x0): c = cantilever_divingboard(*x0) min_natural_frequency_hz = 50e3 print 'Force resolution: %f' % c.force_resolution() return (c.omega_vacuum_hz() - min_natural_frequency_hz)
l = 400e-6 l_pr = 1 # estimated from SEM in paper w_pr = 1 t_pr = 1 w_gap = 1 freq_min = 1e1 freq_max = 1e5 V_bias = 5 N = 4e19 beta = 0.7 c = cantilever_divingboard(freq_min, freq_max, l, w, t, l_pr, w_pr, w_gap, t_pr, V_bias, N) # For L = 400e-6 c.l = 400e-6 c.w = 0.1e-6 print c.omega_damped_hz() c.w = 0.5e-6 print c.omega_damped_hz() c.w = 1e-6 print c.omega_damped_hz() c.w = 5e-6
from cantilever_divingboard import * # Agressive # Minimal thickness and width # Moderative # Conservative v_all = linspace(1, 100, 101) for v_test in v_all: c = cantilever_divingboard( l = 80e-6, w = 500e-9, t = 1e-6, l_pr = 10e-6, w_pr = 500e-9, w_gap = 1e-6, t_pr = 100e-9, V_bias = v_test, N = 4e17, freq_min = 1e0, freq_max = 1e2) print "Resolution (pN): %f Freq (kHz): %f" % (c.force_resolution(), c.omega_damped_hz()/1000)
def enforce_positive_resolution(x0): c = cantilever_divingboard(*x0) return c.force_resolution()
def enforce_maximum_piezo_dimensions(x0): c = cantilever_divingboard(*x0) return min(c.l - c.l_pr, c.w - c.w_pr, c.t - c.t_pr)
from cantilever_divingboard import * def optimize_cantilever(x0): c = cantilever_divingboard(*x0) print x0 return c.force_resolution() x = optimize.anneal(func = optimize_cantilever, x0 = ( 150e-6, 1e-6, 5e-6, 10e-6, 1e-6, 1e-6, 1e-6, 3., 1e15)) c1 = cantilever_divingboard(*x) print 'Cantilever L/W/T: %f %f %f' % (c1.l*1e6, c1.w*1e6, c1.t*1e6) print 'Piezo L/W/T: %f %f %f' % (c1.l_pr*1e6, c1.w_pr*1e6, c1.t_pr*1e6) print 'Resistance: %f' % log10(c1.resistance()) print 'Doping Concentration: %f' % c1.N print 'Force resolution: %f' % c1.force_resolution() print 'Natural freq: %f' % c1.omega_vacuum_hz()
def optimize_cantilever(x0): c = cantilever_divingboard(*x0) print x0 return c.force_resolution()
from cantilever_divingboard import * # We need to scale the parameters before applying the optimization algorithm # Normally there are about 20 orders of magnitude between the dimensions and # the doping concentration, so this is a critical step # Run the script freq_min = 1e3 freq_max = 1e5 omega_min = 100e3 initial_guess = (50e-6, 1e-6, 1e-6, 30e-6, 1e-6, 1e-6, 500e-9, 5., 1e15) constraints = ((30e-6, 100e-6), (500e-9, 20e-6), (1e-6, 10e-6), (2e-6, 100e-6), (500e-9, 5e-6), (500e-9, 20e-6), (30e-9, 10e-6), (1., 10.), (1e15, 4e19)) x = optimize_cantilever(initial_guess, constraints, freq_min, freq_max, omega_min) c = cantilever_divingboard(freq_min, freq_max, x) c.print_performance()
def brute_force(): n = 10 # Number of points to check in each dimension # ASML # 0.45 micron resolution # ??? alignment resolution f_min = 1e2 f_max = 100e3 bandwidth = 100e3 # Others doping = logspace(16, 19, n) bias = linspace(0., 10., n) # Cantilever dimensions length = linspace(10e-6, 100e-6, n) width = linspace(0.45e-6, 10e-6, n) # Min = ASML resolution for frontside DRIE thickness = linspace(100e-9, 10e-6, n) # Min = stability to survive water entry? # For each iteration we'll check that the piezo dimensions are valid first, so match upper limit to length/width/thickness piezo_length = linspace(0.45e-6, max(length), n) piezo_width = linspace(0.45e-6, max(width), n) piezo_gap = linspace(0.45e-6, 10e-6, n) piezo_thickness = linspace(100e-9, max(thickness), n) # Define limits of iteration ii_max = len(doping) jj_max = len(bias) kk_max = len(length) ll_max = len(width) mm_max = len(thickness) nn_max = len(piezo_length) oo_max = len(piezo_width) pp_max = len(piezo_gap) qq_max = len(piezo_thickness) # results = zeros((ii_max, jj_max, kk_max, ll_max, mm_max, nn_max, oo_max, pp_max, qq_max), dtype = Float) min_resolution = 10000. for ii in range(0, ii_max-1): for jj in range(0, jj_max-1): for kk in range(0, kk_max-1): for ll in range(0, ll_max-1): for mm in range(0, mm_max-1): for nn in range(0, nn_max-1): for oo in range(0, oo_max-1): for pp in range(0, pp_max-1): for qq in range(0, qq_max-1): doping_level = doping[ii] bias_voltage = bias[jj] l = length[kk] w = length[ll] t = length[mm] l_pr = length[nn] w_pr = length[oo] w_gap = length[pp] t_pr = length[qq] # Check dimensions are okay, if not skip onto the next for loop iteration if (l_pr >= l) or (w_pr >= w) or (t_pr >= t) or (bias_voltage == 0): continue print bias_voltage c1 = cantilever_divingboard(l, w, t, l_pr, w_pr, w_gap, t_pr, V_bias = bias_voltage, N = doping_level) # print 'Cantilever L/W/T: %f %f %f' % (c1.l*1e6, c1.w*1e6, c1.t*1e6) # print 'Piezo L/W/T: %f %f %f' % (c1.l_pr*1e6, c1.w_pr*1e6, c1.t_pr*1e6) # print 'Doping: %f' % log10(c1.N) # print 'Resistance: %f' % c1.resistance() # print "Integrated noise: %f" % (c1.integrated_noise()*1e8) # print "Sensitivity: %f" % c1.force_sensitivity() # print 'Force resolution: %f' % (c1.force_resolution()*1e12) # print 'Natural freq: %f' % c1.omega_vacuum_hz() # print '\n' if (c1.omega_vacuum_hz() > bandwidth): # results[ii, jj, kk, ll, mm, nn, oo, pp, qq] = c.force_resolution() # print c1.force_resolution()*1e12 if (c1.force_resolution() < min_resolution): min_resolution = c1.force_resolution() return min_resolution
from cantilever_divingboard import * # Agressive # Minimal thickness and width # Moderative # Conservative v_all = linspace(1, 100, 101) for v_test in v_all: c = cantilever_divingboard(l=80e-6, w=500e-9, t=1e-6, l_pr=10e-6, w_pr=500e-9, w_gap=1e-6, t_pr=100e-9, V_bias=v_test, N=4e17, freq_min=1e0, freq_max=1e2) print "Resolution (pN): %f Freq (kHz): %f" % (c.force_resolution(), c.omega_damped_hz() / 1000)