Exemplo n.º 1
0
 def get_gradient_fields(self, monitor_name):
     '''Extracts the fields in the optimizable region. These fields are needed to create the gradient fields'''
     return ls.get_fields(self.fdtd,
                          monitor_name,
                          get_eps=True,
                          get_D=True,
                          nointerpolation=True)
Exemplo n.º 2
0
    def get_fom(self, simulation):

        fields = [
            ls.get_fields(simulation.fdtd, monitor_name)
            for monitor_name in self.monitor_names
        ]

        if self.normalize_to_source_power:
            source_power = np.zeros(np.shape(fields[0].wl))
            for i, wl in enumerate(fields[0].wl):
                source_power[i] = ls.get_source_power(simulation.fdtd, wl=wl)
            self.source_power = source_power
        self.fields = fields

        pointfields = [
            field.getfield(field.x[0], field.y[0], field.z[0],
                           self.wavelengths[0]) for field in fields
        ]
        if self.weight_amplitudes is None:
            fom = sum([
                sum(pointfield * np.conj(pointfield))
                for pointfield in pointfields
            ])
        else:
            sum_of_pointfields = sum([
                pointfield * phase_factor for pointfield, phase_factor in zip(
                    pointfields, self.weight_amplitudes)
            ])
            fom = sum(sum_of_pointfields * np.conj(sum_of_pointfields))
            if self.normalize_to_source_power:
                fom = fom / np.array(source_power)
        return fom
Exemplo n.º 3
0
    def run_forward_solves(self, params):
        """ Generates the new forward simulations, runs them and computes the figure of merit and forward fields. """

        print('Running forward solves')
        self.make_forward_sim(params)
        iter = self.optimizer.iteration if self.store_all_simulations else 0
        self.sim.run(name='forward', iter=iter)

        get_eps = True
        get_D = not self.use_deps
        nointerpolation = not self.geometry.use_interpolation()

        self.forward_fields = get_fields(self.sim.fdtd,
                                         monitor_name='opt_fields',
                                         field_result_name='forward_fields',
                                         get_eps=get_eps,
                                         get_D=get_D,
                                         get_H=False,
                                         nointerpolation=nointerpolation,
                                         unfold_symmetry=self.unfold_symmetry)
        fom = self.fom.get_fom(self.sim)

        if self.store_all_simulations:
            self.sim.remove_data_and_save(
            )  #< Remove the data from the file to save disk space. TODO: Make optional?

        self.fomHist.append(fom)
        print('FOM = {}'.format(fom))
        return fom
Exemplo n.º 4
0
    def get_fom(self, simulation):
        '''

        :param simulation: The simulation object of the base simulation
        :return: The figure of merit
        '''
        field = ls.get_fields(simulation.fdtd, self.monitor_name)
        self.fields = field

        pointfield = field.getfield(field.x[0], field.y[0], field.z[0],
                                    self.wavelengths[0])
        fom = sum(pointfield * np.conj(pointfield))

        return fom
Exemplo n.º 5
0
    def run_forward_solves(self):
        """ Generates the new forward simulations, runs them and computes the figure of merit and forward fields. """

        print('Running forward solves')
        self.make_forward_sim()
        self.sim.run(name='forward', iter=self.optimizer.iteration)
        self.forward_fields = get_fields(self.sim.fdtd,
                                         monitor_name='opt_fields',
                                         get_eps=True,
                                         get_D=True,
                                         get_H=True,
                                         nointerpolation=True)
        fom = self.fom.get_fom(self.sim)
        self.fomHist.append(fom)
        print('FOM = {}'.format(fom))
        return fom
Exemplo n.º 6
0
    def run_adjoint_solves(self):
        """ Generates the adjoint simulations, runs them and extacts the adjoint fields. """

        print('Running adjoint solves')
        self.make_forward_sim()
        self.sim.fdtd.selectpartial('source')
        self.sim.fdtd.delete()
        self.fom.add_adjoint_sources(self.sim)
        self.sim.run(name='adjoint', iter=self.optimizer.iteration)
        self.adjoint_fields = get_fields(self.sim.fdtd,
                                         monitor_name='opt_fields',
                                         get_eps=True,
                                         get_D=True,
                                         get_H=True,
                                         nointerpolation=True)
        self.adjoint_fields.scale(3,
                                  self.fom.get_adjoint_field_scaling(self.sim))
    def process_forward_sim(self, iter):
        forward_name = 'forward_{}'.format(iter)
        self.sim.load(forward_name)
        Optimization.check_simulation_was_successful(self.sim)

        if self.fields_on_cad_only:
            get_fields_on_cad(
                self.sim.fdtd,
                monitor_name='opt_fields',
                field_result_name='forward_fields',
                get_eps=True,
                get_D=not self.use_deps,
                get_H=False,
                nointerpolation=not self.geometry.use_interpolation(),
                unfold_symmetry=self.unfold_symmetry)
            self.forward_fields_wl = get_lambda_from_cad(
                self.sim.fdtd, field_result_name='forward_fields')
        else:
            self.forward_fields = get_fields(
                self.sim.fdtd,
                monitor_name='opt_fields',
                field_result_name='forward_fields',
                get_eps=True,
                get_D=not self.use_deps,
                get_H=False,
                nointerpolation=not self.geometry.use_interpolation(),
                unfold_symmetry=self.unfold_symmetry)
            assert hasattr(self.forward_fields, 'E')
            self.forward_fields_wl = self.forward_fields.wl

        self.forward_fields_iter = int(iter)
        fom = self.fom.get_fom(self.sim)

        if self.store_all_simulations:
            self.sim.remove_data_and_save(
            )  # < Remove the data from the file to save disk space. TODO: Make optional?

        dist_to_target_fom = self.fom.target_fom - fom  # < For plotting/logging we store the distance to a target
        self.full_fom_hist.append(dist_to_target_fom)
        if self.fom.target_fom == 0.0:
            print('FOM = {}'.format(fom))
        else:
            print('FOM = {} ({} - {})'.format(dist_to_target_fom,
                                              self.fom.target_fom, fom))
        return fom
