Пример #1
0
def test_w_against_wr():
    flds.default_Sommerfeld_k_parallel_array = flds.reasonable_Sommerfeld_kpar_contour(
        vacuum_wavelength=wl,
        neff_waypoints=[0, 0.8, 0.8 - 0.1j, 2.1 - 0.1j, 2.1, 7],
        neff_resolution=2e-3)

    laysys_air_1 = lay.LayerSystem(thicknesses=[0, 0], refractive_indices=[1, 1])
    laysys_air_2 = lay.LayerSystem(thicknesses=[0, 250, 0], refractive_indices=[1, 1, 1])

    part1 = part.Sphere(position=[100, -100, 200], refractive_index=1.7, radius=100, l_max=2, m_max=2)
    part2 = part.Sphere(position=[-100, 200, 400], refractive_index=1.7, radius=100, l_max=2, m_max=2)

    w_air_1 = direct_coupling_block(wl, part1, part2, laysys_air_1)
    wr_air_2 = layer_mediated_coupling_block(wl, part1, part2, laysys_air_2)
    
    error = wr_air_2 - w_air_1
    np.testing.assert_almost_equal(wr_air_2, w_air_1, decimal=4)
Пример #2
0

# Parameter input ----------------------------
vacuum_wavelength = 550
plane_wave_polar_angle = np.pi
plane_wave_azimuthal_angle = 0
plane_wave_polarization = 0
plane_wave_amplitude = 1
lmax = 3
neff_waypoints = [0, 0.5, 0.8-0.01j, 2-0.01j, 2.5, 20]
neff_discr = 1e-3

# --------------------------------------------

flds.default_Sommerfeld_k_parallel_array = flds.reasonable_Sommerfeld_kpar_contour(
    vacuum_wavelength=vacuum_wavelength,
    neff_waypoints=neff_waypoints,
    neff_resolution=neff_discr)


# initialize particle object
part1 = part.Sphere(position=[100,100,150], refractive_index=2.4+0.0j, radius=120, l_max=lmax)
part2 = part.Sphere(position=[-100,-100,250], refractive_index=1.9+0.1j, radius=120, l_max=lmax)

# initialize layer system object
lay_sys1 = lay.LayerSystem([0, 400, 0], [1.5, 1.7, 1])
lay_sys2 = lay.LayerSystem([0, 200, 200, 0], [1.5, 1.7, 1.7, 1])

# initialize initial field object
plane_wave = init.PlaneWave(vacuum_wavelength=vacuum_wavelength, polar_angle=plane_wave_polar_angle,
                            azimuthal_angle=plane_wave_azimuthal_angle, polarization=plane_wave_polarization,
                            amplitude=plane_wave_amplitude, reference_point=[0, 0, 400])
import numpy as np


ld = 550
rD1 = [100, -100, 100]
D1 = [1e7, 2e7, 3e7]
rD2 = [-100, 100, -100]
D2 = [-2e7, 3e7, 1e7]

waypoints = [0, 0.8, 0.8-0.1j, 2.1-0.1j, 2.1, 3]
neff_max = 3
neff_discr = 5e-3

# we avoid to use default_k_parallel, because there is some issue when running this test with nose2 ...
kpar = flds.reasonable_Sommerfeld_kpar_contour(
    vacuum_wavelength=ld,
    neff_waypoints=waypoints,
    neff_resolution=neff_discr)



# initialize particle object
# first two spheres in top layer
sphere1 = part.Sphere(position=[200, 200, 500], refractive_index=2.4 + 0.0j, radius=110, l_max=3, m_max=3)
sphere2 = part.Sphere(position=[200, -200, 500], refractive_index=2.4 + 0.0j, radius=110, l_max=3, m_max=3)
# third sphere is in same layer as third dipole
sphere3 = part.Sphere(position=[-200, -200, -400], 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, 2, 1.5])
Пример #4
0
"""Test the functions defined in particle_coupling.py."""

import numpy as np
from smuthi.linearsystem.particlecoupling.direct_coupling import direct_coupling_block
from smuthi.linearsystem.particlecoupling.layer_mediated_coupling import layer_mediated_coupling_block
import smuthi.layers as lay
import smuthi.particles as part
import smuthi.fields as flds

wl = 550

part1 = part.Sphere(position=[100, -100, 200], refractive_index=1.7, radius=100, l_max=2, m_max=2)
part2 = part.Sphere(position=[-100, 200, 300], refractive_index=1.7, radius=100, l_max=2, m_max=2)

flds.default_Sommerfeld_k_parallel_array = flds.reasonable_Sommerfeld_kpar_contour(
    vacuum_wavelength=wl,
    neff_waypoints=[0, 0.8, 0.8 - 0.1j, 2.1 - 0.1j, 2.1, 3],
    neff_resolution=2e-3)


def test_wr_against_prototype():
    laysys_substrate = lay.LayerSystem(thicknesses=[0, 0], refractive_indices=[2 + 0.1j, 1])

    wr_sub00 = layer_mediated_coupling_block(wl, part1, part1, laysys_substrate)
    wr_sub01 = layer_mediated_coupling_block(wl, part1, part2, laysys_substrate)

    wr_sub_0000 = -0.116909038698419 - 0.013001770175717j
    assert abs((wr_sub00[0, 0] - wr_sub_0000) / wr_sub_0000) < 1e-5
    wr_sub_0010 = 0.051728301055665 - 0.030410521218822j
    assert abs((wr_sub01[0, 0] - wr_sub_0010) / wr_sub_0010) < 1e-5
    wr_sub_0110 = -0.028137473050619 - 0.012620163432327j
    assert abs((wr_sub01[1, 0] - wr_sub_0110) / wr_sub_0110) < 1e-5
