General Usage

Every computation combines three building blocks: an excitation, a scatterer, and a quantity to be evaluated at given locations. They are introduced by two simple examples, one for each physics; more details are provided afterwards.


Introductory Examples

Electromagnetic: Plane Wave and PEC Sphere

using SphericalScattering, StaticArrays

# define excitation: plane wave travelling in positive z-direction with x-polarization
ex = planeWave(frequency=10e6) # Hz

# define scatterer: PEC sphere
sp = PECSphere(radius = 1.0)

# define an observation point
point_cart = [SVector(2.0, 2.0, 3.2)]

# compute scattered fields
E  = scatteredfield(sp, ex, ElectricField(point_cart))
H  = scatteredfield(sp, ex, MagneticField(point_cart))
FF = scatteredfield(sp, ex, FarField(point_cart))

Acoustic: Plane Wave and Sound-Hard Sphere

# define the medium: air, with compressibility 1 / (ρc²) and mass density ρ
air = Medium(1 / (1.2 * 343.0^2), 1.2)

# define excitation: plane wave travelling in positive z-direction
ex = Acoustic.planeWave(frequency=1e3, embedding=air) # Hz

# define scatterer: sound-hard sphere
sp = HardSphere(radius = 0.1)

# define an observation point
point_cart = [SVector(0.2, 0.2, 0.3)]

# compute scattered pressure
p  = scatteredfield(sp, ex, Pressure(point_cart))
FF = scatteredfield(sp, ex, FarField(point_cart))
Note

The background medium is defined by the excitation as a Medium(ε, μ), for both physics. For acoustics, the two parameters are read as the compressibility $\varepsilon \rightarrow 1 / (\rho c^2)$ and the mass density $\mu \rightarrow \rho$, see the acoustic plane wave. Since the default is free space, a medium matching the fluid of interest should be provided.


Defining Observation Points

In order to define points the StaticArrays package has to be used.

using StaticArrays

# defining a single point
point_cart = [SVector(2.0, 2.0, 3.2)]

# defining multiple points (along a line)
point_cart = [SVector(5.0, 5.0, z) for z in -2:0.2:2]
Info

A Cartesian basis is used for all coordinates and field components!


Defining an Excitation

For all available excitations a simple constructor with keyword arguments and default values is available:

physicsexcitationconstructordetails
electromagneticplane waveplaneWaveplane wave
electromagneticHertzian and Fitzgerald dipoleHertzianDipole, FitzgeraldDipoledipoles
electromagneticelectric and magnetic ring currentelectricRingCurrent, magneticRingCurrentring currents
electromagneticTE and TM spherical modesSphericalModeTE, SphericalModeTMspherical modes
electromagneticuniform static fieldUniformFielduniform static field
acousticplane waveAcoustic.planeWaveacoustic plane wave
acousticmonopoleAcoustic.monopolemonopole

The acoustic constructors are collected in the Acoustic submodule, so that their names do not clash with the electromagnetic ones.


Defining a Scatterer

For all available scatterers a constructor with keyword arguments is available, e.g.,

sp = PECSphere(radius=1.0)                                        # electromagnetic
sp = DielectricSphere(radius=1.0, filling=Medium(4ε0, μ0))

sp = SoftSphere(radius=1.0)                                       # acoustic
sp = Spheroid{SoundHard}(equatorialRadius=1.0, polarRadius=0.5)   # an oblate spheroid
sp = Disc(SoundSoft; radius=1.0)

The physics of the scatterer has to match that of the excitation. An overview of all constructors and of the type hierarchy behind them is given in Scatterers and Boundary Conditions.


Computing Fields

The incident, scattered, and total fields are computed by

F = field(ex, quantity)                # incident field: the excitation alone
F = scatteredfield(sp, ex, quantity)   # field scattered by the scatterer
F = field(sp, ex, quantity)            # total field: incident plus scattered

where the quantity wraps the locations, e.g.,

E  = field(sp, ex, ElectricField(point_cart))             # electromagnetic
H  = field(sp, ex, MagneticField(point_cart))
Φ  = field(sp, ex, ScalarPotential(point_cart))           # uniform static field
FF = scatteredfield(sp, ex, FarField(point_cart))

p  = field(sp, ex, Pressure(point_cart))                  # acoustic
γ₀ = field(sp, ex, PressureTrace(point_cart))             # on the surface
γ₁ = field(sp, ex, PressureNormalGradient(point_cart))    # on the surface
FF = scatteredfield(sp, ex, FarField(point_cart))

Which quantities are available for which excitation, and how the traces and far fields are defined, is described in Quantities. All functions accept the keyword argument parameter, which controls the truncation of the series, see Accuracy Settings.

Tip

