Esempio n. 1
0
# - You will sometimes also accidentally identify spurious peak frequencies.

src = mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Ez, mp.Vector3(r + 0.1))

sim = mp.Simulation(cell_size=mp.Vector3(sxy, sxy),
                    geometry=[c1, c2],
                    sources=[src],
                    resolution=10,
                    symmetries=[mp.Mirror(mp.Y)],
                    boundary_layers=[mp.PML(dpml)],
                    filename_prefix=prefix)

h = mp.Harminv(mp.Ez, mp.Vector3(r + 0.1), fcen, df)

if not os.path.isdir(path):
    sav.new_dir(path)
os.chdir(path)

#%% SIMULATION: FREQUENCY

start = time()
sim.run(mp.at_beginning(mp.output_epsilon),
        mp.after_sources(h),
        until_after_sources=300)
end = time()
print("Enlapsed time: {:.2f}".format(end - start))

#%% SIMULATION: FIELDS

freqs = [h.modes[i][0] for i in range(len(h.modes))]
Esempio n. 2
0
boundary_layers = [mp.PML(thickness=pml_width)]

source_center = -0.5*cell_width + pml_width
sources = [mp.Source(mp.ContinuousSource(wavelength=wlen, 
                                         is_integrated=is_integrated),
                     center=mp.Vector3(source_center),
                     size=mp.Vector3(0, cell_width, cell_width),
                     component=mp.Ez)]

symmetries = [mp.Mirror(mp.Y), mp.Mirror(mp.Z, phase=-1)]

enlapsed = []

path = os.path.join(home, folder, "{}Results".format(series))
if not os.path.isdir(path): vs.new_dir(path)
file = lambda f : os.path.join(path, f)

#%% OPTION 1: SAVE GET FUNCTIONS ##############################################

def get_line(sim):
    return sim.get_array(
        center=mp.Vector3(*line_center), 
        size=mp.Vector3(*line_size), 
        component=mp.Ez)

def get_plane(sim):
    return sim.get_array(
        center=mp.Vector3(*plane_center), 
        size=mp.Vector3(*plane_size), 
        component=mp.Ez)
Esempio n. 3
0
def main(series, folder, resolution, from_um_factor, r, paper, wlen):
    #%% PARAMETERS

    # Au sphere
    r = r / (from_um_factor * 1e3)  # Radius of sphere now in Meep units
    medium = import_medium("Au", from_um_factor,
                           paper=paper)  # Medium of sphere: gold (Au)

    # Frequency and wavelength
    wlen = wlen / (from_um_factor * 1e3)  # Wavelength now in Meep units

    # Space configuration
    pml_width = 0.38 * wlen  # 0.5 * wlen
    air_width = r / 2  # 2 * r

    # Field Measurements
    period_line = 1
    period_plane = 1
    after_cell_run_time = 10 * wlen

    # Computation time
    enlapsed = []

    # Saving directories
    if series is None:
        series = f"AuSphereField{2*r*from_um_factor*1e3:.0f}WLen{wlen*from_um_factor*1e3:.0f}"
    if folder is None:
        folder = "AuMieSphere/AuSphereField"
    home = vs.get_home()

    #%% 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)]
    # Cause of symmetry, two mirror planes reduce cell size to 1/4

    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)

    source_center = -0.5 * cell_width + pml_width
    print("Resto Source Center: {}".format(source_center % (1 / resolution)))
    sources = [
        mp.Source(mp.ContinuousSource(wavelength=wlen, is_integrated=True),
                  center=mp.Vector3(source_center),
                  size=mp.Vector3(0, cell_width, cell_width),
                  component=mp.Ez)
    ]
    # Ez-polarized monochromatic planewave
    # (its size parameter fills the entire cell in 2d)
    # >> The planewave source extends into the PML
    # ==> is_integrated=True must be specified

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

    path = os.path.join(home, folder, series)
    if not os.path.isdir(path): vs.new_dir(path)
    file = lambda f: os.path.join(path, f)

    #%% SAVE GET FUNCTIONS

    def get_line(sim):
        return sim.get_array(center=mp.Vector3(),
                             size=mp.Vector3(cell_width),
                             component=mp.Ez)

    def get_plane(sim):
        return sim.get_array(center=mp.Vector3(),
                             size=mp.Vector3(0, cell_width, cell_width),
                             component=mp.Ez)

    #%% INITIALIZE

    sim = mp.Simulation(resolution=resolution,
                        cell_size=cell_size,
                        boundary_layers=pml_layers,
                        sources=sources,
                        symmetries=symmetries,
                        geometry=geometry)

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

    #%% DEFINE SAVE STEP FUNCTIONS

    f, save_line = vs.save_slice_generator(sim, file("Lines.h5"), "Ez",
                                           get_line)
    g, save_plane = vs.save_slice_generator(sim, file("Planes.h5"), "Ez",
                                            get_plane)

    to_do_while_running = [
        mp.at_every(period_line, save_line),
        mp.at_every(period_plane, save_plane)
    ]

    #%% RUN!

    temp = time()
    sim.run(*to_do_while_running, until=cell_width + after_cell_run_time)
    del f, g
    enlapsed.append(time() - temp)

    #%% SAVE METADATA

    params = dict(from_um_factor=from_um_factor,
                  resolution=resolution,
                  r=r,
                  paper=paper,
                  pml_width=pml_width,
                  air_width=air_width,
                  cell_width=cell_width,
                  source_center=source_center,
                  wlen=wlen,
                  period_line=period_line,
                  period_plane=period_plane,
                  after_cell_run_time=after_cell_run_time,
                  series=series,
                  folder=folder,
                  home=home,
                  enlapsed=enlapsed)

    f = h5.File(file("Lines.h5"), "r+")
    for a in params:
        f["Ez"].attrs[a] = params[a]
    f.close()
    del f

    g = h5.File(file("Planes.h5"), "r+")
    for a in params:
        g["Ez"].attrs[a] = params[a]
    g.close()
    del g

    sim.reset_meep()
