예제 #1
0
    def test_set_materials(self):

        def change_geom(sim):
            t = sim.meep_time()
            fn = t * 0.02
            geom = [mp.Cylinder(radius=3, material=mp.Medium(index=3.5), center=mp.Vector3(fn, fn)),
                    mp.Ellipsoid(size=mp.Vector3(1, 2, mp.inf), center=mp.Vector3(fn, fn))]

            sim.set_materials(geometry=geom)

        c = mp.Cylinder(radius=3, material=mp.Medium(index=3.5))
        e = mp.Ellipsoid(size=mp.Vector3(1, 2, mp.inf))

        sources = mp.Source(src=mp.GaussianSource(1, fwidth=0.1), component=mp.Hz, center=mp.Vector3())
        symmetries = [mp.Mirror(mp.X, -1), mp.Mirror(mp.Y, -1)]

        sim = mp.Simulation(cell_size=mp.Vector3(10, 10),
                            geometry=[c, e],
                            boundary_layers=[mp.PML(1.0)],
                            sources=[sources],
                            symmetries=symmetries,
                            resolution=16)

        eps = {'arr1': None, 'arr2': None}

        def get_arr1(sim):
            eps['arr1'] = sim.get_array(mp.Dielectric, mp.Volume(mp.Vector3(), mp.Vector3(10, 10)))

        def get_arr2(sim):
            eps['arr2'] = sim.get_array(mp.Dielectric, mp.Volume(mp.Vector3(), mp.Vector3(10, 10)))

        sim.run(mp.at_time(50, get_arr1), mp.at_time(100, change_geom),
                mp.at_end(get_arr2), until=200)

        self.assertFalse(np.array_equal(eps['arr1'], eps['arr2']))
예제 #2
0
파일: simulation.py 프로젝트: stevengj/meep
    def test_set_materials(self):

        def change_geom(sim):
            t = sim.meep_time()
            fn = t * 0.02
            geom = [mp.Cylinder(radius=3, material=mp.Medium(index=3.5), center=mp.Vector3(fn, fn)),
                    mp.Ellipsoid(size=mp.Vector3(1, 2, mp.inf), center=mp.Vector3(fn, fn))]

            sim.set_materials(geometry=geom)

        c = mp.Cylinder(radius=3, material=mp.Medium(index=3.5))
        e = mp.Ellipsoid(size=mp.Vector3(1, 2, mp.inf))

        sources = mp.Source(src=mp.GaussianSource(1, fwidth=0.1), component=mp.Hz, center=mp.Vector3())
        symmetries = [mp.Mirror(mp.X, -1), mp.Mirror(mp.Y, -1)]

        sim = mp.Simulation(cell_size=mp.Vector3(10, 10),
                            geometry=[c, e],
                            boundary_layers=[mp.PML(1.0)],
                            sources=[sources],
                            symmetries=symmetries,
                            resolution=16)

        eps = {'arr1': None, 'arr2': None}

        def get_arr1(sim):
            eps['arr1'] = sim.get_array(mp.Dielectric, mp.Volume(mp.Vector3(), mp.Vector3(10, 10)))

        def get_arr2(sim):
            eps['arr2'] = sim.get_array(mp.Dielectric, mp.Volume(mp.Vector3(), mp.Vector3(10, 10)))

        sim.run(mp.at_time(50, get_arr1), mp.at_time(100, change_geom),
                mp.at_end(get_arr2), until=200)

        self.assertFalse(np.array_equal(eps['arr1'], eps['arr2']))
예제 #3
0
    def test_at_time(self):
        sim = self.init_simple_simulation()
        sim.use_output_directory(self.temp_dir)
        sim.run(mp.at_time(100, mp.output_efield_z), until=200)

        fname = os.path.join(self.temp_dir, 'simulation-ez-000100.00.h5')
        self.assertTrue(os.path.exists(fname))
예제 #4
0
    def test_at_time(self):
        sim = self.init_simple_simulation()
        sim.run(mp.at_time(100, mp.output_efield_z), until=200)

        fname = 'simulation-ez-000100.00.h5'
        self.assertTrue(os.path.exists(fname))

        mp.all_wait()
        if mp.am_master():
            os.remove(fname)
예제 #5
0
파일: simulation.py 프로젝트: stevengj/meep
    def test_at_time(self):
        sim = self.init_simple_simulation()
        sim.run(mp.at_time(100, mp.output_efield_z), until=200)

        fname = 'simulation-ez-000100.00.h5'
        self.assertTrue(os.path.exists(fname))

        mp.all_wait()
        if mp.am_master():
            os.remove(fname)