Exemplo n.º 8
0
    def get_fom(self, simulation):

        fields = ls.get_fields(simulation.fdtd, self.monitor_name, get_H=True)
        source_power = np.zeros(np.shape(fields.wl))
        for i, wl in enumerate(fields.wl):
            source_power[i] = ls.get_source_power(simulation.fdtd, wl=wl)

        self.fields = fields
        self.source_power = source_power
        fom_v_wavelength, phase_preactors = self.mode.calculate_overlap(fields)

        fom_v_wavelength = np.array(fom_v_wavelength) / np.array(source_power)

        self.phase_prefactors = np.array(phase_preactors) / np.array(
            source_power)

        # TODO This does not properly deal with multiple wavelengths right now

        return fom_v_wavelength[0]
Exemplo n.º 9
0
    def get_fom(self, simulation):
        '''Uploads the fields from a completed forward simulation, and performs the mode overlap integral on them'''
        fields = ls.get_fields(simulation.fdtd, self.monitor_name, get_H=True)
        source_power = np.zeros(np.shape(fields.wl))
        for i, wl in enumerate(fields.wl):
            source_power[i] = ls.get_source_power(simulation.fdtd, wl=wl)

        self.fields = fields
        self.source_power = source_power
        fom_v_wavelength, phase_preactors = self.mode.calculate_overlap(
            fields, remove_H=True)

        fom_v_wavelength = np.array(fom_v_wavelength) / np.array(source_power)

        self.phase_prefactors = np.array(phase_preactors) / np.array(
            source_power)

        # TODO This does not properly deal with multiple wavelengths right now

        return fom_v_wavelength[0]
    def process_adjoint_sim(self, iter):
        adjoint_name = 'adjoint_{}'.format(iter)
        self.sim.load(adjoint_name)
        if self.sim.fdtd.layoutmode():
            self.sim.fdtd.run()
        Optimization.check_simulation_was_successful(self.sim)

        if self.fields_on_cad_only:
            get_fields_on_cad(
                self.sim.fdtd,
                monitor_name='opt_fields',
                field_result_name='adjoint_fields',
                get_eps=not self.use_deps,
                get_D=not self.use_deps,
                get_H=False,
                nointerpolation=not self.geometry.use_interpolation(),
                unfold_symmetry=self.unfold_symmetry)
        else:
            self.adjoint_fields = get_fields(
                self.sim.fdtd,
                monitor_name='opt_fields',
                field_result_name='adjoint_fields',
                get_eps=not self.use_deps,
                get_D=not self.use_deps,
                get_H=False,
                nointerpolation=not self.geometry.use_interpolation(),
                unfold_symmetry=self.unfold_symmetry)
            assert hasattr(self.adjoint_fields, 'E')
            self.adjoint_fields.iter = int(iter)

        self.scaling_factor = self.fom.get_adjoint_field_scaling(self.sim)

        if not self.fields_on_cad_only:
            self.adjoint_fields.scale(3, self.scaling_factor)

        if self.store_all_simulations:
            self.sim.remove_data_and_save(
            )  # < Remove the data from the file to save disk space. TODO: Make optional?
Exemplo n.º 11
0
    def run_adjoint_solves(self, params):
        """ Generates the adjoint simulations, runs them and extacts the adjoint fields. """

        has_forward_fields = hasattr(self, 'forward_fields') and hasattr(
            self.forward_fields, 'E')
        params_changed = not np.allclose(params,
                                         self.geometry.get_current_params())
        if not has_forward_fields or params_changed:
            fom = self.run_forward_solves(params)

        print('Running adjoint solves')
        self.make_adjoint_sim(params)

        iter = self.optimizer.iteration if self.store_all_simulations else 0
        self.sim.run(name='adjoint', iter=iter)

        get_eps = not self.use_deps
        get_D = not self.use_deps
        nointerpolation = not self.geometry.use_interpolation()

        #< JN: Try on CAD
        self.adjoint_fields = get_fields(self.sim.fdtd,
                                         monitor_name='opt_fields',
                                         field_result_name='adjoint_fields',
                                         get_eps=get_eps,
                                         get_D=get_D,
                                         get_H=False,
                                         nointerpolation=nointerpolation,
                                         unfold_symmetry=self.unfold_symmetry)
        self.adjoint_fields.scaling_factor = self.fom.get_adjoint_field_scaling(
            self.sim)

        self.adjoint_fields.scale(3, self.adjoint_fields.scaling_factor)

        if self.store_all_simulations:
            self.sim.remove_data_and_save(
            )  #< Remove the data from the file to save disk space. TODO: Make optional?
Exemplo n.º 12
0
    def get_fom(self, simulation):
        fields = ls.get_fields(simulation.fdtd, self.monitor_name, get_H=True)
        self.fields = fields
        source_power = np.zeros(np.shape(fields.wl))
        for i, wl in enumerate(fields.wl):
            source_power[i] = ls.get_source_power(simulation.fdtd, wl=wl)
        self.source_power = source_power

        pointfields = [
            fields.getfield(pos[0], pos[1], pos[2], self.wavelength)
            for pos in self.positions
        ]

        sum_of_pointfields = sum([
            pointfield * phase_factor for pointfield, phase_factor in zip(
                pointfields, self.phase_factors)
        ])
        fom = sum(sum_of_pointfields * np.conj(sum_of_pointfields))

        fom = fom / np.array(source_power)

        # TODO This does not properly deal with multiple wavelengths right now

        return fom