Esempio n. 4
0
wlen_chosen = [405, 532, 642]
epsilon_ext = (1.33)**2  # Water
# E0_func = lambda n : np.array([[0,0,1] for i in range(n)])
E0 = np.array([0, 0, 1])

npoints = 500

folder = "AllWaterField2"

#%% SAVING CONFIGURATION

series = f"{folder}{2*r:1.0f}"
plot_folder = f"DataAnalysis/{folder}/{series}"
home = vs.get_home()
if not os.path.isdir(os.path.join(home, plot_folder)):
    vs.new_dir(os.path.join(home, plot_folder))
plot_file = lambda n: os.path.join(home, plot_folder,
                                   f"AllWaterField{2*r:1.0f}" + n)

#%% INNER MEDIUM EPSILON

wlen = np.linspace(*wlen_range, npoints)

epsilon_func_meep_jc = vmt.epsilon_function(material="Au",
                                            paper="JC",
                                            reference="Meep")
epsilon_func_meep_r = vmt.epsilon_function(material="Au",
                                           paper="R",
                                           reference="Meep")
epsilon_func_exp_jc = vmt.epsilon_function(material="Au",
                                           paper="JC",
Esempio n. 5
0
def main(series, resolution, r, paper, wlen_range, meep_flux, H_field):
    
    #%% PARAMETERS
    
    ### MEAN PARAMETERS
    
    # Units: 10 nm as length unit
    from_um_factor = 10e-3 # Conversion of 1 μm to my length unit (=10nm/1μm)
    
    # Sphere
    r = r / ( from_um_factor * 1e3 ) # Now in Meep units
    
    # Frequency and wavelength
    wlen_range = wlen_range / ( from_um_factor * 1e3 ) # Now in Meep units
    nfreq = 100 # Number of frequencies to discretize range
    cutoff = 3.2
    
    # Computation time
    enlapsed = []
    time_factor_cell = 1.2
    until_after_sources = False
    
    # Saving data
    period_line = 1/10 * min(wlen_range)
    period_plane = 1/50 * min(wlen_range)
    
    # Saving directories
    if series is None:
        series = f"TestParallelRes{resolution}"
    folder = "AuMieSphere/AuMieField"
    home = "/home/vall/Documents/Thesis/ThesisResults/"
    
    ### OTHER PARAMETERS
    
    # Frequency and wavelength
    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 = 0.38 * max(wlen_range)
    air_width = r/2 # 0.5 * max(wlen_range)
    
    #%% 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)
    
    source_center = -0.5*cell_width + pml_width
    print("Resto Source Center: {}".format(source_center%(1/resolution)))
    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
    
    if time_factor_cell is not False:
        until_after_sources = time_factor_cell * cell_width
    else:
        if until_after_sources is False:
            raise ValueError("Either time_factor_cell or until_after_sources must be specified")
        time_factor_cell = until_after_sources/cell_width
    # 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 
    
    def get_line(sim, line_center, line_size, component):
        return sim.get_array(
            center=mp.Vector3(*line_center), 
            size=mp.Vector3(*line_size), 
            component=component) # mp.Ez, mp.Hy
    
    def get_plane(sim, plane_center, plane_size, component):
        return sim.get_array(
            center=mp.Vector3(*plane_center), 
            size=mp.Vector3(*plane_size), 
            component=component)
    
    path = os.path.join(home, folder, f"{series}")
    if (not os.path.isdir(path)) and mp.am_master(): 
        vs.new_dir(path)
    file = lambda f : os.path.join(path, f)
    
    #%% INITIALIZE
    
    sim = mp.Simulation(resolution=resolution,
                        cell_size=cell_size,
                        boundary_layers=pml_layers,
                        sources=sources,
                        k_point=mp.Vector3())
                        # symmetries=symmetries)
    
    if meep_flux:
        # 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=-r),
                                            size=mp.Vector3(0,2*r,2*r)))
        box_x2 = sim.add_flux(freq_center, freq_width, nfreq, 
                              mp.FluxRegion(center=mp.Vector3(x=+r),
                                            size=mp.Vector3(0,2*r,2*r)))
        box_y1 = sim.add_flux(freq_center, freq_width, nfreq,
                              mp.FluxRegion(center=mp.Vector3(y=-r),
                                            size=mp.Vector3(2*r,0,2*r)))
        box_y2 = sim.add_flux(freq_center, freq_width, nfreq,
                              mp.FluxRegion(center=mp.Vector3(y=+r),
                                            size=mp.Vector3(2*r,0,2*r)))
        box_z1 = sim.add_flux(freq_center, freq_width, nfreq,
                              mp.FluxRegion(center=mp.Vector3(z=-r),
                                            size=mp.Vector3(2*r,2*r,0)))
        box_z2 = sim.add_flux(freq_center, freq_width, nfreq,
                              mp.FluxRegion(center=mp.Vector3(z=+r),
                                            size=mp.Vector3(2*r,2*r,0)))
    
    temp = time()
    sim.init_sim()
    enlapsed.append( time() - temp )
    
    #%% DEFINE SAVE STEP FUNCTIONS
    
    def slice_generator_params(get_slice, center, size):
        if H_field: 
            datasets = ["Ez", "Hy"]
            get_slices = [lambda sim: get_slice(sim, center, size, mp.Ez),
                          lambda sim: get_slice(sim, center, size, mp.Hy)]
        else: 
            datasets = "Ez"
            get_slices = lambda sim: get_slice(sim, center, size, mp.Ez)
        return datasets, get_slices
    
    f, save_line = vs.save_slice_generator(sim, file("Lines.h5"), 
        *slice_generator_params(get_line, [0, 0, 0], [cell_width, 0, 0]), 
        parallel=True)
    gx1, save_plane_x1 = vs.save_slice_generator(sim, file("Planes_X1.h5"), 
        *slice_generator_params(get_line, [-r, 0, 0], [0, cell_width, cell_width]), 
        parallel=True)
    gx2, save_plane_x2 = vs.save_slice_generator(sim, file("Planes_X2.h5"),
        *slice_generator_params(get_plane, [r, 0, 0], [0, cell_width, cell_width]),
        parallel=True)
    gy1, save_plane_y1 = vs.save_slice_generator(sim, file("Planes_Y1.h5"), 
        *slice_generator_params(get_plane, [0, -r, 0], [cell_width, 0, cell_width]),
        parallel=True)
    gy2, save_plane_y2 = vs.save_slice_generator(sim, file("Planes_Y2.h5"),
        *slice_generator_params(get_plane, [0, r, 0], [cell_width, 0, cell_width]),
        parallel=True)
    gz1, save_plane_z1 = vs.save_slice_generator(sim, file("Planes_Z1.h5"), 
        *slice_generator_params(get_plane, [0, 0, -r], [cell_width, cell_width, 0]),
        parallel=True)
    gz2, save_plane_z2 = vs.save_slice_generator(sim, file("Planes_Z2.h5"),
        *slice_generator_params(get_plane, [0, 0, r], [cell_width, cell_width, 0]),
        parallel=True)
    
    to_do_while_running = [mp.at_every(period_line, save_line),
                           mp.at_every(period_plane, save_plane_x1),
                           mp.at_every(period_plane, save_plane_x2),
                           mp.at_every(period_plane, save_plane_y1),
                           mp.at_every(period_plane, save_plane_y2),
                           mp.at_every(period_plane, save_plane_z1),
                           mp.at_every(period_plane, save_plane_z2)]
       
    #%% RUN!
    
    temp = time()
    sim.run(*to_do_while_running, until_after_sources=until_after_sources)
    enlapsed.append( time() - temp )
    
    # if meep_flux:
    #     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))
    
    # #%% SAVE METADATA
    
    # params = dict(
    #     from_um_factor=from_um_factor,
    #     resolution=resolution,
    #     r=r,
    #     paper=paper,
    #     wlen_range=wlen_range,
    #     nfreq=nfreq,
    #     cutoff=cutoff,
    #     pml_width=pml_width,
    #     air_width=air_width,
    #     source_center=source_center,
    #     enlapsed=enlapsed,
    #     period_line=period_line,
    #     period_plane=period_plane,
    #     series=series,
    #     folder=folder,
    #     home=home,
    #     until_after_sources=until_after_sources,
    #     time_factor_cell=time_factor_cell,
    #     )
    
    # planes_series = ["X1", "X2", "Y1", "Y2", "Z1", "Z2"]
    # if H_field:
    #     fields_series = ["Ez", "Hy"]
    # else:
    #     fields_series = "Ez"
    
    # f = h5.File(file("Lines.h5"), "r+")
    # for fs in fields_series:
    #     for a in params: f[fs].attrs[a] = params[a]
    f.close()
    # del f
    
    gx1.close()
    gx2.close()
    gy1.close()
    gy2.close()
    gz1.close()
    gz2.close()