예제 #6
0
def main(from_um_factor, resolution_wlen, courant, submerged_index,
         displacement, surface_index, wlen_center, wlen_width, nfreq,
         air_wlen_factor, pml_wlen_factor, flux_wlen_factor, time_factor_cell,
         second_time_factor, series, folder, parallel, n_processes,
         split_chunks_evenly):

    #%% CLASSIC INPUT PARAMETERS
    """
    # Simulation size
    from_um_factor = 100e-3 # Conversion of 1 μm to my length unit (=100nm/1μm)
    resolution_wlen = 20 # >=8 pixels per smallest wavelength, i.e. np.floor(8/wvl_min)
    courant = 0.5
    
    # Nanoparticle specifications: Sphere in Vacuum :)
    paper = "R"
    reference = "Meep"
    displacement = 0 # Displacement of the surface from the bottom of the sphere in nm
    submerged_index = 1.33 # 1.33 for water
    surface_index = 1.54 # 1.54 for glass
    
    # Frequency and wavelength
    wlen_center = 650 # Main wavelength range in nm
    wlen_width = 200 # Wavelength band in nm
    nfreq = 100
    
    # Box dimensions
    pml_wlen_factor = 0.38
    air_wlen_factor = 0.15
    flux_wlen_factor = 0.1
    
    # Simulation time
    time_factor_cell = 1.2
    second_time_factor = 10
    
    # Saving directories
    series = "1stTest"
    folder = "Test/TestDipole/DipoleGlass"
    
    # Configuration
    parallel = False
    n_processes = 1
    split_chunks_evenly = True
    """

    #%% MORE INPUT PARAMETERS

    # Simulation size
    resolution = (from_um_factor * 1e3) * resolution_wlen / (wlen_center +
                                                             wlen_width / 2)
    resolution = int(np.ceil(resolution / 2)) * 2

    # Frequency and wavelength
    cutoff = 3.2  # Gaussian planewave source's parameter of shape
    nazimuthal = 16
    npolar = 20

    ### TREATED INPUT PARAMETERS

    # Nanoparticle specifications: Sphere in Vacuum :)
    displacement = displacement / (from_um_factor * 1e3)  # Now in Meep units

    # Frequency and wavelength
    wlen_center = wlen_center / (from_um_factor * 1e3)  # Now in Meep units
    wlen_width = wlen_width / (from_um_factor * 1e3)  # Now in Meep units
    freq_center = 1 / wlen_center  # Hz center frequency in Meep units
    freq_width = 1 / wlen_width  # Hz range in Meep units from highest to lowest

    # Space configuration
    pml_width = pml_wlen_factor * (wlen_center + wlen_width / 2
                                   )  # 0.5 * max(wlen_range)
    air_width = air_wlen_factor * (wlen_center + wlen_width / 2)
    flux_box_size = flux_wlen_factor * (wlen_center + wlen_width / 2)

    # Computation
    enlapsed = []
    if parallel:
        np_process = mp.count_processors()
    else:
        np_process = 1

    # Saving directories
    if series is None:
        series = "Test"
    if folder is None:
        folder = "Test"
    params_list = [
        "from_um_factor", "resolution_wlen", "resolution", "courant",
        "submerged_index", "displacement", "surface_index", "wlen_center",
        "wlen_width", "cutoff", "nfreq", "nazimuthal", "npolar",
        "flux_box_size", "cell_width", "pml_width", "air_width",
        "until_after_sources", "time_factor_cell", "second_time_factor",
        "enlapsed", "parallel", "n_processes", "split_chunks_evenly", "script",
        "sysname", "path"
    ]

    #%% GENERAL GEOMETRY SETUP

    air_width = air_width - air_width % (1 / resolution)

    pml_width = pml_width - pml_width % (1 / resolution)
    pml_layers = [mp.PML(thickness=pml_width)]

    # symmetries = [mp.Mirror(mp.Y),
    #               mp.Mirror(mp.Z, phase=-1)]
    # Two mirror planes reduce cell size to 1/4
    # Issue related that lead me to comment this lines:
    # https://github.com/NanoComp/meep/issues/1484

    cell_width = 2 * (pml_width + air_width)
    cell_width = cell_width - cell_width % (1 / resolution)
    cell_size = mp.Vector3(cell_width, cell_width, cell_width)

    # surface_center = r/4 - displacement/2 + cell_width/4
    # surface_center = surface_center - surface_center%(1/resolution)
    # displacement = r/2 + cell_width/2 - 2*surface_center

    displacement = displacement - displacement % (1 / resolution)

    flux_box_size = flux_box_size - flux_box_size % (1 / resolution)

    sources = [
        mp.Source(mp.GaussianSource(freq_center,
                                    fwidth=freq_width,
                                    is_integrated=True,
                                    cutoff=cutoff),
                  center=mp.Vector3(),
                  component=mp.Ez)
    ]
    # Ez-polarized point pulse
    # (its size parameter is null and it is centered at zero)
    # >> The planewave source extends into the PML
    # ==> is_integrated=True must be specified

    until_after_sources = time_factor_cell * cell_width * submerged_index
    # Enough time for the pulse to pass through all the cell
    # Originally: Aprox 3 periods of lowest frequency, using T=λ/c=λ in Meep units
    # Now: Aprox 3 periods of highest frequency, using T=λ/c=λ in Meep units

    # if surface_index != 1:
    #     geometry = [mp.Block(material=mp.Medium(index=surface_index),
    #                          center=mp.Vector3(
    #                              - displacement/2 + cell_width/4,
    #                              0, 0),
    #                          size=mp.Vector3(
    #                              cell_width/2 + displacement,
    #                              cell_width, cell_width))]
    # else:
    #     geometry = []
    # A certain material surface underneath it

    home = vs.get_home()
    sysname = vs.get_sys_name()
    path = os.path.join(home, folder, series)
    if not os.path.isdir(path) and vm.parallel_assign(0, n_processes,
                                                      parallel):
        os.makedirs(path)
    file = lambda f: os.path.join(path, f)

    #%% BASE SIMULATION: SETUP

    measure_ram()

    params = {}
    for p in params_list:
        params[p] = eval(p)

    sim = mp.Simulation(resolution=resolution,
                        cell_size=cell_size,
                        boundary_layers=pml_layers,
                        sources=sources,
                        k_point=mp.Vector3(),
                        Courant=courant,
                        default_material=mp.Medium(index=submerged_index),
                        output_single_precision=True,
                        split_chunks_evenly=split_chunks_evenly)

    measure_ram()

    near2far_box = sim.add_near2far(
        freq_center, freq_width, nfreq,
        mp.Near2FarRegion(center=mp.Vector3(x=-flux_box_size / 2),
                          size=mp.Vector3(0, flux_box_size, flux_box_size),
                          weight=-1),
        mp.Near2FarRegion(center=mp.Vector3(x=+flux_box_size / 2),
                          size=mp.Vector3(0, flux_box_size, flux_box_size),
                          weight=+1),
        mp.Near2FarRegion(center=mp.Vector3(y=-flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, 0, flux_box_size),
                          weight=-1),
        mp.Near2FarRegion(center=mp.Vector3(y=+flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, 0, flux_box_size),
                          weight=+1),
        mp.Near2FarRegion(center=mp.Vector3(z=-flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, flux_box_size, 0),
                          weight=-1),
        mp.Near2FarRegion(center=mp.Vector3(z=+flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, flux_box_size, 0),
                          weight=+1))
    measure_ram()
    # used_ram.append(used_ram[-1])

    #%% BASE SIMULATION: INITIALIZE

    temp = time()
    sim.init_sim()
    enlapsed.append(time() - temp)
    measure_ram()

    #%% BASE SIMULATION: SIMULATION :D

    step_ram_function = lambda sim: measure_ram()

    temp = time()
    sim.run(mp.at_beginning(step_ram_function),
            mp.at_time(int(second_time_factor * until_after_sources / 2),
                       step_ram_function),
            mp.at_end(step_ram_function),
            until_after_sources=second_time_factor * until_after_sources)
    #     mp.stop_when_fields_decayed(
    # np.mean(wlen_range), # dT = mean period of source
    # mp.Ez, # Component of field to check
    # mp.Vector3(0.5*cell_width - pml_width, 0, 0), # Where to check
    # 1e-3)) # Factor to decay
    enlapsed.append(time() - temp)
    del temp
    # Aprox 30 periods of lowest frequency, using T=λ/c=λ in Meep units

    #%% BASE SIMULATION: ANGULAR PATTERN ANALYSIS

    freqs = np.linspace(freq_center - freq_center / 2,
                        freq_center + freq_width / 2, nfreq)
    wlens = 1 / freqs

    # fraunhofer_distance = 8 * (r**2) / min(wlen_range)
    # radial_distance = max( 10 * fraunhofer_distance , 1.5 * cell_width/2 )
    # radius of far-field circle must be at least Fraunhofer distance

    radial_distance = cell_width
    azimuthal_angle = np.arange(0, 2 + 2 / nazimuthal,
                                2 / nazimuthal)  # in multiples of pi
    polar_angle = np.arange(0, 1 + 1 / npolar, 1 / npolar)

    poynting_x = []
    poynting_y = []
    poynting_z = []
    poynting_r = []

    for phi in azimuthal_angle:

        poynting_x.append([])
        poynting_y.append([])
        poynting_z.append([])
        poynting_r.append([])

        for theta in polar_angle:

            farfield_dict = sim.get_farfields(
                near2far_box,
                1,
                where=mp.Volume(center=mp.Vector3(
                    radial_distance * np.cos(np.pi * phi) *
                    np.sin(np.pi * theta),
                    radial_distance * np.sin(np.pi * phi) *
                    np.sin(np.pi *
                           theta), radial_distance * np.cos(np.pi * theta))))

            Px = farfield_dict["Ey"] * np.conjugate(farfield_dict["Hz"])
            Px -= farfield_dict["Ez"] * np.conjugate(farfield_dict["Hy"])
            Py = farfield_dict["Ez"] * np.conjugate(farfield_dict["Hx"])
            Py -= farfield_dict["Ex"] * np.conjugate(farfield_dict["Hz"])
            Pz = farfield_dict["Ex"] * np.conjugate(farfield_dict["Hy"])
            Pz -= farfield_dict["Ey"] * np.conjugate(farfield_dict["Hx"])

            Px = np.real(Px)
            Py = np.real(Py)
            Pz = np.real(Pz)

            poynting_x[-1].append(Px)
            poynting_y[-1].append(Py)
            poynting_z[-1].append(Pz)
            poynting_r[-1].append(
                np.sqrt(np.square(Px) + np.square(Py) + np.square(Pz)))

    del phi, theta, farfield_dict, Px, Py, Pz

    poynting_x = np.array(poynting_x)
    poynting_y = np.array(poynting_y)
    poynting_z = np.array(poynting_z)
    poynting_r = np.array(poynting_r)

    #%% BASE SIMULATION: SAVE DATA

    for p in params_list:
        params[p] = eval(p)

    os.chdir(path)
    sim.save_near2far("BaseNear2Far", near2far_box)
    if vm.parallel_assign(0, np_process, parallel):
        f = h5.File("BaseNear2Far.h5", "r+")
        for key, par in params.items():
            f[list(f.keys())[0]].attrs[key] = par
        f.close()
        del f
    os.chdir(syshome)

    if vm.parallel_assign(1, np_process, parallel):
        f = h5.File(file("BaseResults.h5"), "w")
        f["Px"] = poynting_x
        f["Py"] = poynting_y
        f["Pz"] = poynting_z
        f["Pr"] = poynting_r
        for dset in f.values():
            for key, par in params.items():
                dset.attrs[key] = par
        f.close()
        del f

    # if not split_chunks_evenly:
    #     vm.save_chunks(sim, params, path)

    if parallel:
        f = h5.File(file("BaseRAM.h5"),
                    "w",
                    driver='mpio',
                    comm=MPI.COMM_WORLD)
        current_process = mp.my_rank()
        f.create_dataset("RAM", (len(used_ram), np_process), dtype="float")
        f["RAM"][:, current_process] = used_ram
        for a in params:
            f["RAM"].attrs[a] = params[a]
        f.create_dataset("SWAP", (len(used_ram), np_process), dtype="int")
        f["SWAP"][:, current_process] = swapped_ram
        for a in params:
            f["SWAP"].attrs[a] = params[a]
    else:
        f = h5.File(file("BaseRAM.h5"), "w")
        f.create_dataset("RAM", data=used_ram)
        for a in params:
            f["RAM"].attrs[a] = params[a]
        f.create_dataset("SWAP", data=swapped_ram)
        for a in params:
            f["SWAP"].attrs[a] = params[a]
    f.close()
    del f

    sim.reset_meep()

    #%% FURTHER SIMULATION

    if surface_index != 1:

        #% FURTHER SIMULATION: SETUP

        measure_ram()

        params = {}
        for p in params_list:
            params[p] = eval(p)

        sim = mp.Simulation(resolution=resolution,
                            cell_size=cell_size,
                            boundary_layers=pml_layers,
                            sources=sources,
                            k_point=mp.Vector3(),
                            Courant=courant,
                            default_material=mp.Medium(index=surface_index),
                            output_single_precision=True,
                            split_chunks_evenly=split_chunks_evenly)

        measure_ram()

        near2far_box = sim.add_near2far(
            freq_center, freq_width, nfreq,
            mp.Near2FarRegion(center=mp.Vector3(x=-flux_box_size / 2),
                              size=mp.Vector3(0, flux_box_size, flux_box_size),
                              weight=-1),
            mp.Near2FarRegion(center=mp.Vector3(x=+flux_box_size / 2),
                              size=mp.Vector3(0, flux_box_size, flux_box_size),
                              weight=+1),
            mp.Near2FarRegion(center=mp.Vector3(y=-flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, 0, flux_box_size),
                              weight=-1),
            mp.Near2FarRegion(center=mp.Vector3(y=+flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, 0, flux_box_size),
                              weight=+1),
            mp.Near2FarRegion(center=mp.Vector3(z=-flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, flux_box_size, 0),
                              weight=-1),
            mp.Near2FarRegion(center=mp.Vector3(z=+flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, flux_box_size, 0),
                              weight=+1))
        measure_ram()
        # used_ram.append(used_ram[-1])

        #% FURTHER SIMULATION: INITIALIZE

        temp = time()
        sim.init_sim()
        enlapsed.append(time() - temp)
        measure_ram()

        #% FURTHER SIMULATION: SIMULATION :D

        step_ram_function = lambda sim: measure_ram()

        temp = time()
        sim.run(mp.at_beginning(step_ram_function),
                mp.at_time(int(second_time_factor * until_after_sources / 2),
                           step_ram_function),
                mp.at_end(step_ram_function),
                until_after_sources=second_time_factor * until_after_sources)
        #     mp.stop_when_fields_decayed(
        # np.mean(wlen_range), # dT = mean period of source
        # mp.Ez, # Component of field to check
        # mp.Vector3(0.5*cell_width - pml_width, 0, 0), # Where to check
        # 1e-3)) # Factor to decay
        enlapsed.append(time() - temp)
        del temp
        # Aprox 30 periods of lowest frequency, using T=λ/c=λ in Meep units

        #% FURTHER SIMULATION: ANGULAR PATTERN ANALYSIS

        poynting_x2 = []
        poynting_y2 = []
        poynting_z2 = []
        poynting_r2 = []

        for phi in azimuthal_angle:

            poynting_x2.append([])
            poynting_y2.append([])
            poynting_z2.append([])
            poynting_r2.append([])

            for theta in polar_angle:

                farfield_dict = sim.get_farfields(
                    near2far_box,
                    1,
                    where=mp.Volume(center=mp.Vector3(
                        radial_distance * np.cos(np.pi * phi) *
                        np.sin(np.pi * theta),
                        radial_distance * np.sin(np.pi * phi) *
                        np.sin(np.pi *
                               theta), radial_distance *
                        np.cos(np.pi * theta))))

                Px = farfield_dict["Ey"] * np.conjugate(farfield_dict["Hz"])
                Px -= farfield_dict["Ez"] * np.conjugate(farfield_dict["Hy"])
                Py = farfield_dict["Ez"] * np.conjugate(farfield_dict["Hx"])
                Py -= farfield_dict["Ex"] * np.conjugate(farfield_dict["Hz"])
                Pz = farfield_dict["Ex"] * np.conjugate(farfield_dict["Hy"])
                Pz -= farfield_dict["Ey"] * np.conjugate(farfield_dict["Hx"])

                Px = np.real(Px)
                Py = np.real(Py)
                Pz = np.real(Pz)

                poynting_x2[-1].append(Px)
                poynting_y2[-1].append(Py)
                poynting_z2[-1].append(Pz)
                poynting_r2[-1].append(
                    np.sqrt(np.square(Px) + np.square(Py) + np.square(Pz)))

        del phi, theta, farfield_dict, Px, Py, Pz

        poynting_x2 = np.array(poynting_x2)
        poynting_y2 = np.array(poynting_y2)
        poynting_z2 = np.array(poynting_z2)
        poynting_r2 = np.array(poynting_r2)

        #% FURTHER SIMULATION: SAVE DATA

        for p in params_list:
            params[p] = eval(p)

        os.chdir(path)
        sim.save_near2far("FurtherNear2Far", near2far_box)
        if vm.parallel_assign(0, np_process, parallel):
            f = h5.File("FurtherNear2Far.h5", "r+")
            for key, par in params.items():
                f[list(f.keys())[0]].attrs[key] = par
            f.close()
            del f
        os.chdir(syshome)

        if vm.parallel_assign(1, np_process, parallel):
            f = h5.File(file("FurtherResults.h5"), "w")
            f["Px"] = poynting_x2
            f["Py"] = poynting_y2
            f["Pz"] = poynting_z2
            f["Pr"] = poynting_r2
            for dset in f.values():
                for key, par in params.items():
                    dset.attrs[key] = par
            f.close()
            del f

        # if not split_chunks_evenly:
        #     vm.save_chunks(sim, params, path)

        if parallel:
            f = h5.File(file("FurtherRAM.h5"),
                        "w",
                        driver='mpio',
                        comm=MPI.COMM_WORLD)
            current_process = mp.my_rank()
            f.create_dataset("RAM", (len(used_ram), np_process), dtype="float")
            f["RAM"][:, current_process] = used_ram
            for a in params:
                f["RAM"].attrs[a] = params[a]
            f.create_dataset("SWAP", (len(used_ram), np_process), dtype="int")
            f["SWAP"][:, current_process] = swapped_ram
            for a in params:
                f["SWAP"].attrs[a] = params[a]
        else:
            f = h5.File(file("FurtherRAM.h5"), "w")
            f.create_dataset("RAM", data=used_ram)
            for a in params:
                f["RAM"].attrs[a] = params[a]
            f.create_dataset("SWAP", data=swapped_ram)
            for a in params:
                f["SWAP"].attrs[a] = params[a]
        f.close()
        del f

    #%% NORMALIZE AND REARANGE DATA

    if surface_index != 1:
        max_poynting_r = np.max(
            [np.max(np.abs(poynting_r)),
             np.max(np.abs(poynting_r2))])
    else:
        max_poynting_r = np.max(np.abs(poynting_r))

    poynting_x = np.array(poynting_x) / max_poynting_r
    poynting_y = np.array(poynting_y) / max_poynting_r
    poynting_z = np.array(poynting_z) / max_poynting_r
    poynting_r = np.array(poynting_r) / max_poynting_r

    if surface_index != 1:

        poynting_x0 = np.array(poynting_x)
        poynting_y0 = np.array(poynting_y)
        poynting_z0 = np.array(poynting_z)
        poynting_r0 = np.array(poynting_r)

        poynting_x2 = np.array(poynting_x2) / max_poynting_r
        poynting_y2 = np.array(poynting_y2) / max_poynting_r
        poynting_z2 = np.array(poynting_z2) / max_poynting_r
        poynting_r2 = np.array(poynting_r2) / max_poynting_r

    #%%
    """
    poynting_x = np.array(poynting_x0)
    poynting_y = np.array(poynting_y0)
    poynting_z = np.array(poynting_z0)
    poynting_r = np.array(poynting_r0)
    """

    if surface_index != 1:

        polar_limit = np.arcsin(displacement / radial_distance) + .5

        for i in range(len(polar_angle)):
            if polar_angle[i] > polar_limit:
                index_limit = i
                break

        poynting_x[:, index_limit:, :] = poynting_x2[:, index_limit:, :]
        poynting_y[:, index_limit:, :] = poynting_y2[:, index_limit:, :]
        poynting_z[:, index_limit:, :] = poynting_z2[:, index_limit:, :]
        poynting_r[:, index_limit:, :] = poynting_r2[:, index_limit:, :]

        poynting_x[:, index_limit - 1, :] = np.array([[
            np.mean([p2, p0]) for p2, p0 in zip(poy2, poy0)
        ] for poy2, poy0 in zip(poynting_x2[:, index_limit -
                                            1, :], poynting_x0[:, index_limit -
                                                               1, :])])
        poynting_y[:, index_limit - 1, :] = np.array([[
            np.mean([p2, p0]) for p2, p0 in zip(poy2, poy0)
        ] for poy2, poy0 in zip(poynting_y2[:, index_limit -
                                            1, :], poynting_y0[:, index_limit -
                                                               1, :])])
        poynting_z[:, index_limit - 1, :] = np.array([[
            np.mean([p2, p0]) for p2, p0 in zip(poy2, poy0)
        ] for poy2, poy0 in zip(poynting_z2[:, index_limit -
                                            1, :], poynting_z0[:, index_limit -
                                                               1, :])])
        poynting_r[:, index_limit - 1, :] = np.sqrt(
            np.squared(poynting_x[:, index_limit - 1, :]) +
            np.squared(poynting_y[:, index_limit - 1, :]) +
            np.squared(poynting_y[:, index_limit - 1, :]))

    #%% SAVE FINAL DATA

    if surface_index != 1 and vm.parallel_assign(0, np_process, parallel):

        os.remove(file("BaseRAM.h5"))
        os.rename(file("FurtherRAM.h5"), file("RAM.h5"))

    elif vm.parallel_assign(0, np_process, parallel):

        os.rename(file("BaseRAM.h5"), file("RAM.h5"))

    #%% PLOT ANGULAR PATTERN IN 3D

    if vm.parallel_assign(1, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))

        fig = plt.figure()
        plt.suptitle(
            f'Angular Pattern of point dipole molecule at {from_um_factor * 1e3 * wlen_center:.0f} nm'
        )
        ax = fig.add_subplot(1, 1, 1, projection='3d')
        ax.plot_surface(poynting_x[:, :, freq_index],
                        poynting_y[:, :, freq_index],
                        poynting_z[:, :, freq_index],
                        cmap=plt.get_cmap('jet'),
                        linewidth=1,
                        antialiased=False,
                        alpha=0.5)
        ax.set_xlabel(r"$P_x$")
        ax.set_ylabel(r"$P_y$")
        ax.set_zlabel(r"$P_z$")

        plt.savefig(file("AngularPattern.png"))

    #%% PLOT ANGULAR PATTERN PROFILE FOR DIFFERENT POLAR ANGLES

    if vm.parallel_assign(0, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))
        index = [
            list(polar_angle).index(alpha) for alpha in [0, .25, .5, .75, 1]
        ]

        plt.figure()
        plt.suptitle(
            f'Angular Pattern of point dipole molecule at {from_um_factor * 1e3 * wlen_center:.0f} nm'
        )
        ax_plain = plt.axes()
        for i in index:
            ax_plain.plot(poynting_x[:, i, freq_index],
                          poynting_y[:, i, freq_index],
                          ".-",
                          label=rf"$\theta$ = {polar_angle[i]:.2f} $\pi$")
        plt.legend()
        ax_plain.set_xlabel(r"$P_x$")
        ax_plain.set_ylabel(r"$P_y$")
        ax_plain.set_aspect("equal")

        plt.savefig(file("AngularPolar.png"))

    #%% PLOT ANGULAR PATTERN PROFILE FOR DIFFERENT AZIMUTHAL ANGLES

    if vm.parallel_assign(1, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))
        index = [
            list(azimuthal_angle).index(alpha)
            for alpha in [0, .25, .5, .75, 1, 1.25, 1.5, 1.75, 2]
        ]

        plt.figure()
        plt.suptitle(
            f'Angular Pattern of point dipole molecule at {from_um_factor * 1e3 * wlen_center:.0f} nm'
        )
        ax_plain = plt.axes()
        for i in index:
            ax_plain.plot(poynting_x[i, :, freq_index],
                          poynting_z[i, :, freq_index],
                          ".-",
                          label=rf"$\phi$ = {azimuthal_angle[i]:.2f} $\pi$")
        plt.legend()
        ax_plain.set_xlabel(r"$P_x$")
        ax_plain.set_ylabel(r"$P_z$")

        plt.savefig(file("AngularAzimuthal.png"))

    if vm.parallel_assign(0, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))
        index = [
            list(azimuthal_angle).index(alpha)
            for alpha in [0, .25, .5, .75, 1, 1.25, 1.5, 1.75, 2]
        ]

        plt.figure()
        plt.suptitle(
            f'Angular Pattern of point dipole molecule at {from_um_factor * 1e3 * wlen_center:.0f} nm'
        )
        ax_plain = plt.axes()
        for i in index:
            ax_plain.plot(np.sqrt(
                np.square(poynting_x[i, :, freq_index]) +
                np.square(poynting_y[i, :, freq_index])),
                          poynting_z[i, :, freq_index],
                          ".-",
                          label=rf"$\phi$ = {azimuthal_angle[i]:.2f} $\pi$")
        plt.legend()
        ax_plain.set_xlabel(r"$P_\rho$")
        ax_plain.set_ylabel(r"$P_z$")

        plt.savefig(file("AngularAzimuthalAbs.png"))