Пример #5
0
#spheroid1 = part.Spheroid(position=[0, 0, 400],euler_angles=[0, 0, 0],
#                          refractive_index=2.4 + 0.0j, semi_axis_c=50, semi_axis_a=100, l_max=2, m_max=1)
#
#spheroid2 = part.Spheroid(position=[0,0,0],euler_angles=[0, 0, 0],
#                          refractive_index=2.4 + 0.0j, semi_axis_c=100, semi_axis_a=50, l_max=2, m_max=2)

# conventional coupling using svwf addition theorem
W = pacou.direct_coupling_block(vacuum_wavelength=wl,
                                receiving_particle=spheroid2,
                                emitting_particle=spheroid1,
                                layer_system=lay_sys)

# plane wave coupling
k_parallel = flds.reasonable_Sommerfeld_kpar_contour(
    vacuum_wavelength=wl,
    neff_waypoints=[0, 0.9, 0.9 - 0.1j, 1.1 - 0.1j, 1.1, 7],
    neff_resolution=1e-3)

W_pvwf = pacou.direct_coupling_block_pvwf_mediated(
    vacuum_wavelength=wl,
    receiving_particle=spheroid2,
    emitting_particle=spheroid1,
    layer_system=lay_sys,
    k_parallel=k_parallel)


def test_W_block_pvwf_coupling():
    print(W[0, 0])
    print(W_pvwf[0, 0])
    print(W_pvwf[0, 0] / W[0, 0])
def converge_neff_max(simulation,
                      detector="extinction cross section",
                      tolerance=1e-3,
                      max_iter=20,
                      neff_imag=1e-2,
                      neff_step=2e-3,
                      neff_max_increment=0.5,
                      converge_lm=True):
    """Find a suitable truncation value for the multiple scattering Sommerfeld integral contour and update the
    simulation object accordingly.

    Args:
        simulation (smuthi.simulation.Simulation):    Simulation object
        detector (function or string):                Function that accepts a simulation object and returns a detector
                                                      value the change of which is used to define convergence.
                                                      Alternatively, use "extinction cross section" (default) to have
                                                      the extinction cross section as the detector value.
        tolerance (float):                            Relative tolerance for the detector value change.
        max_iter (int):                               Break convergence loops after that number of iterations, even if
                                                      no convergence has been achieved.
        neff_imag (float):                              Extent of the contour into the negative imaginary direction
                                                        (in terms of effective refractive index, n_eff=kappa/omega).
        neff_step (float):                              Discretization of the contour (in terms of eff. refractive
                                                        index).
        neff_max_increment (float):                     Increment the neff_max parameter with that step size
        converge_lm (logical):                          If set to true, update multipole truncation during each step
                                                        (this takes longer time, but is necessary for critical use cases
                                                        like flat particles on a substrate)

    Returns:
        Detector value for converged settings.
    """

    print("")
    print("---------------------------")
    log.write_blue("Searching suitable neff_max")

    update_contour(simulation=simulation,
                   neff_imag=neff_imag,
                   neff_max_offset=0,
                   neff_step=neff_step)

    simulation.k_parallel = flds.reasonable_Sommerfeld_kpar_contour(
        vacuum_wavelength=simulation.initial_field.vacuum_wavelength,
        layer_refractive_indices=simulation.layer_system.refractive_indices,
        neff_imag=neff_imag,
        neff_max_offset=0,
        neff_resolution=neff_step)

    neff_max = simulation.k_parallel[-1] / angular_frequency(
        simulation.initial_field.vacuum_wavelength)
    print("Starting value: neff_max=%f" % neff_max.real)

    if converge_lm:
        with log.LoggerIndented():
            current_value = converge_multipole_cutoff(
                simulation=simulation,
                detector=detector,
                tolerance=tolerance /
                2,  # otherwise, results flucutate by tolerance and convergence check is compromised
                max_iter=max_iter)
    else:
        current_value = evaluate(simulation, detector)

    for _ in range(max_iter):
        old_neff_max = neff_max
        neff_max = neff_max + neff_max_increment
        update_contour(simulation=simulation,
                       neff_imag=neff_imag,
                       neff_max=neff_max,
                       neff_step=neff_step)

        print("---------------------------------------")
        print("Try neff_max = %f" % neff_max.real)

        if converge_lm:
            with log.LoggerIndented():
                new_value = converge_multipole_cutoff(
                    simulation=simulation,
                    detector=detector,
                    tolerance=tolerance,
                    max_iter=max_iter,
                    current_value=current_value)
        else:
            new_value = evaluate(simulation, detector)

        rel_diff = abs(new_value - current_value) / abs(current_value)
        print("Old detector value:", current_value)
        print("New detector value:", new_value)
        print("Relative difference:", rel_diff)

        if rel_diff < tolerance:  # in this case: discard l_max increment
            neff_max = old_neff_max
            update_contour(simulation=simulation,
                           neff_imag=neff_imag,
                           neff_max=neff_max,
                           neff_step=neff_step)
            log.write_green(
                "Relative difference smaller than tolerance. Keep neff_max = %f"
                % neff_max.real)
            return current_value
        else:
            current_value = new_value

    log.write_red("No convergence achieved. Keep neff_max = %i" % neff_max)
    return None