Example #1
0
class ZCG(Grating):
    si_n = interp.interp1d(*zip(*[[nu2lambda(float(f))*10**6, n] for (f, n) in opencsv('materials/silicon_n.csv',1)]))
    si_k = interp.interp1d(*zip(*[[nu2lambda(float(f))*10**6,n] for (f, n) in opencsv('materials/silicon_k.csv',1)]))

    def __init__(self, params, wavelengths, target = None, resample = False):
        super().__init__(params, wavelengths, target, resample)
        self.labels = ['d','ff','tline','tslab','tstep']
        d, ff, tline, tslab, tstep = params
        assert tline > tstep, "tstep cannot be larger than tline"

        #create simulation
        self.sim = S4.New(d, 20)
        
        self.sim.AddMaterial("Vacuum", 1)
        self.sim.AddMaterial("Silicon", 0) #edited later in setmaterials

        self.sim.AddLayer('top', 0, "Vacuum")
        self.sim.AddLayer('step', tstep, "Vacuum")
        self.sim.AddLayer('lines', tline - tstep, "Vacuum")
        self.sim.AddLayer('slab', tslab, "Silicon")
        self.sim.AddLayer('bottom', 0, "Vacuum")

        self.sim.SetRegionRectangle('step', 'Silicon', (-d*ff/4, 0), 0, (d*ff/4, 0))
        self.sim.SetRegionRectangle('lines', 'Silicon', (0,0), 0, (d*ff/2, 0))

        self.sim.SetExcitationPlanewave((0, 0), 0, 1)

    def setmaterials(self, wl):
        self.sim.SetMaterial('Silicon', complex(self.__class__.si_n(wl), self.__class__.si_k(wl))**2)
Example #2
0
class HCG(Grating):
    si_n = interp.interp1d(*zip(
        *[[nu2lambda(float(f)) * 10**6, n]
          for (f, n) in h.opencsv('../matdat/silicon_n.csv', 1)]))
    si_k = interp.interp1d(*zip(
        *[[nu2lambda(float(f)) * 10**6, n]
          for (f, n) in h.opencsv('../matdat/silicon_k.csv', 1)]))

    def __init__(self, params, wavelengths, target):
        Grating.__init__(self, params, wavelengths, target)
        self.d, self.ff, self.tline, self.tslab, self.tstep = params
        self.labels = ['d', 'ff', 'tline', 'tair', 'tstep']
        if self.tstep > self.tline:
            raise ValueError("tstep cannot be larger than tline")

    def evaluate(self):
        if self.fom is None:
            S = S4.New(self.d, 20)

            #materials
            S.AddMaterial("Vacuum", 1)
            S.AddMaterial("Silicon", 1)  #edited later per wavelength

            #layers
            S.AddLayer('top', 0, "Vacuum")
            S.AddLayer('step', self.tstep, "Vacuum")
            S.AddLayer('lines', self.tline - self.tstep, "Vacuum")
            S.AddLayer('airgap', self.tslab, "Vacuum")
            S.AddLayer('bottom', 0, "Silicon")

            #patterning
            S.SetRegionRectangle('step', 'Silicon', (-self.d * self.ff / 4, 0),
                                 0, (self.d * self.ff / 4, 0))
            S.SetRegionRectangle('lines', 'Silicon', (0, 0), 0,
                                 (self.d * self.ff / 2, 0))

            #light
            S.SetExcitationPlanewave((0, 0), 0, 1)

            self.trans = []
            for wl in np.linspace(*self.wls):
                S.SetFrequency(1 / wl)
                S.SetMaterial(
                    'Silicon',
                    complex(self.__class__.si_n(wl),
                            self.__class__.si_k(wl))**2)
                self.trans.append(
                    (wl, float(np.real(S.GetPowerFlux('bottom')[0]))))
            self._calcfom()
            self.findpeak()

        return self.fom
