def diffraction_alphaffi(shape, ks, epsv=(1., 1., 1.), epsa=(0., 0., 0.), betamax=BETAMAX, out=None): ks = np.asarray(ks) ks = abs(ks) beta, phi = betaphi(shape, ks) alpha, f, fi = alphaffi(beta, phi, epsv, epsa, out=out) out = (alpha, f, fi) # try: # b1,betamax = betamax # a = (betamax-b1)/(betamax) # m = tukey(beta,a,betamax) # np.multiply(f,m[...,None,None],f) # except: # pass mask0 = (beta >= betamax) #betamax) fi[mask0] = 0. f[mask0] = 0. alpha[mask0] = 0. #return mask, alpha,f,fi return out
def propagate_4x4_full(field, wavenumbers, layer, nsteps=1, betamax=BETAMAX, out=None): shape = field.shape[-2:] d, epsv, epsa = layer kd = wavenumbers * d / nsteps if out is None: out = np.empty_like(field) out_af = None pm = None ii, jj = np.meshgrid(range(shape[0]), range(shape[1]), copy=False, indexing="ij") for step in range(nsteps): for i in range(len(wavenumbers)): ffield = fft2(field[..., i, :, :, :]) ofield = np.zeros_like(out[..., i, :, :, :]) b, p = betaphi(shape, wavenumbers[i]) mask = b < betamax amplitude = ffield[..., mask] betas = b[mask] phis = p[mask] iind = ii[mask] jind = jj[mask] for bp in sorted(zip(range(len(betas)), betas, phis, iind, jind), key=lambda el: el[1], reverse=False): #for j,bp in enumerate(zip(betas,phis,iind,jind)): j, beta, phi, ieig, jeig = bp out_af = alphaffi(beta, phi, epsv, epsa, out=out_af) alpha, f, fi = out_af pm = phasem(alpha, kd[i], out=pm) w = eigenwave(amplitude.shape[:-1] + shape, ieig, jeig, amplitude=amplitude[..., j]) w = dotmdmf(f, pm, fi, w, out=w) np.add(ofield, w, ofield) out[..., i, :, :, :] = ofield field = out return out
def _transfer_ray_4x4_4(field, wavenumbers, layer, beta=0, phi=0, nsteps=1, dmat=None, out=None): d, epsv, epsa = layer if dmat is None: kd = wavenumbers * d else: kd = wavenumbers * d / 2 alpha, f, fi = alphaffi(beta, phi, epsv, epsa) p = phasem(alpha, kd[..., None, None]) for j in range(nsteps): if dmat is None: field = dotmdmf(f, p, fi, field, out=out) else: field = dotmdmf(f, p, fi, field, out=out) field = diffract(field, dmat, out=field) field = dotmdmf(f, p, fi, field, out=field) return field
def _transfer_ray_4x4_3(field, wavenumbers, layer, dmat1, dmat2, beta=0, phi=0, nsteps=1, betamax=BETAMAX, out=None): d, epsv, epsa = layer kd = wavenumbers * d alpha, f, fi = alphaffi(beta, phi, epsv, epsa) p = phasem(alpha, kd[..., None, None]) for j in range(nsteps): field = dotmf(dmat1, field, out=out) field = ifft2(field, out=field) field = dotmdmf(f, p, fi, field, out=field) field = fft2(field, out=field) field = dotmf(dmat2, field, out=out) return field
def _layer_mat2d(k0, d, epsv, epsa, mask, betaxs, betay, indices, method): n = len(betaxs) kd = k0 * d shape = epsv.shape[-2] out = np.empty(shape=(n, n, 4, 4), dtype=CDTYPE) beta = betaxy2beta(betaxs, betay) phi = betaxy2phi(betaxs, betay) for j, (beta, phi) in enumerate(zip(beta, phi)): alpha, f, fi = alphaffi(beta, phi, epsv, epsa) pmat = phase_mat(alpha, -kd) if method == "4x4_1": pmat[..., 1::2] = 0. elif method != "4x4": raise ValueError("Unsupported method!") wave = eigenwave1(shape, indices[j], amplitude=1.) #m is shape (...,4,4) m = dotmdm(f, pmat, fi) #wave is shape (...) make it broadcastable to (...,4,4) mw = m * wave[..., None, None] mf = mfft(mw, overwrite_x=True) mf = mf[mask, ...] out[:, j, :, :] = mf #for i,mfj in enumerate(mf): # out[i,j,:,:] = mfj return out
def field_correction_matrix(beta, phi, ks, d=1., epsv=(1, 1, 1), epsa=(0, 0, 0.), out=None): alpha, f, fi = alphaffi(beta, phi, epsv, epsa) kd = -np.asarray(ks) * d pmat = phase_matrix(alpha, kd) return dotmdm(f, pmat, fi, out=out)
def _layer_mat3d(k0, d, epsv, epsa, mask, betas, phis, indices, method): n = len(betas) kd = k0 * d #/2. shape = epsv.shape[-3], epsv.shape[-2] if method.startswith("2x2"): out = np.empty(shape=(n, n, 2, 2), dtype=CDTYPE) else: out = np.empty(shape=(n, n, 4, 4), dtype=CDTYPE) for j, (beta, phi) in enumerate(zip(betas, phis)): if method.startswith("2x2"): alpha, fmat = alphaf(beta, phi, epsv, epsa) f = tmm.E_mat(fmat, mode=+1, copy=False) fi = inv(f) pmat = phase_mat(alpha[..., ::2], kd) else: alpha, f, fi = alphaffi(beta, phi, epsv, epsa) pmat = phase_mat(alpha, -kd) if method == "4x4_1": pmat[..., 1::2] = 0. if method != "4x4": raise ValueError("Unsupported method.") wave = eigenwave(shape, indices[j, 0], indices[j, 1], amplitude=1.) m = dotmdm(f, pmat, fi) mw = m * wave[..., None, None] mf = mfft2(mw, overwrite_x=True) #dd = np.linspace(0,1.,10)*d # dmat = 0. # for dm in dd: # dmat = dmat + second_field_diffraction_matrix(shape, -k0, beta, phi,dm, # epsv = (1.5,1.5,1.5), # epsa = (0.,0.,0.), betamax = 1.4) /len(dd) # mf = dotmm(dmat,mf) mf = mf[mask, ...] out[:, j, :, :] = mf return out
def _transfer_ray_4x4_2(field, wavenumbers, layer, beta=0, phi=0, nsteps=1, dmatpn=None, out=None, tmpdata=None): _out = {} if tmpdata is None else tmpdata d, epsv, epsa = layer if dmatpn is None: kd = wavenumbers * d else: dmatp, dmatn = dmatpn kd = wavenumbers * d / 2 alpha, f, fi = alphaffi(beta, phi, epsv, epsa, out=_out.get("affi")) p = phasem(alpha, kd[..., None, None], out=_out.get("p")) if tmpdata is not None: tmpdata["affi"] = (alpha, f, fi) tmpdata["p"] = p if dmatpn is not None: e = E_mat(f, mode=None) ei = inv(e, out=_out.get("ei")) if tmpdata is not None: tmpdata["ei"] = ei for j in range(nsteps): if dmatpn is None: field = dotmdmf(f, p, fi, field, out=out) else: field = dotmdmf(e, p, fi, field, out=out) diffract(field[..., 0::2, :, :], dmatp, out=field[..., 0::2, :, :]) diffract(field[..., 1::2, :, :], dmatn, out=field[..., 1::2, :, :]) field = dotmdmf(f, p, ei, field, out=field) return field
np.linspace(0.0, 0.9999, 1000), dtype="float32" ) #in case we compiled for float32, this has to be float not duouble #: phi angle of the input light - will make a diffference for anisotropic layer phi = 0.0 _phi = 0 pol1 = (-np.sin(_phi), np.cos(_phi)) pol2 = (np.cos(_phi), np.sin(_phi)) #: we must view them in rotated frame, with respect to the ray phi value. pol1 = jones4.jonesvec(pol1, phi) pol2 = jones4.jonesvec(pol2, phi) #build field matrices a, f, fi = tmm.alphaffi(betas, phi, eps_layer, eps_angles) aout, fout, g = tmm.alphaffi( betas, phi, eps_out, eps_angles) #eps_angles does nothing because eps_out is isotropic ain, fin, g = tmm.alphaffi( betas, phi, eps_in, eps_angles) #eps_angles does nothing because eps_in is isotropic dot = dtmm.linalg.dotmm dotd = dtmm.linalg.dotmd dotmdm = dtmm.linalg.dotmdm dotmv = dtmm.linalg.dotmv intensity = tmm.intensity intensity = tmm.poynting p = tmm.phase_mat(a, -kd) #p = np.exp(-1j*a*kd)
kd = 2*np.pi/wavelengths[:,None]* step * d #: input epsilon -air eps_in = dtmm.refind2eps([nin]*3) #: layer epsilon eps_layer = dtmm.refind2eps(n) eps_values = np.array([eps_layer]*(nlayers+2), dtype = "complex64") eps_values[0] = dtmm.refind2eps([nin]*3) eps_values[-1] = dtmm.refind2eps([nout]*3) #stack = d,eps_values, eps_angles #cmat = tmm.stack_mat(stack,kd, beta = beta, phi = phi) #build field matrices a,f,fi = tmm.alphaffi(beta,phi,eps_values, eps_angles) fout = f[-1] fin = f[0] #now build layer matrices #: in 4x4 we are propagating backward--- minus sign must be taken in the phase p = tmm.phase_mat(a,-kd) # uncoment this to test that setting backward propagating waves to zero, # you have single reflections only... -same result as 2x2 with reflection. #p[...,1::2] = 0. #4x4 characteristic matrix m = dotmdm(f,p,fi)