def launch_dashboard(name=None): """ Attempt to launch GUI dashboard. Parameters ---------- name: str Optional label to appear in the dashboard GUI window title. """ # skip if dashboard already running or disabled by configuration options global dashboard_socket, dashboard_process, dbserver_process host, port, size = [ adj_opt('dashboard_' + s) for s in ['host', 'port', 'size'] ] if dashboard_socket is not None or size == 0.0: return # if port==0, try to launch GUI dashboard as a multiprocessing.Process() if port == 0: try: dashboard_socket, sock2 = socket.socketpair() dashboard_process = multiprocessing.Process(target=run_dashboard, args=(sock2, )) dashboard_process.start() title = 'meep_adjoint dashboard' + ( ' for {}'.format(name)) if name else '' cpus = mp.count_processors() update_dashboard( ['clear', 'title ' + title, 'cpus {}'.format(cpus)]) except: dashboard_socket, dashboard_process, dbserver_process = None, None, None get_exception_info(msg='failed to fork dashboard process', warning=True) return # if port!=0, try connecting to a TCP server at that port on the host if host == 'localhost': fork_dashboard_server() try: dashboard_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) dashboard_socket.settimeout(nw_timeout()) log('connecting to dashboard server: {}:{}...'.format(host, port)) dashboard_socket.connect((host, port)) title = 'meep_adjoint dashboard' + ( ' for {}'.format(name)) if name else '' cpus = mp.count_processors() update_dashboard(['clear', 'title ' + title, 'cpus {}'.format(cpus)]) except: dashboard_socket, dashboard_process, dbserver_process = None, None, None get_exception_info(msg='failed to connect to dashboard server', warning=True)
def test_chunk_layout_binary_partition(self): chunk_layout = mp.BinaryPartition(data=[( mp.X, -2.0), 0, [(mp.Y, 1.5), [(mp.X, 3.0), 1, [(mp.Y, -0.5), 4, 3]], 2]]) cell_size = mp.Vector3(10.0, 5.0, 0) sim = mp.Simulation(cell_size=cell_size, resolution=10, chunk_layout=chunk_layout) sim.init_sim() owners = sim.structure.get_chunk_owners() areas = [ v.surroundings().full_volume() for v in sim.structure.get_chunk_volumes() ] process_ids, chunk_areas = traverse_tree(chunk_layout, -0.5 * cell_size, 0.5 * cell_size) self.assertListEqual([int(f) for f in owners], [f % mp.count_processors() for f in process_ids]) self.assertListEqual(areas, chunk_areas)
def test_timing_data(self): resolution = 20 cell_size = mp.Vector3(10, 10) pml = [mp.PML(1)] center = mp.Vector3(2, -1) result = [] fcen = 0.15 df = 0.1 sources = [ mp.Source(src=mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3()) ] geometry = [ mp.Block(center=mp.Vector3(), size=mp.Vector3(mp.inf, 3, mp.inf), material=mp.Medium(epsilon=12)) ] sim = mp.Simulation(resolution=resolution, cell_size=cell_size, boundary_layers=pml, sources=sources, geometry=geometry, geometry_center=center) sim.run(until=50) timing_data = sim.get_timing_data() # Non-exhaustive collection of steps where some time should be spent: EXPECTED_NONZERO_TIMESINKS = (mp.Stepping, mp.Boundaries, mp.FieldUpdateB, mp.FieldUpdateH, mp.FieldUpdateD, mp.FieldUpdateE) # Due to the problem setup, no time should be spent on these steps: EXPECTED_ZERO_TIMESINKS = (mp.MPBTime, mp.GetFarfieldsTime) for sink in itertools.chain(EXPECTED_NONZERO_TIMESINKS, EXPECTED_ZERO_TIMESINKS): self.assertIn(sink, timing_data.keys()) self.assertEqual(len(timing_data[sink]), mp.count_processors()) np.testing.assert_array_equal(sim.time_spent_on(sink), timing_data[sink]) for sink in EXPECTED_NONZERO_TIMESINKS: for t in timing_data[sink]: self.assertGreater(t, 0) for sink in EXPECTED_ZERO_TIMESINKS: for t in timing_data[sink]: self.assertEqual(t, 0) self.assertGreaterEqual( sum(timing_data[mp.Stepping]), sum(timing_data[mp.FieldUpdateB]) + sum(timing_data[mp.FieldUpdateH]) + sum(timing_data[mp.FieldUpdateD]) + sum(timing_data[mp.FieldUpdateE]) + sum(timing_data[mp.FourierTransforming]))
def visualize_chunks(sim): if sim.structure is None: sim.init_sim() import matplotlib.pyplot as plt import matplotlib.cm import matplotlib.colors from mpl_toolkits.mplot3d import Axes3D from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection vols = sim.structure.get_chunk_volumes() owners = sim.structure.get_chunk_owners() def plot_box(box, proc, fig, ax): low = mp.Vector3(box.low.x, box.low.y, box.low.z) high = mp.Vector3(box.high.x, box.high.y, box.high.z) points = [low, high] x_len = mp.Vector3(high.x) - mp.Vector3(low.x) y_len = mp.Vector3(y=high.y) - mp.Vector3(y=low.y) xy_len = mp.Vector3(high.x, high.y) - mp.Vector3(low.x, low.y) points += [low + x_len] points += [low + y_len] points += [low + xy_len] points += [high - x_len] points += [high - y_len] points += [high - xy_len] points = np.array([np.array(v) for v in points]) edges = [[points[0], points[2], points[4], points[3]], [points[1], points[5], points[7], points[6]], [points[0], points[3], points[5], points[7]], [points[1], points[4], points[2], points[6]], [points[3], points[4], points[1], points[5]], [points[0], points[7], points[6], points[2]]] faces = Poly3DCollection(edges, linewidths=1, edgecolors='k') color_with_alpha = matplotlib.colors.to_rgba(chunk_colors[proc], alpha=0.2) faces.set_facecolor(color_with_alpha) ax.add_collection3d(faces) # Plot the points themselves to force the scaling of the axes ax.scatter(points[:, 0], points[:, 1], points[:, 2], s=0) if mp.am_master(): fig = plt.figure() ax = fig.add_subplot(111, projection='3d') chunk_colors = matplotlib.cm.rainbow( np.linspace(0, 1, mp.count_processors())) for i, v in enumerate(vols): plot_box(mp.gv2box(v.surroundings()), owners[i], fig, ax) ax.set_aspect('auto') plt.show()
def test_meep_default_chunk_layout(self): cell_size = mp.Vector3(10.0, 5.0, 0) sim = mp.Simulation(cell_size=cell_size, resolution=10) sim.init_sim() owners = sim.structure.get_chunk_owners() areas = [ v.surroundings().full_volume() for v in sim.structure.get_chunk_volumes() ] chunk_layout = sim.chunk_layout process_ids, chunk_areas = traverse_tree(chunk_layout, -0.5 * cell_size, 0.5 * cell_size) self.assertListEqual([int(f) for f in owners], [f % mp.count_processors() for f in process_ids]) self.assertListEqual(areas, chunk_areas)
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"))
from __future__ import division import unittest import meep as mp @unittest.skipIf(mp.count_processors() < 2, "MPI specific test") class TestDivideParallelProcesses(unittest.TestCase): def test_divide_parallel_processes(self): resolution = 20 sxy = 4 dpml = 1 cell = mp.Vector3(sxy+2*dpml,sxy+2*dpml) pml_layers = [mp.PML(dpml)] n = mp.divide_parallel_processes(2) fcen = 1.0/(n+1) sources = [mp.Source(src=mp.GaussianSource(fcen,fwidth=0.2*fcen), center=mp.Vector3(), component=mp.Ez)] symmetries = [mp.Mirror(mp.X), mp.Mirror(mp.Y)] self.sim = mp.Simulation(cell_size=cell, resolution=resolution, sources=sources, symmetries=symmetries,
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"))