def test_grad_for_E(self): print('\ttesting E fields in FDTD (forward mode)') F = fdtd(self.eps_r, dL=self.dL, npml=self.pml) def objective(c): F = fdtd(c * self.eps_r, dL=self.dL, npml=self.pml) S = 0.0 for t_index in range(self.steps): fields = F.forward(Jx=self.gaussian(t_index)) S += fields['Ex'] + fields['Ey'] + fields['Ez'] return S c0 = 2.0 jac_autograd_for = jacobian(objective, mode='forward')(c0) jac_numerical = jacobian(objective, mode='numerical', step_size=DEPS)(c0) if VERBOSE: print('\tobjective function value: ', objective(self.eps_arr)) print('\tjacobian (auto): \n\t\t', jac_autograd_for) print('\tjacobian (num): \n\t\t', jac_numerical) self.check_gradient_error(jac_numerical, jac_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)
def test_Ez_forward(self): print('\ttesting forward-mode Ez in FDFD') f = fdfd_ez(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 Hx, Hy, Ez = f.solve(c * self.eps_r * self.source_ez) return npa.square(npa.abs(Ez)) \ + npa.square(npa.abs(Hx)) \ + npa.square(npa.abs(Hy)) 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_Ez_lin(self): print('\ttesting linear Ez in FDFD') f = fdfd_ez(self.omega, self.dL, self.eps_lin, self.pml) def J_fdfd(eps_arr): f.eps_r = eps_arr.reshape((self.Nx, self.Ny)) # set the source amplitude to the permittivity at that point Hx, Hy, Ez = f.solve(self.source_ez) return npa.sum(npa.square(npa.abs(Ez))) \ + npa.sum(npa.square(npa.abs(Hx))) \ + npa.sum(npa.square(npa.abs(Hy))) grad_autograd_rev = jacobian(J_fdfd, mode='reverse')(self.eps_lin) grad_numerical = jacobian(J_fdfd, mode='numerical')(self.eps_lin) if VERBOSE: print('\tobjective function value: ', J_fdfd(self.eps_lin)) print('\tgrad (auto): \n\t\t', grad_autograd_rev) print('\tgrad (num): \n\t\t', grad_numerical) self.check_gradient_error(grad_numerical, grad_autograd_rev)
def test_Ez_nl(self): print('\ttesting reverse-mode nonlinear Ez in FDFD') f = fdfd_ez_nl(self.omega, self.dL, self.eps_nl, self.pml) Hx, Hy, Ez = f.solve(self.source_ez) mod_strength = self.chi3 * np.max(np.square(np.abs(Ez))) print('\t\tmodulation strength (chi3 * max(|E|^2)) = {}'.format( mod_strength)) def J_fdfd(eps_arr): eps_lin = eps_arr.reshape((self.Nx, self.Ny)) # construct nonlinear epsilon using autograd numpy wrapper eps_nl = lambda Ez: eps_lin + 3 * eps_lin * self.chi3 * npa.square( npa.abs(Ez)) # set the permittivity f.eps_r = eps_nl # set the source amplitude to the permittivity at that point Hx, Hy, Ez = f.solve(self.source_ez) return npa.sum(npa.square(npa.abs(Ez))) \ + npa.sum(npa.square(npa.abs(Hx))) \ + npa.sum(npa.square(npa.abs(Hy))) grad_autograd_rev = jacobian(J_fdfd, mode='reverse')(self.eps_lin) grad_numerical = jacobian(J_fdfd, mode='numerical')(self.eps_lin) if VERBOSE: print('\tobjective function value: ', J_fdfd(self.eps_lin)) print('\tgrad (auto): \n\t\t', grad_autograd_rev) print('\tgrad (num): \n\t\t', grad_numerical) self.check_gradient_error(grad_numerical, grad_autograd_rev)
def test_grad_rev_E(self): print('\ttesting E fields in FDTD (reverse mode)') F = fdtd(self.eps_r, dL=self.dL, npml=self.pml) def objective(eps_arr): F.eps_r = eps_arr.reshape((self.Nx, self.Ny, self.Nz)) S = 0.0 for t_index in range(self.steps): fields = F.forward(Jz=self.gaussian(t_index)) S += npa.sum(fields['Ex'] + fields['Ey'] + fields['Ez']) return S jac_autograd_rev = jacobian(objective, mode='reverse')(self.eps_arr) jac_numerical = jacobian(objective, mode='numerical', step_size=DEPS)(self.eps_arr) if VERBOSE: print('\tobjective function value: ', objective(self.eps_arr)) print('\tjacobian (auto): \n\t\t', jac_autograd_rev) print('\tjacobian (num): \n\t\t', jac_numerical) self.check_gradient_error(jac_numerical, jac_autograd_rev)