Cube with anechoic condition (Interior)

Importing related packages

using BoundaryIntegralEquations # For BIEs
using IterativeSolvers          # For gmres
using LinearAlgebra             # For Diagonal
using Plots                     # For 2d plots
using Meshes                    # For 3d mesh plots
import GLMakie as wgl

Setting up constants

frequency = 54.59;                              # Frequency                [Hz]
c  = 343;                                       # Speed up sound           [m/s]
ρ₀ = 1.21;                                      # Mean density             [kg/m^3]
Z₀ = ρ₀*c;                                      # Characteristic impedance [Rayl]
P₀ = 1.0;                                       # Pressure of plane wave   [m/s]
l  = 1.0;                                       # Length of cube           [m]
k  = 2π*frequency/c;                            # Computing the wavenumber

Loading Mesh

Loading and visualizing the triangular cube mesh

mesh_file = joinpath(dirname(pathof(BoundaryIntegralEquations)),"..","examples","meshes","1m_cube_extra_coarse");
physics_orders  = [:linear,:geometry,:disctriconstant,:disctrilinear,:disctriquadratic];
mesh = load3dTriangularComsolMesh(mesh_file;geometry_order=:linear, physics_order=physics_orders[5])
bc_pre = [1] .- 1; # The .-1 is due to COMSOL 0-indexing of exported entities
bc_ane = [6] .- 1; # The .-1 is due to COMSOL 0-indexing of exported entities

Creating simple meshes for full mesh and boundary condition

simple_mesh = create_bc_simple_mesh(mesh,[bc_pre; bc_ane],false);
simple_pre  = create_bc_simple_mesh(mesh,bc_pre);
simple_ana  = create_bc_simple_mesh(mesh,bc_ane);

We now plot the mesh with the pressure condition shown in red and the anechoic condition shown in blue

fig = viz(simple_pre;showfacets=true,color=:red)
viz!(simple_mesh;showfacets=true,alpha=0.1)
viz!(simple_ana;showfacets=true,color=:blue)

Analytical Solution

The analytical description of the interior pressure of a planewave is given by

\[ p(x) = P_0\exp(-\mathrm{i}kx),\]

where $P_0$ is the magnitude of the planewave. We now compute the analytical expression is computed at the points

x_ana = collect(0.0:0.01:1)
p_analytical = P₀*exp.(-im*k*x_ana);

Solution using the dense BEM

We start by solving the BEM system using dense matrices. For this we need to first assemble the matrices

F,G,C = assemble_parallel!(mesh,k,mesh.sources,n=4,m=4,progress=false);
H  = Diagonal(C) - F; # Adding the integral free term

Now we find the correct indicies

bc_pre = 0 .== mesh.entities;
bc_ane = 5 .== mesh.entities;
bc1 = sort(unique(mesh.physics_topology[:,bc_pre]));
bc2 = sort(unique(mesh.physics_topology[:,bc_ane]));

First we define the $p=1$ bc at $x=0$

ps = zeros(ComplexF64,length(C));
ps[bc1] .= 1.0;
bs = -(H*ps); # Computing right-hand side

Then we define the anechoic condition at $x=1$.

Z = zeros(ComplexF64,length(C));
Z[bc1] .=  1.0;  # Unknown velocities
Z[bc2] .= -im*k; # Impedance condition
Hmask = ones(ComplexF64,length(C));
Hmask[bc1] .= 0.0; # Known pressures
A = H*Diagonal(Hmask) + G*Diagonal(-Z);

Using this we can solve for the surface pressure

z_bem = gmres(A,bs);

Extracting correct surface pressures

p_bem = copy(z_bem);
p_bem[bc1] .= 1.0;

Extracting correct surface velocities

v_bem = zeros(ComplexF64,length(C));
v_bem[bc1] = z_bem[bc1];
v_bem[bc2] = p_bem[bc2]*(-im*k);

Solution using the FMM-BEM

