Cube with vibrating sides (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
wgl.set_theme!(resolution=(1600, 1600))

Setting up constants

frequency = 100.0;      # Frequency                [Hz]
c  = 343.0;             # Speed up sound           [m/s]
ρ₀ = 1.21;              # Mean density             [kg/m^3]
Z₀ = ρ₀*c;              # Characteristic impedance [Rayl]
v₀ = 1.0;               # Speed in the x-direction [m/s]
k  = 2π*frequency/c;    # Wavenumber

Loading and visualizing the triangular cube mesh

First we define the path to the mesh file

mesh_file = joinpath(dirname(pathof(BoundaryIntegralEquations)),"..","examples","meshes","1m_cube_extremely_coarse");

Now we read in the mesh

physics_orders  = [:linear,:geometry,:disctriconstant,:disctrilinear,:disctriquadratic];
mesh = load3dTriangularComsolMesh(mesh_file;geometry_order=:linear, physics_order=physics_orders[5])
Number of elements: 	 84
Number of unkowns:  	 504
Geometry defined by:	 BoundaryIntegralEquations.TriangularLinear{Float64}
Physics defined by: 	 BoundaryIntegralEquations.DiscontinuousTriangularQuadratic{Float64}

We now define the mesh entity that contain the boundary condition. In this case it is boundary 0.

bc_ents = [0];

Now two simple meshes is created. One for the boundary condition and one for the remaining part of the mesh

simple_bc   = create_bc_simple_mesh(mesh,bc_ents);
simple_mesh = create_bc_simple_mesh(mesh,bc_ents,false);

Using the simple meshes we can visualize the mesh, with boundary 0 (where velocity condition will be applied) shown in red

fig = viz(simple_mesh;showfacets=true)
viz!(simple_bc;showfacets=true,color=:red)

Analytical Solution

The analytical description of the interior pressure in unit cube with the side at $x=0$ be applied a velocity of $v_{0}$

\[ p_\text{analytical}(x) = -\frac{\mathrm{i}Z_0v_{0}\cos(k(1 - x))}{\sin(k)}\]

where $Z_0$ is the characteristic impedance and $k$ is the wavenumber. We now compute the analytical expression is computed at the points

x_ana = collect(0.00:0.01:1)
p_analytical = -im*Z₀*v₀*cos.(k*(1 .- x_ana))/(sin(k));

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

In order to apply the boundary coniditon we must find the nodes corresponding to surface entity 0

bc_elements = 0 .== mesh.entities;
bc2 = sort(unique(mesh.physics_topology[:,bc_elements]));

We now define a vector corresponding to the velocities at bc2

v_bem = zeros(ComplexF64,length(C));
v_bem[bc2] .= im*Z₀*k*v₀*mesh.normals[1,bc2];

Using this we can define the right-hand side

b = G*v_bem;

Finally the pressures can be computed by solving a linear system of equations

p_bem = gmres(H,b;verbose=true);
=== gmres ===
rest	iter	resnorm
  1	  1	1.87e+03
  1	  2	9.34e+02
  1	  3	5.08e+02
  1	  4	1.82e+02
  1	  5	8.10e+01
  1	  6	3.87e+01
  1	  7	1.92e+01
  1	  8	7.68e+00
  1	  9	3.56e+00
  1	 10	1.37e+00
  1	 11	6.31e-01
  1	 12	2.55e-01
  1	 13	1.52e-01
  1	 14	6.56e-02
  1	 15	4.23e-02
  1	 16	1.67e-02
  1	 17	8.77e-03
  1	 18	3.87e-03
  1	 19	1.79e-03
  1	 20	1.09e-03
  2	  1	7.55e-04
  2	  2	4.27e-04
  2	  3	3.52e-04
  2	  4	3.14e-04
  2	  5	1.64e-04
  2	  6	8.69e-05
  2	  7	3.65e-05
  2	  8	1.99e-05

Solution using the FMM-BEM

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

Gf = FMMGOperator(mesh,k,depth=2);
Ff = FMMFOperator(mesh,k,depth=2);
Hf = 0.5I - Ff;
bf = Gf*v_bem;                     # Computing right-hand side
p_fmm = gmres(Hf,bf;verbose=true); # Solving the linear system
=== gmres ===
rest	iter	resnorm
  1	  1	1.87e+03
  1	  2	7.28e+02
  1	  3	1.83e+02
  1	  4	5.64e+01
  1	  5	1.38e+01
  1	  6	2.95e+00
  1	  7	9.62e-01
  1	  8	2.50e-01
  1	  9	6.49e-02
  1	 10	2.44e-02
  1	 11	7.74e-03
  1	 12	2.61e-03
  1	 13	1.01e-03
  1	 14	2.21e-04
  1	 15	7.88e-05
  1	 16	2.60e-05

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). Below $N$ linearly spaced points defined by $(x,0.5,0.5)$ with $x\in[0.1,0.9]$ is created.

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=5,m=5,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_bem;

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

plot(x_ana,abs.(p_analytical./Z₀), label="Analytical")
scatter!(x,abs.(p_field./Z₀),  label="Full", markershape=:rect)
scatter!(x,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.