NiHu
2.0
|
This tutorial explains how to use NiHu for evaluating the Rayleigh integral. The Rayleigh integral describes acoustic radiation from an infinite vibrating plane.
In this tutorial, we learn how to connect NiHu with Matlab. The problem geometry and parameters will be imported from, and the results will be passed back to Matlab using NiHu's Matlab interface.
The Rayleigh integral computes the acoustic pressure \( p({\bf x}) \) radiated from a vibrating planar surface \( S \) embedded into an infinite rigid plane. The vibrating surface is characterised by its normal velocity function \( v({\bf y}) \). The radiated pressure is evaluated as
\( \displaystyle p({\bf x}) = \int_S G({\bf x}, {\bf y}) v({\bf y}) dS_y = \left(\mathcal{G}v\right)_S({\bf x}) , \)
where \( G \) denotes the fundamental solution of the Helmholtz equation in 3D
\( G({\bf x}, {\bf y}) = \exp(-\mathrm{i}kr)/4\pi r, \quad r = |{\bf y} - {\bf x}| . \)
The velocity field on the surface \( S \) is discretised using piecewise constant or isoparametric interpolation functions:
\( v({\bf y}) = \sum_j w_j({\bf y}) v_j \)
The radiated pressure (the Rayleigh integral) is evaluated in a set of field points \( {\bf x}_i \). For later convenience, we consider the field points as locations in a so called field point domain \( F \). Evaluating the pressure in the field points is equivalent to pre-multiplying the Rayleigh integral with Dirac delta functions located at the field points \( {\bf x}_i \) and integrating with respect to the variable \( {\bf x} \) over the field point domain:
\( \displaystyle p({\bf x}_i) = \sum_j \left(\mathcal{G}w_j \right)_S({\bf x}_i) \cdot v_j = \sum_j \left< \delta_{{\bf x}_i}, \left(\mathcal{G}w_j \right)_S \right>_F \cdot v_j = \sum_j Z_{ij} v_j , \)
where \( Z_{ij} \) denotes the transfer impedance matrix.
Our program is organised as follows:
We need three modules from the NiHu library
We further define two typedef
s for Matlab matrices NiHu::mex::real_matrix and NiHu::mex::complex_matrix. These matrices are allocated in Matlab's memory, in Matlab format, but are used by NiHu just as if they were C++ Eigen matrices.
Our executable code will be called from Matlab using the syntax
[Z_trans, Z_rad] = rayleigh_integral_3d(surf_nodes, surf_elements, field_nodes, field_elements, wave_number);
The input and output arguments are catched by the C++ function mexFunction
whose parameters are
nlhs
the number of left hand side (output) parameters (two in our case)lhs
array of pointers pointing to the Matlab memory, where the output arguments (Z_trans
and Z_rad
) are allocatednrhs
the number of right hand side input parameters (five in our case)rhs
array of pointers pointing to the Matlab memory, where the five input arguments are allocatedThe radiator surface mesh and the field point mesh is instantiated in C++ as follows:
dMatrix
). The class' constructor refers to the Matlab input pointer. The resulting dMatrix
objects are light-weight interfaces (views) providing convenient indexing capabilities for the Matlab data.The function spaces are generated from the two meshes as follows:
We instantiate the integral operator \( \mathcal{G} \) using the Helmholtz kernel as follows:
mxGetPr
that returns a pointer to the real data.double
). The abbreviation SLP refers to the single layer potential.We allocate memory for the output complex matrices:
cMatrix
) allocates a Matlab output matrix of given dimensions in Matlab memory.The weighted double integrals are evaluated using the operator notations:
The two last lines of code are syntactically identical, but there is a great difference.
The complete source of the C++ code is found here: tutorial/rayleigh_integral_3d.mex.cpp
The compiled executable can be called from Matlab, as demonstrated in the example below:
The generated plot looks like