コード例 #1
0
def test_layerresponse_method():
    fromlayer = 2
    tolayer = 1
    kp = np.linspace(0, 2) * omega
    a = np.linspace(0, 2 * np.pi)
    layer_system = lay.LayerSystem(thicknesses=layer_d,
                                   refractive_indices=layer_n)
    ref = [0, 0, layer_system.reference_z(fromlayer)]
    pwe_up = fldex.PlaneWaveExpansion(k=omega * 1.2,
                                      k_parallel=kp,
                                      azimuthal_angles=a,
                                      kind='upgoing',
                                      reference_point=ref)
    pwe_up.coefficients[0, :, :] = np.exp(-pwe_up.k_parallel_grid() / omega)
    pwe_down = fldex.PlaneWaveExpansion(k=omega * 1.2,
                                        k_parallel=kp,
                                        azimuthal_angles=a,
                                        kind='downgoing',
                                        reference_point=ref)
    pwe_down.coefficients[0, :, :] = 2j * np.exp(
        -pwe_up.k_parallel_grid() / omega * 3)

    pwe_r_up, pwe_r_down = layer_system.response(pwe_up, fromlayer, tolayer)
    pwe_r_up2, pwe_r_down2 = layer_system.response(pwe_down, fromlayer,
                                                   tolayer)
    pwe_r_up3, pwe_r_down3 = layer_system.response((pwe_up, pwe_down),
                                                   fromlayer, tolayer)
コード例 #2
0
    def plane_wave_expansion(self, layer_system, i):
        """Plane wave expansion for the plane wave including its layer system response. As it already is a plane wave,
        the plane wave expansion is somehow trivial (containing only one partial wave, i.e., a discrete plane wave
        expansion).

        Args:
            layer_system (smuthi.layers.LayerSystem): Layer system object
            i (int): layer number in which the plane wave expansion is valid

        Returns:
            Tuple of smuthi.field_expansion.PlaneWaveExpansion objects. The first element is an upgoing PWE, whereas the
            second element is a downgoing PWE.
        """
        if np.cos(self.polar_angle) > 0:
            iP = 0
            kind = 'upgoing'
        else:
            iP = layer_system.number_of_layers() - 1
            kind = 'downgoing'

        niP = layer_system.refractive_indices[iP]
        neff = np.sin([self.polar_angle]) * niP
        alpha = np.array([self.azimuthal_angle])

        angular_frequency = coord.angular_frequency(self.vacuum_wavelength)
        k_iP = niP * angular_frequency
        k_Px = k_iP * np.sin(self.polar_angle) * np.cos(self.azimuthal_angle)
        k_Py = k_iP * np.sin(self.polar_angle) * np.sin(self.azimuthal_angle)
        k_Pz = k_iP * np.cos(self.polar_angle)
        z_iP = layer_system.reference_z(iP)
        amplitude_iP = self.amplitude * np.exp(
            -1j * (k_Px * self.reference_point[0] +
                   k_Py * self.reference_point[1] + k_Pz *
                   (self.reference_point[2] - z_iP)))
        loz = layer_system.lower_zlimit(iP)
        upz = layer_system.upper_zlimit(iP)
        pwe_exc = fldex.PlaneWaveExpansion(k=k_iP,
                                           k_parallel=neff * angular_frequency,
                                           azimuthal_angles=alpha,
                                           kind=kind,
                                           reference_point=[0, 0, z_iP],
                                           lower_z=loz,
                                           upper_z=upz)
        pwe_exc.coefficients[self.polarization, 0, 0] = amplitude_iP
        pwe_up, pwe_down = layer_system.response(pwe_exc,
                                                 from_layer=iP,
                                                 to_layer=i)
        if iP == i:
            if kind == 'upgoing':
                pwe_up = pwe_up + pwe_exc
            elif kind == 'downgoing':
                pwe_down = pwe_down + pwe_exc

        return pwe_up, pwe_down
