def mapping(x, filter_radius, eta, beta): filtered_field = mpa.conic_filter(x, filter_radius, design_shape.x, design_shape.y, design_region_resolution) projected_field = mpa.tanh_projection(filtered_field, beta, eta) return projected_field.flatten()
def test_offdiagonal(self): print("*** TESTING OFFDIAGONAL COMPONENTS ***") filt = lambda x: mpa.conic_filter(x.reshape( (Nx, Ny)), 0.25, design_region_size.x, design_region_size.y, design_region_resolution).flatten() ## test the single frequency and multi frequency case for frequencies in [[fcen], [1 / 1.58, fcen, 1 / 1.53]]: ## compute gradient using adjoint solver adjsol_obj, adjsol_grad = adjoint_solver(filt(p), MonitorObject.EIGENMODE, frequencies, sapphire) ## backpropagate the gradient if len(frequencies) > 1: bp_adjsol_grad = np.zeros(adjsol_grad.shape) for i in range(len(frequencies)): bp_adjsol_grad[:, i] = tensor_jacobian_product(filt, 0)( p, adjsol_grad[:, i]) else: bp_adjsol_grad = tensor_jacobian_product(filt, 0)(p, adjsol_grad) ## compute unperturbed S12 S12_unperturbed = forward_simulation(filt(p), MonitorObject.EIGENMODE, frequencies, sapphire) ## compare objective results print( "S12 -- adjoint solver: {}, traditional simulation: {}".format( adjsol_obj, S12_unperturbed)) self.assertClose(adjsol_obj, S12_unperturbed, epsilon=1e-6) ## compute perturbed S12 S12_perturbed = forward_simulation(filt(p + dp), MonitorObject.EIGENMODE, frequencies, sapphire) ## compare gradients if bp_adjsol_grad.ndim < 2: bp_adjsol_grad = np.expand_dims(bp_adjsol_grad, axis=1) adj_scale = (dp[None, :] @ bp_adjsol_grad).flatten() fd_grad = S12_perturbed - S12_unperturbed print( "Directional derivative -- adjoint solver: {}, FD: {}".format( adj_scale, fd_grad)) tol = 0.1 if mp.is_single_precision() else 0.04 self.assertClose(adj_scale, fd_grad, epsilon=tol)