def domain_integral_equation_old(simparams, farfield_samples=0):
    """
    Function that calculates the E field on a 2D plane when a planewave is
    incident on a specific angle. The algorithm as proposed in 
    [Olivier J. F. Martin and Nicolas B. Piller, Electromagnetic scattering
     in polarizable back-grounds] is used.

    Parameters
    ----------
    simulation_size : tuple containing two integers
        Size of the simulation grid in x- and y-direction, respecitvely. 
    step_size : float
        Distance between each point in the simulation grid in meters.
    wavelength : float
        Wavelength of the incident plane wave.
    input_angle : float
        Input angle of the incident plane wave in radians.
    relative_permittivity : 2D array of (complex) numbers
        2D array with relative permittivities of the plane on which the plane
        wave is incident. Size should be given by simulation_size.
    farfield_samples : int, optional
        Amount of farfield samples. The default is 0.

    Returns
    -------
    E_field : 2D array of complex numbers
        Calculated electric field.
    farfield : array of complex numbers, optional
        Calculated farfield samples.

    """
    #Initialization: read parameters from dictionary
    simulation_size = simparams['simulation_size']
    # array containing number of evaluation points in x,y-directions
    wavelength = simparams['wavelength']
    # wavelength = wavelength of incident plane wave
    relative_permittivity = simparams['relative_permittivity']
    # relative_permittivity = relative permittivity at all evaluation points
    input_angle = simparams['input_angle']
    # input_angle = angle of incident wave, with respect to x-axis
    step_size = simparams['step_size']
    # step_size = physical distance between points in relative_permittivity

    #Initialization: break to prevent errors later on
    if (np.size(relative_permittivity, 0) != simulation_size[0]):
        raise Exception(
            "Error, number of x-coordinates in relative permittivity matrix incorrect"
        )
    if (np.size(relative_permittivity, 1) != simulation_size[1]):
        raise Exception(
            "Error, number of y-coordinates in relative permittivity matrix incorrect"
        )

    # Relative permittivity of background, set to 1 by default
    epsilon_B = 1

    # Create vector with all grid locations
    # x and y coordinates included
    r = np.array(list(np.ndindex(simulation_size[0],
                                 simulation_size[1]))) * step_size

    # Incident field
    E_0 = np.sqrt(mu_0 / epsilon_0)  #Amplitude of incident wave
    E_incident = np.matrix.flatten(
        create_planewave(r, E_0, wavelength, input_angle, simulation_size,
                         step_size, epsilon_B), 'C')
    k_rho = 2 * np.pi / wavelength * np.sqrt(
        epsilon_B)  #Wave number of incident field

    #Preparation for matrix calculations
    # Volume of each mesh part
    V_mesh = np.square(step_size)  #constant for all squares of the mesh
    # Self contribution to the electric field
    R_eff = np.sqrt(V_mesh / np.pi)  #Effective radius
    beta = 1  # No coupling between TE and TM polarizations
    gamma = R_eff / k_rho * hankel1(
        1, k_rho * R_eff) + 2j / (np.pi * np.square(k_rho))
    M = 1j * np.pi / 2 * beta * gamma  #gamma and M formulas from MartinPiller paper

    # Contrast between background relative permittivity and permittivity at
    # a specific location + convert matrix to vector
    Delta_epsilon = np.matrix.flatten(relative_permittivity, 'C') - epsilon_B

    # Calculate Euclidean distance between all points in the plane
    varrho = pdist(r, 'euclidean')  #Length (r*(r-1))/2
    # Calculate G matrix, formula from MartinPiller paper
    G_condensed = 1j / 4 * hankel1(0, k_rho * varrho)
    # Convert condensed G matrix to square form
    G = squareform(G_condensed)
    # Set diagonal of G matrix to M/V_mesh
    np.fill_diagonal(G, M / V_mesh)  #Addition of self-term

    # Total E field (vector)
    nloc = simulation_size[0] * simulation_size[1]  #Size of G matrix
    # Matrix calculation as given in MartinPiller paper
    E_r = np.linalg.inv(
        np.identity(nloc) -
        k_rho**2 * G @ np.diag(Delta_epsilon * V_mesh)) @ E_incident
    # Reshape E field to be a 2d matrix for understanding and visualization
    E_field = np.reshape(E_r, simulation_size, order='C')

    # Calculate farfield samples if requested
    if (farfield_samples != 0):
        # TODO: Find farfield samples
        ff_step = max(simulation_size
                      ) * 10 * step_size  #Each sample further away from origin
        rho_samples = range(0, farfield_samples + 1)
        G_ff = 1j / 4 * hankel1(0, k_rho * rho_samples)
        Delta_epsilon_ff = np.matrix.flatten(np.zeros(
            (farfield_samples,
             1)))  #Assume farfield samples are inside background medium
        #E_ff = np.matmul(np.linalg.inv(np.identity(1*farfield_samples) - np.matmul(G_ff.T, np.diag(Delta_epsilon_ff))*V_mesh*np.square(k_0) - M*np.square(k_0)*np.diag(Delta_epsilon_ff)), E_incident)
        farfield = 0
        return E_field, farfield
    else:
        return E_field
