Pulsating sphere (Interior)

Importing related packages

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

Setting up constants

frequency = 54.59;      # Frequency                [Hz]
c  = 343.0;             # Speed up sound           [m/s]
ρ₀ = 1.21;              # Mean density             [kg/m^3]
Z₀ = ρ₀*c;              # Characteristic impedance [Rayl]
vr = 1.0;               # Speed in the r-direction [m/s]
a  = 1.0;               # Radius of sphere_1m      [m]
k  = 2π*frequency/c;    # Wavenumber

Loading Mesh

Loading and visualizing the triangular (spherical) mesh

mesh_file = joinpath(dirname(pathof(BoundaryIntegralEquations)),"..","examples","meshes","sphere_1m_coarse");
mesh = load3dTriangularComsolMesh(mesh_file)
Number of elements: 	 464
Number of unkowns:  	 930
Geometry defined by:	 BoundaryIntegralEquations.TriangularQuadratic{Float64}
Physics defined by: 	 BoundaryIntegralEquations.TriangularQuadratic{Float64}

Analytical Solution

The analytical description of the interior pressure of an z-oscilating sphere is given by

\[ p_\text{analytical}(r) = \mathrm{i}Z_0v_r\left(\frac{a}{r}\right)\frac{ka\sin(kr)}{ka\cos(ka) - \sin(ka)}\]

where $a$ is the sphere radius and $r (\leq a)$ is the distance from origo to the point $(x,y,z)$. From this the analytical expression is computed

z_ana = 0:0.01:1
p_analytical = im*Z₀*vr*(a./z_ana).*(k*a*sin.(k*z_ana))/(k*a*cos(k*a) - sin(k*a));

Solution using the 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=2,m=2,progress=false);
H  = Diagonal(1.0 .- C) - F; # Adding the integral free term

We now setup the right-hand side

vs = im*Z₀*k*vr*ones(length(C));
b  = G*vs; # Computing right-hand side

Using this we can solve for the surface pressure

p_bem = gmres(H,b;verbose=true);
=== gmres ===
rest	iter	resnorm
  1	  1	1.05e+01
  1	  2	4.39e-01
  1	  3	1.89e-02
  1	  4	3.52e-03
  1	  5	1.75e-04
  1	  6	8.42e-06

Similarly we can compute the BEM solution using the Fast Multipole Operators

Gf = FMMGOperator(mesh,k);
Ff = FMMFOperator(mesh,k);
Hf = Diagonal(1.0 .- C) - Ff;
bf = Gf*vs;                        # Computing right-hand side
p_fmm = gmres(Hf,bf;verbose=true); # Solving the linear system
=== gmres ===
rest	iter	resnorm
  1	  1	8.63e+00
  1	  2	3.97e-01
  1	  3	1.12e-02
  1	  4	2.03e-03
  1	  5	1.68e-04
  1	  6	7.99e-06

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 $N$ points (as columns)

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

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

Fp,Gp,_ = 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*vs;
pf_field = Fp*p_fmm + Gp*vs;

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

plot(z_ana,abs.(p_analytical./Z₀),label="Analytical")
scatter!(z,abs.(p_field./Z₀),  label="Full", markershape=:rect)
scatter!(z,abs.(pf_field./Z₀), label="FMM")
ylabel!("p/Z₀"); 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=abs.(data_viz/Z₀))
wgl.Colorbar(fig[1,2],label="|p/Z₀|");


This page was generated using Literate.jl.