예제 #7
0
def main(from_um_factor, resolution, courant, r, material, paper, reference,
         submerged_index, displacement, surface_index, wlen_range, nfreq,
         air_r_factor, pml_wlen_factor, flux_r_factor, time_factor_cell,
         second_time_factor, series, folder, parallel, n_processes, n_cores,
         n_nodes, split_chunks_evenly, load_flux, load_chunks, near2far):

    #%% CLASSIC INPUT PARAMETERS
    """
    # Simulation size
    from_um_factor = 10e-3 # Conversion of 1 μm to my length unit (=10nm/1μm)
    resolution = 2 # >=8 pixels per smallest wavelength, i.e. np.floor(8/wvl_min)
    courant = 0.5
    
    # Nanoparticle specifications: Sphere in Vacuum :)
    r = 51.5  # Radius of sphere in nm
    paper = "R"
    reference = "Meep"
    displacement = 0 # Displacement of the surface from the bottom of the sphere in nm
    submerged_index = 1 # 1.33 for water
    surface_index = 1 # 1.54 for glass
    
    # Frequency and wavelength
    wlen_range = np.array([350,500]) # Wavelength range in nm
    nfreq = 100
    
    # Box dimensions
    pml_wlen_factor = 0.38
    air_r_factor = 0.5
    flux_r_factor = 0 #0.1
    
    # Simulation time
    time_factor_cell = 1.2
    second_time_factor = 10
    
    # Saving directories
    series = "SilverRes4"
    folder = "Test/TestSilver"
    
    # Configuration
    parallel = False
    n_processes = 1
    n_cores = 1
    n_nodes = 1
    split_chunks_evenly = True
    load_flux = False
    load_chunks = True    
    near2far = False
    """

    #%% MORE INPUT PARAMETERS

    # Frequency and wavelength
    cutoff = 3.2  # Gaussian planewave source's parameter of shape
    nazimuthal = 16
    npolar = 20

    ### TREATED INPUT PARAMETERS

    # Nanoparticle specifications: Sphere in Vacuum :)
    r = r / (from_um_factor * 1e3)  # Now in Meep units
    if reference == "Meep":
        medium = vmt.import_medium(material,
                                   from_um_factor=from_um_factor,
                                   paper=paper)
        # Importing material constants dependant on frequency from Meep Library
    elif reference == "RIinfo":
        medium = vmt.MediumFromFile(material,
                                    paper=paper,
                                    reference=reference,
                                    from_um_factor=from_um_factor)
        # Importing material constants dependant on frequency from external file
    else:
        raise ValueError("Reference for medium not recognized. Sorry :/")
    displacement = displacement / (from_um_factor * 1e3)  # Now in Meep units

    # Frequency and wavelength
    wlen_range = np.array(wlen_range)
    wlen_range = wlen_range / (from_um_factor * 1e3)  # Now in Meep units
    freq_range = 1 / wlen_range  # Hz range in Meep units from highest to lowest
    freq_center = np.mean(freq_range)
    freq_width = max(freq_range) - min(freq_range)

    # Space configuration
    pml_width = pml_wlen_factor * max(wlen_range)  # 0.5 * max(wlen_range)
    air_width = air_r_factor * r  # 0.5 * max(wlen_range)
    flux_box_size = 2 * (1 + flux_r_factor) * r

    # Saving directories
    if series is None:
        series = "Test"
    if folder is None:
        folder = "Test"
    params_list = [
        "from_um_factor", "resolution", "courant", "material", "r", "paper",
        "reference", "submerged_index", "displacement", "surface_index",
        "wlen_range", "nfreq", "nazimuthal", "npolar", "cutoff",
        "flux_box_size", "cell_width", "pml_width", "air_width",
        "source_center", "until_after_sources", "time_factor_cell",
        "second_time_factor", "enlapsed", "parallel", "n_processes", "n_cores",
        "n_nodes", "split_chunks_evenly", "near2far", "script", "sysname",
        "path"
    ]

    #%% GENERAL GEOMETRY SETUP

    air_width = air_width - air_width % (1 / resolution)

    pml_width = pml_width - pml_width % (1 / resolution)
    pml_layers = [mp.PML(thickness=pml_width)]

    # symmetries = [mp.Mirror(mp.Y),
    #               mp.Mirror(mp.Z, phase=-1)]
    # Two mirror planes reduce cell size to 1/4
    # Issue related that lead me to comment this lines:
    # https://github.com/NanoComp/meep/issues/1484

    cell_width = 2 * (pml_width + air_width + r)
    cell_width = cell_width - cell_width % (1 / resolution)
    cell_size = mp.Vector3(cell_width, cell_width, cell_width)

    # surface_center = r/4 - displacement/2 + cell_width/4
    # surface_center = surface_center - surface_center%(1/resolution)
    # displacement = r/2 + cell_width/2 - 2*surface_center

    displacement = displacement - displacement % (1 / resolution)

    flux_box_size = flux_box_size - flux_box_size % (1 / resolution)

    source_center = -0.5 * cell_width + pml_width
    sources = [
        mp.Source(mp.GaussianSource(freq_center,
                                    fwidth=freq_width,
                                    is_integrated=True,
                                    cutoff=cutoff),
                  center=mp.Vector3(source_center),
                  size=mp.Vector3(0, cell_width, cell_width),
                  component=mp.Ez)
    ]
    # Ez-polarized planewave pulse
    # (its size parameter fills the entire cell in 2d)
    # >> The planewave source extends into the PML
    # ==> is_integrated=True must be specified

    until_after_sources = time_factor_cell * cell_width * submerged_index
    # Enough time for the pulse to pass through all the cell
    # Originally: Aprox 3 periods of lowest frequency, using T=λ/c=λ in Meep units
    # Now: Aprox 3 periods of highest frequency, using T=λ/c=λ in Meep units

    geometry = [mp.Sphere(material=medium, center=mp.Vector3(), radius=r)]
    # Au sphere with frequency-dependant characteristics imported from Meep.

    if surface_index != 1:
        geometry = [
            mp.Block(material=mp.Medium(index=surface_index),
                     center=mp.Vector3(
                         r / 2 - displacement / 2 + cell_width / 4, 0, 0),
                     size=mp.Vector3(cell_width / 2 - r + displacement,
                                     cell_width, cell_width)), *geometry
        ]
    # A certain material surface underneath it

    home = vs.get_home()
    sysname = vs.get_sys_name()
    path = os.path.join(home, folder, series)
    if not os.path.isdir(path) and vm.parallel_assign(0, n_processes,
                                                      parallel):
        os.makedirs(path)
    file = lambda f: os.path.join(path, f)

    # Computation
    enlapsed = []

    parallel_specs = np.array([n_processes, n_cores, n_nodes], dtype=int)
    max_index = np.argmax(parallel_specs)
    for index, item in enumerate(parallel_specs):
        if item == 0: parallel_specs[index] = 1
    parallel_specs[0:max_index] = np.full(parallel_specs[0:max_index].shape,
                                          max(parallel_specs))
    n_processes, n_cores, n_nodes = parallel_specs
    parallel = max(parallel_specs) > 1
    del parallel_specs, max_index, index, item

    if parallel:
        np_process = mp.count_processors()
    else:
        np_process = 1

    #%% FIRST RUN

    measure_ram()

    params = {}
    for p in params_list:
        params[p] = eval(p)

    stable, max_courant = vm.check_stability(params)
    if stable:
        print("As a whole, the simulation should be stable")
    else:
        print("As a whole, the simulation could not be stable")
        print(f"Recommended maximum courant factor is {max_courant}")

    if load_flux:
        try:
            flux_path = vm.check_midflux(params)[0]
            flux_needed = False
        except:
            flux_needed = True
    else:
        flux_needed = True

    if load_chunks and not split_chunks_evenly:
        try:
            chunks_path = vm.check_chunks(params)[0]
            chunk_layout = os.path.join(chunks_path, "Layout.h5")
            chunks_needed = False
        except:
            chunks_needed = True
            flux_needed = True
    else:
        if not split_chunks_evenly:
            chunks_needed = True
            flux_needed = True
        else:
            chunk_layout = None
            chunks_needed = False

    if chunks_needed:

        sim = mp.Simulation(
            resolution=resolution,
            cell_size=cell_size,
            boundary_layers=pml_layers,
            sources=sources,
            k_point=mp.Vector3(),
            Courant=courant,
            default_material=mp.Medium(index=submerged_index),
            output_single_precision=True,
            split_chunks_evenly=split_chunks_evenly,
            # symmetries=symmetries,
            geometry=geometry)

        sim.init_sim()

        chunks_path = vm.save_chunks(sim, params, path)
        chunk_layout = os.path.join(chunks_path, "Layout.h5")

        del sim

    if flux_needed:

        #% FIRST RUN: SET UP

        measure_ram()

        sim = mp.Simulation(resolution=resolution,
                            cell_size=cell_size,
                            boundary_layers=pml_layers,
                            sources=sources,
                            k_point=mp.Vector3(),
                            Courant=courant,
                            default_material=mp.Medium(index=submerged_index),
                            split_chunks_evenly=split_chunks_evenly,
                            chunk_layout=chunk_layout,
                            output_single_precision=True)  #,
        # symmetries=symmetries)
        # >> k_point zero specifies boundary conditions needed
        # for the source to be infinitely extended

        measure_ram()

        # Scattered power --> Computed by surrounding it with closed DFT flux box
        # (its size and orientation are irrelevant because of Poynting's theorem)
        box_x1 = sim.add_flux(
            freq_center, freq_width, nfreq,
            mp.FluxRegion(center=mp.Vector3(x=-flux_box_size / 2),
                          size=mp.Vector3(0, flux_box_size, flux_box_size)))
        box_x2 = sim.add_flux(
            freq_center, freq_width, nfreq,
            mp.FluxRegion(center=mp.Vector3(x=+flux_box_size / 2),
                          size=mp.Vector3(0, flux_box_size, flux_box_size)))
        box_y1 = sim.add_flux(
            freq_center, freq_width, nfreq,
            mp.FluxRegion(center=mp.Vector3(y=-flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, 0, flux_box_size)))
        box_y2 = sim.add_flux(
            freq_center, freq_width, nfreq,
            mp.FluxRegion(center=mp.Vector3(y=+flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, 0, flux_box_size)))
        box_z1 = sim.add_flux(
            freq_center, freq_width, nfreq,
            mp.FluxRegion(center=mp.Vector3(z=-flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, flux_box_size, 0)))
        box_z2 = sim.add_flux(
            freq_center, freq_width, nfreq,
            mp.FluxRegion(center=mp.Vector3(z=+flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, flux_box_size, 0)))
        # Funny you can encase the sphere (r radius) so closely (2r-sided box)

        measure_ram()

        if near2far:
            near2far_box = sim.add_near2far(
                freq_center, freq_width, nfreq,
                mp.Near2FarRegion(center=mp.Vector3(x=-flux_box_size / 2),
                                  size=mp.Vector3(0, flux_box_size,
                                                  flux_box_size),
                                  weight=-1),
                mp.Near2FarRegion(center=mp.Vector3(x=+flux_box_size / 2),
                                  size=mp.Vector3(0, flux_box_size,
                                                  flux_box_size),
                                  weight=+1),
                mp.Near2FarRegion(center=mp.Vector3(y=-flux_box_size / 2),
                                  size=mp.Vector3(flux_box_size, 0,
                                                  flux_box_size),
                                  weight=-1),
                mp.Near2FarRegion(center=mp.Vector3(y=+flux_box_size / 2),
                                  size=mp.Vector3(flux_box_size, 0,
                                                  flux_box_size),
                                  weight=+1),
                mp.Near2FarRegion(center=mp.Vector3(z=-flux_box_size / 2),
                                  size=mp.Vector3(flux_box_size, flux_box_size,
                                                  0),
                                  weight=-1),
                mp.Near2FarRegion(center=mp.Vector3(z=+flux_box_size / 2),
                                  size=mp.Vector3(flux_box_size, flux_box_size,
                                                  0),
                                  weight=+1))
            measure_ram()
        else:
            near2far_box = None
            # used_ram.append(used_ram[-1])

        #% FIRST RUN: INITIALIZE

        temp = time()
        sim.init_sim()
        enlapsed.append(time() - temp)
        measure_ram()

        step_ram_function = lambda sim: measure_ram()

        #% FIRST RUN: SIMULATION NEEDED TO NORMALIZE

        temp = time()
        sim.run(mp.at_beginning(step_ram_function),
                mp.at_time(int(until_after_sources / 2), step_ram_function),
                mp.at_end(step_ram_function),
                until_after_sources=until_after_sources)
        #     mp.stop_when_fields_decayed(
        # np.mean(wlen_range), # dT = mean period of source
        # mp.Ez, # Component of field to check
        # mp.Vector3(0.5*cell_width - pml_width, 0, 0), # Where to check
        # 1e-3)) # Factor to decay
        enlapsed.append(time() - temp)

        #% SAVE MID DATA

        for p in params_list:
            params[p] = eval(p)

        flux_path = vm.save_midflux(sim, box_x1, box_x2, box_y1, box_y2,
                                    box_z1, box_z2, near2far_box, params, path)

        freqs = np.asarray(mp.get_flux_freqs(box_x1))
        box_x1_flux0 = np.asarray(mp.get_fluxes(box_x1))
        box_x2_flux0 = np.asarray(mp.get_fluxes(box_x2))
        box_y1_flux0 = np.asarray(mp.get_fluxes(box_y1))
        box_y2_flux0 = np.asarray(mp.get_fluxes(box_y2))
        box_z1_flux0 = np.asarray(mp.get_fluxes(box_z1))
        box_z2_flux0 = np.asarray(mp.get_fluxes(box_z2))

        data_mid = np.array([
            1e3 * from_um_factor / freqs, box_x1_flux0, box_x2_flux0,
            box_y1_flux0, box_y2_flux0, box_z1_flux0, box_z2_flux0
        ]).T

        header_mid = [
            "Longitud de onda [nm]", "Flujo X10 [u.a.]", "Flujo X20 [u.a]",
            "Flujo Y10 [u.a]", "Flujo Y20 [u.a]", "Flujo Z10 [u.a]",
            "Flujo Z20 [u.a]"
        ]

        if vm.parallel_assign(0, n_processes, parallel):
            vs.savetxt(file("MidFlux.txt"),
                       data_mid,
                       header=header_mid,
                       footer=params)

        if not split_chunks_evenly:
            vm.save_chunks(sim, params, path)

        if parallel:
            f = h5.File(file("MidRAM.h5"),
                        "w",
                        driver='mpio',
                        comm=MPI.COMM_WORLD)
            current_process = mp.my_rank()
            f.create_dataset("RAM", (len(used_ram), np_process), dtype="float")
            f["RAM"][:, current_process] = used_ram
            for a in params:
                f["RAM"].attrs[a] = params[a]
            f.create_dataset("SWAP", (len(used_ram), np_process), dtype="int")
            f["SWAP"][:, current_process] = swapped_ram
            for a in params:
                f["SWAP"].attrs[a] = params[a]
        else:
            f = h5.File(file("MidRAM.h5"), "w")
            f.create_dataset("RAM", data=used_ram)
            for a in params:
                f["RAM"].attrs[a] = params[a]
            f.create_dataset("SWAP", data=swapped_ram)
            for a in params:
                f["SWAP"].attrs[a] = params[a]
        f.close()
        del f

        #% PLOT FLUX FOURIER MID DATA

        if vm.parallel_assign(1, np_process, parallel):
            ylims = (np.min(data_mid[:, 1:]), np.max(data_mid[:, 1:]))
            ylims = (ylims[0] - .1 * (ylims[1] - ylims[0]),
                     ylims[1] + .1 * (ylims[1] - ylims[0]))

            fig, ax = plt.subplots(3, 2, sharex=True)
            fig.subplots_adjust(hspace=0, wspace=.05)
            for a in ax[:, 1]:
                a.yaxis.tick_right()
                a.yaxis.set_label_position("right")
            for a, h in zip(np.reshape(ax, 6), header_mid[1:]):
                a.set_ylabel(h)

            for d, a in zip(data_mid[:, 1:].T, np.reshape(ax, 6)):
                a.plot(1e3 * from_um_factor / freqs, d)
                a.set_ylim(*ylims)
            ax[-1, 0].set_xlabel("Wavelength [nm]")
            ax[-1, 1].set_xlabel("Wavelength [nm]")

            plt.savefig(file("MidFlux.png"))
            del fig, ax, ylims, a, h

        sim.reset_meep()

    #%% SECOND RUN: SETUP

    measure_ram()

    sim = mp.Simulation(
        resolution=resolution,
        cell_size=cell_size,
        boundary_layers=pml_layers,
        sources=sources,
        k_point=mp.Vector3(),
        Courant=courant,
        default_material=mp.Medium(index=submerged_index),
        output_single_precision=True,
        split_chunks_evenly=split_chunks_evenly,
        chunk_layout=chunk_layout,
        # symmetries=symmetries,
        geometry=geometry)

    measure_ram()

    box_x1 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(x=-flux_box_size / 2),
                      size=mp.Vector3(0, flux_box_size, flux_box_size)))
    box_x2 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(x=+flux_box_size / 2),
                      size=mp.Vector3(0, flux_box_size, flux_box_size)))
    box_y1 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(y=-flux_box_size / 2),
                      size=mp.Vector3(flux_box_size, 0, flux_box_size)))
    box_y2 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(y=+flux_box_size / 2),
                      size=mp.Vector3(flux_box_size, 0, flux_box_size)))
    box_z1 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(z=-flux_box_size / 2),
                      size=mp.Vector3(flux_box_size, flux_box_size, 0)))
    box_z2 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(z=+flux_box_size / 2),
                      size=mp.Vector3(flux_box_size, flux_box_size, 0)))

    measure_ram()

    if near2far:
        near2far_box = sim.add_near2far(
            freq_center, freq_width, nfreq,
            mp.Near2FarRegion(center=mp.Vector3(x=-flux_box_size / 2),
                              size=mp.Vector3(0, flux_box_size, flux_box_size),
                              weight=-1),
            mp.Near2FarRegion(center=mp.Vector3(x=+flux_box_size / 2),
                              size=mp.Vector3(0, flux_box_size, flux_box_size),
                              weight=+1),
            mp.Near2FarRegion(center=mp.Vector3(y=-flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, 0, flux_box_size),
                              weight=-1),
            mp.Near2FarRegion(center=mp.Vector3(y=+flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, 0, flux_box_size),
                              weight=+1),
            mp.Near2FarRegion(center=mp.Vector3(z=-flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, flux_box_size, 0),
                              weight=-1),
            mp.Near2FarRegion(center=mp.Vector3(z=+flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, flux_box_size, 0),
                              weight=+1))
        measure_ram()
    else:
        near2far_box = None
        # used_ram.append(used_ram[-1])

    #%% SECOND RUN: INITIALIZE

    temp = time()
    sim.init_sim()
    enlapsed.append(time() - temp)
    measure_ram()

    #%% LOAD FLUX FROM FILE

    vm.load_midflux(sim, box_x1, box_x2, box_y1, box_y2, box_z1, box_z2,
                    near2far_box, flux_path)

    measure_ram()

    freqs = np.asarray(mp.get_flux_freqs(box_x1))
    box_x1_flux0 = np.asarray(mp.get_fluxes(box_x1))
    box_x1_data = sim.get_flux_data(box_x1)
    box_x2_data = sim.get_flux_data(box_x2)
    box_y1_data = sim.get_flux_data(box_y1)
    box_y2_data = sim.get_flux_data(box_y2)
    box_z1_data = sim.get_flux_data(box_z1)
    box_z2_data = sim.get_flux_data(box_z2)
    if near2far: near2far_data = sim.get_near2far_data(near2far_box)

    temp = time()
    sim.load_minus_flux_data(box_x1, box_x1_data)
    sim.load_minus_flux_data(box_x2, box_x2_data)
    sim.load_minus_flux_data(box_y1, box_y1_data)
    sim.load_minus_flux_data(box_y2, box_y2_data)
    sim.load_minus_flux_data(box_z1, box_z1_data)
    sim.load_minus_flux_data(box_z2, box_z2_data)
    if near2far: sim.load_minus_near2far_data(near2far_box, near2far_data)
    enlapsed.append(time() - temp)
    del box_x1_data, box_x2_data, box_y1_data, box_y2_data
    del box_z1_data, box_z2_data
    if near2far: del near2far_data

    measure_ram()

    #%% SECOND RUN: SIMULATION :D

    step_ram_function = lambda sim: measure_ram()

    temp = time()
    sim.run(mp.at_beginning(step_ram_function),
            mp.at_time(int(second_time_factor * until_after_sources / 2),
                       step_ram_function),
            mp.at_end(step_ram_function),
            until_after_sources=second_time_factor * until_after_sources)
    #     mp.stop_when_fields_decayed(
    # np.mean(wlen_range), # dT = mean period of source
    # mp.Ez, # Component of field to check
    # mp.Vector3(0.5*cell_width - pml_width, 0, 0), # Where to check
    # 1e-3)) # Factor to decay
    enlapsed.append(time() - temp)
    del temp
    # Aprox 30 periods of lowest frequency, using T=λ/c=λ in Meep units

    box_x1_flux = np.asarray(mp.get_fluxes(box_x1))
    box_x2_flux = np.asarray(mp.get_fluxes(box_x2))
    box_y1_flux = np.asarray(mp.get_fluxes(box_y1))
    box_y2_flux = np.asarray(mp.get_fluxes(box_y2))
    box_z1_flux = np.asarray(mp.get_fluxes(box_z1))
    box_z2_flux = np.asarray(mp.get_fluxes(box_z2))

    #%% SCATTERING ANALYSIS

    scatt_flux = box_x1_flux - box_x2_flux
    scatt_flux = scatt_flux + box_y1_flux - box_y2_flux
    scatt_flux = scatt_flux + box_z1_flux - box_z2_flux

    intensity = box_x1_flux0 / (flux_box_size)**2
    # Flux of one of the six monitor planes / Área
    # (the closest one, facing the planewave source)
    # This is why the six sides of the flux box are separated
    # (Otherwise, the box could've been one flux object with weights ±1 per side)

    scatt_cross_section = np.divide(scatt_flux, intensity)
    # Scattering cross section σ =
    # = scattered power in all directions / incident intensity.

    scatt_eff_meep = -1 * scatt_cross_section / (np.pi * r**2)
    # Scattering efficiency =
    # = scattering cross section / cross sectional area of the sphere

    freqs = np.array(freqs)
    scatt_eff_theory = [
        ps.MieQ(np.sqrt(medium.epsilon(f)[0, 0] * medium.mu(f)[0, 0]),
                1e3 * from_um_factor / f,
                2 * r * 1e3 * from_um_factor,
                nMedium=submerged_index,
                asDict=True)['Qsca'] for f in freqs
    ]
    # The simulation results are validated by comparing with
    # analytic theory of PyMieScatt module

    #%% ANGULAR PATTERN ANALYSIS

    if near2far:

        fraunhofer_distance = 8 * (r**2) / min(wlen_range)
        radial_distance = max(10 * fraunhofer_distance, 1.5 * cell_width / 2)
        # radius of far-field circle must be at least Fraunhofer distance

        azimuthal_angle = np.arange(0, 2 + 2 / nazimuthal,
                                    2 / nazimuthal)  # in multiples of pi
        polar_angle = np.arange(0, 1 + 1 / npolar, 1 / npolar)

        poynting_x = []
        poynting_y = []
        poynting_z = []
        poynting_r = []

        for phi in azimuthal_angle:

            poynting_x.append([])
            poynting_y.append([])
            poynting_z.append([])
            poynting_r.append([])

            for theta in polar_angle:

                farfield_dict = sim.get_farfields(
                    near2far_box,
                    1,
                    where=mp.Volume(center=mp.Vector3(
                        radial_distance * np.cos(np.pi * phi) *
                        np.sin(np.pi * theta),
                        radial_distance * np.sin(np.pi * phi) *
                        np.sin(np.pi *
                               theta), radial_distance *
                        np.cos(np.pi * theta))))

                Px = farfield_dict["Ey"] * np.conjugate(farfield_dict["Hz"])
                Px -= farfield_dict["Ez"] * np.conjugate(farfield_dict["Hy"])
                Py = farfield_dict["Ez"] * np.conjugate(farfield_dict["Hx"])
                Py -= farfield_dict["Ex"] * np.conjugate(farfield_dict["Hz"])
                Pz = farfield_dict["Ex"] * np.conjugate(farfield_dict["Hy"])
                Pz -= farfield_dict["Ey"] * np.conjugate(farfield_dict["Hx"])

                Px = np.real(Px)
                Py = np.real(Py)
                Pz = np.real(Pz)

                poynting_x[-1].append(Px)
                poynting_y[-1].append(Py)
                poynting_z[-1].append(Pz)
                poynting_r[-1].append(
                    np.sqrt(np.square(Px) + np.square(Py) + np.square(Pz)))

        poynting_x = np.array(poynting_x)
        poynting_y = np.array(poynting_y)
        poynting_z = np.array(poynting_z)
        poynting_r = np.array(poynting_r)

    #%% SAVE FINAL DATA

    for p in params_list:
        params[p] = eval(p)

    data = np.array(
        [1e3 * from_um_factor / freqs, scatt_eff_meep, scatt_eff_theory]).T

    header = [
        "Longitud de onda [nm]", "Sección eficaz efectiva (Meep) [u.a.]",
        "Sección eficaz efectiva (Theory) [u.a.]"
    ]

    data_base = np.array([
        1e3 * from_um_factor / freqs, box_x1_flux0, box_x1_flux, box_x2_flux,
        box_y1_flux, box_y2_flux, box_z1_flux, box_z2_flux, intensity,
        scatt_flux, scatt_cross_section
    ]).T

    header_base = [
        "Longitud de onda [nm]", "Flujo X10 [u.a.]", "Flujo X1 [u.a]",
        "Flujo X2 [u.a]", "Flujo Y1 [u.a]", "Flujo Y2 [u.a]", "Flujo Z1 [u.a]",
        "Flujo Z2 [u.a]", "Intensidad incidente [u.a.]",
        "Flujo scattereado [u.a.]", "Sección eficaz de scattering [u.a.]"
    ]

    if vm.parallel_assign(0, np_process, parallel):
        vs.savetxt(file("Results.txt"), data, header=header, footer=params)
        vs.savetxt(file("BaseResults.txt"),
                   data_base,
                   header=header_base,
                   footer=params)

    if near2far:

        header_near2far = [
            "Poynting medio Px [u.a.]", "Poynting medio Py [u.a.]",
            "Poynting medio Pz [u.a.]", "Poynting medio Pr [u.a.]"
        ]

        data_near2far = [
            poynting_x.reshape(poynting_x.size),
            poynting_y.reshape(poynting_y.size),
            poynting_z.reshape(poynting_z.size),
            poynting_r.reshape(poynting_r.size)
        ]

        if vm.parallel_assign(1, np_process, parallel):
            vs.savetxt(file("Near2FarResults.txt"),
                       data_near2far,
                       header=header_near2far,
                       footer=params)

    if not split_chunks_evenly:
        vm.save_chunks(sim, params, path)

    if parallel:
        f = h5.File(file("RAM.h5"), "w", driver='mpio', comm=MPI.COMM_WORLD)
        current_process = mp.my_rank()
        f.create_dataset("RAM", (len(used_ram), np_process), dtype="float")
        f["RAM"][:, current_process] = used_ram
        for a in params:
            f["RAM"].attrs[a] = params[a]
        f.create_dataset("SWAP", (len(used_ram), np_process), dtype="int")
        f["SWAP"][:, current_process] = swapped_ram
        for a in params:
            f["SWAP"].attrs[a] = params[a]
    else:
        f = h5.File(file("RAM.h5"), "w")
        f.create_dataset("RAM", data=used_ram)
        for a in params:
            f["RAM"].attrs[a] = params[a]
        f.create_dataset("SWAP", data=swapped_ram)
        for a in params:
            f["SWAP"].attrs[a] = params[a]
    f.close()
    del f

    if flux_needed and vm.parallel_assign(0, np_process, parallel):
        os.remove(file("MidRAM.h5"))

    #%% PLOT ALL TOGETHER

    if vm.parallel_assign(0, np_process, parallel) and surface_index == 1:
        plt.figure()
        plt.plot(1e3 * from_um_factor / freqs,
                 scatt_eff_meep,
                 'bo-',
                 label='Meep')
        plt.plot(1e3 * from_um_factor / freqs,
                 scatt_eff_theory,
                 'ro-',
                 label='Theory')
        plt.xlabel('Wavelength [nm]')
        plt.ylabel('Scattering efficiency [σ/πr$^{2}$]')
        plt.legend()
        plt.title('Scattering of Au Sphere With {:.1f} nm Radius'.format(
            r * from_um_factor * 1e3))
        plt.tight_layout()
        plt.savefig(file("Comparison.png"))

    #%% PLOT SEPARATE

    if vm.parallel_assign(1, np_process, parallel):
        plt.figure()
        plt.plot(1e3 * from_um_factor / freqs,
                 scatt_eff_meep,
                 'bo-',
                 label='Meep')
        plt.xlabel('Wavelength [nm]')
        plt.ylabel('Scattering efficiency [σ/πr$^{2}$]')
        plt.legend()
        plt.title('Scattering of Au Sphere With {:.1f} nm Radius'.format(
            r * from_um_factor * 1e3))
        plt.tight_layout()
        plt.savefig(file("Meep.png"))

    if vm.parallel_assign(0, np_process, parallel) and surface_index == 1:
        plt.figure()
        plt.plot(1e3 * from_um_factor / freqs,
                 scatt_eff_theory,
                 'ro-',
                 label='Theory')
        plt.xlabel('Wavelength [nm]')
        plt.ylabel('Scattering efficiency [σ/πr$^{2}$]')
        plt.legend()
        plt.title('Scattering of Au Sphere With {:.1f} nm Radius'.format(r *
                                                                         10))
        plt.tight_layout()
        plt.savefig(file("Theory.png"))

    #%% PLOT ONE ABOVE THE OTHER

    if vm.parallel_assign(1, np_process, parallel) and surface_index == 1:
        fig, axes = plt.subplots(nrows=2, sharex=True)
        fig.subplots_adjust(hspace=0)
        plt.suptitle('Scattering of Au Sphere With {:.1f} nm Radius'.format(
            r * from_um_factor * 1e3))

        axes[0].plot(1e3 * from_um_factor / freqs,
                     scatt_eff_meep,
                     'bo-',
                     label='Meep')
        axes[0].yaxis.tick_right()
        axes[0].set_ylabel('Scattering efficiency [σ/πr$^{2}$]')
        axes[0].legend()

        axes[1].plot(1e3 * from_um_factor / freqs,
                     scatt_eff_theory,
                     'ro-',
                     label='Theory')
        axes[1].set_xlabel('Wavelength [nm]')
        axes[1].set_ylabel('Scattering efficiency [σ/πr$^{2}$]')
        axes[1].legend()

        plt.savefig(file("SeparatedComparison.png"))

    #%% PLOT FLUX FOURIER FINAL DATA

    if vm.parallel_assign(0, np_process, parallel):

        ylims = (np.min(data_base[:, 2:8]), np.max(data_base[:, 2:8]))
        ylims = (ylims[0] - .1 * (ylims[1] - ylims[0]),
                 ylims[1] + .1 * (ylims[1] - ylims[0]))

        fig, ax = plt.subplots(3, 2, sharex=True)
        fig.subplots_adjust(hspace=0, wspace=.05)
        plt.suptitle('Final flux of Au Sphere With {:.1f} nm Radius'.format(
            r * from_um_factor * 1e3))
        for a in ax[:, 1]:
            a.yaxis.tick_right()
            a.yaxis.set_label_position("right")
        for a, h in zip(np.reshape(ax, 6), header_base[1:7]):
            a.set_ylabel(h)

        for d, a in zip(data_base[:, 3:9].T, np.reshape(ax, 6)):
            a.plot(1e3 * from_um_factor / freqs, d)
            a.set_ylim(*ylims)
        ax[-1, 0].set_xlabel("Wavelength [nm]")
        ax[-1, 1].set_xlabel("Wavelength [nm]")

        plt.savefig(file("FinalFlux.png"))

    #%% PLOT ANGULAR PATTERN IN 3D

    if near2far and vm.parallel_assign(1, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))

        fig = plt.figure()
        plt.suptitle(
            'Angular Pattern of Au Sphere With {:.1f} nm Radius at {:.1f} nm'.
            format(r * from_um_factor * 1e3,
                   from_um_factor * 1e3 / freqs[freq_index]))
        ax = fig.add_subplot(1, 1, 1, projection='3d')
        ax.plot_surface(poynting_x[:, :, freq_index],
                        poynting_y[:, :, freq_index],
                        poynting_z[:, :, freq_index],
                        cmap=plt.get_cmap('jet'),
                        linewidth=1,
                        antialiased=False,
                        alpha=0.5)
        ax.set_xlabel(r"$P_x$")
        ax.set_ylabel(r"$P_y$")
        ax.set_zlabel(r"$P_z$")

        plt.savefig(file("AngularPattern.png"))

    #%% PLOT ANGULAR PATTERN PROFILE FOR DIFFERENT POLAR ANGLES

    if near2far and vm.parallel_assign(0, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))
        index = [
            list(polar_angle).index(alpha) for alpha in [0, .25, .5, .75, 1]
        ]

        plt.figure()
        plt.suptitle(
            'Angular Pattern of Au Sphere With {:.1f} nm Radius at {:.1f} nm'.
            format(r * from_um_factor * 1e3,
                   from_um_factor * 1e3 / freqs[freq_index]))
        ax_plain = plt.axes()
        for i in index:
            ax_plain.plot(poynting_x[:, i, freq_index],
                          poynting_y[:, i, freq_index],
                          ".-",
                          label=rf"$\theta$ = {polar_angle[i]:.2f} $\pi$")
        plt.legend()
        ax_plain.set_xlabel(r"$P_x$")
        ax_plain.set_ylabel(r"$P_y$")
        ax_plain.set_aspect("equal")

        plt.savefig(file("AngularPolar.png"))

    #%% PLOT ANGULAR PATTERN PROFILE FOR DIFFERENT AZIMUTHAL ANGLES

    if near2far and vm.parallel_assign(1, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))
        index = [
            list(azimuthal_angle).index(alpha)
            for alpha in [0, .25, .5, .75, 1, 1.25, 1.5, 1.75, 2]
        ]

        plt.figure()
        plt.suptitle(
            'Angular Pattern of Au Sphere With {:.1f} nm Radius at {:.1f} nm'.
            format(r * from_um_factor * 1e3,
                   from_um_factor * 1e3 / freqs[freq_index]))
        ax_plain = plt.axes()
        for i in index:
            ax_plain.plot(poynting_x[i, :, freq_index],
                          poynting_z[i, :, freq_index],
                          ".-",
                          label=rf"$\phi$ = {azimuthal_angle[i]:.2f} $\pi$")
        plt.legend()
        ax_plain.set_xlabel(r"$P_x$")
        ax_plain.set_ylabel(r"$P_z$")

        plt.savefig(file("AngularAzimuthal.png"))

    if near2far and vm.parallel_assign(0, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))
        index = [
            list(azimuthal_angle).index(alpha)
            for alpha in [0, .25, .5, .75, 1, 1.25, 1.5, 1.75, 2]
        ]

        plt.figure()
        plt.suptitle(
            'Angular Pattern of Au Sphere With {:.1f} nm Radius at {:.1f} nm'.
            format(r * from_um_factor * 1e3,
                   from_um_factor * 1e3 / freqs[freq_index]))
        ax_plain = plt.axes()
        for i in index:
            ax_plain.plot(np.sqrt(
                np.square(poynting_x[i, :, freq_index]) +
                np.square(poynting_y[i, :, freq_index])),
                          poynting_z[i, :, freq_index],
                          ".-",
                          label=rf"$\phi$ = {azimuthal_angle[i]:.2f} $\pi$")
        plt.legend()
        ax_plain.set_xlabel(r"$P_\rho$")
        ax_plain.set_ylabel(r"$P_z$")

        plt.savefig(file("AngularAzimuthalAbs.png"))