epsilon_grid = dynamic_to_grid(locations, epsilon, location_sizes, plane_size, step_size)
show_plane(np.real(epsilon_grid), step_size)

# Plot location points on plane
fig = plt.figure()
for loc in locations:
    plt.scatter(loc[0], loc[1], s=5, color='black')
plt.gca().set_aspect('equal')
plt.ylim(0, plane_size[1])
plt.xlim(0, plane_size[0])
plt.xlabel("X [m]")
plt.ylabel("Y [m]")

# Calculate incident wave on locations
E_0 = np.sqrt(mu_0/epsilon_0) # Amplitude of incident wave
E_incident = create_planewave(locations, E_0, wavelength, input_angle, plane_size, step_size)

# Convert to grid again
E_incident_grid = dynamic_to_grid(locations, E_incident, location_sizes, plane_size, step_size)
show_plane(np.real(E_incident_grid), step_size)

# Plot locations of static grid
max_size = 4
size_limits = [0, 100, 1000]
locations, location_sizes, epsilon = grid_to_dynamic(epsilon_circle, step_size, size_limits)
# Plot location points on plane
fig = plt.figure()
for loc in locations:
    plt.scatter(loc[0], loc[1], s=5, color='black')
plt.gca().set_aspect('equal')
plt.ylim(0, plane_size[1])
示例#3
0
def domain_integral_equation(simparams):
    #Initialization: read parameters from dictionary
    wavelength = simparams['wavelength']
    # wavelength = wavelength of incident plane wave
    permittivity = simparams['relative_permittivity']
    # relative_permittivity = relative permittivity at all evaluation points
    input_angle = simparams['input_angle']
    # input_angle = angle of incident wave, with respect to x-axis
    step_size = simparams['step_size']
    # step_size = physical distance between points in relative_permittivity
    simulation_size = simparams['simulation_size']
    # array containing number of evaluation points in x,y-directions
    if 'dynamic_sample_distance' in simparams:
        dynamic_sample_distance = simparams['dynamic_sample_distance']
        size_limits = simparams['size_limits']
    else:
        dynamic_sample_distance = False
    if 'farfield_samples' in simparams:
        farfield_samples = simparams['farfield_samples']
    else:
        farfield_samples = 0

    # Prepare inputs for dynamic sampling distances
    if dynamic_sample_distance:
        locations, location_sizes, permittivity = grid_to_dynamic(
            permittivity, step_size, size_limits)
    else:
        locations = (np.array(
            list(np.ndindex(simulation_size[0], simulation_size[1]))) +
                     0.5) * step_size
        location_sizes = np.ones(np.shape(locations)[0])
        permittivity = np.matrix.flatten(permittivity)

    # Prepare farfield samples if they are requested
    if farfield_samples != 0:
        # Add and calculate values farfield
        ff_distance = 10 * wavelength  #Farfield calculated at this distance from cylinder
        ff_angle = np.linspace(
            0, 2 * np.pi, farfield_samples, endpoint=False
        )  #Starting angle in radians 45 degrees from incident
        # Locations of the farfield samples
        loc_ff = np.array(
            [np.cos(ff_angle + np.pi / 2),
             np.sin(ff_angle + np.pi / 2)]).T * ff_distance
        loc_ff = np.array([
            loc_ff[:, 0] + simulation_size[0] / 2 * step_size,
            loc_ff[:, 1] + simulation_size[0] / 2 * step_size
        ]).T  #Shift locations around center of simulation plane
        # Add the farfield samples to the simulation locations
        locations = np.append(locations, loc_ff, axis=0)
        location_sizes = np.append(location_sizes, np.ones(farfield_samples))
        permittivity = np.append(
            permittivity, np.ones(farfield_samples)
        )  #Farfield samples are in background medium, which is vacuum so permittivity is 1

    # Calculate incident wave on locations
    E_0 = np.sqrt(mu_0 /
                  epsilon_0)  #Amplitude of incident wave in background medium
    E_incident = create_planewave(locations, E_0, wavelength, input_angle,
                                  simulation_size, step_size)

    # Calculate scattering
    E = martin98(locations, E_incident, permittivity, location_sizes,
                 wavelength, step_size)

    # Extract farfield samples
    if farfield_samples != 0:
        E_ff = E[-farfield_samples:]
        E = E[:-farfield_samples]
        E_ff = E_ff / E_0  #Normalizing over E_0
    else:
        E_ff = []

    # Convert result to grid again
    if dynamic_sample_distance:
        E_grid = np.conjugate(
            dynamic_to_grid(locations[:len(E)], E, location_sizes[:len(E)],
                            simulation_size, step_size))
    else:
        E_grid = np.reshape(np.conjugate(E), simulation_size, order='C')

    return E_grid.T, E_ff
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Feb 15 15:24:02 2021

