def waves2field2(waves, fmat, jones=None, phi=0, mode=+1): """Converts scalar waves to vector field data.""" if jones is None: fvec1 = field4(fmat, jones=jonesvec((1, 0), phi), amplitude=waves, mode=mode) fvec2 = field4(fmat, jones=jonesvec((0, 1), phi), amplitude=waves, mode=mode) field1 = itranspose(fvec1) field2 = itranspose(fvec2) shape = list(field1.shape) shape.insert(-4, 2) out = np.empty(shape=shape, dtype=field1.dtype) out[..., 0, :, :, :, :] = field1 out[..., 1, :, :, :, :] = field2 else: #fvec = field4(fmat, jones = jonesvec((1,0),phi), amplitude = waves, mode = mode) fvec = field4(fmat, jones=jonesvec(jones, phi), amplitude=waves, mode=mode) out = itranspose(fvec).copy() return out
def project_normalized_local(field, dmat, window=None, ref=None, out=None): f1 = fft2(field) f2 = dotmf(dmat, f1, out=f1) f = ifft2(f2, out=f2) pmat1 = normal_polarizer(jonesvec(transpose(f[..., ::2, :, :]))) pmat2 = -pmat1 pmat2[..., 0, 0] += 1 pmat2[..., 1, 1] += 1 #pmat1 + pmat2 = identity by definition pmat2[..., 2, 2] += 1 #pmat1 + pmat2 = identity by definition pmat2[..., 3, 3] += 1 #pmat1 + pmat2 = identity by definition if ref is not None: intensity1 = field2intensity(dotmf(pmat1, ref)) ref = dotmf(pmat2, ref) else: intensity1 = field2intensity(dotmf(pmat1, field)) ref = dotmf(pmat2, field) intensity2 = field2intensity(f) f = normalize_field(f, intensity1, intensity2) out = np.add(f, ref, out=out) if window is not None: out = np.multiply(out, window, out=out) return out
def normal_polarizer(jones=(1, 0)): """A 4x4 polarizer for normal incidence light. It works reasonably well also for off-axis light, but it introduces weak reflections and depolarization. For off-axis planewaves you should use ray_polarizer instead of this.""" p = polarizer(jonesvec(jones)) pmat = np.zeros(shape=p.shape[:-2] + (4, 4), dtype=p.dtype) pmat[..., ::2, ::2] = p pmat[..., 1, 1] = p[..., 0, 0] pmat[..., 3, 3] = p[..., 1, 1] pmat[..., 1, 3] = -p[..., 0, 1] pmat[..., 3, 1] = -p[..., 1, 0] return pmat
def ray_polarizer( jones=(1, 0), beta=0, phi=0, epsv=(1., 1., 1.), epsa=(0., 0., 0.), ): """Returns a ray polarizer that should be applied in real space. Good for beams that can be approximated with a single wave vector and with a direction of ray propagation beta and phi parameters. See also mode_polarizer, which is for non-planewave field data.""" epsv = np.asarray(epsv, CDTYPE) epsa = np.asarray(epsa, FDTYPE) beta = np.asarray(beta, FDTYPE) phi = np.asarray(phi, FDTYPE) alpha, f = alphaf(beta, phi, epsv, epsa) jones = jonesvec(jones, phi) pmat = polarizer4x4(jones, f) return pmat
def mode_polarizer(shape, ks, jones=(1, 0), epsv=(1., 1., 1.), epsa=(0., 0., 0.), betamax=BETAMAX): """Returns a mode polarizer that should be applied in fft space. This is the most general polarizer that does not introduce any reflections for any kind of nonhomogeneous or homogeneous field.""" ks = np.asarray(ks, FDTYPE) ks = abs(ks) epsv = np.asarray(epsv, CDTYPE) epsa = np.asarray(epsa, FDTYPE) beta, phi = betaphi(shape, ks) alpha, f = diffraction_alphaf(shape, ks, epsv=epsv, epsa=epsa, betamax=betamax) beta, phi = betaphi(shape, ks) jones = jonesvec(jones, phi) pmat = polarizer4x4(jones, f) return pmat
nlayers = 100 #: which wavelengths to compute (in nanometers) k = np.linspace(2 * np.pi / 700, 2 * np.pi / 400, 200) wavelengths = 2 * np.pi / k #:ordinary refractive index of LC no = 1.5 #:extraordinary ne = 1.62 #--------------- # implementation #--------------- step = thickness * 1000 / nlayers #in nanometers x_jvec = jones.jonesvec((1, 0)) y_jvec = jones.jonesvec((0, 1)) phis = np.linspace(0, np.pi / 2, nlayers) #twist rotation angle phase = (ne - no) * k * step #phase retardation in each of the layers matrices = [jones.polarizer(x_jvec)] #x polarizer #add retarders... left handed TN for phi in phis: matrices.append(jones.retarder(phase, phi)) #next, we multiply matrices together in reverse order ...tn2.tn1.tn0.x jmat = jones.multi_dot(matrices, reverse=True) normally_white_jmat = jones.dotmm(jones.polarizer(y_jvec),
#: substrate epsilon eps_out = dtmm.refind2eps(nout) #: ray beta parameters; beta is nin*np.sin(theta) betas = np.array( np.linspace(0.0, 0.9999999, 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 _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 = jones.jonesvec(pol1, phi) pol2 = jones.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
# the inverse, with reflections eti = tmm.Eti_mat(f[:-1], f[1:], mode=+1) p2 = tmm.phase_mat(a, kd, mode=+1)[:, 1:] #2x2 characteristic matrix m2 = dotmdm(e, p2, ei) #no reflections m2t = dotmdm(e, p2, eti) #with reflections # multiply matrices together over second axis (first axis is wavelenght, second are layers) cmat = linalg.multi_dot(m, axis=1) #the 2x2 matrices must be multiplied in reverse order... because we propagate forward cmat2 = linalg.multi_dot(m2, axis=1, reverse=True) cmat2t = linalg.multi_dot(m2t, axis=1, reverse=True) jx = jones.jonesvec((1, 0), phi) jy = jones.jonesvec((0, 1), phi) #field projection matrices - used to take the forward propagating or backward propagating waves pmat = tmm.projection_mat(fout, mode=+1) mmat = tmm.projection_mat(fin, mode=-1) fvec = tmm.field4(fin, jones=jx) #fvec = tmm.field4old(fin,jones = jx) fvec = np.array([fvec] * nwavelengths) tfvec2 = tmm.transmit2x2(fvec, cmat2, fmatout=fout[None, ...]) tfvec2r = tmm.transmit2x2(fvec, cmat2t, fmatout=fout[None, ...]) tfvec4 = tmm.transmit(fvec, cmat,