예제 #8
0
                    sources=sources,
                    resolution=resolution)

# reflected flux
refl = sim.add_flux(fcen, df, nfreq, refl_fr)

tran_fr = mp.FluxRegion(center=mp.Vector3(0.5 * sx - dpml - 0.5, 4.0, 0),
                        size=mp.Vector3(0.0, 2.0 * width, 0))
tran = sim.add_flux(fcen, df, nfreq, tran_fr)

# for normal run, load negated fields to subtract incident from refl. fields
sim.load_minus_flux_data(refl, straight_refl_data)

pt = mp.Vector3(4.0, 0.5 * sx - dpml - 0.5)

sim.run(mp.at_time(200, mp.output_efield_z),
        until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, pt, 1e-3))

bend_refl_flux = mp.get_fluxes(refl)
bend_tran_flux = mp.get_fluxes(tran)
flux_freqs = mp.get_flux_freqs(refl)

wl = []
Rs = []
Ts = []

for i in range(0, nfreq):
    wl = np.append(wl, 1 / flux_freqs[i])
    Rs = np.append(Rs, -bend_refl_flux[i] / straight_tran_flux[i])
    Ts = np.append(Ts, bend_tran_flux[i] / straight_tran_flux[i])
예제 #9
0
def notch(w):

    print("#----------------------------------------")
    print("NOTCH WIDTH: %s nanometers" % (w * 1000))
    print("#----------------------------------------")

    # w is the width of the notch in the waveguide

    #Waveguide Math
    e = 0.4  # etch fraction [0 -> 1]

    h2 = h * (1 - e)  #height of the etched region
    d = 1  #spacing of the waveguides
    posd = d / 2  #pos half d
    negd = -d / 2  #neg half d

    ang = 80  #angle of the sidewall
    angrad = ang * pi / 180
    bottomoffset = h / tan(angrad)
    c = bottomoffset / 2
    r = sqrt(bottomoffset**2 + h**2)
    fcen = 1 / wavelength
    df = 0.05

    n_e = 2.2012  # refractive index inside waveguide (at wavelength 0.6372)
    n_c = 1.4569  # refractive index outside waveguide (at wavelength 0.6372)

    #Waveguide Geometry
    cell = mp.Vector3(a, H)

    default_material = mp.Medium(epsilon=n_c**2)
    core_material = mp.Medium(epsilon=n_e**2)

    geometry = [
        mp.Block(cell, center=mp.Vector3(0, 0), material=default_material),
        mp.Block(mp.Vector3(a + 2 * h, h),
                 center=mp.Vector3(0, 0),
                 material=core_material),
        # mp.Block(mp.Vector3(w, e * h),
        mp.Block(mp.Vector3(w, e * h),
                 center=mp.Vector3(0, h2 / 2),
                 material=default_material)
    ]

    # pml_layers = [mp.PML(0.2)]
    pml_layers = [mp.Absorber(thickness=pmlthickness)]
    # resolution = 50

    r00 = None
    r01 = None
    r10 = None
    r11 = None

    t00 = None
    t01 = None
    t10 = None
    t11 = None

    su0 = None
    sd0 = None
    su1 = None
    sd1 = None

    only_fund = True

    modes = [0, 1]

    if only_fund:
        modes = [0]

    # for mode in [0, 1]:
    for mode in modes:

        if mode == 0:
            eig_parity = mp.EVEN_Y  # Fundamental
            print("-----------")
            print("MODE TYPE: FUNDAMENTAL")

        else:
            eig_parity = mp.ODD_Y  # First Order
            print("-----------")
            print("MODE TYPE: FIRST ORDER")

        sources = [
            mp.EigenModeSource(mp.GaussianSource(frequency=fcen, fwidth=df),
                               size=mp.Vector3(0, H),
                               center=mp.Vector3(Ls, 0),
                               eig_parity=eig_parity)
        ]

        sim = mp.Simulation(cell_size=cell,
                            boundary_layers=pml_layers,
                            geometry=geometry,
                            sources=sources,
                            resolution=resolution,
                            force_complex_fields=True)
        '''
		#--------------------------------------------------
		#FOR DISPLAYING THE GEOMETRY

		sim.run(until = 200)

		eps_data = sim.get_array(center=mp.Vector3(), size=cell, component=mp.Dielectric)
		plt.figure(dpi=100)
		plt.imshow(eps_data.transpose(), interpolation='spline36', cmap='binary')
		#plt.axis('off')
		plt.show()

		quit()
		#----------------------------------------------------
		'''
        '''
		#------------------------------------------------------
		#FOR GENERATING THE ELECTRIC FIELD GIF
		#Note: After running this program, write the following commands in Terminal:
		    # $ source deactivate mp
		    # $ cd notch-out/
		    # $ python ../NotchIP.py

		sim.use_output_directory()
		sim.run(mp.at_beginning(mp.output_epsilon),
		        mp.to_appended("ez", mp.at_every(0.6, mp.output_efield_z)),
		        until = 200)
		#sim.run(mp.at_every(0.6 , mp.output_png(mp.Ez, "-Zc dkbluered")), until=200)

		#---------------------------------------------------------
		'''

        #---------------------------------------------------------
        # FOR GENERATING THE TRANSMITTANCE SPECTRUM

        nfreq = 20  # number of frequencies at which to compute flux

        refl_fr1 = mp.FluxRegion(center=mp.Vector3(Lr1, 0),
                                 size=mp.Vector3(
                                     0, monitorheight))  # Reflected flux 1
        refl_fr2 = mp.FluxRegion(center=mp.Vector3(Lr2, 0),
                                 size=mp.Vector3(
                                     0, monitorheight))  # Reflected flux 2
        tran_fr = mp.FluxRegion(center=mp.Vector3(Lt, 0),
                                size=mp.Vector3(
                                    0, monitorheight))  # Transmitted flux
        su_fr = mp.FluxRegion(center=mp.Vector3(0, monitorheight / 2),
                              size=mp.Vector3(
                                  a, 0))  # Flux loss above the waveguide
        sd_fr = mp.FluxRegion(center=mp.Vector3(0, -monitorheight / 2),
                              size=mp.Vector3(
                                  a, 0))  # Flux loss below the waveguide

        refl1 = sim.add_flux(fcen, df, nfreq, refl_fr1)
        refl2 = sim.add_flux(fcen, df, nfreq, refl_fr2)
        tran = sim.add_flux(fcen, df, nfreq, tran_fr)
        su = sim.add_flux(fcen, df, nfreq, su_fr)
        sd = sim.add_flux(fcen, df, nfreq, sd_fr)

        # ------------------------ CODE FOR SEPARATING FUND AND FIRST ORDER MODE STARTS HERE ------------------------

        y_list = np.arange(-H / 2, H / 2, 1 / resolution)

        refl_vals = []
        tran_vals = []

        def get_refl_slice(sim):
            # print(sim.get_array(center=mp.Vector3(Lr1,0), size=mp.Vector3(0,H), component=mp.Ez, cmplx=True))
            # refl_val = sim.get_array(center=mp.Vector3(Lr1,0), size=mp.Vector3(0,H), component=mp.Ez, cmplx=True)
            refl_vals.append(
                sim.get_array(center=mp.Vector3(Lr1, 0),
                              size=mp.Vector3(0, H),
                              component=mp.Ez,
                              cmplx=True))

        def get_tran_slice(sim):
            # print(sim.get_array(center=mp.Vector3(Lt, 0), size=mp.Vector3(0,H), component=mp.Ez, cmplx=True))
            # tran_val = sim.get_array(center=mp.Vector3(Lt, 0), size=mp.Vector3(0,H), component=mp.Ez, cmplx=True)
            tran_vals.append(
                sim.get_array(center=mp.Vector3(Lt, 0),
                              size=mp.Vector3(0, H),
                              component=mp.Ez,
                              cmplx=True))

        pt = mp.Vector3(9.75, 0)  # Hardcoded?

        gif = True

        if gif:  # and w == 0.1:
            sim.use_output_directory()
            sim.run(mp.at_beginning(mp.output_epsilon),
                    mp.at_end(get_refl_slice),
                    mp.at_end(get_tran_slice),
                    until=100)
            # sim.run(mp.at_every(wavelength / 20, mp.output_efield_z), until=wavelength)
            sim.run(mp.at_every(
                wavelength / 20,
                mp.output_png(
                    mp.Ez,
                    "-RZc bluered -A notch-out/notch-eps-000000.00.h5 -a gray:.2"
                )),
                    until=19 * wavelength / 20)
            sim.run(until_after_sources=mp.stop_when_fields_decayed(
                50, mp.Ez, pt, 1e-3))
        else:
            sim.run(mp.at_beginning(mp.output_epsilon),
                    mp.at_time(100, get_refl_slice),
                    mp.at_time(100, get_tran_slice),
                    until_after_sources=mp.stop_when_fields_decayed(
                        50, mp.Ez, pt, 1e-3))

        os.system("cp notch-out/notch-ez-000100.00.png " + str(int(w * 1000)) +
                  "-" + str(mode) + ".png")
        os.system("convert notch-out/notch-ez-*.png " + str(int(w * 1000)) +
                  "-" + str(mode) + ".gif")

        refl_val = refl_vals[0]
        tran_val = tran_vals[0]

        # n_eff must satisfy n_e <= n_eff <= n_c for the mode to be bound.

        def fund_func(n_eff):
            if n_eff >= n_c and n_eff <= n_e:
                return sqrt(n_eff**2 - n_c**2) - sqrt(n_e**2 - n_eff**2) * tan(
                    pi * h / wavelength * sqrt(n_e**2 - n_eff**2))

        def first_order_func(n_eff):
            if n_eff >= n_c and n_eff <= n_e:
                return sqrt(n_eff**2 - n_c**2) - sqrt(n_e**2 - n_eff**2) * tan(
                    pi * h / wavelength * sqrt(n_e**2 - n_eff**2) - pi / 2)

        initial_guess = (n_c + n_e) / 2

        n_eff_fund = fsolve(fund_func, initial_guess)
        n_eff_first = fsolve(first_order_func, n_c)

        print(n_eff_fund, n_eff_first)

        assert (n_eff_fund > n_eff_first)

        if len(n_eff_funds) == 0:
            n_eff_funds.append(n_eff_fund[0])

        if len(n_eff_firsts) == 0:
            n_eff_firsts.append(n_eff_first[0])

        ky0_fund = np.absolute(2 * pi / wavelength *
                               sqrt(n_e**2 - n_eff_fund**2))
        ky0_first = np.absolute(2 * pi / wavelength *
                                sqrt(n_e**2 - n_eff_first**2))

        ky1_fund = np.absolute(2 * pi / wavelength *
                               sqrt(n_eff_fund**2 - n_c**2))
        ky1_first = np.absolute(2 * pi / wavelength *
                                sqrt(n_eff_first**2 - n_c**2))

        E_fund = lambda y: cos(ky0_fund * y) if np.absolute(
            y) < h / 2 else cos(ky0_fund * h / 2) * np.exp(-ky1_fund * (
                np.absolute(y) - h / 2))
        E_first_order = lambda y: sin(ky0_first * y) if np.absolute(
            y) < h / 2 else sin(ky0_first * h / 2) * np.exp(-ky1_first * (
                np.absolute(y) - h / 2)) * np.sign(y)
        # y_list = np.arange(-H/2+.5/resolution, H/2-.5/resolution, 1/resolution)

        #print("Y LIST: ", y_list)
        #print("SIZE OF Y LIST: ", y_list.size)

        E_fund_vec = np.zeros(y_list.size)
        E_first_order_vec = np.zeros(y_list.size)

        for index in range(y_list.size):
            y = y_list[index]
            E_fund_vec[index] = E_fund(y)
            E_first_order_vec[index] = E_first_order(y)

        # print("r VECTOR: ", 	refl_val)
        # print("t VECTOR: ", 	tran_val)
        # print("E0 VECTOR: ", 	E_fund_vec)
        # print("E1 VECTOR: ", 	E_first_order_vec)

        # plt.plot(y_list, refl_val*100,'bo-',label='reflectance')
        # plt.plot(y_list, tran_val*1,'ro-',label='transmittance')
        # plt.plot(y_list, E_fund_vec,'go-',label='E0')
        # plt.plot(y_list, E_first_order_vec, 'co-', label='E1')
        # # plt.axis([40.0, 300.0, 0.0, 100.0])
        # plt.xlabel("y (um)")
        # plt.ylabel("Field")
        # plt.legend(loc="center right")
        # plt.show()

        fund_refl_amp = np.conj(
            np.dot(refl_val, E_fund_vec) / np.dot(E_fund_vec, E_fund_vec)
        )  # Conjugate becasue MEEP uses physics exp(kz-wt) rather than engineering exp(wt-kz)
        first_order_refl_amp = np.conj(
            np.dot(refl_val, E_first_order_vec) /
            np.dot(E_first_order_vec, E_first_order_vec))
        fund_tran_amp = np.conj(
            np.dot(tran_val, E_fund_vec) / np.dot(E_fund_vec, E_fund_vec))
        first_order_tran_amp = np.conj(
            np.dot(tran_val, E_first_order_vec) /
            np.dot(E_first_order_vec, E_first_order_vec))

        # fund_refl_power = 			np.abs(fund_tran_amp)			** 2
        fund_refl_power = np.abs(fund_refl_amp)**2
        first_order_refl_power = np.abs(first_order_refl_amp)**2
        fund_tran_power = np.abs(fund_tran_amp)**2
        first_order_tran_power = np.abs(first_order_tran_amp)**2

        print(fund_refl_power, first_order_refl_power, fund_tran_power,
              first_order_tran_power)

        fund_refl_ratio = fund_refl_power / (fund_refl_power +
                                             first_order_refl_power)
        first_order_refl_ratio = first_order_refl_power / (
            fund_refl_power + first_order_refl_power)
        fund_tran_ratio = fund_tran_power / (fund_tran_power +
                                             first_order_tran_power)
        first_order_tran_ratio = first_order_tran_power / (
            fund_tran_power + first_order_tran_power)

        print("Percentage of reflected light in fundamental mode: ",
              fund_refl_ratio * 100)
        print("Percentage of reflected light in first order mode: ",
              first_order_refl_ratio * 100)
        print("Percentage of transmitted light in fundamental mode: ",
              fund_tran_ratio * 100)
        print("Percentage of transmitted light in first order mode: ",
              first_order_tran_ratio * 100)

        # ------------------------ CODE FOR SEPARATING FUND AND FIRST ORDER MODE ENDS HERE ------------------------

        wl = []  #list of wavelengths

        refl1_flux = mp.get_fluxes(refl1)
        refl2_flux = mp.get_fluxes(refl2)
        tran_flux = mp.get_fluxes(tran)
        su_flux = mp.get_fluxes(su)
        sd_flux = mp.get_fluxes(sd)

        flux_freqs = mp.get_flux_freqs(refl1)

        for i in range(nfreq):
            wl = np.append(wl, 1 / flux_freqs[i])
            print(1 / flux_freqs[i])

        for ind, elt in enumerate(wl):
            #print(round(elt, 4))
            if round(elt, 3) == 0.637:
                #print("ALERT: MATCH FOUND")
                index = ind

        R = -refl1_flux[index] / (refl2_flux[index] - refl1_flux[index])
        T = tran_flux[index] / (refl2_flux[index] - refl1_flux[index])
        S = (refl2_flux[index] - tran_flux[index]) / (refl2_flux[index] -
                                                      refl1_flux[index])
        Su = su_flux[index] / (refl2_flux[index] - refl1_flux[index])
        Sd = -sd_flux[index] / (refl2_flux[index] - refl1_flux[index])

        S_correction = (1 - R - T) / (Su + Sd)

        print(R, T, S, Su, Sd)

        r = sqrt(R)
        t = sqrt(T)

        # The amplitude ... times the phase ... accounting for the distance to the detector (Reverse exp(-kz) of phase).
        r_fund = (r * fund_refl_ratio) * (
            fund_refl_amp / np.abs(fund_refl_amp)
        ) * (
            np.exp(2j * pi * (-Lr1 - w / 2) * n_eff_fund / wavelength)
        )  # Lr1 is negative because it is the (negative) position of the monitor, not the distace from the monitor to the center.
        r_first = (r * first_order_refl_ratio) * (
            first_order_refl_amp / np.abs(first_order_refl_amp)) * (np.exp(
                2j * pi * (-Lr1 - w / 2) * n_eff_first / wavelength))
        t_fund = (t * fund_tran_ratio) * (
            fund_tran_amp / np.abs(fund_tran_amp)) * (np.exp(
                2j * pi * (Lt - w / 2) * n_eff_fund / wavelength))
        t_first = (t * first_order_tran_ratio) * (
            first_order_tran_amp / np.abs(first_order_tran_amp)) * (np.exp(
                2j * pi * (Lt - w / 2) * n_eff_first / wavelength))

        if mode == 0:
            r00 = r_fund
            r01 = r_first

            t00 = t_fund
            t01 = t_first

            su0 = sqrt(np.abs(Su * S_correction))
            sd0 = sqrt(np.abs(Sd * S_correction))

            r00s.append(r00[0])
            r01s.append(r01[0])
            t00s.append(t00[0])
            t01s.append(t01[0])
            su0s.append(su0)
            sd0s.append(sd0)

            if only_fund:
                r10s.append(0)
                r11s.append(0)
                t10s.append(0)
                t11s.append(1)
                su1s.append(0)
                sd1s.append(0)
        else:
            r10 = r_fund
            r11 = r_first

            t10 = t_fund
            t11 = t_first

            su1 = sqrt(np.abs(Su * S_correction))
            sd1 = sqrt(np.abs(Sd * S_correction))

            r10s.append(r10[0])
            r11s.append(r11[0])
            t10s.append(t10[0])
            t11s.append(t11[0])
            su1s.append(su1)
            sd1s.append(sd1)

        norm_Su = S * Su / (Su + Sd)

        NET = round((R + T + S) * 100, 0)
        if NET > 100.0:
            NET = 100.0

        NET_LOSS = round((Su + Sd) / S * 100, 0)
        if NET_LOSS > 100.0:
            NET_LOSS = 100.0
        '''
		np.append(ws, [w * 1000])
		np.append(Rs, [R * 100])
		np.append(Ts, [T * 100])
		np.append(Ss, [S * 100])
		np.append(NET_LIST, [NET])
		np.append(Sus, [Su * 100])
		np.append(Sds, [Sd * 100])
		np.append(NET_LOSS_LIST, [NET_LOSS])
		np.append(norm_Sus, [norm_Su * 100])
		'''

        if mode == 0:
            ws.append(w * 1000)
            Rs.append(R * 100)
            Ts.append(T * 100)
            Ss.append(S * 100)
            NET_LIST.append(NET)
            Sus.append(Su * 100)
            Sds.append(Sd * 100)
            NET_LOSS_LIST.append(NET_LOSS)
            norm_Sus.append(norm_Su * 100)

        if mode == 0:

            f1.write("--------------------------------------------------- \n")

            f1.write("Notch Width: %s nanometers \n" % (w * 1000))
            f1.write("Reflection Percentage: %s\n" % (R * 100))
            f1.write("Transmission Percentage: %s\n" % (T * 100))
            f1.write("Total Loss Percentage: %s\n" % (S * 100))
            f1.write("Percentage of Light Accounted For: %s\n" % (NET))
            f1.write("Upper Loss Percentage: %s\n" % (Su * 100))
            f1.write("Lower Loss Percentage: %s\n" % (Sd * 100))
            f1.write("Percentage of Total Loss Accounted For: %s\n" %
                     (NET_LOSS))
            f1.write("Normalized Upper Loss Percentage: %s\n" %
                     (norm_Su * 100))
            f1.write("\n \n")

            f1.write("FUNDAMENTAL MODE \n")
            f1.write("n_eff:   %s\n" % (n_eff_fund[0]))
            f1.write("Re(r00): %s\n" % (np.real(r00))[0])
            f1.write("Im(r00): %s\n" % (np.imag(r00))[0])
            f1.write("Re(r01): %s\n" % (np.real(r01))[0])
            f1.write("Im(r01): %s\n" % (np.imag(r01))[0])
            f1.write("Re(t00): %s\n" % (np.real(t00))[0])
            f1.write("Im(t00): %s\n" % (np.imag(t00))[0])
            f1.write("Re(t01): %s\n" % (np.real(t01))[0])
            f1.write("Im(t01): %s\n" % (np.imag(t01))[0])
            f1.write("Re(su0): %s\n" % (np.real(su0)))
            f1.write("Im(su0): %s\n" % (np.imag(su0)))
            f1.write("Re(sd0): %s\n" % (np.real(sd0)))
            f1.write("Im(sd0): %s\n" % (np.imag(sd0)))
            f1.write("\n")

        else:

            f1.write("FIRST ORDER MODE \n")
            f1.write("n_eff:   %s\n" % (n_eff_first[0]))
            f1.write("Re(r10): %s\n" % (np.real(r10))[0])
            f1.write("Im(r10): %s\n" % (np.imag(r10))[0])
            f1.write("Re(r11): %s\n" % (np.real(r11))[0])
            f1.write("Im(r11): %s\n" % (np.imag(r11))[0])
            f1.write("Re(t10): %s\n" % (np.real(t10))[0])
            f1.write("Im(t10): %s\n" % (np.imag(t10))[0])
            f1.write("Re(t11): %s\n" % (np.real(t11))[0])
            f1.write("Im(t11): %s\n" % (np.imag(t11))[0])
            f1.write("Re(su1): %s\n" % (np.real(su1)))
            f1.write("Im(su1): %s\n" % (np.imag(su1)))
            f1.write("Re(sd1): %s\n" % (np.real(sd1)))
            f1.write("Im(sd1): %s\n" % (np.imag(sd1)))

            f1.write("--------------------------------------------------- \n")

        sim.reset_meep()