The locations are distributed over the available threads, for all excitations but the dipoles. Start Julia with several threads, e.g., julia --threads=auto, to make use of them.

Tip

For a spheroid, the expensive modal coefficients can be computed once and reused for several quantities, see Reusing the Modal Coefficients.


Radar Cross Section

For an electromagnetic plane wave, the bistatic and the monostatic radar cross section are computed by

σ = rcs(sp, ex, points_cart)   # bistatic

σ = rcs(sp, ex)                # monostatic

Conversion Between Bases

Methods are provided to convert between Cartesian and spherical coordinates, whose convention is given under Spherical Coordinates:

point_cart = SphericalScattering.sph2cart.(point_sph)

point_sph  = SphericalScattering.cart2sph.(point_cart)

Converting fields:

F_cart = SphericalScattering.convertSpherical2Cartesian.(F_sph,  point_sph)

F_sph  = SphericalScattering.convertCartesian2Spherical.(F_cart, point_sph)

Plotting Fields

To visualize far-fields and near-fields the functions

SphericalScattering.sphericalGridPoints — Function
patternPoints(;r=1.0, resolution=5)

Convenience function returning points (in Cartesian and spherical coordinates) on a spherical grid at a distance 'r' and a resolution in degrees.

source
SphericalScattering.phiCutPoints — Function
phiCutPoints(ϕ; r=1.0, resolution=1)

Convenience function returning points (in Cartesian coordinates) on a phi cut at a distance 'r' and a resolution in degrees.

source
SphericalScattering.thetaCutPoints — Function
thetaCutPoints(ϑ; r=1.0, resolution=1)

Convenience function returning points (in Cartesian coordinates) on a theta cut at a distance 'r' and a resolution in degrees.

source

as well as the functions

plotff(F, points_sph; scale="log", normalize=true, type="abs")

plotffcut(F, points; scale="log", normalize=true, format="polar")

are provided (after loading the PlotlyJS package). For more details see the visualization of fields examples.

Surface densities, such as the traces of the pressure on an acoustic scatterer, are plotted on the surface of the scatterer itself:

SphericalScattering.surfacePoints — Function
surfacePoints(sphere::Scatterer; resolution=5)

Points on the surface of the scatterer on a grid suited for plotting surface densities, see plotsurface, with a resolution in degrees.

The points are arranged as a matrix: the rows run from the pole in the direction of the axis to the opposite one, the columns around the axis, the last column repeating the first, so that the surface is closed. They are given in Cartesian coordinates, so that any quantity can be computed at them by the general API, e.g., field(sp, ex, PressureTrace(points)).

For a spheroid the rows are equispaced in the polar angle $θ$ with $η = \cos θ$, so that the tips of a prolate spheroid are resolved as well as its equator. For a disc the rows with $η > 0$ lie on the face whose normal is the axis, those with $η < 0$ on the opposite one; they are displaced from the disc by a tiny fraction of its radius along the axis, which determines the face (exactly on the disc both faces share their Cartesian coordinates). The rim itself is omitted, as the Neumann trace is singular there; the outermost rows lie half a step before it.

source
SphericalScattering.plotsurface — Function
plotsurface(sphere::Scatterer, values, points; type="abs", scale="linear", normalize=false, clip=1.0, gap=0.02, title="")
plotsurface(sphere::Scatterer{<:AcousticBoundary}, excitation::AcousticExcitation, Q; total=true, resolution=5, parameter=Parameter(), kwargs...)

Plot a density on the surface of the scatterer as a coloured surface, available after loading PlotlyJS.

The first method plots the values given at the points of surfacePoints, which have been computed by the general API, e.g., field(sp, ex, PressureTrace(points)). Optional arguments:

  • type: "abs", "real", "imag", or "phase" (in degrees, with a cyclic colour scale)
  • scale: "linear" or "log" (in dB, for type="abs" only)
  • normalize: whether the values are normalized to their largest magnitude
  • clip: the quantile of the magnitudes at which the colour scale saturates, e.g., 0.98 for a density that is singular at the rim of a disc
  • gap: the visual distance of the two faces of a disc, relative to its radius
  • title: the title of the colour bar

The second method computes the surface density itself, for Q being PressureTrace, PressureNormalGradient, or PressureJump (a disc only), and plots it: the total density, or the scattered one for total=false. The outward normals of a spheroid are employed for the Neumann trace, and its modal coefficients are computed once. The keyword arguments kwargs are passed on to the first method.

The two faces of a disc are plotted as two surfaces, separated by the gap along its axis.

source

For example, the total pressure on a spheroid is computed and plotted by

points = surfacePoints(sp)
p = field(sp, ex, PressureTrace(points))

plotsurface(sp, p, points)

or in short by plotsurface(sp, ex, PressureTrace), see the visualization of surface densities.