def test_Hz_forward(self): print('\ttesting forward-mode Hz in FDFD') f = fdfd_hz(self.omega, self.dL, self.eps_r, self.pml) def J_fdfd(c): # set the permittivity f.eps_r = c * self.eps_r # set the source amplitude to the permittivity at that point Ex, Ey, Hz = f.solve(c * self.eps_r * self.source_hz) return npa.square(npa.abs(Hz)) \ + npa.square(npa.abs(Ex)) \ + npa.square(npa.abs(Ey)) grad_autograd_for = jacobian(J_fdfd, mode='forward')(1.0) grad_numerical = jacobian(J_fdfd, mode='numerical')(1.0) if VERBOSE: print('\tobjective function value: ', J_fdfd(1.0)) print('\tgrad (auto): \n\t\t', grad_autograd_for) print('\tgrad (num): \n\t\t', grad_numerical) self.check_gradient_error(grad_numerical, grad_autograd_for)
def test_Hz_reverse(self): print('\ttesting reverse-mode Hz in FDFD') f = fdfd_hz(self.omega, self.dL, self.eps_r, self.pml) def J_fdfd(eps_arr): eps_r = eps_arr.reshape((self.Nx, self.Ny)) # set the permittivity f.eps_r = eps_r # set the source amplitude to the permittivity at that point Ex, Ey, Hz = f.solve(eps_r * self.source_hz, iterative=True) return npa.sum(npa.square(npa.abs(Hz))) \ + npa.sum(npa.square(npa.abs(Ex))) \ + npa.sum(npa.square(npa.abs(Ey))) grad_autograd_rev = jacobian(J_fdfd, mode='reverse')(self.eps_arr) grad_numerical = jacobian(J_fdfd, mode='numerical')(self.eps_arr) if VERBOSE: print('\tobjective function value: ', J_fdfd(self.eps_arr)) print('\tgrad (auto): \n\t\t', grad_autograd_rev) print('\tgrad (num): \n\t\t\n', grad_numerical) self.check_gradient_error(grad_numerical, grad_autograd_rev)
omega = 2 * np.pi * 200e12 dL = 4e-8 eps_max = 2 npml = 10 spc = 10 L = 3e-6 Nx, Ny = 2*npml + 4*spc + int(L/dL), 2*npml + 4*spc + int(L/dL) eps_r = np.ones((Nx, Ny)) # make source source = np.zeros((Nx, Ny)) source[npml+spc, Ny//2] = 1 # make design region box_region = np.zeros((Nx, Ny)) box_region[npml+2*spc:npml+2*spc+int(L/dL), npml+2*spc:npml+2*spc+int(L/dL)] = 1 probe = np.zeros((Nx, Ny), dtype=np.complex128) probe[-npml-spc, Ny//2] = 1 F = fdfd_hz(omega, dL, eps_r, [npml, npml]) # define the gradient for autograd grad_I = grad(intensity) from scipy.optimize import minimize bounds = [(1, eps_max) if box_region.flatten()[i] == 1 else (1,1) for i in range(eps_r.size)] minimize(intensity, eps_r, args=(), method='L-BFGS-B', jac=grad_I, bounds=bounds, tol=None, callback=None, options={'disp': True, 'maxcor': 10, 'ftol': 2.220446049250313e-09, 'gtol': 1e-05, 'eps': 1e-08, 'maxfun': 15000, 'maxiter': 150, 'iprint': -1, 'maxls': 20})