コード例 #3
0
    def plane_wave_expansion(self,
                             layer_system,
                             i,
                             k_parallel_array=None,
                             azimuthal_angles_array=None):
        """Plane wave expansion of the Gaussian beam.
        
        Args:
            layer_system (smuthi.layer.LayerSystem):    stratified medium
            i (int):                                    layer number in which to evaluate the expansion
            k_parallel_array (numpy.ndarray):           in-plane wavenumber array for the expansion. if none specified,
                                                        self.k_parallel_array is used
            azimuthal_angles_array (numpy.ndarray):     azimuthal angles for the expansion. if none specified,
                                                        self.azimuthal_angles_array is used
            
        Returns:
            tuple of to smuthi.field_expansion.PlaneWaveExpansion objects, one for upgoing and one for downgoing 
            component
        """
        if k_parallel_array is None:
            k_parallel_array = self.k_parallel_array
        if azimuthal_angles_array is None:
            azimuthal_angles_array = self.azimuthal_angles_array

        if np.cos(self.polar_angle) > 0:
            iG = 0  # excitation layer number
            kind = 'upgoing'
        else:
            iG = layer_system.number_of_layers() - 1
            kind = 'downgoing'

        niG = layer_system.refractive_indices[
            iG]  # refractive index in excitation layer
        if niG.imag:
            warnings.warn('beam coming from absorbing medium')
        k_iG = niG * self.angular_frequency()
        z_iG = layer_system.reference_z(iG)
        loz = layer_system.lower_zlimit(iG)
        upz = layer_system.upper_zlimit(iG)
        pwe_exc = fldex.PlaneWaveExpansion(
            k=k_iG,
            k_parallel=k_parallel_array,
            azimuthal_angles=azimuthal_angles_array,
            kind=kind,
            reference_point=[0, 0, z_iG],
            lower_z=loz,
            upper_z=upz)

        k_Gx = k_iG * np.sin(self.polar_angle) * np.cos(self.azimuthal_angle)
        k_Gy = k_iG * np.sin(self.polar_angle) * np.sin(self.azimuthal_angle)

        kp = pwe_exc.k_parallel_grid()
        al = pwe_exc.azimuthal_angle_grid()

        kx = kp * np.cos(al)
        ky = kp * np.sin(al)
        kz = pwe_exc.k_z_grid()

        w = self.beam_waist
        r_G = self.reference_point

        g = (self.amplitude * w**2 / (4 * np.pi) *
             np.exp(-w**2 / 4 * ((kx - k_Gx)**2 + (ky - k_Gy)**2)) *
             np.exp(-1j * (kx * r_G[0] + ky * r_G[1] + kz * (r_G[2] - z_iG))))

        pwe_exc.coefficients[0, :, :] = g * np.cos(
            al - self.azimuthal_angle + self.polarization * np.pi / 2)
        if np.cos(self.polar_angle) > 0:
            pwe_exc.coefficients[1, :, :] = g * np.sin(
                al - self.azimuthal_angle + self.polarization * np.pi / 2)
        else:
            pwe_exc.coefficients[1, :, :] = -g * np.sin(
                al - self.azimuthal_angle + self.polarization * np.pi / 2)

        pwe_up, pwe_down = layer_system.response(pwe_exc,
                                                 from_layer=iG,
                                                 to_layer=i)
        if iG == i:
            if kind == 'upgoing':
                pwe_up = pwe_up + pwe_exc
            elif kind == 'downgoing':
                pwe_down = pwe_down + pwe_exc

        return pwe_up, pwe_down
コード例 #4
0
ファイル: layers.py プロジェクト: shepherdYoung/smuthi
    def response(self, pwe, from_layer, to_layer):
        """Evaluate the layer system response to an electromagnetic excitation inside the layer system.

        Args:
            pwe (tuple or smuthi.field_expansion.PlaneWaveExpansion):  Either specify a PlaneWaveExpansion object that
                                                                       that represents the electromagnetic excitation,
                                                                       or a tuple of two PlaneWaveExpansion objects
                                                                       representing the upwards- and downwards
                                                                       propagating partial waves of the excitation.
            from_layer (int):   Layer number in which the excitation is located
            to_layer (int):     Layer number in which the layer response is to be evaluated

        Returns:
            Tuple (pwe_up, pwe_sown) of PlaneWaveExpansion objects representing the layer system response to the
            excitation.
        """
        if hasattr(pwe, '__len__'):
            if len(pwe) == 2:
                pwe_up_0, pwe_down_0 = self.response(pwe[0], from_layer,
                                                     to_layer)
                pwe_up_1, pwe_down_1 = self.response(pwe[1], from_layer,
                                                     to_layer)
                pwe_up = pwe_up_0 + pwe_up_1
                pwe_down = pwe_down_0 + pwe_down_1
            else:
                raise ValueError(
                    'pwe argument must be either PlaneWaveExpansion or tuple of length two'
                )
        else:
            assert pwe.reference_point == [0, 0, self.reference_z(from_layer)]
            omega = pwe.k / self.refractive_indices[from_layer]
            k_to_layer = omega * self.refractive_indices[to_layer]
            reference_point = [0, 0, self.reference_z(to_layer)]
            loz, upz = self.lower_zlimit(to_layer), self.upper_zlimit(to_layer)
            pwe_up = fldex.PlaneWaveExpansion(
                k=k_to_layer,
                k_parallel=pwe.k_parallel,
                azimuthal_angles=pwe.azimuthal_angles,
                kind='upgoing',
                reference_point=reference_point,
                lower_z=loz,
                upper_z=upz)
            pwe_down = fldex.PlaneWaveExpansion(
                k=k_to_layer,
                k_parallel=pwe.k_parallel,
                azimuthal_angles=pwe.azimuthal_angles,
                kind='downgoing',
                reference_point=reference_point,
                lower_z=loz,
                upper_z=upz)
            for pol in range(2):
                L = layersystem_response_matrix(pol, self.thicknesses,
                                                self.refractive_indices,
                                                pwe.k_parallel, omega,
                                                from_layer, to_layer)
                if pwe.kind == 'upgoing':
                    pwe_up.coefficients[pol, :, :] = L[
                        0, 0, :][:, None] * pwe.coefficients[pol, :, :]
                    pwe_down.coefficients[pol, :, :] = L[
                        1, 0, :][:, None] * pwe.coefficients[pol, :, :]
                elif pwe.kind == 'downgoing':
                    pwe_up.coefficients[pol, :, :] = L[
                        0, 1, :][:, None] * pwe.coefficients[pol, :, :]
                    pwe_down.coefficients[pol, :, :] = L[
                        1, 1, :][:, None] * pwe.coefficients[pol, :, :]
                else:
                    raise ValueError('pwe type undefined')

        return pwe_up, pwe_down
