wr13 = layer_mediated_coupling_block(vacuum_wavelength, sphere1, sphere3, lay_sys) w13 = direct_coupling_block(vacuum_wavelength, sphere1, sphere3, lay_sys) # initialize initial field object init_fld = init.PlaneWave(vacuum_wavelength=vacuum_wavelength, polar_angle=polar_angle,azimuthal_angle=azimuthal_angle, polarization=polarization, amplitude=amplitude) # initialize simulation object simulation_direct = simul.Simulation(layer_system=lay_sys, particle_list=particle_list, initial_field=init_fld, solver_type='LU', store_coupling_matrix=True, log_to_terminal=(not sys.argv[0].endswith('nose2'))) # suppress output if called by nose simulation_direct.run() coefficients_direct = particle_list[0].scattered_field.coefficients cu.enable_gpu() simulation_lookup_linear_gpu = simul.Simulation(layer_system=lay_sys, particle_list=particle_list, initial_field=init_fld, solver_type='gmres', store_coupling_matrix=False, coupling_matrix_lookup_resolution=lookup_resol, coupling_matrix_interpolator_kind='linear', log_to_terminal=(not sys.argv[0].endswith('nose2'))) # suppress output if called by nose simulation_lookup_linear_gpu.run() coefficients_lookup_linear_gpu = particle_list[0].scattered_field.coefficients simulation_lookup_cubic_gpu = simul.Simulation(layer_system=lay_sys, particle_list=particle_list, initial_field=init_fld, solver_type='gmres', store_coupling_matrix=False, coupling_matrix_lookup_resolution=lookup_resol, coupling_matrix_interpolator_kind='cubic', log_to_terminal=(not sys.argv[0].endswith('nose2'))) # suppress output if called by nose simulation_lookup_cubic_gpu.run() coefficients_lookup_cubic_gpu = particle_list[0].scattered_field.coefficients
# The script runs with Smuthi version 0.8.6 # #*****************************************************************************# import smuthi.initial_field as init import smuthi.particles as part import smuthi.simulation as simul import smuthi.layers as lay import smuthi.postprocessing.scattered_field as sf import smuthi.utility.cuda as cu import numpy as np import scipy.interpolate as interp import matplotlib.pyplot as plt import os # Enable GPU usage. Uncomment if you receive GPU related errors cu.enable_gpu() vacuum_wavelength = 550 # Set the multipole truncation order # We invite the user to play with this parameter to see how it affects # accuracy and runtime. lmax = 5 # particles sphere = part.Sphere(position=[300, 300, 250], refractive_index=3, radius=120, l_max=lmax) cylinder = part.FiniteCylinder(position=[300, -300, 250],
def testElectricField(self): try: import pycuda.autoinit except ImportError: self.skipTest('PyCUDA is not available') ld = 550 rD = [100, -100, 100] D = [1e7, 2e7, 3e7] #waypoints = [0, 0.8, 0.8 - 0.1j, 2.1 - 0.1j, 2.1, 4] #neff_discr = 2e-2 #coord.set_default_k_parallel(vacuum_wavelength=ld, neff_waypoints=waypoints, neff_resolution=neff_discr) # initialize particle object sphere1 = part.Sphere(position=[200, 200, 300], refractive_index=2.4 + 0.0j, radius=110, l_max=3, m_max=3) sphere2 = part.Sphere(position=[-200, -200, 300], refractive_index=2.4 + 0.0j, radius=120, l_max=3, m_max=3) sphere3 = part.Sphere(position=[-200, 200, 300], refractive_index=2.5 + 0.0j, radius=90, l_max=3, m_max=3) part_list = [sphere1, sphere2, sphere3] # initialize layer system object lay_sys = lay.LayerSystem([0, 400, 0], [1 + 6j, 2.3, 1.5]) # initialize dipole object dipole = init.DipoleSource(vacuum_wavelength=ld, dipole_moment=D, position=rD) # run simulation simulation = simul.Simulation( layer_system=lay_sys, particle_list=part_list, initial_field=dipole, log_to_terminal='nose2' not in sys.modules.keys()) # suppress output if called by nose simulation.run() xarr = np.array([-300, 400, -100, 200]) yarr = np.array([200, -100, 400, 300]) zarr = np.array([-50, 200, 600, 700]) scat_fld_exp = sf.scattered_field_piecewise_expansion( ld, part_list, lay_sys) e_x_scat_cpu, e_y_scat_cpu, e_z_scat_cpu = scat_fld_exp.electric_field( xarr, yarr, zarr) e_x_init_cpu, e_y_init_cpu, e_z_init_cpu = simulation.initial_field.electric_field( xarr, yarr, zarr, lay_sys) cu.enable_gpu() scat_fld_exp = sf.scattered_field_piecewise_expansion( ld, part_list, lay_sys) e_x_scat_gpu, e_y_scat_gpu, e_z_scat_gpu = scat_fld_exp.electric_field( xarr, yarr, zarr) e_x_init_gpu, e_y_init_gpu, e_z_init_gpu = simulation.initial_field.electric_field( xarr, yarr, zarr, lay_sys) np.testing.assert_allclose(np.linalg.norm(e_x_scat_cpu), np.linalg.norm(e_x_scat_gpu), rtol=1e-5) np.testing.assert_allclose(np.linalg.norm(e_y_scat_cpu), np.linalg.norm(e_y_scat_gpu), rtol=1e-5) np.testing.assert_allclose(np.linalg.norm(e_z_scat_cpu), np.linalg.norm(e_z_scat_gpu), rtol=1e-5) np.testing.assert_allclose(np.linalg.norm(e_x_init_cpu), np.linalg.norm(e_x_init_gpu), rtol=1e-5) np.testing.assert_allclose(np.linalg.norm(e_y_init_cpu), np.linalg.norm(e_y_init_gpu), rtol=1e-5) np.testing.assert_allclose(np.linalg.norm(e_z_init_cpu), np.linalg.norm(e_z_init_gpu), rtol=1e-5)
def read_input_yaml(filename): """Parse input file Args: filename (str): relative path and filename of input file Returns: smuthi.simulation.Simulation object containing the params of the input file """ print('Reading ' + os.path.abspath(filename)) with open(filename, 'r') as input_file: input_data = yaml.load(input_file.read()) cu.enable_gpu(input_data.get('enable GPU', False)) # wavelength wl = float(input_data['vacuum wavelength']) # set default coordinate arrays angle_unit = input_data.get('angle unit') if angle_unit == 'degree': angle_factor = np.pi / 180 else: angle_factor = 1 angle_resolution = input_data.get('angular resolution', np.pi / 180 / angle_factor) * angle_factor smuthi.fields.default_azimuthal_angles = np.arange(0, 2 * np.pi + angle_resolution / 2, angle_resolution) smuthi.fields.default_polar_angles = np.arange(0, np.pi + angle_resolution / 2, angle_resolution) neff_resolution = float(input_data.get('n_effective resolution', 1e-2)) neff_max = input_data.get('max n_effective') if neff_max is None: ref_ind = [float(n) for n in input_data['layer system']['refractive indices']] neff_max = max(np.array(ref_ind).real) + 1 neff_imag = float(input_data.get('n_effective imaginary deflection', 5e-2)) smuthi.fields.default_Sommerfeld_k_parallel_array = smuthi.fields.reasonable_Sommerfeld_kpar_contour( vacuum_wavelength=wl, neff_resolution=neff_resolution, neff_max=neff_max, neff_imag=neff_imag) # initialize simulation lookup_resolution = input_data.get('coupling matrix lookup resolution', None) if lookup_resolution is not None and lookup_resolution <= 0: lookup_resolution = None simulation = smuthi.simulation.Simulation(solver_type=input_data.get('solver type', 'LU'), solver_tolerance=float(input_data.get('solver tolerance', 1e-4)), store_coupling_matrix=input_data.get('store coupling matrix', True), coupling_matrix_lookup_resolution=lookup_resolution, coupling_matrix_interpolator_kind=input_data.get('interpolation order', 'linear'), input_file=filename, length_unit=input_data.get('length unit'), output_dir=input_data.get('output folder'), save_after_run=input_data.get('save simulation')) # particle collection particle_list = [] particle_input = input_data['scattering particles'] if isinstance(particle_input, str): particle_type = 'sphere' with open(particle_input, 'r') as particle_specs_file: for line in particle_specs_file: if len(line.split()) > 0: if line.split()[-1] == 'spheres': particle_type = 'sphere' elif line.split()[-1] == 'spheroids': particle_type = 'spheroid' elif line.split()[-1] == 'cylinders': particle_type = 'finite cylinder' if not line.split()[0] == '#': numeric_line_data = [float(x) for x in line.split()] pos = numeric_line_data[:3] if particle_type == 'sphere': r = numeric_line_data[3] n = numeric_line_data[4] + 1j * numeric_line_data[5] l_max = int(numeric_line_data[6]) m_max = int(numeric_line_data[7]) particle_list.append(part.Sphere(position=pos, refractive_index=n, radius=r, l_max=l_max, m_max=m_max)) if particle_type == 'spheroid': c = numeric_line_data[3] a = numeric_line_data[4] beta = numeric_line_data[5] alpha = numeric_line_data[6] n = numeric_line_data[7] + 1j * numeric_line_data[8] l_max = int(numeric_line_data[9]) m_max = int(numeric_line_data[10]) particle_list.append(part.Spheroid(position=pos, polar_angle=beta, azimuthal_angle=beta, refractive_index=n, semi_axis_c=c, semi_axis_a=a, l_max=l_max, m_max=m_max)) if particle_type == 'finite cylinder': r = numeric_line_data[3] h = numeric_line_data[4] beta = numeric_line_data[5] alpha = numeric_line_data[6] n = numeric_line_data[7] + 1j * numeric_line_data[8] l_max = int(numeric_line_data[9]) m_max = int(numeric_line_data[10]) particle_list.append(part.FiniteCylinder(position=pos, polar_angle=beta, azimuthal_angle=beta, refractive_index=n, cylinder_radius=r, cylinder_height=h, l_max=l_max, m_max=m_max)) else: for prtcl in input_data['scattering particles']: n = (float(prtcl['refractive index']) + 1j * float(prtcl['extinction coefficient'])) pos = [float(prtcl['position'][0]), float(prtcl['position'][1]), float(prtcl['position'][2])] l_max = int(prtcl['l_max']) m_max = int(prtcl.get('m_max', l_max)) if prtcl['shape'] == 'sphere': r = float(prtcl['radius']) particle_list.append(part.Sphere(position=pos, refractive_index=n, radius=r, l_max=l_max, m_max=m_max)) else: nfmds_settings = prtcl.get('NFM-DS settings', {}) use_ds = nfmds_settings.get('use discrete sources', True) nint = nfmds_settings.get('nint', 200) nrank = nfmds_settings.get('nrank', l_max + 2) t_matrix_method = {'use discrete sources': use_ds, 'nint': nint, 'nrank': nrank} polar_angle=prtcl.get('polar angle', 0) azimuthal_angle=prtcl.get('azimuthal angle', 0) if prtcl['shape'] == 'spheroid': c = float(prtcl['semi axis c']) a = float(prtcl['semi axis a']) particle_list.append(part.Spheroid(position=pos, polar_angle=polar_angle, azimuthal_angle=azimuthal_angle, refractive_index=n, semi_axis_a=a, semi_axis_c=c, l_max=l_max, m_max=m_max, t_matrix_method=t_matrix_method)) elif prtcl['shape'] == 'finite cylinder': h = float(prtcl['cylinder height']) r = float(prtcl['cylinder radius']) particle_list.append(part.FiniteCylinder(position=pos, polar_angle=polar_angle, azimuthal_angle=azimuthal_angle, refractive_index=n, cylinder_radius=r, cylinder_height=h, l_max=l_max, m_max=m_max, t_matrix_method=t_matrix_method)) else: raise ValueError('Currently, only spheres, spheroids and finite cylinders are implemented') simulation.particle_list = particle_list # layer system thick = [float(d) for d in input_data['layer system']['thicknesses']] ref_ind = [float(n) for n in input_data['layer system']['refractive indices']] ext_coeff = [float(n) for n in input_data['layer system']['extinction coefficients']] ref_ind = np.array(ref_ind) + 1j * np.array(ext_coeff) ref_ind = ref_ind.tolist() simulation.layer_system = lay.LayerSystem(thicknesses=thick, refractive_indices=ref_ind) # initial field infld = input_data['initial field'] if infld['type'] == 'plane wave': a = float(infld.get('amplitude', 1)) pol_ang = angle_factor * float(infld['polar angle']) az_ang = angle_factor * float(infld['azimuthal angle']) if infld['polarization'] == 'TE': pol = 0 elif infld['polarization'] == 'TM': pol = 1 else: raise ValueError('polarization must be "TE" or "TM"') ref = [float(infld.get('reference point', [0,0,0])[0]), float(infld.get('reference point', [0,0,0])[1]), float(infld.get('reference point', [0,0,0])[2])] initial_field = init.PlaneWave(vacuum_wavelength=wl, polar_angle=pol_ang, azimuthal_angle=az_ang, polarization=pol, amplitude=a, reference_point=ref) elif infld['type'] == 'Gaussian beam': a = float(infld['amplitude']) pol_ang = angle_factor * float(infld['polar angle']) az_ang = angle_factor * float(infld['azimuthal angle']) if infld['polarization'] == 'TE': pol = 0 elif infld['polarization'] == 'TM': pol = 1 else: raise ValueError('polarization must be "TE" or "TM"') ref = [float(infld['focus point'][0]), float(infld['focus point'][1]), float(infld['focus point'][2])] ang_res = infld.get('angular resolution', np.pi / 180 / angle_factor) * angle_factor bet_arr = np.arange(0, np.pi/2, ang_res) if pol_ang <= np.pi: kparr = np.sin(bet_arr) * simulation.layer_system.wavenumber(layer_number=0, vacuum_wavelength=wl) else: kparr = np.sin(bet_arr) * simulation.layer_system.wavenumber(layer_number=-1, vacuum_wavelength=wl) wst = infld['beam waist'] aarr = np.concatenate([np.arange(0, 2 * np.pi, ang_res), [2 * np.pi]]) initial_field = init.GaussianBeam(vacuum_wavelength=wl, polar_angle=pol_ang, azimuthal_angle=az_ang, polarization=pol, beam_waist=wst, k_parallel_array=kparr, azimuthal_angles_array=aarr, amplitude=a, reference_point=ref) elif infld['type'] == 'dipole source': pos = [float(infld['position'][i]) for i in range(3)] mom = [float(infld['dipole moment'][i]) for i in range(3)] initial_field = init.DipoleSource(vacuum_wavelength=wl, dipole_moment=mom, position=pos) elif infld['type'] == 'dipole collection': initial_field = init.DipoleCollection(vacuum_wavelength=wl) dipoles = infld['dipoles'] for dipole in dipoles: pos = [float(dipole['position'][i]) for i in range(3)] mom = [float(dipole['dipole moment'][i]) for i in range(3)] dip = init.DipoleSource(vacuum_wavelength=wl, dipole_moment=mom, position=pos) initial_field.append(dip) simulation.initial_field = initial_field # post processing simulation.post_processing = pp.PostProcessing() if input_data.get('post processing'): for item in input_data['post processing']: if item['task'] == 'evaluate far field': simulation.post_processing.tasks.append(item) elif item['task'] == 'evaluate near field': simulation.post_processing.tasks.append(item) return simulation
flip_z = get_center[2] - sphere_z_global_offset_nm flip_z = device_height_nm - flip_z - (layer_spacing_nm - layer_thickness_nm) get_center[2] = flip_z smuthi_spheres.append( smuthi.particles.Sphere( position=list(get_center), refractive_index=random_indices[sphere_idx], radius=(random_radii[sphere_idx] / nm), l_max=lmax)) mie_start = time.time() cu.enable_gpu(use_gpu) if use_gpu and not cu.use_gpu: print("Failed to load pycuda, skipping simulation") sys.exit(1) print("number of particles = " + str(len(smuthi_spheres))) simulation = smuthi.simulation.Simulation( layer_system=two_layers, particle_list=smuthi_spheres, initial_field=smuthi_plane_wave, solver_type='gmres', store_coupling_matrix=False, coupling_matrix_interpolator_kind='linear', coupling_matrix_lookup_resolution=50, #5, solver_tolerance=1e-4, length_unit='nm')
def simulate_N_spheres(number_of_spheres=100, direct_inversion=True, use_gpu=False, solver_tolerance=5e-4, lookup_resolution=5, interpolation_order='linear', make_illustrations=False): # Initialize the layer system: substrate (glass) and ambient (air) two_layers = smuthi.layers.LayerSystem(thicknesses=[0, 0], refractive_indices=[1.52, 1]) # Initial field plane_wave = smuthi.initial_field.PlaneWave( vacuum_wavelength=550, polar_angle=np.pi, # from top azimuthal_angle=0, polarization=0) # 0=TE 1=TM spheres_list = vogel_spiral(number_of_spheres) # Initialize and run simulation cu.enable_gpu(use_gpu) if use_gpu and not cu.use_gpu: print("Failed to load pycuda, skipping simulation") return [0, 0, 0] if direct_inversion: simulation = smuthi.simulation.Simulation(layer_system=two_layers, particle_list=spheres_list, initial_field=plane_wave) else: simulation = smuthi.simulation.Simulation( layer_system=two_layers, particle_list=spheres_list, initial_field=plane_wave, solver_type='gmres', solver_tolerance=solver_tolerance, store_coupling_matrix=False, coupling_matrix_lookup_resolution=lookup_resolution, coupling_matrix_interpolator_kind=interpolation_order) preparation_time, solution_time, _ = simulation.run() # compute cross section ecs = smuthi.postprocessing.far_field.extinction_cross_section( initial_field=plane_wave, particle_list=spheres_list, layer_system=two_layers) if make_illustrations: azimuthal_angles = np.arange(0, 361, 0.5, dtype=float) * np.pi / 180 polar_angles = np.arange(0, 181, 0.25, dtype=float) * np.pi / 180 dscs = smuthi.postprocessing.far_field.scattering_cross_section( initial_field=plane_wave, particle_list=spheres_list, layer_system=two_layers, polar_angles=polar_angles, azimuthal_angles=azimuthal_angles, ) # display differential scattering cross section smuthi.postprocessing.graphical_output.show_far_field( far_field=dscs, save_plots=True, show_plots=True, save_data=False, tag='dscs_%ispheres' % number_of_spheres, log_scale=True) xlim = max([abs(sphere.position[0]) for sphere in spheres_list]) * 1.1 plt.figure() plt.xlim([-xlim, xlim]) plt.xlabel('x (nm)') plt.ylabel('y (nm)') plt.ylim([-xlim, xlim]) plt.gca().set_aspect("equal") plt.title("Vogel spiral with %i spheres" % number_of_spheres) smuthi.postprocessing.graphical_output.plot_particles( -1e5, 1e5, -1e5, 1e5, 0, 0, spheres_list, 1000, False) plt.savefig("vogel_spiral_%i.png" % number_of_spheres) return [(ecs["top"] + ecs["bottom"]).real, preparation_time, solution_time]