示例#1
0
    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)
示例#2
0
def spectral_power(ff):
    """ This function computes the spectral power as a function of fill factor
        will autograd/differentiate this with FMD (cevijacobian function)
    """

    # setup FDTD using explicit projection into permittivity
    eps_teeth_proj = projection(teeth_density, (1 - ff), sub_eps, grating_eps)
    eps_total = eps_teeth_proj + eps_base
    F = fdtd(eps_total, dl, [npml, npml, 0])

    # compute fields at each time step at the source above
    # note: we're solving the reciprocal problem of a waveguide -> free space coupler
    measured = []
    print('-> running FDTD within objective function')
    for t_index in range(steps):
        if t_index % 1000 == 0:
            print('   - done with time step {} of {} ({}%)'.format(
                t_index, steps, int(t_index / steps * 100)))
        fields = F.forward(Jz=source_fn(t_index))
        measured.append(npa.sum(fields['Ez'] * source))

    # get spectral power through FFT
    print('-> computing FFT')
    measured_f = my_fft(npa.array(measured))
    spect_power = npa.square(npa.abs(measured_f)) / source_p
    return spect_power
示例#3
0
        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
示例#4
0
    def test_fields_H(self):

        F = fdtd(self.eps_r, dL=self.dL, npml=self.pml)

        fig, ax = plt.subplots(figsize=(10, 10))
        im = ax.pcolormesh(np.zeros((self.Nx, self.Ny)), cmap='RdBu')

        for t_index in range(self.steps):

            fields = F.forward(Jx=self.gaussian(t_index))

            if t_index % self.skip_rate == 0:

                max_E = np.abs(fields['Hz']).max()
                im.set_array(fields['Hz'][:, :, 0].ravel())
                im.set_clim([-1, 1])
                plt.pause(0.001)
                ax.set_title('time = {}'.format(t_index))
示例#5
0
    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)
示例#6
0
omega = 2*np.pi*200e12
dL = 5e-8
pml = [npml, npml, 0]

# source parameters
sigma = 10e-15
total_time = 0.5e-12
t0 = sigma * 10

source_amp = 1
source_pos = np.zeros((Nx, Ny, Nz))
source_pos[npml+10, Ny//2, Nz//2] = source_amp

# starting relative permittivity (random for debugging)
eps_r   = np.random.random((Nx, Ny, Nz)) + 1
F = fdtd(eps_r, dL=dL, npml=pml)
dt = F.dt

steps = int(total_time / dt)
print('{} time steps'.format(steps))

gaussian = lambda t: source_amp * np.exp(-(t - t0 / dt)**2 / 2 / (sigma / dt)**2)
source = lambda t: source_pos * gaussian(t) * np.cos(omega * t * dt)

plt.plot(dt * np.arange(steps), np.sum(source(np.arange(steps)), axis=(0,1)))
plt.xlabel('time (sec)')
plt.ylabel('source amplitude')
plt.show()

measure_pos = np.zeros((Nx, Ny, Nz))
measure_pos[-npml-10, Ny//2, Nz//2] = 1
示例#7
0
# plot the wavegiude mode source array
if plot_all:
    plt.imshow(np.real(imarr(wg_mode)), cmap='magma')
    plt.title('modal source array')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.show()
""" DEFINE TIME DOMAIN PROBLEM """

# reshape things for the FDTD
eps_total = eps_total.reshape((Nx, Ny, 1))
source = source.reshape((Nx, Ny, 1))

# make an FDTD and get its time step
F_t = fdtd(eps_total, dl, [npml, npml, 0])
dt = F_t.dt
steps = int(total_time / dt)
times = np.arange(steps)
print('-> total of {} time steps'.format(steps))

# make a gaussian source
gaussian = lambda t: np.exp(-(t - t0 / dt)**2 / 2 /
                            (sigma / dt)**2) * np.cos(omega0 * t * dt)
source_fn = lambda t: np.abs(wg_mode) * gaussian(t)
spect_in = np.square(np.abs(my_fft(gaussian(times))))
delta_f = 1 / steps / dt
freq_x = np.arange(steps) * delta_f

# compute normalization power spectrum
F_norm = fdtd(eps_base.reshape((Nx, Ny, 1)), dl, [npml, npml, 0])