Example #1
0
    def place_adjoint_source(self, dJ):
        dt = self.sim.fields.dt  # the timestep size from sim.fields.dt of the forward sim
        self.sources = []
        dJ = dJ.flatten()

        #TODO far_pts in 3d or cylindrical, perhaps py_v3_to_vec from simulation.py
        self.all_nearsrcdata = self.monitor.swigobj.near_sourcedata(
            mp.vec(self.far_pt.x, self.far_pt.y), dJ)
        for near_data in self.all_nearsrcdata:
            cur_comp = near_data.near_fd_comp
            amp_arr = np.array(near_data.amp_arr).reshape(-1, self.num_freq)
            scale = amp_arr * adj_src_scale(self, dt, include_resolution=False)

            if self.num_freq == 1:
                self.sources += [
                    mp.IndexedSource(self.time_src, near_data, scale[:, 0])
                ]
            else:
                src = FilteredSource(self.time_src.frequency, self.frequencies,
                                     scale, dt)
                (num_basis, num_pts) = src.nodes.shape
                for basis_i in range(num_basis):
                    self.sources += [
                        mp.IndexedSource(src.time_src_bf[basis_i], near_data,
                                         src.nodes[basis_i])
                    ]

        return self.sources
Example #2
0
    def place_adjoint_source(self, dJ):
        dt = self.sim.fields.dt  # the timestep size from sim.fields.dt of the forward sim
        self.sources = []
        if dJ.ndim == 4:
            dJ = np.sum(dJ, axis=0)
        dJ = dJ.flatten()
        farpt_list = np.array([list(pi) for pi in self.far_pts]).flatten()
        far_pt0 = self.far_pts[0]
        far_pt_vec = py_v3_to_vec(self.sim.dimensions, far_pt0,
                                  self.sim.is_cylindrical)

        self.all_nearsrcdata = self.monitor.swigobj.near_sourcedata(
            far_pt_vec, farpt_list, self.nfar_pts, dJ)
        for near_data in self.all_nearsrcdata:
            cur_comp = near_data.near_fd_comp
            amp_arr = np.array(near_data.amp_arr).reshape(-1, self.num_freq)
            scale = amp_arr * adj_src_scale(self, dt, include_resolution=False)

            if self.num_freq == 1:
                self.sources += [
                    mp.IndexedSource(self.time_src, near_data, scale[:, 0])
                ]
            else:
                src = FilteredSource(self.time_src.frequency, self.frequencies,
                                     scale, dt)
                (num_basis, num_pts) = src.nodes.shape
                for basis_i in range(num_basis):
                    self.sources += [
                        mp.IndexedSource(src.time_src_bf[basis_i], near_data,
                                         src.nodes[basis_i])
                    ]

        return self.sources
Example #3
0
    def place_adjoint_source(self, dJ):
        time_src = self._create_time_profile()
        sources = []

        mon_size = self.sim.fields.dft_monitor_size(self._monitor.swigobj,
                                                    self.volume.swigobj,
                                                    self.component)
        dJ = dJ.astype(np.complex128)
        if np.prod(mon_size) * self.num_freq != dJ.size and np.prod(
                mon_size) * self.num_freq**2 != dJ.size:
            raise ValueError('The format of J is incorrect!')

        # The objective function J is a vector. Each component corresponds to a frequency.
        if np.prod(
                mon_size) * self.num_freq**2 == dJ.size and self.num_freq > 1:
            dJ = np.sum(dJ, axis=1)
        '''The adjoint solver requires the objective function
        to be scalar valued with regard to objective arguments
        and position, but the function may be vector valued
        with regard to frequency. In this case, the Jacobian
        will be of the form [F,F,...] where F is the number of
        frequencies. Because of linearity, we can sum across the
        second frequency dimension to calculate a frequency
        scale factor for each point (rather than a scale vector).
        '''

        self.all_fouriersrcdata = self._monitor.swigobj.fourier_sourcedata(
            self.volume.swigobj, self.component, self.sim.fields, dJ)

        for fourier_data in self.all_fouriersrcdata:
            amp_arr = np.array(fourier_data.amp_arr).reshape(-1, self.num_freq)
            scale = amp_arr * self._adj_src_scale(include_resolution=False)

            if self.num_freq == 1:
                sources += [
                    mp.IndexedSource(time_src, fourier_data, scale[:, 0],
                                     not self.yee_grid)
                ]
            else:
                src = FilteredSource(time_src.frequency, self._frequencies,
                                     scale, self.sim.fields.dt)
                (num_basis, num_pts) = src.nodes.shape
                for basis_i in range(num_basis):
                    sources += [
                        mp.IndexedSource(src.time_src_bf[basis_i],
                                         fourier_data, src.nodes[basis_i],
                                         not self.yee_grid)
                    ]
        return sources