def compute_fom_and_gradient( self, omega, device_permittivity, focal_point_x_loc, fom_scaling=1.0 ): fwd_Ez = self.compute_forward_fields( omega, device_permittivity ) fom = fom_scaling * np.abs( fwd_Ez[ focal_point_x_loc, self.focal_point_y ] )**2 adj_source = np.zeros( ( self.simulation_width_voxels, self.simulation_height_voxels ), dtype=np.complex ) adj_source[ focal_point_x_loc, self.focal_point_y ] = np.conj( fwd_Ez[ focal_point_x_loc, self.focal_point_y ] ) simulation = ceviche.fdfd_ez( omega, self.mesh_size_m, self.rel_eps_simulation, [ self.pml_voxels, self.pml_voxels ] ) adj_Hx, adj_Hy, adj_Ez = simulation.solve( adj_source ) gradient = fom_scaling * 2 * np.real( omega * eps_nought * fwd_Ez * adj_Ez / 1j ) if self.field_blur: blur_fwd_Ez_real = gaussian_filter( np.real( fwd_Ez ), sigma=self.field_blur_size_voxels ) blur_fwd_Ez_imag = gaussian_filter( np.imag( fwd_Ez ), sigma=self.field_blur_size_voxels ) blur_adj_Ez_real = gaussian_filter( np.real( adj_Ez ), sigma=self.field_blur_size_voxels ) blur_adj_Ez_imag = gaussian_filter( np.imag( adj_Ez ), sigma=self.field_blur_size_voxels ) blur_fwd_Ez = blur_fwd_Ez_real + 1j * blur_fwd_Ez_imag blur_adj_Ez = blur_adj_Ez_real + 1j * blur_adj_Ez_imag gradient = fom_scaling * 2 * np.real( omega * eps_nought * blur_fwd_Ez * blur_adj_Ez / 1j ) return fom, gradient
def compute_fom_and_gradient(omega, mesh_size_m, relative_permittivity, pml_cells, fwd_src_y_loc, focal_point_x_loc, focal_point_y_loc): simulation_width_cells = relative_permittivity.shape[0] simulation_height_cells = relative_permittivity.shape[1] simulation = ceviche.fdfd_ez(omega, mesh_size_m, relative_permittivity, pml_cells) fwd_src_x = np.arange(0, simulation_width_cells) fwd_src_y = fwd_src_y_loc * np.ones(fwd_src_x.shape, dtype=int) fwd_source = np.zeros((simulation_width_cells, simulation_height_cells), dtype=np.complex) fwd_source[fwd_src_x, fwd_src_y] = 1 fwd_Hx, fwd_Hy, fwd_Ez = simulation.solve(fwd_source) focal_point_y = focal_point_y_loc focal_point_x = focal_point_x_loc fom = np.abs(fwd_Ez[focal_point_x, focal_point_y])**2 adj_source = np.zeros((simulation_width_cells, simulation_height_cells), dtype=np.complex) adj_source[focal_point_x, focal_point_y] = np.conj(fwd_Ez[focal_point_x, focal_point_y]) adj_Hx, adj_Hy, adj_Ez = simulation.solve(adj_source) gradient = 2 * np.real(omega * eps_nought * fwd_Ez * adj_Ez / 1j) return fom, gradient
def compute_fom_and_gradient_ez(self, omega_idx, device_permittivity): omega = self.omega_values[omega_idx] fwd_Hx, fwd_Hy, fwd_Ez = self.compute_forward_fields_ez( omega, device_permittivity) fom = (1. / self.ez_transmission_normalization[omega_idx] ) * self.compute_fom_from_fields_ez( fwd_Hx, fwd_Hy, fwd_Ez, self.src_scattered_Hx_by_omega[omega_idx, :], self.src_scattered_Hy_by_omega[omega_idx, :], self.src_scattered_Ez_by_omega[omega_idx, :]) scattered_Hx = ( fwd_Hx[self.transmission_x_bounds[0]:self.transmission_x_bounds[1], self.transmission_y] - self.src_scattered_Hx_by_omega[omega_idx, :]) adj_source = np.zeros( (self.simulation_width_voxels, self.simulation_height_voxels), dtype=np.complex) adj_source[self.transmission_x_bounds[0]:self.transmission_x_bounds[1], self.transmission_y] = np.conj(scattered_Hx) simulation = ceviche.fdfd_ez(omega, self.mesh_size_m, self.rel_eps_simulation, [self.pml_voxels, self.pml_voxels]) adj_Hx, adj_Hy, adj_Ez = simulation.solve(adj_source) gradient = (1. / self.ez_transmission_normalization[omega_idx] ) * 2 * np.real(omega * eps_nought * fwd_Ez * adj_Ez / (1j)) return fom, gradient
def compute_forward_fields( self, omega, device_permittivity ): self.rel_eps_simulation[ self.device_width_start : self.device_width_end, self.device_height_start : self.device_height_end ] = device_permittivity simulation = ceviche.fdfd_ez( omega, self.mesh_size_m, self.rel_eps_simulation, [ self.pml_voxels, self.pml_voxels ] ) fwd_Hx, fwd_Hy, fwd_Ez = simulation.solve( self.fwd_source ) return fwd_Ez
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_reverse(self): print('\ttesting reverse-mode Ez in FDFD') f = fdfd_ez(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 Hx, Hy, Ez = f.solve(eps_r * 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_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', grad_numerical) self.check_gradient_error(grad_numerical, grad_autograd_rev)
def eval_loss( self, omega ): print( self.max_relative_permittivity ) self.rel_eps_simulation[ :, : ] = self.max_relative_permittivity simulation = ceviche.fdfd_ez( omega, self.mesh_size_m, self.rel_eps_simulation, [ self.pml_voxels, self.pml_voxels ] ) fwd_Hx, fwd_Hy, fwd_Ez = simulation.solve( self.fwd_source ) return fwd_Ez
def test_Ez(self): print('\ttesting Ez') F = fdfd_ez(self.omega, self.dL, self.eps_r, self.npml) Hx, Hy, Ez = F.solve(self.source) Ez_max = np.max(np.abs(Ez)) plt.imshow(np.real(Ez), cmap='RdBu', vmin=-Ez_max / 5, vmax=Ez_max / 5) plt.show()
def test_Ez(self): print('\ttesting Ez') F = fdfd_ez(self.omega, self.dL, self.eps_r, self.npml) Hx, Hy, Ez = F.solve(self.source) plot_component = Ez field_max = np.max(np.abs(plot_component)) plt.imshow(np.real(plot_component), cmap='RdBu', vmin=-field_max / 5, vmax=field_max / 5) plt.show()
def viz_sim(epsr): """Solve and visualize a simulation with permittivity 'epsr' """ simulation = fdfd_ez(omega, dl, epsr, [Npml, Npml]) Hx, Hy, Ez = simulation.solve(source) fig, ax = plt.subplots(1, 2, constrained_layout=True, figsize=(6,3)) ceviche.viz.real(Ez, outline=epsr, ax=ax[0], cbar=False) ax[0].plot(input_slice.x*np.ones(len(input_slice.y)), input_slice.y, 'g-') for output_slice in output_slices: ax[0].plot(output_slice.x*np.ones(len(output_slice.y)), output_slice.y, 'r-') ceviche.viz.abs(epsr, ax=ax[1], cmap='Greys'); plt.show() return (simulation, ax)
def compute_fom_and_gradient_and_fields( self, omega, device_permittivity, focal_point_x_loc, fom_scaling=1.0 ): fwd_Ez = self.compute_forward_fields( omega, device_permittivity ) fom = fom_scaling * np.abs( fwd_Ez[ focal_point_x_loc, self.focal_point_y ] )**2 adj_source = np.zeros( ( self.simulation_width_voxels, self.simulation_height_voxels ), dtype=np.complex ) adj_source[ focal_point_x_loc, self.focal_point_y ] = np.conj( fwd_Ez[ focal_point_x_loc, self.focal_point_y ] ) simulation = ceviche.fdfd_ez( omega, self.mesh_size_m, self.rel_eps_simulation, [ self.pml_voxels, self.pml_voxels ] ) adj_Hx, adj_Hy, adj_Ez = simulation.solve( adj_source ) gradient = fom_scaling * 2 * np.real( omega * eps_nought * fwd_Ez * adj_Ez / 1j ) return fom, gradient, fwd_Ez
def compute_forward_fields_ez(self, omega, device_permittivity, normalization_permittivity=False): self.rel_eps_simulation[self.device_width_start:self.device_width_end, self.device_height_start:self. device_height_end] = device_permittivity choose_permittivity = self.rel_eps_simulation if normalization_permittivity: choose_permittivity = np.ones(self.rel_eps_simulation.shape) simulation = ceviche.fdfd_ez(omega, self.mesh_size_m, choose_permittivity, [self.pml_voxels, self.pml_voxels]) fwd_Hx, fwd_Hy, fwd_Ez = simulation.solve(self.fwd_source_ez) return fwd_Hx, fwd_Hy, fwd_Ez
def compute_fom(omega, mesh_size_m, relative_permittivity, pml_cells, fwd_src_y_loc, focal_point_x_loc, focal_point_y_loc): simulation_width_cells = relative_permittivity.shape[0] simulation_height_cells = relative_permittivity.shape[1] simulation = ceviche.fdfd_ez(omega, mesh_size_m, relative_permittivity, pml_cells) fwd_src_x = np.arange(0, simulation_width_cells) fwd_src_y = fwd_src_y_loc * np.ones(fwd_src_x.shape, dtype=int) fwd_source = np.zeros((simulation_width_cells, simulation_height_cells), dtype=np.complex) fwd_source[fwd_src_x, fwd_src_y] = 1 fwd_Hx, fwd_Hy, fwd_Ez = simulation.solve(fwd_source) focal_point_y = focal_point_y_loc focal_point_x = focal_point_x_loc fom = np.abs(fwd_Ez[focal_point_x, focal_point_y])**2 return fom
def plot_subcell_gradient_variations( self, omega_idx, factor ): import matplotlib.pyplot as plt import_density = upsample( self.design_density, self.coarsen_factor ) device_permittivity = self.density_to_permittivity( import_density ) device_width_array = np.linspace( 0, 1, self.device_width_voxels ) device_height_array = np.linspace( 0, 1, self.device_height_voxels ) interp_width_array = np.linspace( 0, 1, factor * self.device_width_voxels ) interp_height_array = np.linspace( 0, 1, factor * self.device_height_voxels ) omega = self.omega_values[ omega_idx ] fwd_Ez = self.compute_forward_fields( omega, device_permittivity ) focal_point_x_loc = self.focal_spots_x_voxels[ 0 ] interp_spline_fwd_real = RectBivariateSpline( device_width_array, device_height_array, np.real( fwd_Ez[ self.device_width_start : self.device_width_end, self.device_height_start : self.device_height_end ] ) ) interp_spline_fwd_imag = RectBivariateSpline( device_width_array, device_height_array, np.imag( fwd_Ez[ self.device_width_start : self.device_width_end, self.device_height_start : self.device_height_end ] ) ) adj_source = np.zeros( ( self.simulation_width_voxels, self.simulation_height_voxels ), dtype=np.complex ) adj_source[ focal_point_x_loc, self.focal_point_y ] = np.conj( fwd_Ez[ focal_point_x_loc, self.focal_point_y ] ) simulation = ceviche.fdfd_ez( omega, self.mesh_size_m, self.rel_eps_simulation, [ self.pml_voxels, self.pml_voxels ] ) adj_Hx, adj_Hy, adj_Ez = simulation.solve( adj_source ) interp_spline_adj_real = RectBivariateSpline( device_width_array, device_height_array, np.real( adj_Ez[ self.device_width_start : self.device_width_end, self.device_height_start : self.device_height_end ] ) ) interp_spline_adj_imag = RectBivariateSpline( device_width_array, device_height_array, np.imag( adj_Ez[ self.device_width_start : self.device_width_end, self.device_height_start : self.device_height_end ] ) ) interpolated_fwd_real = interp_spline_fwd_real( interp_width_array, interp_height_array ) interpolated_adj_real = interp_spline_adj_real( interp_width_array, interp_height_array ) interpolated_fwd_imag = interp_spline_fwd_imag( interp_width_array, interp_height_array ) interpolated_adj_imag = interp_spline_adj_imag( interp_width_array, interp_height_array ) interpolated_fwd = interpolated_fwd_real + 1j * interpolated_fwd_imag interpolated_adj = interpolated_adj_real + 1j * interpolated_adj_imag interp_grad = 2 * np.real( interpolated_fwd * interpolated_adj ) averaged_grad = np.zeros( ( self.device_width_voxels, self.device_height_voxels ) ) middle_grad = 2 * np.real( fwd_Ez[ self.device_width_start : self.device_width_end, self.device_height_start : self.device_height_end ] * adj_Ez[ self.device_width_start : self.device_width_end, self.device_height_start : self.device_height_end ] ) for x_idx in range( 0, self.device_width_voxels ): for y_idx in range( 0, self.device_height_voxels ): for off_x in range( 0, factor ): start_x = x_idx * factor for off_y in range( 0, factor ): start_y = y_idx * factor averaged_grad[ x_idx, y_idx ] += ( ( 1. / ( factor * factor ) ) * interp_grad[ start_x + off_x, start_y + off_y ] ) plt.subplot( 1, 3, 1 ) plt.imshow( middle_grad, cmap='Blues' ) plt.colorbar() plt.subplot( 1, 3, 2 ) plt.imshow( averaged_grad, cmap='Blues' ) plt.colorbar() plt.subplot( 1, 3, 3 ) plt.imshow( ( middle_grad - averaged_grad ), cmap='Greens' ) plt.colorbar() plt.show() half_width = int( factor * 0.5 * self.device_width_voxels ) half_height = int( factor * 0.5 * self.device_height_voxels ) plt.subplot( 1, 3, 1 ) plt.imshow( np.abs( interpolated_fwd[ half_width : ( half_width + self.coarsen_factor * 2 * factor ), half_height : ( half_height + self.coarsen_factor * 2 * factor) ] ), cmap='Reds' ) plt.colorbar() plt.subplot( 1, 3, 2 ) plt.imshow( np.abs( interpolated_adj[ half_width : ( half_width + self.coarsen_factor * 2 * factor ), half_height : ( half_height + self.coarsen_factor * 2 * factor) ] ), cmap='Reds' ) plt.colorbar() plt.subplot( 1, 3, 3 ) plt.imshow( np.real( interpolated_fwd[ half_width : ( half_width + self.coarsen_factor * 2 * factor ), half_height : ( half_height + self.coarsen_factor * 2 * factor ) ] * interpolated_adj[ half_width : ( half_width + self.coarsen_factor * 2 * factor ), half_height : ( half_height + self.coarsen_factor * 2 * factor ) ] ), cmap='Reds' ) plt.colorbar() plt.show()
# 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 # make the accelration probe probe = np.zeros((Nx, Ny), dtype=np.complex128) probe[-npml - spc, Ny // 2] = 1 # plot the probe through channel if PLOT: plt.imshow(np.abs(probe + box_region + source).T) plt.show() # vacuum test, get normalization F_lin = fdfd_ez(omega, dL, eps_r, [npml, npml]) F_nl = fdfd_ez_nl(omega, dL, eps_nl, [npml, npml]) Hx, Hy, Ez = F_lin.solve(source) H_mag = np.sqrt(np.square(np.abs(Hx)) + np.square(np.abs(Hy))) E_mag = np.abs(Ez) I_H0 = np.abs(np.square(np.sum(H_mag * probe))) I_E0 = np.abs(np.square(np.sum(E_mag * probe))) print('I_E0 = {}'.format(I_E0)) # plot the vacuum fields if PLOT: plt.imshow(np.real(Ez).T, cmap='RdBu') plt.title('real(Hz)') plt.xlabel('y')
focal_points_x = [ int(device_width_start + 0.25 * device_width_voxels), int(device_width_start + 0.75 * device_width_voxels) ] device_density = np.random.random( (int(device_width_voxels / density_coarsen_factor), int(device_height_voxels / density_coarsen_factor))) upsampled_density = upsample(device_density, density_coarsen_factor) device_permittivity = density_to_permittivity(upsampled_density) rel_eps_simulation[device_width_start:device_width_end, device_height_start:device_height_end] = device_permittivity omega = omega_values[int(0.5 * num_lambda_values)] simulation = ceviche.fdfd_ez(omega, mesh_size_m, rel_eps_simulation, [pml_voxels, pml_voxels]) fwd_src_x = np.arange(0, simulation_width_voxels) fwd_src_y_line = fwd_src_y * np.ones(fwd_src_x.shape, dtype=int) fwd_source = np.zeros((simulation_width_voxels, simulation_height_voxels), dtype=np.complex) fwd_source[fwd_src_x, fwd_src_y_line] = 1 import time start = time.time() fwd_Hx, fwd_Hy, fwd_Ez = simulation.solve(fwd_source) elapsed = time.time() - start print("The elapsed time was " + str(elapsed))