예제 #10
0
    def notch(w):

        print("#----------------------------------------")
        print("NOTCH WIDTH: %s nanometers" % (w * 1000))
        print("#----------------------------------------")

        # w is the width of the notch in the waveguide

        angrad = ang * pi / 180
        bottomoffset = e * h / tan(angrad)

        vertices = [
            mp.Vector3(w / 2 + bottomoffset, (.5 + e) * h),
            mp.Vector3(-w / 2 - bottomoffset, (.5 + e) * h),
            mp.Vector3(-w / 2 + bottomoffset, (.5 - e) * h),
            mp.Vector3(w / 2 - bottomoffset, (.5 - e) * h)
        ]

        if bottomoffset > w / 2:
            ratio = (w / 2) / bottomoffset
            vertices = [
                mp.Vector3(w / 2, h / 2),
                mp.Vector3(-w / 2, h / 2),
                mp.Vector3(0, (.5 - e * ratio) * h)
            ]

        print(vertices)

        #Waveguide Geometry
        cell = mp.Vector3(a, H)

        geometry = [
            mp.Block(cell, center=mp.Vector3(0, 0), material=default_material),
            mp.Block(mp.Vector3(a, hu + h / 2),
                     center=mp.Vector3(0, (hu + h / 2) / 2),
                     material=upper_material),
            mp.Block(mp.Vector3(a, hl + h / 2),
                     center=mp.Vector3(0, -(hl + h / 2) / 2),
                     material=lower_material),
            mp.Block(mp.Vector3(a, h),
                     center=mp.Vector3(0, 0),
                     material=core_material)
        ]

        if w > 0:
            geometry.append(
                mp.Prism(vertices, height=1, material=upper_material))

        pml_layers = [mp.Absorber(thickness=dpml)]

        r00 = None
        r01 = None
        r10 = None
        r11 = None

        t00 = None
        t01 = None
        t10 = None
        t11 = None

        su0 = None
        sd0 = None
        su1 = None
        sd1 = None

        modes = [0, 1]

        if only_fund:
            modes = [0]

        # eig_parity_fund = 	mp.EVEN_Z+mp.EVEN_Y;
        # eig_parity_first = 	mp.EVEN_Z+mp.ODD_Y;

        eig_parity_fund = mp.EVEN_Y
        eig_parity_first = mp.ODD_Y

        # for mode in [0, 1]:
        for mode in modes:

            if mode == 0:
                eig_parity = eig_parity_fund  # Fundamental
                print("-----------")
                print("MODE TYPE: FUNDAMENTAL")

            else:
                eig_parity = eig_parity_first  # First Order
                print("-----------")
                print("MODE TYPE: FIRST ORDER")

            # sources = [	mp.EigenModeSource(
            # 				mp.GaussianSource(	frequency = fcen,
            # 									fwidth = df),
            # 									size = mp.Vector3(0,H),
            # 									center = mp.Vector3(Ls, 0),
            # 									eig_parity = eig_parity) ]

            sources = [
                mp.EigenModeSource(mp.ContinuousSource(frequency=fcen),
                                   size=mp.Vector3(0, monitorheight),
                                   center=mp.Vector3(Ls, 0),
                                   eig_parity=eig_parity)
            ]

            sim = mp.Simulation(cell_size=cell,
                                boundary_layers=pml_layers,
                                geometry=geometry,
                                sources=sources,
                                resolution=resolution,
                                force_complex_fields=True)
            '''
			#--------------------------------------------------
			#FOR DISPLAYING THE GEOMETRY

			sim.run(until = 200)

			eps_data = sim.get_array(center=mp.Vector3(), size=cell, component=mp.Dielectric)
			plt.figure(dpi=100)
			plt.imshow(eps_data.transpose(), interpolation='spline36', cmap='binary')
			#plt.axis('off')
			plt.show()

			quit()
			#----------------------------------------------------
			'''
            '''
			#------------------------------------------------------
			#FOR GENERATING THE ELECTRIC FIELD GIF
			#Note: After running this program, write the following commands in Terminal:
			    # $ source deactivate mp
			    # $ cd notchtest-out/
			    # $ python ../NotchIP.py

			sim.use_output_directory()
			sim.run(mp.at_beginning(mp.output_epsilon),
			        mp.to_appended("ez", mp.at_every(0.6, mp.output_efield_z)),
			        until = 200)
			#sim.run(mp.at_every(0.6 , mp.output_png(mp.Ez, "-Zc dkbluered")), until=200)

			#---------------------------------------------------------
			'''

            #---------------------------------------------------------
            # FOR GENERATING THE TRANSMITTANCE SPECTRUM

            # nfreq = 1  # number of frequencies at which to compute flux
            #
            # refl_fr1 = 	mp.FluxRegion(center=mp.Vector3(Lr1,0), 	size=mp.Vector3(0,monitorheight))	# Reflected flux 1
            # refl_fr2 = 	mp.FluxRegion(center=mp.Vector3(Lr2,0), 	size=mp.Vector3(0,monitorheight))	# Reflected flux 2
            # tran_fr = 	mp.FluxRegion(center=mp.Vector3(Lt,0), 		size=mp.Vector3(0,monitorheight))	# Transmitted flux
            # su_fr = 	mp.FluxRegion(center=mp.Vector3(0, monitorheight/2),	size=mp.Vector3(a,0))	# Flux loss above the waveguide
            # sd_fr = 	mp.FluxRegion(center=mp.Vector3(0,-monitorheight/2), 	size=mp.Vector3(a,0))	# Flux loss below the waveguide
            #
            # refl1 = sim.add_flux(fcen, df, nfreq, refl_fr1)
            # refl2 = sim.add_flux(fcen, df, nfreq, refl_fr2)
            # tran = 	sim.add_flux(fcen, df, nfreq, tran_fr)
            # su = 	sim.add_flux(fcen, df, nfreq, su_fr)
            # sd = 	sim.add_flux(fcen, df, nfreq, sd_fr)

            # ------------------------ CODE FOR SEPARATING FUND AND FIRST ORDER MODE STARTS HERE ------------------------

            refl_vals = []
            tran_vals = []

            def get_refl_slice(sim):
                # print(sim.get_array(center=mp.Vector3(Lr1,0), size=mp.Vector3(0,H), component=mp.Ez, cmplx=True))
                # refl_val = sim.get_array(center=mp.Vector3(Lr1,0), size=mp.Vector3(0,H), component=mp.Ez, cmplx=True)
                refl_vals.append(
                    sim.get_array(center=mp.Vector3(Lr1, 0),
                                  size=mp.Vector3(
                                      0, monitorheight - 2 / resolution),
                                  component=mp.Ez,
                                  cmplx=True))

            def get_tran_slice(sim):
                # print(sim.get_array(center=mp.Vector3(Lt, 0), size=mp.Vector3(0,H), component=mp.Ez, cmplx=True))
                # tran_val = sim.get_array(center=mp.Vector3(Lt, 0), size=mp.Vector3(0,H), component=mp.Ez, cmplx=True)
                tran_vals.append(
                    sim.get_array(center=mp.Vector3(Lt, 0),
                                  size=mp.Vector3(
                                      0, monitorheight - 2 / resolution),
                                  component=mp.Ez,
                                  cmplx=True))

            gif = True

            # T = 50*(a-4)/12;
            T = 60

            if resolution == 50:
                epsform = "eps-000000.00"
            else:
                epsform = "eps-000000000"

            if gif:  # and w == 0.1:
                sim.use_output_directory()
                sim.run(mp.at_beginning(mp.output_epsilon),
                        mp.at_every(
                            1,
                            mp.output_png(
                                mp.Ez,
                                "-RZc bluered -A notchtest-out/notchtest-" +
                                epsform + ".h5 -a gray:.2")),
                        mp.at_end(get_refl_slice),
                        mp.at_end(get_tran_slice),
                        until=T)

                os.system("convert notchtest-out/notchtest-ez-*.png    " +
                          casedash + "-" + str(int(w * 1000)) + "-" +
                          str(mode) + "-full.gif")
                os.system("rm notchtest-out/notchtest-ez-*.png")

                nfreq = 1  # number of frequencies at which to compute flux

                refl_fr1 = mp.FluxRegion(
                    center=mp.Vector3(Lr1, 0),
                    size=mp.Vector3(0, monitorheight))  # Reflected flux 1
                refl_fr2 = mp.FluxRegion(
                    center=mp.Vector3(Lr2, 0),
                    size=mp.Vector3(0, monitorheight))  # Reflected flux 2
                tran_fr = mp.FluxRegion(
                    center=mp.Vector3(Lt, 0),
                    size=mp.Vector3(0, monitorheight))  # Transmitted flux
                su_fr = mp.FluxRegion(
                    center=mp.Vector3(0, monitorheight / 2),
                    size=mp.Vector3(a, 0))  # Flux loss above the waveguide
                sd_fr = mp.FluxRegion(
                    center=mp.Vector3(0, -monitorheight / 2),
                    size=mp.Vector3(a, 0))  # Flux loss below the waveguide

                refl1 = sim.add_flux(fcen, df, nfreq, refl_fr1)
                refl2 = sim.add_flux(fcen, df, nfreq, refl_fr2)
                tran = sim.add_flux(fcen, df, nfreq, tran_fr)
                su = sim.add_flux(fcen, df, nfreq, su_fr)
                sd = sim.add_flux(fcen, df, nfreq, sd_fr)

                # sim.run(mp.at_every(wavelength / 20, mp.output_efield_z), until=wavelength)
                # sim.run(mp.at_every(wavelength/20 , mp.output_png(mp.Ez, "-RZc bluered -A notchtest-out/notchtest-eps-000000000.h5 -a gray:.2")), until=19*wavelength/20)
                sim.run(mp.at_every(
                    wavelength / 20,
                    mp.output_png(
                        mp.Ez, "-RZc bluered -A notchtest-out/notchtest-" +
                        epsform + ".h5 -a gray:.2")),
                        until=19 * wavelength / 20)
                sim.run(until=20)
                # sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, mp.Vector3(), 1e-5))
            else:
                sim.run(mp.at_beginning(mp.output_epsilon),
                        mp.at_time(T, get_refl_slice),
                        mp.at_time(T, get_tran_slice))  #,
                # until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, mp.Vector3(), 1e-5))

            os.system("h5topng notchtest-out/notchtest-" + epsform +
                      ".h5; mv notchtest-out/notchtest-" + epsform + ".png " +
                      casedash + "-" + str(int(w * 1000)) + "-" + str(mode) +
                      "-eps.png")
            # os.system("cp notchtest-out/notchtest-ez-000100.00.png " 	+ case + "-" + str(int(w*1000)) + "-" + str(mode) + ".png")
            os.system("convert notchtest-out/notchtest-ez-*.png    " +
                      casedash + "-" + str(int(w * 1000)) + "-" + str(mode) +
                      ".gif")
            os.system("rm notchtest-out/notchtest-ez-*.png")

            # get_eigenmode(fcen, mp., refl_fr1, 1, kpoint)
            # v = mp.volume(mp.vec(Lr1, -monitorheight/2), mp.vec(Lr1, monitorheight/2))
            # mode = get_eigenmode(fcen, mp.X, v, v, 1, mp.vec(0, 0, 0), True, 0, 0, 1e-7, True)
            # print(mode.amplitude)

            # coef_refl_fund = 	mp.get_eigenmode_coefficients_and_kpoints(refl_fr1, 1, eig_parity=eig_parity_fund, 	eig_resolution=resolution, eig_tolerance=1e-7)
            # coef_refl_first = 	mp.get_eigenmode_coefficients_and_kpoints(refl_fr1, 1, eig_parity=eig_parity_first, eig_resolution=resolution, eig_tolerance=1e-7)
            #
            # coef_tran_fund = 	mp.get_eigenmode_coefficients_and_kpoints(tran_fr, 	1, eig_parity=eig_parity_fund, 	eig_resolution=resolution, eig_tolerance=1e-7)
            # coef_tran_first = 	mp.get_eigenmode_coefficients_and_kpoints(tran_fr, 	1, eig_parity=eig_parity_first, eig_resolution=resolution, eig_tolerance=1e-7)

            ep = mp.ODD_Z

            coef_refl_fund, vgrp, kpoints_fund = sim.get_eigenmode_coefficients(
                refl1, [1],
                eig_parity=ep,
                eig_resolution=resolution,
                eig_tolerance=1e-7)
            coef_refl_first, vgrp, kpoints_first = sim.get_eigenmode_coefficients(
                refl1, [2],
                eig_parity=ep,
                eig_resolution=resolution,
                eig_tolerance=1e-7)

            coef_tran_fund, vgrp, kpoints_fund = sim.get_eigenmode_coefficients(
                tran, [1],
                eig_parity=ep,
                eig_resolution=resolution,
                eig_tolerance=1e-7)
            coef_tran_first, vgrp, kpoints_first = sim.get_eigenmode_coefficients(
                tran, [2],
                eig_parity=ep,
                eig_resolution=resolution,
                eig_tolerance=1e-7)

            # print(kpoints_fund)
            # print(kpoints_first)
            # print(kpoints_fund[0])
            # print(type(kpoints_fund[0]))
            # print(dir(kpoints_fund[0]))

            n_eff_fund = wavelength * kpoints_fund[0].x
            n_eff_first = wavelength * kpoints_first[0].x

            print(n_eff_fund)
            print(n_eff_first)

            # print(coef_refl_fund)
            # print(type(coef_refl_fund))
            # print(dir(coef_refl_fund))

            # print(coef_refl_fund[0])
            # print(coef_refl_fund[0][0,0,:])
            #
            # fund_refl_amp = 		coef_refl_fund[0][0,0,1];
            # first_order_refl_amp =	coef_refl_first[0][0,0,1];
            # fund_tran_amp =			coef_tran_fund[0][0,0,0];
            # first_order_tran_amp =	coef_tran_first[0][0,0,0];

            print("get_eigenmode_coefficients:\n")

            print(coef_refl_fund)
            print(coef_refl_first)
            print(coef_tran_fund)
            print(coef_tran_first)

            print("\n")
            # print(coef_refl_fund[0,0,:])

            fund_refl_amp = coef_refl_fund[0, 0, 1]
            first_order_refl_amp = coef_refl_first[0, 0, 1]
            fund_tran_amp = coef_tran_fund[0, 0, 0]
            first_order_tran_amp = coef_tran_first[0, 0, 0]

            refl_val = refl_vals[0]
            tran_val = tran_vals[0]

            # n_eff must satisfy n_e <= n_eff <= n_c for the mode to be bound.

            def fund_func(n_eff):
                if n_eff >= n_c and n_eff <= n_e:
                    return sqrt(
                        n_eff**2 - n_c**2) - sqrt(n_e**2 - n_eff**2) * tan(
                            pi * h / wavelength * sqrt(n_e**2 - n_eff**2))

            def first_order_func(n_eff):
                if n_eff >= n_c and n_eff <= n_e:
                    return sqrt(n_eff**2 -
                                n_c**2) - sqrt(n_e**2 - n_eff**2) * tan(
                                    pi * h / wavelength *
                                    sqrt(n_e**2 - n_eff**2) - pi / 2)

            initial_guess = (n_c + n_e) / 2

            # n_eff_fund = 	fsolve(fund_func, initial_guess)
            # n_eff_first = 	fsolve(first_order_func, n_c)

            print(n_eff_fund, n_eff_first)

            assert (n_eff_fund > n_eff_first)

            if len(n_eff_funds) == 0:
                n_eff_funds.append(n_eff_fund)

            if len(n_eff_firsts) == 0:
                n_eff_firsts.append(n_eff_first)

            ky0_fund = np.abs(2 * pi / wavelength *
                              sqrt(n_e**2 - n_eff_fund**2))
            ky0_first = np.abs(2 * pi / wavelength *
                               sqrt(n_e**2 - n_eff_first**2))

            ky1_fund = ky0_fund  # np.abs(2 * pi / wavelength * sqrt(n_eff_fund **2 - n_c**2))
            ky1_first = ky0_first  # np.abs(2 * pi / wavelength * sqrt(n_eff_first**2 - n_c**2))

            E_fund = lambda y: cos(ky0_fund * y) if np.abs(y) < h / 2 else cos(
                ky0_fund * h / 2) * np.exp(-ky1_fund * (np.abs(y) - h / 2))
            E_first_order = lambda y: sin(ky0_first * y) if np.abs(
                y) < h / 2 else sin(ky0_first * h / 2) * np.exp(-ky1_first * (
                    np.abs(y) - h / 2)) * np.sign(y)
            # y_list = np.arange(-H/2+.5/resolution, H/2-.5/resolution, 1/resolution)

            #print("Y LIST: ", y_list)
            #print("SIZE OF Y LIST: ", y_list.size)

            E_fund_vec = np.zeros(y_list.size)
            E_first_order_vec = np.zeros(y_list.size)

            for index in range(y_list.size):
                y = y_list[index]
                E_fund_vec[index] = E_fund(y)
                E_first_order_vec[index] = E_first_order(y)

            # print(dir(sim))
            # print(type(sim.get_eigenmode_coefficients))
            # print(dir(sim.get_eigenmode_coefficients))
            # print(type(sim.get_eigenmode))
            # print(dir(sim.get_eigenmode))
            # print(sim.get_eigenmode.__code__.co_varnames)
            # print(sim.get_eigenmode.__defaults__)

            # E1 = sim.get_eigenmode(fcen, mp.X, refl1.where, 1, None)
            # E2 = sim.get_eigenmode(fcen, mp.X, refl1.where, 2, None)
            # E3 = sim.get_eigenmode(fcen, mp.X, refl1.where, 3, None)
            # E4 = sim.get_eigenmode(fcen, mp.X, refl1.where, 4, None)

            # E1 = sim.get_eigenmode(fcen, mp.X, refl1.where, 1, mp.Vector3(0, 0, 0))
            # E2 = sim.get_eigenmode(fcen, mp.X, refl1.where, 2, mp.Vector3(0, 0, 0))
            # E3 = sim.get_eigenmode(fcen, mp.X, refl1.where, 3, mp.Vector3(0, 0, 0))
            # E4 = sim.get_eigenmode(fcen, mp.X, refl1.where, 4, mp.Vector3(0, 0, 0))

            # print(refl1.where)
            # numEA = 0
            # E1 = sim.fields.get_eigenmode(fcen, mp.X, refl1.where, refl1.where, 1, mp.vec(0,0,0), True, 0, numEA, 1e-7, True)

            # print(type(E1))
            # print(dir(E1))
            #
            # print(refl1.where)
            # # print(E1, E2, E3, E4)
            # print(E1.amplitude, E1.band_num, E1.group_velocity, E1.k)
            # print(type(E1.amplitude))
            # print(dir(E1.amplitude))
            # print(doc(E1.amplitude))
            # print(self(E1.amplitude))
            # print(E1.amplitude(y_list))
            # print(type(E1.amplitude(y_list)))
            # print(dir(E1.amplitude(y_list)))
            # print(E1.amplitude, E2.amplitude, E3.amplitude, E4.amplitude)

            # E1 = sim.get_eigenmode(fcen, mp.X, refl1.where, refl1.where, 1, mp.vec(0, 0, 0))
            # E2 = sim.get_eigenmode(fcen, mp.X, refl1.where, refl1.where, 2, mp.vec(0, 0, 0))
            # E3 = sim.get_eigenmode(fcen, mp.X, refl1.where, refl1.where, 3, mp.vec(0, 0, 0))
            # E4 = sim.get_eigenmode(fcen, mp.X, refl1.where, refl1.where, 4, mp.vec(0, 0, 0))

            # print(y_list)
            #
            # E1a = np.zeros(y_list.size, dtype='Complex128');
            # E2a = np.zeros(y_list.size, dtype='Complex128');
            # E3a = np.zeros(y_list.size, dtype='Complex128');
            # E4a = np.zeros(y_list.size, dtype='Complex128');
            #
            # # print(mp.eigenmode_amplitude.__code__.co_varnames)
            # # print(mp.eigenmode_amplitude.__defaults__)
            #
            # for i in range(y_list.size):
            # 	# print(E1)
            # 	# print(E1.swigobj)
            # 	# print(E1.amplitude)
            # 	# print(mp.vec(Lr1, y_list[i], 0))
            # 	# print(mp.Vector3(Lr1, y_list[i], 0))
            # 	# print(mp.Ez)
            # 	# E1a[i] = mp.eigenmode_amplitude(E1.swigobj, mp.vec(Lr1, y_list[i], 0), mp.Ez);
            # 	eval_point = mp.vec(Lr1, y_list[i], 0)
            # 	# print(eval_point)
            # 	E1a[i] = mp.eigenmode_amplitude(E1.swigobj, eval_point, mp.Ex)
            # 	E2a[i] = mp.eigenmode_amplitude(E2.swigobj, eval_point, mp.Ex)
            # 	E3a[i] = mp.eigenmode_amplitude(E3.swigobj, eval_point, mp.Ex)
            # 	E4a[i] = mp.eigenmode_amplitude(E4.swigobj, eval_point, mp.Ex)
            # 	# E1a[i] = mp.eigenmode_amplitude(E1.amplitude, mp.Vector3(Lr1, y_list[i], 0), mp.Ez);
            #
            # plt.plot(y_list, np.abs(E1a)**2, 'bo-', label='E1')
            # plt.plot(y_list, np.abs(E2a)**2, 'ro-', label='E2')
            # plt.plot(y_list, np.abs(E3a)**2, 'go-', label='E3')
            # plt.plot(y_list, np.abs(E4a)**2, 'co-', label='E4')
            # # plt.axis([40.0, 300.0, 0.0, 100.0])
            # plt.xlabel("y (um)")
            # plt.ylabel("Field (a.u.)")
            # plt.legend(loc="center right")
            # plt.show()

            # print("r VECTOR: ", 	refl_val)
            # print("t VECTOR: ", 	tran_val)
            # print("E0 VECTOR: ", 	E_fund_vec)
            # print("E1 VECTOR: ", 	E_first_order_vec)

            # fund_refl_amp_2 = 			np.conj(np.dot(refl_val, E_fund_vec) 		/ np.dot(E_fund_vec, E_fund_vec))					# Conjugate becasue MEEP uses physics exp(kz-wt) rather than engineering exp(wt-kz)
            # first_order_refl_amp_2 = 	np.conj(np.dot(refl_val, E_first_order_vec) / np.dot(E_first_order_vec, E_first_order_vec))
            # fund_tran_amp_2 = 			np.conj(np.dot(tran_val, E_fund_vec) 		/ np.dot(E_fund_vec, E_fund_vec))
            # first_order_tran_amp_2 = 	np.conj(np.dot(tran_val, E_first_order_vec) / np.dot(E_first_order_vec, E_first_order_vec))

            fund_refl_amp0 = fund_refl_amp
            fund_tran_amp0 = fund_tran_amp

            fund_refl_amp = np.conj(
                np.dot(refl_val, E0) / np.dot(E0, E0)
            )  # Conjugate becasue MEEP uses physics exp(kz-wt) rather than engineering exp(wt-kz)
            first_order_refl_amp = 0  # np.conj(np.dot(refl_val, E1[:,2]) / np.dot(E1[:,2], E1[:,2]))
            fund_tran_amp = np.conj(np.dot(tran_val, E0) / np.dot(E0, E0))
            first_order_tran_amp = 0  # np.conj(np.dot(tran_val, E1[:,2]) / np.dot(E1[:,2], E1[:,2]))

            fund_refl = np.conj(fund_refl_amp) * E0
            not_fund_refl = refl_val - fund_refl
            fund_tran = np.conj(fund_tran_amp) * E0
            not_fund_tran = tran_val - fund_tran

            fund_refl_power = np.dot(np.conj(fund_refl), fund_refl)
            not_fund_refl_power = np.dot(np.conj(not_fund_refl), not_fund_refl)
            fund_tran_power = np.dot(np.conj(fund_tran), fund_tran)
            not_fund_tran_power = np.dot(np.conj(not_fund_tran), not_fund_tran)

            f2.write(
                "%s, " %
                [fund_refl_amp0, fund_tran_amp0, fund_refl_amp, fund_tran_amp])

            # assert(fund_refl_power + not_fund_refl_power == 1)
            # assert(fund_tran_power + not_fund_tran_power == 1)
            # f2.write("\n");

            fund_refl_ratio = np.abs(fund_refl_power /
                                     (fund_refl_power + not_fund_refl_power))
            first_order_refl_ratio = 0
            fund_tran_ratio = np.abs(fund_tran_power /
                                     (fund_tran_power + not_fund_tran_power))
            first_order_tran_ratio = 0

            f2.write("%s, " % [
                fund_refl_ratio, fund_refl_power, not_fund_refl_power,
                fund_refl_power + not_fund_refl_power, fund_tran_ratio,
                fund_tran_power, not_fund_tran_power,
                fund_tran_power + not_fund_tran_power
            ])

            plt.plot(y_list, np.abs(refl_val), 'bo-', label='reflectance')
            plt.plot(y_list, np.abs(tran_val), 'ro-', label='transmittance')
            plt.plot(y_list, E0, 'go-', label='E0')
            plt.plot(y_list, fund_refl, 'co-', label='over')
            plt.plot(y_list, not_fund_refl, 'ko-', label='over')
            # plt.axis([40.0, 300.0, 0.0, 100.0])
            plt.xlabel("y (um)")
            plt.ylabel("Field")
            plt.legend(loc="center right")
            plt.savefig(case + "fields.png")
            plt.close()

            #
            # print("\n")
            #
            # print(tran_val.size, refl_val.size)
            #
            # print("\n")
            #
            # print(tran_val, refl_val, E0)
            #
            # print("\n")
            # # print(np.conj(tran_val), tran_val, E1[:,2])
            # #
            # # print(np.conj(refl_val), refl_val, E1[:,2])
            #
            # refl_tot_power = np.abs(np.dot(np.conj(refl_val), refl_val))
            # tran_tot_power = np.abs(np.dot(np.conj(tran_val), tran_val))
            #
            # print(fund_refl_amp, refl_tot_power, fund_tran_amp, tran_tot_power)

            # print(fund_refl_amp 		, fund_refl_amp_2 		)
            # print(first_order_refl_amp 	, first_order_refl_amp_2)
            # print(fund_tran_amp 		, fund_tran_amp_2 		)
            # print(first_order_tran_amp 	, first_order_tran_amp_2)
            #
            # print(np.angle(fund_refl_amp), 			np.angle(fund_refl_amp_2))
            # print(np.angle(first_order_refl_amp), 	np.angle(first_order_refl_amp_2))
            # print(np.angle(fund_tran_amp), 			np.angle(fund_tran_amp_2))
            # print(np.angle(first_order_tran_amp), 	np.angle(first_order_tran_amp_2))

            # fund_refl_power = 			np.abs(fund_tran_amp)			** 2
            # fund_refl_power = 			np.abs(fund_refl_amp)			** 2
            # first_order_refl_power = 	np.abs(first_order_refl_amp) 	** 2
            # fund_tran_power = 			np.abs(fund_tran_amp) 			** 2
            # first_order_tran_power = 	np.abs(first_order_tran_amp) 	** 2

            # print(fund_refl_power, first_order_refl_power, fund_tran_power, first_order_tran_power)

            # fund_refl_ratio = 			fund_refl_power 		/ (fund_refl_power + first_order_refl_power)
            # first_order_refl_ratio = 	first_order_refl_power 	/ (fund_refl_power + first_order_refl_power)
            # fund_tran_ratio = 			fund_tran_power 		/ (fund_tran_power + first_order_tran_power)
            # first_order_tran_ratio = 	first_order_tran_power 	/ (fund_tran_power + first_order_tran_power)

            # fund_refl_power = 			np.abs(fund_refl_amp)			** 2
            # first_order_refl_power = 	np.abs(first_order_refl_amp)	** 2
            # fund_tran_power = 			np.abs(fund_tran_amp)			** 2
            # first_order_tran_power = 	np.abs(first_order_tran_amp)	** 2
            #
            # fund_refl_ratio = 			fund_refl_power 		/ refl_tot_power
            # first_order_refl_ratio = 	first_order_refl_power 	/ refl_tot_power
            # fund_tran_ratio = 			fund_tran_power 		/ tran_tot_power
            # first_order_tran_ratio = 	first_order_tran_power 	/ tran_tot_power
            #
            # fund_refl_ratio = 			1
            # first_order_refl_ratio = 	0
            # fund_tran_ratio = 			1
            # first_order_tran_ratio = 	0

            print("Percentage of reflected light in fundamental mode: ",
                  fund_refl_ratio * 100)
            print("Percentage of reflected light in first order mode: ",
                  first_order_refl_ratio * 100)
            print("Percentage of transmitted light in fundamental mode: ",
                  fund_tran_ratio * 100)
            print("Percentage of transmitted light in first order mode: ",
                  first_order_tran_ratio * 100)

            # ------------------------ CODE FOR SEPARATING FUND AND FIRST ORDER MODE ENDS HERE ------------------------

            wl = []  #list of wavelengths

            refl1_flux = mp.get_fluxes(refl1)
            refl2_flux = mp.get_fluxes(refl2)
            tran_flux = mp.get_fluxes(tran)
            su_flux = mp.get_fluxes(su)
            sd_flux = mp.get_fluxes(sd)

            flux_freqs = mp.get_flux_freqs(refl1)

            for i in range(nfreq):
                wl = np.append(wl, 1 / flux_freqs[i])
                print(1 / flux_freqs[i])

            # for ind, elt in enumerate(wl):
            #     #print(round(elt, 4))
            #     if round(elt, 3) == 0.637:
            #         #print("ALERT: MATCH FOUND")
            #         index = ind

            index = 0

            rp = refl1_flux[index]
            tp = tran_flux[index]

            # print("rp/tp:\n")
            # print(rp)
            # print(tp)
            # print("\n")

            R = -refl1_flux[index] / (refl2_flux[index] - refl1_flux[index])
            T = tran_flux[index] / (refl2_flux[index] - refl1_flux[index])
            S = (refl2_flux[index] - tran_flux[index]) / (refl2_flux[index] -
                                                          refl1_flux[index])
            Su = su_flux[index] / (refl2_flux[index] - refl1_flux[index])
            Sd = -sd_flux[index] / (refl2_flux[index] - refl1_flux[index])

            S_correction = (1 - R - T) / (Su + Sd)

            # print(R, T, S, Su, Sd)

            r = sqrt(R)
            t = sqrt(T)

            r_fund = (r * fund_refl_ratio) * np.exp(
                1j * np.angle(fund_refl_amp) + 2j * pi *
                (-Lr1 - w / 2) * n_eff_fund / wavelength
            )  # Lr1 is negative because it is the (negative) position of the monitor, not the distace from the monitor to the center.
            r_first = (r * first_order_refl_ratio) * np.exp(
                1j * np.angle(first_order_refl_amp) + 2j * pi *
                (-Lr1 - w / 2) * n_eff_first / wavelength)
            t_fund = (t * fund_tran_ratio
                      ) * np.exp(1j * np.angle(fund_tran_amp) + 2j * pi *
                                 (Lt - w / 2) * n_eff_fund / wavelength)
            t_first = (t * first_order_tran_ratio) * np.exp(
                1j * np.angle(first_order_tran_amp) + 2j * pi *
                (Lt - w / 2) * n_eff_first / wavelength)

            if mode == 0:
                r00 = r_fund
                r01 = r_first

                t00 = t_fund
                t01 = t_first

                su0 = sqrt(np.abs(Su * S_correction))
                sd0 = sqrt(np.abs(Sd * S_correction))
                # su0 = sqrt(Su)
                # sd0 = sqrt(Sd)

                r00s.append(r00)
                r01s.append(r01)
                t00s.append(t00)
                t01s.append(t01)
                su0s.append(su0)
                sd0s.append(sd0)

                if only_fund:
                    r10s.append(0)
                    r11s.append(0)
                    t10s.append(0)
                    t11s.append(1)
                    su1s.append(0)
                    sd1s.append(0)
            else:
                r10 = r_fund
                r11 = r_first

                t10 = t_fund
                t11 = t_first

                su1 = sqrt(np.abs(Su * S_correction))
                sd1 = sqrt(np.abs(Sd * S_correction))
                # su1 = sqrt(Su)
                # sd1 = sqrt(Sd)

                r10s.append(r10)
                r11s.append(r11)
                t10s.append(t10)
                t11s.append(t11)
                su1s.append(su1)
                sd1s.append(sd1)

            norm_Su = S * Su / (Su + Sd)

            NET = round((R + T + S) * 100, 0)
            if NET > 100.0:
                NET = 100.0

            NET_LOSS = round((Su + Sd) / S * 100, 0)
            if NET_LOSS > 100.0:
                NET_LOSS = 100.0
            '''
			np.append(ws, [w * 1000])
			np.append(Rs, [R * 100])
			np.append(Ts, [T * 100])
			np.append(Ss, [S * 100])
			np.append(NET_LIST, [NET])
			np.append(Sus, [Su * 100])
			np.append(Sds, [Sd * 100])
			np.append(NET_LOSS_LIST, [NET_LOSS])
			np.append(norm_Sus, [norm_Su * 100])
			'''

            if mode == 0:
                ws.append(w * 1000)
                Rs.append(R * 100)
                Ts.append(T * 100)
                Ss.append(S * 100)
                NET_LIST.append(NET)
                Sus.append(Su * 100)
                Sds.append(Sd * 100)
                NET_LOSS_LIST.append(NET_LOSS)
                norm_Sus.append(norm_Su * 100)

            if mode == 0:

                f1.write(
                    "--------------------------------------------------- \n")

                f1.write("Notch Width: %s nanometers \n" % (w * 1000))
                f1.write("Reflection Percentage: %s\n" % (R * 100))
                f1.write("Transmission Percentage: %s\n" % (T * 100))
                f1.write("Total Loss Percentage: %s\n" % (S * 100))
                f1.write("Percentage of Light Accounted For: %s\n" % (NET))
                f1.write("Upper Loss Percentage: %s\n" % (Su * 100))
                f1.write("Lower Loss Percentage: %s\n" % (Sd * 100))
                f1.write("Percentage of Total Loss Accounted For: %s\n" %
                         (NET_LOSS))
                f1.write("Normalized Upper Loss Percentage: %s\n" %
                         (norm_Su * 100))
                f1.write("\n \n")

                f1.write("FUNDAMENTAL MODE \n")
                f1.write("n_eff:   %s\n" % (n_eff_fund))
                f1.write("Re(r00): %s\n" % (np.real(r00)))
                f1.write("Im(r00): %s\n" % (np.imag(r00)))
                f1.write("Re(r01): %s\n" % (np.real(r01)))
                f1.write("Im(r01): %s\n" % (np.imag(r01)))
                f1.write("Re(t00): %s\n" % (np.real(t00)))
                f1.write("Im(t00): %s\n" % (np.imag(t00)))
                f1.write("Re(t01): %s\n" % (np.real(t01)))
                f1.write("Im(t01): %s\n" % (np.imag(t01)))
                f1.write("Re(su0): %s\n" % (np.real(su0)))
                f1.write("Im(su0): %s\n" % (np.imag(su0)))
                f1.write("Re(sd0): %s\n" % (np.real(sd0)))
                f1.write("Im(sd0): %s\n" % (np.imag(sd0)))
                f1.write("\n")

            else:

                f1.write("FIRST ORDER MODE \n")
                f1.write("n_eff:   %s\n" % (n_eff_first))
                f1.write("Re(r10): %s\n" % (np.real(r10)))
                f1.write("Im(r10): %s\n" % (np.imag(r10)))
                f1.write("Re(r11): %s\n" % (np.real(r11)))
                f1.write("Im(r11): %s\n" % (np.imag(r11)))
                f1.write("Re(t10): %s\n" % (np.real(t10)))
                f1.write("Im(t10): %s\n" % (np.imag(t10)))
                f1.write("Re(t11): %s\n" % (np.real(t11)))
                f1.write("Im(t11): %s\n" % (np.imag(t11)))
                f1.write("Re(su1): %s\n" % (np.real(su1)))
                f1.write("Im(su1): %s\n" % (np.imag(su1)))
                f1.write("Re(sd1): %s\n" % (np.real(sd1)))
                f1.write("Im(sd1): %s\n" % (np.imag(sd1)))

                f1.write(
                    "--------------------------------------------------- \n")

            sim.reset_meep()