@author: Arwin
"""
import numpy as np
from scipy.constants import speed_of_light
from helpers.visualize import show_plane
from helpers.create_incident_wave import create_planewave

plane_size = (200, 100)
step_size = 0.01

# Create a 0.75x0.5meter plane with the amplitude of the electric field of a
# plane wave with a frequency of 1Ghz with an incident angle of 45 degrees.
frequency = 1e9
wavelength = speed_of_light / frequency
E_plane = create_planewave(plane_size, step_size, 1, wavelength,
                           45 * np.pi / 180)
show_plane(np.real(E_plane), step_size)
def dynamic_shaping(simparams, farfield_samples):
    #Initialization: read parameters from dictionary
    locations = simparams['locations']

    wavelength = simparams['wavelength']
    # wavelength = wavelength of incident plane wave
    permittivity = simparams['relative_permittivity']
    # relative_permittivity = relative permittivity at all evaluation points
    input_angle = simparams['input_angle']
    # input_angle = angle of incident wave, with respect to x-axis
    step_size = simparams['step_size']
    # step_size = physical distance between points in relative_permittivity
    location_sizes = simparams['location_sizes']
    plane_size = simparams['simulation_size']
    # array containing number of evaluation points in x,y-directions
    epsilon_circle = simparams['relative_permittivity']
    #Permittivity of the circle
    simulation_size = plane_size
    loc_ff = []
    if (farfield_samples != 0):
        #Add and calculate values farfield
        ff_distance = 200  #Farfield calculated at this distance from cylinder

        ff_angle = np.linspace(0, np.pi * 2 - 2 * np.pi / farfield_samples,
                               farfield_samples)
        # for k in range(farfield_samples):
        loc_ff = ([
            np.cos(ff_angle) * ff_distance +
            (simulation_size[0] / 2 * step_size),
            np.sin(ff_angle) * ff_distance +
            (simulation_size[1] / 2 * step_size)
        ])
        # loc_ff = ([np.cos(ff_angle)*ff_distance, np.sin(ff_angle)*ff_distance])

        loc_ff = np.transpose(np.reshape(loc_ff, (2, farfield_samples)))
        # loc_ff = loc_ff+np.sqrt(2*(simulation_size[0]/2*step_size)**2)
        # loc_ff = loc_ff+(simulation_size[0]/2*step_size)

        locations = np.append(
            locations, loc_ff,
            axis=0)  # Add ff locations, with respective size and permittivity
        location_sizes = np.append(location_sizes, np.ones(farfield_samples))
        permittivity = np.append(permittivity, np.ones(farfield_samples))

        # Convert back to test
        epsilon_grid = dynamic_to_grid(locations, permittivity, location_sizes,
                                       plane_size, step_size, farfield_samples)

        # Calculate incident wave on locations
        E_0 = np.sqrt(mu_0 / epsilon_0)  # Amplitude of incident wave
        E_incident = create_planewave(locations, E_0, wavelength, input_angle,
                                      simulation_size, step_size)

        # Convert to grid again
        E_incident_grid = dynamic_to_grid(locations, E_incident,
                                          location_sizes, plane_size,
                                          step_size, farfield_samples)

        # Calculate scattering
        E = martin98(locations, E_incident, permittivity, location_sizes,
                     wavelength, step_size)
        #Taking out farfield samples
        E_ff = E[len(E) - farfield_samples:len(E)]
        E_ff = E_ff / E_0
        E_ff = E_ff * ff_distance  #Cancelling the 1/r dependence
        E = E[0:len(E) - farfield_samples]
        # Convert result to grid
        E_grid = dynamic_to_grid(locations, E, location_sizes, plane_size,
                                 step_size, farfield_samples)
        show_plane_ff(np.absolute(E_ff),
                      loc_ff,
                      ff_angle,
                      ff_distance,
                      title="Locations farfield of algorithm solution")
    else:
        # Convert back to test
        epsilon_grid = dynamic_to_grid(locations, permittivity, location_sizes,
                                       plane_size, step_size, farfield_samples)

        # Calculate incident wave on locations
        E_0 = np.sqrt(mu_0 / epsilon_0)  # Amplitude of incident wave
        E_incident = create_planewave(locations, E_0, wavelength, input_angle,
                                      simulation_size, step_size)

        # Convert to grid again
        E_incident_grid = dynamic_to_grid(locations, E_incident,
                                          location_sizes, plane_size,
                                          step_size, farfield_samples)

        # Calculate scattering
        E = martin98(locations, E_incident, permittivity, location_sizes,
                     wavelength, step_size)
        # Convert result to grid
        E_grid = dynamic_to_grid(locations, E, location_sizes, plane_size,
                                 step_size, farfield_samples)
        E_ff = []
    return E_grid, E_ff