def main(series, folder, resolution, from_um_factor, d, h, paper, wlen_range,
         nfreq):

    #%% PARAMETERS

    ### MEAN PARAMETERS

    # Units: 10 nm as length unit
    from_um_factor = 10e-3  # Conversion of 1 μm to my length unit (=10nm/1μm)

    # Au sphere
    medium = import_medium("Au", from_um_factor,
                           paper=paper)  # Medium of sphere: gold (Au)
    d = d / (from_um_factor * 1e3)  # Diameter is now in Meep units
    h = h / (from_um_factor * 1e3)  # Height is now in Meep units

    # Frequency and wavelength
    wlen_range = wlen_range / (from_um_factor * 1e3
                               )  # Wavelength range now in Meep units
    nfreq = 100  # Number of frequencies to discretize range
    cutoff = 3.2

    # Computation time
    enlapsed = []
    time_factor_cell = 1.2
    until_after_sources = False
    second_time_factor = 10

    # Saving directories
    home = vs.get_home()

    ### OTHER PARAMETERS

    # Units
    # uman = MeepUnitsManager(from_um_factor=from_um_factor)

    # Frequency and wavelength
    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 = 0.38 * max(wlen_range)
    air_width = max(d / 2, h / 2) / 2  # 0.5 * max(wlen_range)

    #%% 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_z = 2 * (pml_width + air_width + h / 2
                        )  # Parallel to polarization.
    cell_width_z = cell_width_z - cell_width_z % (1 / resolution)

    cell_width_r = 2 * (pml_width + air_width + d / 2
                        )  # Parallel to incidence.
    cell_width_r = cell_width_r - cell_width_r % (1 / resolution)

    cell_size = mp.Vector3(cell_width_r, cell_width_r, cell_width_z)

    source_center = -0.5 * cell_width_r + pml_width
    # print("Resto Source Center: {}".format(source_center%(1/resolution)))
    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_r, cell_width_z),
                  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

    if time_factor_cell is not False:
        until_after_sources = time_factor_cell * cell_width_r
    else:
        if until_after_sources is False:
            raise ValueError(
                "Either time_factor_cell or until_after_sources must be specified"
            )
        time_factor_cell = until_after_sources / cell_width_r
    # 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.Ellipsoid(size=mp.Vector3(d, d, h),
                     material=medium,
                     center=mp.Vector3())
    ]
    # Au ellipsoid with frequency-dependant characteristics imported from Meep.

    path = os.path.join(home, folder, f"{series}")
    if not os.path.isdir(path) and mp.am_master():
        vs.new_dir(path)
    file = lambda f: os.path.join(path, f)

    #%% FIRST RUN: SET UP

    sim = mp.Simulation(resolution=resolution,
                        cell_size=cell_size,
                        boundary_layers=pml_layers,
                        sources=sources,
                        k_point=mp.Vector3())  #,
    # symmetries=symmetries)
    # >> k_point zero specifies boundary conditions needed
    # for the source to be infinitely extended

    # 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=-d / 2), size=mp.Vector3(0, d, h)))
    box_x2 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(x=+d / 2), size=mp.Vector3(0, d, h)))
    box_y1 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(y=-d / 2), size=mp.Vector3(d, 0, h)))
    box_y2 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(y=+d / 2), size=mp.Vector3(d, 0, h)))
    box_z1 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(z=-h / 2), size=mp.Vector3(d, d, 0)))
    box_z2 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(z=+h / 2), size=mp.Vector3(d, d, 0)))
    # Funny you can encase the ellipsoid (diameter d and height h) so closely
    # (dxdxh-sided box)

    #%% FIRST RUN: INITIALIZE

    temp = time()
    sim.init_sim()
    enlapsed.append(time() - temp)
    """
    112x112x112 with resolution 4
    (48 cells inside diameter)
    ==> 30 s to build
    
    112x112x112 with resolution 2
    (24 cells inside diameter)
    ==> 4.26 s to build
    
    116x116x116 with resolution 2
    (24 cells inside diameter)
    ==> 5.63 s
    
    98 x 98 x 98 with resolution 3
    (36 cells inside diameter)
    ==> 9.57 s
    
    172x172x172 with resolution 2
    (24 cells inside diameter)
    ==> 17.47 s
    
    67 x 67 x 67 with resolution 4
    (48 cells inside diameter)
    ==> 7.06 s
    
    67,375 x 67,375 x 67,375 with resolution 8
    (100 cells inside diameter)
    ==> 56.14 s
    """

    #%% FIRST RUN: SIMULATION NEEDED TO NORMALIZE

    temp = time()
    sim.run(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)
    """
    112x112x112 with resolution 2
    (24 cells inside diameter)
    ==> 135.95 s to complete 1st run
    
    116x116x116 with resolution 2
    (24 cells inside diameter)
    ==> 208 s to complete 1st run
    
    67 x 67 x 67 with resolution 4
    (48 cells inside diameter)
    ==> 2000 s = 33 min to complete 1st run
    """

    freqs = np.asarray(mp.get_flux_freqs(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)

    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))

    # field = sim.get_array(center=mp.Vector3(),
    #                       size=(cell_width, cell_width, cell_width),
    #                       component=mp.Ez)

    sim.reset_meep()

    #%% SAVE MID DATA

    params = dict(
        from_um_factor=from_um_factor,
        resolution=resolution,
        d=d,
        h=h,
        paper=paper,
        wlen_range=wlen_range,
        nfreq=nfreq,
        cutoff=cutoff,
        pml_width=pml_width,
        air_width=air_width,
        source_center=source_center,
        enlapsed=enlapsed,
        series=series,
        folder=folder,
        pc=pc,
        until_after_sources=until_after_sources,
        time_factor_cell=time_factor_cell,
        second_time_factor=second_time_factor,
    )

    # f = h5.File(file("MidField.h5"), "w")
    # f.create_dataset("Ez", data=field)
    # for a in params: f["Ez"].attrs[a] = params[a]
    # f.close()
    # del f

    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 mp.am_master():
        vs.savetxt(file("MidFlux.txt"),
                   data_mid,
                   header=header_mid,
                   footer=params)

    #%% PLOT FLUX FOURIER MID DATA

    if mp.my_rank() == 1:
        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, hm in zip(np.reshape(ax, 6), header_mid[1:]):
            a.set_ylabel(hm)

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

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

    #%% PLOT FLUX WALLS FIELD

    # if mp.am_master():
    # index_to_space = lambda i : i/resolution - cell_width/2
    # space_to_index = lambda x : round(resolution * (x + cell_width/2))

    # field_walls = [field[space_to_index(-r),:,:],
    #                 field[space_to_index(r),:,:],
    #                 field[:,space_to_index(-r),:],
    #                 field[:,space_to_index(r),:],
    #                 field[:,:,space_to_index(-r)],
    #                 field[:,:,space_to_index(r)]]

    # zlims = (np.min([np.min(f) for f in field_walls]),
    #           np.max([np.max(f) for f in field_walls]))

    # fig, ax = plt.subplots(3, 2)
    # fig.subplots_adjust(hspace=0.25)
    # for a, hm in zip(np.reshape(ax, 6), header_mid[1:]):
    #     a.set_title(hm.split(" ")[1].split("0")[0])

    # for f, a in zip(field_walls, np.reshape(ax, 6)):
    #     a.imshow(f.T, interpolation='spline36', cmap='RdBu',
    #               vmin=zlims[0], vmax=zlims[1])
    #     a.axis("off")

    # plt.savefig(file("MidField.png"))

    #%% SECOND RUN: SETUP

    sim = mp.Simulation(
        resolution=resolution,
        cell_size=cell_size,
        boundary_layers=pml_layers,
        sources=sources,
        k_point=mp.Vector3(),
        # symmetries=symmetries,
        geometry=geometry)

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

    #%% SECOND RUN: INITIALIZE

    temp = time()
    sim.init_sim()
    enlapsed.append(time() - temp)
    """
    112x112x112 with resolution 2
    (24 cells in diameter)
    ==> 5.16 s to build with sphere
    
    116x116x116 with resolution 2
    (24 cells inside diameter)
    ==> 9.71 s to build with sphere
    
    67 x 67 x 67 with resolution 4
    (48 cells inside diameter)
    ==> 14.47 s to build with sphere
    """

    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)
    enlapsed.append(time() - temp)
    del box_x1_data, box_x2_data, box_y1_data, box_y2_data
    del box_z1_data, box_z2_data
    """
    112x112x112 with resolution 2
    (24 cells in diameter)
    ==> 0.016 s to add flux
    
    116x116x116 with resolution 2
    (24 cells inside diameter)
    ==> 0.021 s to add flux
    
    67 x 67 x 67 with resolution 4
    (48 cells inside diameter)
    ==> 0.043 s to add flux
    """

    #%% SECOND RUN: SIMULATION :D

    temp = time()
    sim.run(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))

    #%% 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 / (d**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 * d**2)
    # Scattering efficiency =
    # = scattering cross section / cross sectional area of the sphere
    # WATCH IT! Is this the correct cross section?

    freqs = np.array(freqs)

    #%% SAVE FINAL DATA

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

    header = ["Longitud de onda [nm]", "Sección eficaz efectiva (Meep) [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 mp.am_master():
        vs.savetxt(file("Results.txt"), data, header=header, footer=params)
        vs.savetxt(file("BaseResults.txt"),
                   data_base,
                   header=header_base,
                   footer=params)

    #%% PLOT SCATTERING

    if mp.my_rank() == 1:
        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(f'Scattering of Au Ellipsoid ({ 1e3*from_um_factor*d }x' +
                  f'{ 1e3*from_um_factor*d }x{ 1e3*from_um_factor*h } nm)')
        plt.tight_layout()
        plt.savefig(file("ScattSpectra.png"))

    #%% PLOT ABSORPTION

    if mp.am_master():
        plt.figure()
        plt.plot(1e3 * from_um_factor / freqs,
                 1 - scatt_eff_meep,
                 'bo-',
                 label='Meep')
        plt.xlabel('Wavelength [nm]')
        plt.ylabel('Absorption efficiency [σ/πr$^{2}$]')
        plt.legend()
        plt.title(f'Absorption of Au Ellipsoid ({ 1e3*from_um_factor*d }x' +
                  f'{ 1e3*from_um_factor*d }x{ 1e3*from_um_factor*h } nm)')
        plt.tight_layout()
        plt.savefig(file("AbsSpectra.png"))