Example #3
0
def omega2lambda(omega):
    """
    Convert omega to wavelength
    """
    from scipy.constants import nu2lambda
    from math import pi
    nu = omega / (2 * pi)
    return nu2lambda(nu)
    def add_dispersion(self, incident_angle, input_time, input_complex_time, center_freq, mixing = 1):
        theta_i = np.deg2rad(incident_angle) # convert angle in degree to radian

        d_time = np.abs(input_time[1] - input_time[0]) # time spacing
        d_freq = 1/d_time # frequency spacing
        numpoints = len(input_complex_time) # number of point in the input signal
        input_complex_freq = fftpack.fft(input_complex_time) # fourier transform to get frequency domain
        input_freq = fftpack.fftfreq(numpoints) * d_freq # calculate frequency bins
        input_freq = np.fft.fftshift(input_freq) # rearrange frequency bins
        input_freq += center_freq # center frequency bins at center frequency
        input_amp_freq, input_phase_freq = rect_to_polar(input_complex_freq) # split into amplitude and phase

        center_wavelength = nu2lambda(center_freq) # wavelength corresponding to center frequency
        theta_r0 = np.arcsin(center_wavelength/self.grating_d - np.sin(theta_i)) # reflected angle of center wavelength
        k_0 = 2 * np.pi/center_wavelength * self.grating_L # phase velocity shift
        reciprocal_vg = ((1 + np.sin(theta_i) * np.sin(theta_r0))/(speed_of_light * np.cos(theta_r0)))*self.grating_L # group velocity shift

        # add phase to input signal using grating dispersion equation
        add_phase = [] # phase to be added
        output_amp_freq = input_amp_freq # output amplitude in frequency domain
        for index, freq in enumerate(input_freq):
            wavelength = nu2lambda(freq)
            dw = 2*np.pi*(freq - center_freq)
            sin_theta_r = wavelength / self.grating_d - np.sin(theta_i) # sine of reflected angle
            if np.abs(sin_theta_r) <= 1: # value of sine is valid
                add_ph = 2 * np.pi / (wavelength) * self.grating_L * np.cos(np.arcsin(sin_theta_r)) # grating-added dispersion
                add_ph -= (k_0 + reciprocal_vg*dw) # remove pulse shifting (only want changes of pulse's shape)
            else: # value is invalid
                add_ph = 0
                output_amp_freq[index] = 0 # this wavelength is not reflected
            add_phase.append(add_ph)
        add_phase = np.array(add_phase)

        output_phase_freq = input_phase_freq + mixing * add_phase # add phase to the input pulse

        output_complex_freq = polar_to_rect(output_amp_freq, output_phase_freq)
        output_complex_time = fftpack.ifft(output_complex_freq) # inverse fourier transform to get time domain

        return output_complex_time
def test_nu_to_lambda():
    assert_equal(sc.nu2lambda(1), sc.speed_of_light)
Example #6
0
class BiZCG(Grating):
    si_n = interp.interp1d(*zip(
        *[[nu2lambda(float(f)) * 10**6, n]
          for (f, n) in h.opencsv('../matdat/silicon_n.csv', 1)]))
    si_k = interp.interp1d(*zip(
        *[[nu2lambda(float(f)) * 10**6, n]
          for (f, n) in h.opencsv('../matdat/silicon_k.csv', 1)]))

    def __init__(self, params, wavelengths, target, angle=5):
        Grating.__init__(self, params, wavelengths, target)
        self.labels = ['d', 'ff', 'tline1', 'tline2', 'tslab', 'angle']
        self.d, self.ff, self.tline1, self.tline2, self.tslab, self.angle = params
        if self.tline2 > self.tline1:
            self.tline2, self.tline1 = self.tline1, self.tline2
        if self.tslab + self.tline2 < 0:
            raise ValueError("-self.tline > self.tslab")

    def evaluate(self):
        if self.fom is None:
            S = S4.New(self.d, 20)

            #materials
            S.AddMaterial("Vacuum", 1)
            S.AddMaterial("Silicon", 1)  #edited later per wavelength

            #layers
            S.AddLayer('top', 0, "Vacuum")
            S.AddLayer('line1', self.tline1 - self.tline2, "Vacuum")
            S.AddLayer('line2', self.tline2 - self.tslab, "Vacuum")
            S.AddLayer('slab', self.tslab, "Silicon")
            S.AddLayer('bottom', 0, "Vacuum")

            #patterning
            S.SetRegionRectangle('line1', 'Silicon',
                                 (-3 * self.d * self.ff / 8, 0), 0,
                                 (self.d * self.ff / 8, 0))
            S.SetRegionRectangle('line2', 'Silicon',
                                 (-3 * self.d * self.ff / 8, 0), 0,
                                 (self.d * self.ff / 8, 0))
            S.SetRegionRectangle('line2', 'Silicon', (self.d * self.ff / 8, 0),
                                 0, (self.d * self.ff / 8, 0))

            all_trans = []
            for theta in (0, self.angle):
                #light
                S.SetExcitationPlanewave((0, 0), np.sin(theta), np.cos(theta))

                self.trans = []
                for wl in np.linspace(*self.wls):
                    S.SetFrequency(1 / wl)
                    S.SetMaterial(
                        'Silicon',
                        complex(self.__class__.si_n(wl),
                                self.__class__.si_k(wl))**2)
                    self.trans.append(
                        (wl, float(np.real(S.GetPowerFlux('bottom')[0]))))
                all_trans.append(self.trans)

            trans_metadata = []
            for trans in all_trans:
                self.trans = trans
                self.fom, self.peak, self.linewidth = 3 * (None, )
                self.findpeak()
                self._calcfom()
                trans_metadata.append((self.fom, self.peak, self.linewidth))
            self.trans = all_trans
            self.fom, self.peak, self.linewidth = max(trans_metadata)
        return self.fom

    def mutate(self):
        child = Grating.mutate(self)
        if random() > 2 / 3:
            child.params[3] = -min(self.tline2, 0.9 * self.tslab)
        child.params[5] = self.angle
        return child

    def crossbreed(self, rhs):
        child = Grating.mutate(self)
        child.params[5] = self.angle
        return child
