def traceSPO(R, L, F, N, M, span=pi / 12, d=.605, t=.775): """Trace SPO surfaces sequentially. Collect rays from each SPO shell and set them to the PT rays at the end. Start at the inner radius, use the wafer and pore thicknesses to vignette and compute the next radius, loop while radius is less than Rout. """ #Ray bookkeeping arrays tx = np.zeros(M * N) ty = np.zeros(M * N) tz = np.zeros(M * N) tl = np.zeros(M * N) tm = np.zeros(M * N) tn = np.zeros(M * N) tux = np.zeros(M * N) tuy = np.zeros(M * N) tuz = np.zeros(M * N) #Loop through shell radii and collect rays for i in range(M): #Set up source annulus PT.subannulus(R[i], R[i] + d, span, N) #Transform rays to be above xy plane PT.n = -PT.n PT.transform(0, 0, -100., 0, 0, 0) #Trace to primary PT.spoPrimary(R[i], F) PT.reflect() #Vignette ind = np.logical_and(PT.z <= L[i], PT.z >= 0.) if np.sum(ind) < N: pdb.set_trace() PT.vignette(np.logical_and(PT.z <= L[i], PT.z >= 0.)) #Trace to secondary PT.spoSecondary(R[i], F) PT.reflect() #Vignette ind = np.logical_and(PT.z <= 0., PT.z >= -L[i]) if np.sum(ind) < N: pdb.set_trace() PT.vignette(ind) #Collect rays try: tx[i * N:(i + 1) * N] = PT.x ty[i * N:(i + 1) * N] = PT.y tz[i * N:(i + 1) * N] = PT.z tl[i * N:(i + 1) * N] = PT.l tm[i * N:(i + 1) * N] = PT.m tn[i * N:(i + 1) * N] = PT.n tux[i * N:(i + 1) * N] = PT.ux tuy[i * N:(i + 1) * N] = PT.uy tuz[i * N:(i + 1) * N] = PT.uz except: pdb.set_trace() #Set to PT rays try: PT.x = tx PT.y = ty PT.z = tz PT.l = tl PT.m = tm PT.n = tn PT.ux = tux PT.uy = tuy PT.uz = tuz except: pdb.set_trace() return
def traceCyl(align): """Traces a cylindrical approximation to Wolter I geometry Assumes 1 m radius of curvature in accordance with OAB samples align is a 12 element array giving the transformations to be applied to each mirror Uses identical set of rays each run defined upon module import Adds a restraint such that any vignetting over 25% results in a huge merit function """ #Set up source np.random.seed(5) a, p, d, e = con.woltparam(1000., 10000.) r0 = con.primrad(10025., 1000., 10000.) r1 = con.primrad(10125., 1000., 10000.) dphi = 100. / 1000. PT.subannulus(r0, r1, dphi, 10**4) PT.transform(0, 0, 0, np.pi, 0, 0) PT.transform(0, 0, -10500., 0, 0, 0) #Trace primary cylinder: go to tangent point at center #of mirror and then rotate to cone angle, then move #to new cylinder axis and tracecyl rt = con.primrad(10075., 1000., 10000.) PT.transform(rt, 0, 0, 0, a, 0) PT.transform(*align[:6]) PT.transform(0, 0, 0, np.pi / 2, 0, 0) PT.transform(-1000., 0, 0, 0, 0, 0) PT.cyl(1000.) #Vignette rays missing physical surface ind = np.logical_and(abs(PT.z) < 50., abs(PT.y) < 50.) PT.vignette(ind=ind) #Reflect and reverse transformations PT.reflect() PT.transform(1000., 0, 0, 0, 0, 0) PT.itransform(0, 0, 0, np.pi / 2, 0, 0) PT.itransform(*align[:6]) PT.itransform(rt, 0, 0, 0, a, 0) #Trace secondary cylinder: same principle as before rt = con.secrad(9925., 1000., 10000.) PT.transform(0, 0, -150., 0, 0, 0) PT.transform(rt, 0, 0, 0, 3 * a, 0) PT.transform(*align[6:]) PT.transform(0, 0, 0, np.pi / 2, 0, 0) PT.transform(-1000., 0, 0, 0, 0, 0) PT.cyl(1000.) #Vignette rays missing physical surface ind = np.logical_and(abs(PT.z) < 50., abs(PT.y) < 50.) PT.vignette(ind=ind) #Reflect and reverse transformations PT.reflect() PT.transform(1000., 0, 0, 0, 0, 0) PT.itransform(0, 0, 0, np.pi / 2, 0, 0) PT.itransform(*align[6:]) PT.itransform(rt, 0, 0, 0, 3 * a, 0) #Go down to nominal focus PT.transform(0, 0, -9925., 0, 0, 0) PT.flat() #Compute merit function nom = PT.rmsCentroid() / 10**4 * 180. / np.pi * 60**2 nom = nom + max((9500. - np.size(PT.x)), 0.) return nom