コード例 #5
0
vb = [0, 800]

layer_system = lay.LayerSystem([0, 0], [1, 1])

x = np.array([fieldpoint[0]])
y = np.array([fieldpoint[1]])
z = np.array([fieldpoint[2]])

swe = fldex.SphericalWaveExpansion(k=k, l_max=3, m_max=3, kind='outgoing', reference_point=swe_ref)
swe.coefficients[0] = 2
swe.coefficients[1] = -3j
swe.coefficients[16] = 1
swe.coefficients[18] = 0.5

kp2 = np.linspace(0, 2, num=1000) * k
pwe = fldex.PlaneWaveExpansion(k=k, k_parallel=kp2, azimuthal_angles=a, kind='upgoing', reference_point=pwe_ref,
                               lower_z=vb[0], upper_z=vb[1])
pwe.coefficients[0, :, :] = 100000 * np.exp(- pwe.k_parallel_grid() / k / 20)
pwe.coefficients[1, :, :] = -100000 * np.exp(- pwe.k_parallel_grid() / k / 10)


def test_swe2pwe():
    ex, ey, ez = swe.electric_field(x, y, z)
    pwe_up, pwe_down = fldex.swe_to_pwe_conversion(swe, k_parallel=kp, azimuthal_angles=a, layer_system=layer_system)
    ex2, ey2, ez2 = pwe_up.electric_field(x, y, z)
    err2 = abs(ex - ex2) ** 2 + abs(ey - ey2) ** 2 + abs(ez - ez2) ** 2
    norme2 = abs(ex) ** 2 + abs(ey) ** 2 + abs(ez) ** 2
    print('relative error:', np.sqrt(err2 / norme2))
    assert np.sqrt(err2 / norme2) < 5e-3