def test_nu_to_lambda():
    assert_equal(sc.nu2lambda(1), sc.speed_of_light)
Example #8
0
def omega2lambda(omega):
    """Convert omega to wavelength."""
    from scipy.constants import nu2lambda
    from math import pi
    nu = omega / (2 * pi)
    return nu2lambda(nu)
    def startClicked(self):
        # place here the location of the Lumerical "lumapi" library
        spec_win = importlib.util.spec_from_file_location(
            "lumapi", self.ui.lineEdit_lumapi.text())
        # Functions that perform the actual loading
        lumapi = importlib.util.module_from_spec(spec_win)
        spec_win.loader.exec_module(lumapi)
        global fdtd, CIGS_Reflection_dataframe

        #fdtd = lumapi.FDTD(hide=True)

        CIGS_Monitors = self.ui.lineEdit_CIGS_M.text()
        CIGS_Material = self.ui.lineEdit_Mat_CIGS.text()
        Substrate_Monitors = self.ui.lineEdit_Substr_M.text()
        Reflection_Monitors = self.ui.lineEdit_Reflection_M.text()

        for i, files in enumerate(sorted_FDTD):

            self.ui.Results_List.setItem(i, 0, QTableWidgetItem(str(files)))
            self.ui.Results_List.setItem(i, 1, QTableWidgetItem("0"))
            self.ui.Results_List.setItem(i, 2, QTableWidgetItem("0"))

            if i == 0:
                self.ui.Results_List.setHorizontalHeaderLabels(
                    ('Simulation Files', 'CIGS Jsc', 'parasitic Jsc')
                )  #this only needs to run once to set the name of the headers

                fdtd = lumapi.FDTD(hide=False, filename=files)
                if not fdtd.havedata(CIGS_Monitors):
                    fdtd.runanalysis
                    fdtd.save

                if self.ui.checkBox_EQE.isChecked():

                    CIGS_EQE_dataframe = pandas.DataFrame(nu2lambda(
                        np.squeeze(fdtd.getresult(CIGS_Monitors, "f"))),
                                                          columns=['λ'])
                    CIGS_Jsc_list = []
                    CIGS_Reflection_dataframe = pandas.DataFrame(nu2lambda(
                        np.squeeze(fdtd.getresult(Reflection_Monitors, "f"))),
                                                                 columns=['λ'])
                if self.ui.checkBox_Parasit.isChecked():
                    parasitic_EQE_dataframe = pandas.DataFrame(nu2lambda(
                        np.squeeze(fdtd.getresult(CIGS_Monitors, "f"))),
                                                               columns=['λ'])
                    parasitic_Jsc_list = []

                if self.ui.checkBox_export_charge.isChecked():
                    model_dataframe = pandas.DataFrame(columns=[
                        'FDTD_name', 'Metal_thickness', 'Dielectric_thickness',
                        'Encapsulation_gap', 'contact_dimension'
                    ])
                    fdtd.select("::model")
                    model_dataframe.loc[i] = [
                        files,
                        fdtd.get('Metal_thickness'),
                        fdtd.get('Dielectric_thickness'),
                        fdtd.get('Encapsulation_gap'),
                        fdtd.get('contact_dimension')
                    ]

                if self.ui.checkBox_Mesh.isChecked():
                    CIGS_Mesh_list = []

                # calculate stuff for the jsc
                AM15G = fdtd.solar(1)
                AM15G = np.asarray(AM15G).squeeze()
                wavelength = fdtd.solar(0)
                wavelength = np.asarray(wavelength).squeeze()
                qhc = (sc.e / (sc.h * sc.c))

                frequency = nu2lambda(fdtd.getresult(CIGS_Monitors, "f"))
                frequency = frequency.flatten()
                interpolator = interpolate.interp1d(wavelength, AM15G)
                interpolated_AM15G = interpolator(frequency)

            if i != 0:
                fdtd.load(files)
                if not fdtd.havedata(CIGS_Monitors):
                    fdtd.runanalysis
                    fdtd.save

            if self.ui.checkBox_export_charge.isChecked():
                fdtd.select("::model")
                model_dataframe.loc[i] = [
                    files,
                    fdtd.get('Metal_thickness'),
                    fdtd.get('Dielectric_thickness'),
                    fdtd.get('Encapsulation_gap'),
                    fdtd.get('contact_dimension')
                ]

            if self.ui.checkBox_EQE.isChecked():

                tolerance = float(
                    self.ui.doubleSpinBox.text()
                )  #takes the tolerance to the isclose function from the Spinbox UI element
                CIGS_EQE_data = CIGS_EQE(CIGS_Monitors, CIGS_Material,
                                         self.ui.checkBox_Gen.isChecked(),
                                         files, tolerance)
                CIGS_EQE_data = CIGS_EQE_data.flatten()
                CIGS_EQE_dataframe.insert(i + 1, "EQE " + files, CIGS_EQE_data)
                Jsc_integrated = integrate.simps(
                    frequency * qhc * interpolated_AM15G * CIGS_EQE_data,
                    frequency) * 0.1  #mA/cm^2
                CIGS_Jsc_list.append(Jsc_integrated)
                self.ui.Results_List.setItem(
                    i, 1, QTableWidgetItem(str(Jsc_integrated)))
                CIGS_Reflection_data = reflection_results(Reflection_Monitors)

                CIGS_Reflection_dataframe.insert(i + 1,
                                                 "Reflection EQE " + files,
                                                 CIGS_Reflection_data)

            if self.ui.checkBox_Parasit.isChecked():
                tolerance = float(self.ui.doubleSpinBox.text())
                parasitic_EQE_data = parasitic_eqe(Substrate_Monitors,
                                                   CIGS_Material, tolerance)
                parasitic_EQE_data = parasitic_EQE_data.flatten()
                parasitic_EQE_dataframe.insert(i + 1, "parasitic EQE " + files,
                                               parasitic_EQE_data)
                parasitic_Jsc_integrated = integrate.simps(
                    frequency * qhc * interpolated_AM15G * parasitic_EQE_data,
                    frequency) * 0.1
                parasitic_Jsc_list.append(parasitic_Jsc_integrated)
                self.ui.Results_List.setItem(
                    i, 2, QTableWidgetItem(str(parasitic_Jsc_integrated)))

            if self.ui.checkBox_Mesh.isChecked():
                Mesh_result = mesh_per_volume()
                CIGS_Mesh_list.append(Mesh_result)

            self.ui.Files_List.setItem(i, 1, QTableWidgetItem('Processed'))

        if self.ui.checkBox_EQE.isChecked():

            CIGS_EQE_dataframe.to_excel('CIGS_EQE.xlsx', index=False)
            CIGS_Reflection_dataframe.to_excel('Reflection.xlsx', index=False)
            CIGS_Jsc_dict = dict(zip(sorted_FDTD, CIGS_Jsc_list))
            CIGS_Jsc_dataframe = pandas.DataFrame([CIGS_Jsc_dict])
            CIGS_Jsc_dataframe.to_excel('CIGS_Jsc.xlsx', index=False)

        if self.ui.checkBox_Parasit.isChecked():
            parasitic_EQE_dataframe.to_excel('parasitic_eqe.xlsx', index=False)
            parasitic_Jsc_dict = dict(zip(sorted_FDTD, parasitic_Jsc_list))
            parasitic_Jsc_dataframe = pandas.DataFrame([parasitic_Jsc_dict])
            parasitic_Jsc_dataframe.to_excel('parasitic_Jsc.xlsx', index=False)

        if self.ui.checkBox_export_charge.isChecked():
            model_dataframe.to_csv("model_dataframe.csv", index=False)

        if self.ui.checkBox_Mesh.isChecked():
            CIGS_Mesh_dict = dict(zip(sorted_FDTD, CIGS_Mesh_list))
            CIGS_Mesh_dataframe = pandas.DataFrame([CIGS_Mesh_dict])
            CIGS_Mesh_dataframe.to_excel('Mesh_Volume.xlsx', index=False)

        fdtd.close()
Example #10
0
def test_nu_to_lambda():
    assert_equal(sc.nu2lambda([sc.speed_of_light, 1]), [1, sc.speed_of_light])
Example #11
0
def wn2lambda(wn):
    return nu2lambda(wn2nu(wn))