First we define the two operators

Gf = FMMGOperator(mesh,k,depth=2);
Ff = FMMFOperator(mesh,k,depth=2);
Hf = 0.5I - Ff;

Then we compute the right-hand side and the linear system similar to before. Note that the system matrix will be represented by a collection of linear maps

bf = -(Hf*ps);
Af = Hf*Diagonal(Hmask) + Gf*Diagonal(-Z)
1344×1344 LinearMaps.LinearCombination{ComplexF64} with 2 maps:
  1344×1344 LinearMaps.CompositeMap{ComplexF64} with 2 maps:
    1344×1344 LinearMaps.WrappedMap{ComplexF64} of
      1344×1344 LinearAlgebra.Diagonal{ComplexF64, Vector{ComplexF64}}
    1344×1344 LinearMaps.LinearCombination{ComplexF64} with 2 maps:
      1344×1344 LinearMaps.UniformScalingMap{Float64} with scaling factor: 0.5
      1344×1344 LinearMaps.ScaledMap{ComplexF64} with scale: -1 of
        1344×1344 BoundaryIntegralEquations.FMMFOperator{ComplexF64}
  1344×1344 LinearMaps.CompositeMap{ComplexF64} with 2 maps:
    1344×1344 LinearMaps.WrappedMap{ComplexF64} of
      1344×1344 LinearAlgebra.Diagonal{ComplexF64, Vector{ComplexF64}}
    1344×1344 BoundaryIntegralEquations.FMMGOperator{ComplexF64}

Similary to before we can now solve the linear system using an iterative scheme

z_fmm = gmres(Af,bf);

Finally we extract the pressure (and assert the pressures at boundary 1)

p_fmm = copy(z_fmm);
p_fmm[bc1] .= 1.0;

as well as the surface velocities

v_fmm = zeros(ComplexF64,length(C));
v_fmm[bc1] = z_fmm[bc1];
v_fmm[bc2] = p_fmm[bc2]*(-im*k);

Field evaluations

In order to compare the results with the analytical solution we must use the found surface pressures to compute pressure at the interior field points. We therefore start by creating a matrix of points (as columns). Thi is done by chosing $N$ linearly spaced points defined by $(x,0.5,0.5)$ with $x\in[0.1,0.9]$.

N = 20;
x = collect(0.1:(0.9-0.1)/(N-1):0.9);
y = 0.5ones(N);
z = 0.5ones(N);
X_fieldpoints = [x'; y'; z'];

Using the described field-points we can assemble the (dense) matrices for the field point evaluation

Fp,Gp,Cp = assemble_parallel!(mesh,k,X_fieldpoints,n=2,m=2,progress=false);

Using the matrices we can evalute the pressure at the field points using the previously found surface pressure

p_field  = Fp*p_bem + Gp*v_bem;
pf_field = Fp*p_fmm + Gp*v_fmm;

Plotting the field point pressure it can be seen that all 3 methods find the correct pressures

plot(x_ana,real.(p_analytical/P₀),  label="Re-Analytical")
scatter!(x,real.(p_field/P₀),   label="Re-Full", markershape=:rect)
scatter!(x,real.(pf_field/P₀),  label="Re-FMM")
plot!(x_ana,imag.(p_analytical/P₀), label="Im-Analytical")
scatter!(x,imag.(p_field/P₀),   label="Im-Full", markershape=:rect)
scatter!(x,imag.(pf_field/P₀),  label="Im-FMM")
xlabel!("r/a")

The surface pressures can also be plotted. Note that it is only possible to plot linear meshes, meaing that we must remove the quadratic parts.

data_mesh,data_viz = create_vizualization_data(mesh,p_fmm)
fig, ax, hm = viz(data_mesh;showfacets=true, color=real.(data_viz/P₀))
wgl.Colorbar(fig[1,2],label="Re(p/p₀)");


This page was generated using Literate.jl.