JuliaWaveScattering / MultipleScattering.jl

A Julia library for simulating, processing, and plotting multiple scattering of waves.
Other
45 stars 12 forks source link

Allow different incident waves #10

Closed arturgower closed 6 years ago

arturgower commented 6 years ago

Clearly having the option to use a point source (or collection of point sources) or an incident plane wave, will greatly increase the usefulness of this library. So we need a type for all Incident waves.

The essential data for this type is a scattering function (x,y) -> scattering coefficients, i.e. given any point returns the scattering coefficients of a Bessel J expansion. One major issue is that we are not allowed to save functions. So we can not have this scattering function as a field of, say, FrequencySimulation. This is why I removed the impulse function and replaced with an impulse vector for the Fourier transforms. One possible solution is to allow for only plane waves or sum of point sources, then by recording which one was used, we can then recreate scattering function.

jondea commented 6 years ago

Having the sources as a container of two functions is attractive, but what about this for a Julian solution: sources can contain two Exprs instead of functions. Here's a quick draft

# MultipleScattering/src/source.jl
include("domain/particle.jl")

"Immutable struct"
struct Source
    field_expr::Expr
    coef_expr::Expr
end

import Base.(+)

function +(a::Source,b::Source)
    Source(
        parse(string(string(a.field_expr)," + ",string(b.field_expr))),
        parse(string(string(a.coef_expr)," + ",string(b.coef_expr))),
    )
end

"Helper function to return a plane wave source"
function planar_wave_source{T}(magnitude::Complex{T},direction::Vector{T})
    # Have to use string interpolation
    Source(
        :(($(magnitude))*exp(k*(x[1]*$(direction[1])+ x[2]*$(direction[2])))),
        :([1.0+0.0im]),
    )
end

"Safe access function for getting values of function from Source. DOESN'T WORK"
function get_source_field{T}(source::Source,x::Vector{T},k::T)::Complex{T}
    return eval(source.field_expr)
end

"Safe access function for getting coefficients from Source. DOESN'T WORK"
function get_coefs{T}(source::Source,p::Particle{T},k::T)::Vector{Complex{T}}
    return eval(source.coef_expr)
end

The basics work really well in global scope (try adding two planar waves!).

include("src/source.jl")
pw = planar_wave_source(1.0+0.0im,[1.0,0.0])
pw2 = planar_wave_source(1.0+0.0im,[0.0,1.0])
sum_pw = pw + pw2

x= [1.0,1.0]
k=10.0
eval(sum_pw.field_expr)

But unfortunately eval only works in the global scope. Is there a solution somewhere here? Could we just use expressions when saving the FrequencySimulation?

jondea commented 6 years ago

In the experimental branch there is generic type

type Source{P<:PhysicalProperties,T<:AbstractFloat}
    field::Function
    coef::Function
end

which although crude is very simple and allows us to naturally take linear combinations of different source types.

This however means it is hard to save such objects. Instead of trying to develop complicated and brittle solutions like using Exprs, I would suggest that if you want to save a simulation, just save the script you used to generate it. This will of course be much more practical now that we have a separate SimulationResult type.