Example #1
0
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],
Example #3
0
    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)
Example #4
0
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
Example #5
0
            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')
Example #6
0
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]