def test_pwe2swe():
コード例 #6
0
def scattered_field_pwe(vacuum_wavelength,
                        particle_list,
                        layer_system,
                        layer_number,
                        k_parallel='default',
                        azimuthal_angles='default',
                        include_direct=True,
                        include_layer_response=True):
    """Calculate the plane wave expansion of the scattered field of a set of particles.

    Args:
        vacuum_wavelength (float):          Vacuum wavelength (length unit)
        particle_list (list):               List of Particle objects
        layer_system (smuthi.layers.LayerSystem):  Stratified medium
        layer_number (int):                 Layer number in which the plane wave expansion should be valid
        k_parallel (numpy.ndarray or str):          in-plane wavenumbers array. 
                                                    if 'default', use smuthi.coordinates.default_k_parallel
        azimuthal_angles (numpy.ndarray or str):    azimuthal angles array
                                                    if 'default', use smuthi.coordinates.default_azimuthal_angles
        include_direct (bool):              If True, include the direct scattered field
        include_layer_response (bool):      If True, include the layer system response

    Returns:
        A tuple of PlaneWaveExpansion objects for upgoing and downgoing waves.
    """

    sys.stdout.write(
        'Evaluating scattered field plane wave expansion in layer number %i ...\n'
        % layer_number)
    sys.stdout.flush()

    omega = coord.angular_frequency(vacuum_wavelength)
    k = omega * layer_system.refractive_indices[layer_number]
    z = layer_system.reference_z(layer_number)
    vb = (layer_system.lower_zlimit(layer_number),
          layer_system.upper_zlimit(layer_number))
    pwe_up = fldex.PlaneWaveExpansion(k=k,
                                      k_parallel=k_parallel,
                                      azimuthal_angles=azimuthal_angles,
                                      kind='upgoing',
                                      reference_point=[0, 0, z],
                                      lower_z=vb[0],
                                      upper_z=vb[1])
    pwe_down = fldex.PlaneWaveExpansion(k=k,
                                        k_parallel=k_parallel,
                                        azimuthal_angles=azimuthal_angles,
                                        kind='downgoing',
                                        reference_point=[0, 0, z],
                                        lower_z=vb[0],
                                        upper_z=vb[1])

    for iS, particle in enumerate(
            tqdm(particle_list,
                 desc='Scatt. field pwe          ',
                 file=sys.stdout,
                 bar_format='{l_bar}{bar}| elapsed: {elapsed} '
                 'remaining: {remaining}')):

        i_iS = layer_system.layer_number(particle.position[2])

        # direct contribution
        if i_iS == layer_number and include_direct:
            pu, pd = fldex.swe_to_pwe_conversion(
                swe=particle.scattered_field,
                k_parallel=k_parallel,
                azimuthal_angles=azimuthal_angles,
                layer_system=layer_system)
            pwe_up = pwe_up + pu
            pwe_down = pwe_down + pd

        # layer mediated contribution
        if include_layer_response:
            pu, pd = fldex.swe_to_pwe_conversion(
                swe=particle.scattered_field,
                k_parallel=k_parallel,
                azimuthal_angles=azimuthal_angles,
                layer_system=layer_system,
                layer_number=layer_number,
                layer_system_mediated=True)
            pwe_up = pwe_up + pu
            pwe_down = pwe_down + pd

    return pwe_up, pwe_down
コード例 #7
0
def scattered_field_piecewise_expansion(vacuum_wavelength,
                                        particle_list,
                                        layer_system,
                                        k_parallel='default',
                                        azimuthal_angles='default',
                                        layer_numbers=None):
    """Compute a piecewise field expansion of the scattered field.

    Args:
        vacuum_wavelength (float):                  vacuum wavelength
        particle_list (list):                       list of smuthi.particles.Particle objects
        layer_system (smuthi.layers.LayerSystem):   stratified medium
        k_parallel (numpy.ndarray or str):          in-plane wavenumbers array. 
                                                    if 'default', use smuthi.coordinates.default_k_parallel
        azimuthal_angles (numpy.ndarray or str):    azimuthal angles array
                                                    if 'default', use smuthi.coordinates.default_azimuthal_angles
        layer_numbers (list):                       if specified, append only plane wave expansions for these layers
        

    Returns:
        scattered field as smuthi.field_expansion.PiecewiseFieldExpansion object

    """

    if layer_numbers is None:
        layer_numbers = range(layer_system.number_of_layers())

    sfld = fldex.PiecewiseFieldExpansion()
    for i in tqdm(layer_numbers,
                  desc='Scatt. field expansion    ',
                  file=sys.stdout,
                  bar_format='{l_bar}{bar}| elapsed: {elapsed} '
                  'remaining: {remaining}'):
        # layer mediated scattered field ---------------------------------------------------------------------------
        k = coord.angular_frequency(
            vacuum_wavelength) * layer_system.refractive_indices[i]
        ref = [0, 0, layer_system.reference_z(i)]
        vb = (layer_system.lower_zlimit(i), layer_system.upper_zlimit(i))
        pwe_up = fldex.PlaneWaveExpansion(k=k,
                                          k_parallel=k_parallel,
                                          azimuthal_angles=azimuthal_angles,
                                          kind='upgoing',
                                          reference_point=ref,
                                          lower_z=vb[0],
                                          upper_z=vb[1])
        pwe_down = fldex.PlaneWaveExpansion(k=k,
                                            k_parallel=k_parallel,
                                            azimuthal_angles=azimuthal_angles,
                                            kind='downgoing',
                                            reference_point=ref,
                                            lower_z=vb[0],
                                            upper_z=vb[1])
        for particle in particle_list:
            add_up, add_down = fldex.swe_to_pwe_conversion(
                particle.scattered_field, k_parallel, azimuthal_angles,
                layer_system, i, True)
            pwe_up = pwe_up + add_up
            pwe_down = pwe_down + add_down

        # in bottom_layer, suppress upgoing waves, and in top layer, suppress downgoing waves
        if i > 0:
            sfld.expansion_list.append(pwe_up)
        if i < layer_system.number_of_layers() - 1:
            sfld.expansion_list.append(pwe_down)

    # direct field ---------------------------------------------------------------------------------------------
    for particle in particle_list:
        sfld.expansion_list.append(particle.scattered_field)

    return sfld