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])
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