241 *
#include <deal.II/base/conditional_ostream.h>
242 *
#include <deal.II/base/function.h>
243 *
#include <deal.II/base/index_set.h>
244 *
#include <deal.II/base/tensor.h>
245 *
#include <deal.II/base/utilities.h>
247 *
#include <deal.II/dofs/dof_handler.h>
248 *
#include <deal.II/dofs/dof_tools.h>
250 *
#include <deal.II/fe/fe_nothing.h>
251 *
#include <deal.II/fe/fe_q.h>
252 *
#include <deal.II/fe/fe_system.h>
253 *
#include <deal.II/fe/fe_values.h>
255 *
#include <deal.II/grid/grid_in.h>
256 *
#include <deal.II/grid/grid_out.h>
257 *
#include <deal.II/grid/grid_tools.h>
259 *
#include <deal.II/lac/affine_constraints.h>
260 *
#include <deal.II/lac/full_matrix.h>
261 *
#include <deal.II/lac/generic_linear_algebra.h>
262 *
#include <deal.II/lac/petsc_solver.h>
263 *
#include <deal.II/lac/vector.h>
265 *
#include <deal.II/numerics/data_out.h>
266 *
#include <deal.II/numerics/vector_tools.h>
268 *
#include <filesystem>
270 *
#include <iostream>
274 *
namespace VibroAcousticProblem
279 * geometric tolerance
282 *
constexpr double geom_tol = 1
e-10;
288 * By
default, boundary indicators are 0
306 *
return the isotropic loss factor
309 *
std::complex<double>
312 *
return std::complex<double>{1., 0.01};
317 * calculation of the linear strain tensor
323 *
const unsigned int shape_func,
324 *
const unsigned int q_point)
328 *
for (
unsigned int i = 0; i < dim; ++i)
329 *
tmp[i][i] = fe_values.shape_grad_component(shape_func, q_point, i)[i];
331 *
for (
unsigned int i = 0; i < dim; ++i)
332 *
for (
unsigned int j = i + 1; j < dim; ++j)
334 *
(fe_values.shape_grad_component(shape_func, q_point, i)[j] +
335 *
fe_values.shape_grad_component(shape_func, q_point, j)[i]) /
343 * Returning the stiffness tensor of the wall
348 *
get_stiffness_tensor()
350 *
const double E = 31600. * 1e6;
351 *
const double v = 0.2;
352 *
double lambda = v / (1 - 2 * v) * 1 / (1 + v) *
E;
353 *
double mu = 0.5 * 1 / (1 + v) * E;
356 *
for (
unsigned int i = 0; i < dim; ++i)
357 *
for (
unsigned int j = 0; j < dim; ++j)
358 *
for (
unsigned int k = 0; k < dim; ++k)
359 *
for (
unsigned int l = 0;
l < dim; ++
l)
360 *
stiffness_tensor[i][j][k][l] =
361 *
(((i == k) && (j ==
l) ? mu : 0.0) +
362 *
((i ==
l) && (j == k) ?
mu : 0.0) +
363 *
((i == j) && (k ==
l) ?
lambda : 0.0));
364 *
return stiffness_tensor;
369 * Returning the density of the wall
373 *
get_density_structure()
375 *
return 2.275 * 1
e-3;
380 * Returning the density of air
386 *
return 1.204 * 1
e-6;
391 * Returning the speed of sound
402 * Implementation of a perfectly matched layer
406 *
class PML :
public Function<dim, std::complex<double>>
409 *
explicit PML(
double omega)
415 *
, pml_coeff_degree(2.0)
416 *
, pml_coeff(1.e4 / omega)
426 *
b_neg[0] = std::numeric_limits<double>::lowest();
436 *
b_neg[1] = -1826.0;
446 *
b_neg[2] = -2591.0;
453 * calculates the
value of the complex coordinate stretch
458 *
Vector<std::complex<double>> &value)
const override;
463 *
std::array<double, dim> b_pos, b_neg;
464 *
std::array<double, dim> t_pos, t_neg;
466 *
double pml_coeff_degree;
473 *
Vector<std::complex<double>> &value)
const
477 *
for (
unsigned int d = 0;
d < dim; ++
d)
479 *
double coeff = 0.0;
481 *
if (p[d] > b_pos[d])
483 *
const double x_prime = p[
d] - b_pos[
d];
484 *
const double a_coeff =
485 *
pml_coeff /
std::pow(t_pos[d], pml_coeff_degree);
486 *
coeff = a_coeff *
std::pow(x_prime, pml_coeff_degree);
488 *
else if (p[d] < b_neg[d])
490 *
const double x_prime = b_neg[
d] - p[
d];
491 *
const double a_coeff =
492 *
pml_coeff /
std::pow(t_neg[d], pml_coeff_degree);
493 *
coeff = a_coeff *
std::pow(x_prime, pml_coeff_degree);
498 * complex coordinate stretching: s = 1 + i * sigma(x)
501 *
value[
d] = std::complex<double>(1.0, coeff);
507 * Creation of a diffuse sound field
for excitation of the wall on the source
512 *
class DiffuseSoundField :
public Function<dim, std::complex<double>>
515 *
DiffuseSoundField(
unsigned int N,
double omega,
MPI_Comm mpi_communicator)
519 *
, dist_0_1(0.0, 1.)
520 *
, generator(
static_cast<int>(omega))
525 * Only let
one rank 0 create the
random variables of the diffuse sound
529 *
const unsigned int rank =
536 *
for (
unsigned int n = 0; n <
N; ++n)
538 *
phi[n] = dist_0_2PI(generator);
539 *
Phi[n] =
std::acos(dist_0_1(generator));
540 *
phase[n] = dist_0_2PI(generator);
545 * ... and
broadcast from rank 0 to all ranks.
554 * Generation of kn on all ranks
557 *
for (
unsigned int n = 0; n <
N; n++)
559 *
double scale = (omega / get_sound_speed());
564 *
k_vector.push_back(k);
569 * Calculation of the total pressure on the source side
574 *
std::vector<std::complex<double>> &values,
575 *
const unsigned int component = 0)
const override;
579 * Calculation of the
gradient of the total pressure on the source side
584 *
std::vector<
Tensor<1, dim, std::complex<double>>> &gradients,
585 *
const unsigned int component = 0)
const override;
589 * Calculation of the incident sound pressure on the source side
593 *
value_list_incidence(
const std::vector<
Point<dim>> &points,
594 *
std::vector<std::complex<double>> &values,
595 *
const unsigned int component = 0)
const;
609 *
std::uniform_real_distribution<double> dist_0_2PI;
610 *
std::uniform_real_distribution<double> dist_0_1;
611 *
std::mt19937 generator;
615 * variables of the diffuse field
618 *
std::vector<double> phi, Phi, phase, kn_x, kn_y, kn_z;
619 *
std::vector<Tensor<1, dim, double>> k_vector;
631 *
DiffuseSoundField<dim>::value_list(
const std::vector<
Point<dim>> &points,
632 *
std::vector<std::complex<double>> &values,
633 *
const unsigned int component)
const
635 *
AssertThrow(component == 0, ExcMessage(
"only component 0 is implemented"));
636 *
values.resize(points.size());
637 *
std::complex<double> j{0., 1.};
639 *
for (
unsigned int q = 0; q < points.size(); ++q)
641 *
const auto &q_p = points[q];
643 *
for (
unsigned int n = 0; n <
N; n++)
647 * sound waves traveling towards the wall...
650 *
double dot_towards = 0.;
651 *
double dot_reflection = 0.;
653 *
for (
unsigned int d = 0;
d < dim;
d++)
657 * sound waves traveling towards the wall...
660 *
dot_towards += k_vector[n][
d] * q_p[
d];
663 * ... and reflections.
668 *
dot_reflection -= k_vector[n][
d] * q_p[
d];
672 *
dot_reflection += k_vector[n][
d] * q_p[
d];
677 * sound waves traveling towards the wall...
683 * ... and reflections.
694 *
DiffuseSoundField<dim>::value_list_incidence(
696 *
std::vector<std::complex<double>> &values,
697 *
const unsigned int component)
const
699 *
AssertThrow(component == 0, ExcMessage(
"only component 0 is implemented"));
701 *
values.resize(points.size());
702 *
std::complex<double> j{0., 1.};
703 *
for (
unsigned int q = 0; q < points.size(); ++q)
705 *
const auto &q_p = points[q];
707 *
for (
unsigned int n = 0; n <
N; n++)
711 * Only sound waves traveling towards the wall.
714 *
double dot_towards = 0.;
715 *
for (
unsigned int d = 0;
d < dim;
d++)
719 * Sound waves traveling towards the wall.
722 *
dot_towards += k_vector[n][
d] * q_p[
d];
726 * Only sound waves traveling towards the wall.
737 *
DiffuseSoundField<dim>::gradient_list(
739 *
std::vector<
Tensor<1, dim, std::complex<double>>> &gradients,
740 *
const unsigned int component)
const
742 *
AssertThrow(component == 0, ExcMessage(
"only component 0 is implemented"));
745 *
const std::complex<double> j{0.0, 1.0};
746 *
for (
unsigned int q = 0; q < points.size(); ++q)
748 *
const auto &q_p = points[q];
749 *
for (
unsigned int d = 0;
d < dim; ++
d)
750 *
gradients[q][d] = 0.;
752 *
for (
unsigned int n = 0; n <
N; ++n)
755 *
for (
unsigned int d = 0;
d < dim; ++
d)
756 *
dot += k_vector[n][d] * q_p[d];
758 *
const std::complex<double> exp_term =
759 *
std::exp(-j * dot + j * phase[n]);
761 *
for (
unsigned int d = 0;
d < dim; ++
d)
762 *
gradients[q][d] += (-j * k_vector[n][d]) * exp_term *
763 *
(1. /
std::sqrt(2. *
static_cast<double>(N))) *
770 *
class HarmonicResponse
773 *
HarmonicResponse(
double omega);
775 *
run(
bool write_output =
false);
787 * calculate the magnitude of u and p
791 *
calculate_magnitude();
795 * calculation of sound power at receiver side
for one cell
799 *
cell_receiver_sound_power(
802 *
const double &omega);
806 * calculation of sound power at sender side
810 *
incident_sound_power();
813 * calculation of sound power at receiver side
817 *
receiver_sound_power();
820 * Assemble the air-structure coupling terms
821 * This function implements the assembly of the air-structure interface.
825 *
assemble_air_structure_interface_term(
828 *
FullMatrix<std::complex<double>> &local_interface_matrix,
829 *
const double &omega);
834 *
const QGauss<dim> quadrature_formula_structure, quadrature_formula_air;
835 *
const QGauss<dim - 1> face_quadrature_formula_structure,
836 *
face_quadrature_formula_air;
852 *
const double omega;
853 *
DiffuseSoundField<dim> field;
858 *
HarmonicResponse<dim>::HarmonicResponse(
double omega)
859 *
: mpi_communicator(MPI_COMM_WORLD)
860 *
, triangulation(mpi_communicator,
866 *
, quadrature_formula_structure(fe_structure.degree + 1)
867 *
, quadrature_formula_air(fe_air.degree + 1)
868 *
, face_quadrature_formula_structure(fe_structure.degree + 1)
869 *
, face_quadrature_formula_air(fe_air.degree + 1)
870 *
, dof_handler(triangulation)
874 *
, field(1.e3, omega, mpi_communicator)
877 *
static_assert(dim == 3,
878 *
"HarmonicResponse is only implemented for dim == 3");
879 *
fe_collection.push_back(fe_structure);
880 *
fe_collection.push_back(fe_air);
881 *
q_collection.push_back(quadrature_formula_structure);
882 *
q_collection.push_back(quadrature_formula_air);
883 *
q_face_collection.push_back(face_quadrature_formula_structure);
884 *
q_face_collection.push_back(face_quadrature_formula_air);
889 *
HarmonicResponse<dim>::setup_system()
893 * Set material
id and active FE indices.
896 *
for (
const auto &cell : dof_handler.cell_iterators())
898 *
cell->set_material_id(static_cast<unsigned
int>(MaterialID::Concrete));
900 *
if ((cell->center()[0] - 203.) > 0.)
902 *
cell->set_material_id(
static_cast<unsigned int>(MaterialID::Air));
905 *
for (
const auto &cell : dof_handler.active_cell_iterators())
907 *
if (cell->is_locally_owned())
909 *
cell->set_active_fe_index(
910 *
static_cast<unsigned
int>(MaterialID::Concrete));
912 *
if ((cell->center()[0] - 203.) > 0.)
914 *
if (cell->is_locally_owned())
916 *
cell->set_active_fe_index(
917 *
static_cast<unsigned int>(MaterialID::Air));
923 * Definition of FE space
926 *
dof_handler.distribute_dofs(fe_collection);
927 *
pcout <<
" Number of degrees of freedom = " << dof_handler.n_dofs()
930 *
locally_owned_dofs = dof_handler.locally_owned_dofs();
931 *
locally_relevant_dofs.clear();
934 *
locally_relevant_solution.reinit(locally_owned_dofs,
935 *
locally_relevant_dofs,
937 *
locally_relevant_magnitude.reinit(locally_owned_dofs, mpi_communicator);
938 *
system_rhs.reinit(locally_owned_dofs, mpi_communicator);
945 *
constraints.clear();
946 *
constraints.reinit(locally_owned_dofs, locally_relevant_dofs);
954 *
for (
const auto &cell : dof_handler.active_cell_iterators())
956 *
if (cell->is_locally_owned())
958 *
for (unsigned
int f = 0; f < cell->n_faces(); ++f)
960 *
const auto face = cell->face(f);
961 *
const auto p = face->center();
962 *
if (
std::abs(p[0] - 203.) < geom_tol &&
963 *
(cell->material_id() ==
964 *
static_cast<unsigned int>(MaterialID::Concrete)))
966 *
cell->face(f)->set_user_index(
967 *
static_cast<unsigned int>(SurfaceID::ReceiverSide));
971 *
cell->face(f)->set_user_index(
972 *
static_cast<unsigned int>(SurfaceID::SourceSide) &&
973 *
(cell->material_id() ==
974 *
static_cast<unsigned int>(MaterialID::Concrete)));
976 *
if (cell->face(f)->at_boundary())
978 *
if ((p[0] + geom_tol) < 203. && p[0] > geom_tol)
980 *
cell->face(f)->set_boundary_id(
981 *
static_cast<unsigned int>(SurfaceID::FixedBoundary));
983 *
if (
std::abs(p[0] - 1312.) < geom_tol &&
984 *
cell->material_id() ==
985 *
static_cast<unsigned int>(MaterialID::Air))
987 *
cell->face(f)->set_boundary_id(
988 *
static_cast<unsigned int>(SurfaceID::ZeroPressure));
996 * The wall is fixed at its outer boundary
1004 *
static_cast<unsigned int>(SurfaceID::FixedBoundary),
1007 *
component_mask_displacement);
1008 *
constraints.close();
1014 *
locally_owned_dofs,
1016 *
locally_relevant_dofs);
1017 *
system_matrix.reinit(locally_owned_dofs,
1018 *
locally_owned_dofs,
1020 *
mpi_communicator);
1023 *
template <
int dim>
1025 *
HarmonicResponse<dim>::assemble_system()
1038 *
q_face_collection,
1045 * Common face quadrature
1048 *
const QGauss<dim - 1> common_face_quadrature(fe_collection.max_degree() +
1052 * FE face
values for surface integration
1056 *
common_face_quadrature,
1061 *
common_face_quadrature,
1067 *
common_face_quadrature,
1074 *
common_face_quadrature,
1080 * Local element
matrix for a cell
1086 * Local
interface matrix between air and structure DoFs
1090 *
fe_air.n_dofs_per_cell(), fe_structure.n_dofs_per_cell());
1098 *
std::vector<types::global_dof_index> local_dof_indices;
1099 *
std::vector<types::global_dof_index> neighbor_dof_indices;
1103 *
for (
const auto &cell : dof_handler.active_cell_iterators())
1105 *
if (cell->is_locally_owned())
1109 * Assemble air cells contributions
1113 *
static_cast<unsigned
int>(MaterialID::Air))
1117 *
hp_fe_values.reinit(cell);
1121 *
const unsigned int dofs_per_cell = fe_air.n_dofs_per_cell();
1123 *
cell_matrix.reinit(dofs_per_cell, dofs_per_cell);
1124 *
cell_rhs.reinit(dofs_per_cell);
1125 *
local_dof_indices.resize(dofs_per_cell);
1126 *
neighbor_dof_indices.resize(fe_structure.n_dofs_per_cell());
1127 *
const double sound_speed = get_sound_speed();
1134 *
const std::complex<double> k = (omega / sound_speed);
1136 *
for (
unsigned int q = 0; q < n_q_points; ++q)
1138 *
const auto JxW = fe_values.JxW(q);
1139 *
const Point<dim> &q_point = fe_values.quadrature_point(q);
1142 * calucalte
lambda and
J for PML
1146 *
pml.vector_value(q_point, lambda);
1147 *
const std::complex<double>
J =
1150 *
for (
unsigned int i = 0; i < dofs_per_cell; ++i)
1152 *
const double phi_i = fe_values[pressure].value(i, q);
1156 * Gradient of phi_i, which is multiplied by 1/
lambda
1160 *
fe_values[pressure].gradient(i, q);
1161 *
for (
unsigned int d = 0;
d < dim; ++
d)
1162 *
phi_i_i[d] *= 1.0 / lambda[d];
1164 *
for (
unsigned int j = 0; j < dofs_per_cell; ++j)
1166 *
const double phi_j =
1167 *
fe_values[pressure].value(j, q);
1171 * Gradient of phi_j, which is multiplied by
1176 *
fe_values[pressure].gradient(j, q);
1177 *
for (
unsigned int d = 0;
d < dim; ++
d)
1178 *
phi_j_j[d] *= 1.0 / lambda[d];
1181 *
cell_matrix[i][j] -= Utilities::fixed_power<2>(k) *
1182 *
phi_i * phi_j * JxW *
J;
1188 *
assemble local system to global system.
1191 *
cell->get_dof_indices(local_dof_indices);
1192 *
constraints.distribute_local_to_global(cell_matrix,
1194 *
local_dof_indices,
1200 * Here, the air-structure
interface is considered. Similar to
1201 * step 46, 3 possibilities exist: The neighbor is
1202 * at the same refinement
level and has no children, the
1203 * neighbor has children and the neighbor is coarser.
1206 *
for (
const auto f : cell->face_indices())
1208 *
if (!cell->at_boundary(f))
1210 *
const auto neighbor = cell->neighbor(f);
1211 *
if (neighbor->material_id() ==
1212 *
static_cast<unsigned int>(MaterialID::Concrete))
1216 *
if (neighbor->center()[0]<203.)
1222 * The neighbor is at the same refinement
level and
1226 *
if ((cell->neighbor(f)->level() == cell->level()) &&
1227 *
(cell->neighbor(f)->has_children() ==
false))
1229 *
air_fe_face_values.reinit(cell, f);
1230 *
elasticity_fe_face_values.reinit(
1231 *
cell->neighbor(f),
1232 *
cell->neighbor_of_neighbor(f));
1233 *
assemble_air_structure_interface_term(
1234 *
elasticity_fe_face_values,
1235 *
air_fe_face_values,
1236 *
local_interface_matrix,
1238 *
cell->neighbor(f)->get_dof_indices(
1239 *
neighbor_dof_indices);
1240 *
constraints.distribute_local_to_global(
1241 *
local_interface_matrix,
1242 *
local_dof_indices,
1243 *
neighbor_dof_indices,
1248 * The neighbor has children.
1251 *
else if ((cell->neighbor(f)->level() ==
1253 *
(cell->neighbor(f)->has_children() ==
1256 *
for (
unsigned int subface = 0;
1257 *
subface < cell->face(f)->n_children();
1260 *
air_fe_sub_face_values.reinit(cell,
1263 *
elasticity_fe_face_values.reinit(
1264 *
cell->neighbor_child_on_subface(f,
1266 *
cell->neighbor_of_neighbor(f));
1267 *
assemble_air_structure_interface_term(
1268 *
elasticity_fe_face_values,
1269 *
air_fe_sub_face_values,
1270 *
local_interface_matrix,
1272 *
cell->neighbor_child_on_subface(f, subface)
1273 *
->get_dof_indices(neighbor_dof_indices);
1274 *
constraints.distribute_local_to_global(
1275 *
local_interface_matrix,
1276 *
local_dof_indices,
1277 *
neighbor_dof_indices,
1283 * The neighbor is coarser.
1286 *
else if (cell->neighbor_is_coarser(f))
1288 *
air_fe_face_values.reinit(cell, f);
1289 *
elasticity_fe_sub_face_values.reinit(
1290 *
cell->neighbor(f),
1291 *
cell->neighbor_of_coarser_neighbor(f).first,
1292 *
cell->neighbor_of_coarser_neighbor(f).second);
1293 *
assemble_air_structure_interface_term(
1294 *
elasticity_fe_sub_face_values,
1295 *
air_fe_face_values,
1296 *
local_interface_matrix,
1298 *
cell->neighbor(f)->get_dof_indices(
1299 *
neighbor_dof_indices);
1300 *
constraints.distribute_local_to_global(
1301 *
local_interface_matrix,
1302 *
local_dof_indices,
1303 *
neighbor_dof_indices,
1312 * Assemble structure cells contributions
1315 *
else if (cell->is_locally_owned() &&
1316 *
cell->material_id() ==
1317 *
static_cast<unsigned int>(MaterialID::Concrete))
1321 *
hp_fe_values.reinit(cell);
1325 *
const unsigned int dofs_per_cell =
1326 *
fe_structure.n_dofs_per_cell();
1328 *
cell_matrix.reinit(dofs_per_cell, dofs_per_cell);
1329 *
cell_rhs.reinit(dofs_per_cell);
1330 *
local_dof_indices.resize(dofs_per_cell);
1331 *
neighbor_dof_indices.resize(fe_air.n_dofs_per_cell());
1334 *
get_stiffness_tensor<dim>();
1335 *
const double density = get_density_structure();
1336 *
const std::complex<double> iso_loss = get_iso_loss();
1338 *
for (
unsigned int q = 0; q < n_q_points; ++q)
1340 *
const auto JxW = fe_values.JxW(q);
1341 *
for (
unsigned int i = 0; i < dofs_per_cell; ++i)
1344 *
fe_values[displacement].value(i, q);
1345 *
for (
unsigned int j = 0; j < dofs_per_cell; ++j)
1348 *
fe_values[displacement].value(j, q);
1350 *
get_strain(fe_values, i, q);
1352 *
get_strain(fe_values, j, q);
1353 *
cell_matrix[i][j] += eps_phi_i * stiffness_tensor *
1354 *
iso_loss * eps_phi_j * JxW;
1356 *
Utilities::fixed_power<2>(omega) * phi_j * phi_i *
1363 * Here the diffuse sound field is considered on the source side
1367 *
for (
const auto face_no : cell->face_indices())
1369 *
if (cell->face(face_no)->user_index() ==
1370 *
static_cast<unsigned
int>(SurfaceID::SourceSide))
1372 *
hp_fe_face_values.
reinit(cell, face_no);
1375 *
const unsigned int n_face_q_points =
1377 *
for (
unsigned int i = 0; i < dofs_per_cell; ++i)
1379 *
if (fe_structure.has_support_on_face(i, face_no))
1381 *
std::vector<std::complex<double>> pressure(
1383 *
const auto face_quadrature_points =
1384 *
fe_face_values.get_quadrature_points();
1385 *
field.value_list(face_quadrature_points,
1388 *
for (
unsigned int q = 0; q < n_face_q_points;
1391 *
const auto JxW = fe_face_values.JxW(q);
1393 *
fe_face_values[displacement].value(i, q);
1395 *
-fe_face_values.normal_vector(q);
1396 *
cell_rhs[i] += pressure[q] *
1397 *
(NormalVector * phi_i) * JxW;
1403 *
cell->get_dof_indices(local_dof_indices);
1404 *
constraints.distribute_local_to_global(cell_matrix,
1406 *
local_dof_indices,
1416 *
template <
int dim>
1418 *
HarmonicResponse<dim>::assemble_air_structure_interface_term(
1421 *
FullMatrix<std::complex<double>> &local_interface_matrix,
1422 *
const double &omega)
1426 *
local_interface_matrix = 0;
1427 *
const auto density_air = get_density_air();
1428 *
const unsigned int n_face_quadrature_points =
1429 *
air_fe_face_values.n_quadrature_points;
1431 *
for (
unsigned int q = 0; q < n_face_quadrature_points; ++q)
1434 *
-air_fe_face_values.normal_vector(q);
1435 *
for (
unsigned int i = 0; i < air_fe_face_values.dofs_per_cell; ++i)
1437 *
const double phi_i = air_fe_face_values[pressure].value(i, q);
1438 *
for (
unsigned int j = 0;
1439 *
j < elasticity_fe_face_values.dofs_per_cell;
1443 *
elasticity_fe_face_values[displacement].value(j, q);
1444 *
local_interface_matrix[i][j] +=
1445 *
density_air * Utilities::fixed_power<2>(omega) * phi_i *
1446 *
normalVectorStructure * phi_j * air_fe_face_values.JxW(q);
1447 *
local_interface_matrix[i][j] +=
1448 *
phi_j * normalVectorStructure * phi_i *
1449 *
elasticity_fe_face_values.JxW(q);
1457 * calculation of incident sound power on the source side
1460 *
template <
int dim>
1462 *
HarmonicResponse<dim>::incident_sound_power()
1466 *
face_quadrature_formula_structure,
1469 *
std::vector<types::global_dof_index> local_dof_indices;
1471 *
double sound_power = 0.;
1472 *
const double density_air = get_density_air();
1473 *
for (
const auto &cell : dof_handler.active_cell_iterators())
1475 *
if (cell->is_locally_owned())
1477 *
for (
const auto face_no : cell->face_indices())
1479 *
if (cell->face(face_no)->at_boundary() &&
1480 *
(cell->face(face_no)->user_index() ==
1481 *
static_cast<unsigned
int>(SurfaceID::SourceSide)) &&
1483 *
static_cast<unsigned
int>(MaterialID::Concrete)))
1485 *
structure_fe_face_values.
reinit(cell, face_no);
1486 *
const unsigned int n_face_q_points =
1487 *
structure_fe_face_values.n_quadrature_points;
1488 *
std::vector<std::complex<double>> pressure(n_face_q_points);
1489 *
const auto face_quadrature_points =
1490 *
structure_fe_face_values.get_quadrature_points();
1491 *
field.value_list_incidence(face_quadrature_points,
1493 *
std::vector<Tensor<1, dim, std::complex<double>>>
1494 *
pressure_gradients(n_face_q_points);
1495 *
field.gradient_list(face_quadrature_points,
1496 *
pressure_gradients);
1497 *
for (
unsigned int q = 0; q < n_face_q_points; ++q)
1500 *
-structure_fe_face_values.normal_vector(q);
1501 *
const auto JxW = structure_fe_face_values.JxW(q);
1502 *
std::complex<double> v_n =
1503 *
(-1.0 / (omega * std::complex<double>(0., 1.) *
1505 *
(pressure_gradients[q] * NormalVector);
1507 *
0.5 * std::real(pressure[q] * std::conj(v_n) * JxW);
1513 *
return sound_power;
1518 * Calculating the sound power on the receiver side
1521 *
template <
int dim>
1523 *
HarmonicResponse<dim>::receiver_sound_power()
1527 * Common face quadrature
1530 *
const QGauss<dim - 1> common_face_quadrature(fe_collection.max_degree() +
1534 * FE face
values for surface integration
1538 *
common_face_quadrature,
1544 *
common_face_quadrature,
1551 *
common_face_quadrature,
1559 *
common_face_quadrature,
1563 *
double sound_power = 0.;
1564 *
for (
const auto &cell : dof_handler.active_cell_iterators())
1566 *
if (cell->is_locally_owned())
1568 *
for (
const auto f : cell->face_indices())
1570 *
if ((cell->face(f)->user_index() ==
1571 *
static_cast<unsigned
int>(SurfaceID::ReceiverSide)) &&
1572 *
!cell->at_boundary(f) &&
1574 *
static_cast<unsigned
int>(MaterialID::Concrete)))
1576 *
const auto neighbor = cell->neighbor(f);
1579 * The neighbor is at the same refinement
level and has no
1583 *
if ((neighbor->level() == cell->level()) &&
1584 *
(neighbor->has_children() ==
false) &&
1585 *
(neighbor->material_id() ==
1586 *
static_cast<unsigned int>(MaterialID::Air)))
1588 *
elasticity_fe_face_values.reinit(cell, f);
1589 *
air_fe_face_values.reinit(
1590 *
neighbor, cell->neighbor_of_neighbor(f));
1592 *
cell_receiver_sound_power(elasticity_fe_face_values,
1593 *
air_fe_face_values,
1598 * The neighbor has children.
1601 *
else if ((neighbor->level() == cell->level()) &&
1602 *
(neighbor->has_children() ==
true))
1604 *
for (
unsigned int subface = 0;
1605 *
subface < cell->face(f)->n_children();
1608 *
elasticity_fe_sub_face_values.reinit(cell,
1611 *
air_fe_face_values.reinit(
1612 *
cell->neighbor_child_on_subface(f, subface),
1613 *
cell->neighbor_of_neighbor(f));
1614 *
sound_power += cell_receiver_sound_power(
1615 *
elasticity_fe_sub_face_values,
1616 *
air_fe_face_values,
1622 * The neighbor is coarser.
1625 *
else if (cell->neighbor_is_coarser(f))
1627 *
elasticity_fe_face_values.reinit(cell, f);
1628 *
air_fe_sub_face_values.reinit(
1630 *
cell->neighbor_of_coarser_neighbor(f).first,
1631 *
cell->neighbor_of_coarser_neighbor(f).second);
1633 *
cell_receiver_sound_power(elasticity_fe_face_values,
1634 *
air_fe_sub_face_values,
1641 *
return sound_power;
1644 *
template <
int dim>
1646 *
HarmonicResponse<dim>::cell_receiver_sound_power(
1649 *
const double &omega)
1651 *
std::vector<types::global_dof_index> local_dof_indices;
1654 *
const unsigned int n_q_points = air_fe_face_values.n_quadrature_points;
1655 *
double sound_power = 0.;
1658 *
std::vector<std::complex<double>> local_dof_values_pressure(
1659 *
air_fe_face_values.n_quadrature_points);
1660 *
air_fe_face_values[pressure].get_function_values(locally_relevant_solution,
1661 *
local_dof_values_pressure);
1663 *
std::vector<Tensor<1, dim, std::complex<double>>>
1664 *
local_dof_values_displacement(n_q_points);
1665 *
elasticity_fe_face_values[displacement].get_function_values(
1666 *
locally_relevant_solution, local_dof_values_displacement);
1667 *
for (
unsigned int q = 0; q < n_q_points; ++q)
1670 *
air_fe_face_values.normal_vector(q);
1671 *
const auto JxW = air_fe_face_values.JxW(q);
1672 *
std::complex<double> normal_velocity =
1673 *
local_dof_values_displacement[q] * NormalVector *
1674 *
std::complex<double>(0., 1.) * omega;
1677 *
std::real(local_dof_values_pressure[q] * std::conj(normal_velocity)) *
1680 *
return sound_power;
1683 *
template <
int dim>
1685 *
HarmonicResponse<dim>::solve()
1688 *
locally_owned_dofs, mpi_communicator);
1691 *
solver.solve(system_matrix, completely_distributed_solution, system_rhs);
1692 *
constraints.distribute(completely_distributed_solution);
1693 *
locally_relevant_solution = completely_distributed_solution;
1696 *
template <
int dim>
1698 *
HarmonicResponse<dim>::calculate_magnitude()
1700 *
for (
const auto i : locally_owned_dofs)
1702 *
const std::complex<double>
value = locally_relevant_solution[i];
1705 * For postprocessing, the real part represents the magnitude,
while the
1706 * imaginary part vanishes.
1709 *
locally_relevant_magnitude[i] =
std::abs(value);
1713 *
template <
int dim>
1715 *
HarmonicResponse<dim>::run(
bool write_output)
1717 *
static bool mode_output =
false;
1721 *
pcout <<
"Debug mode" << std::endl;
1723 *
pcout <<
"Release mode" << std::endl;
1725 *
mode_output =
true;
1728 *
const double frequency = omega / (
numbers::PI * 2.);
1729 *
pcout << std::endl <<
"Frequency = " << frequency <<
" Hz" << std::endl;
1733 *
std::ifstream input_file(
"./tria.inp");
1734 *
grid_in.read_abaqus(input_file);
1735 *
triangulation.refine_global(1);
1736 *
for (
const auto &cell : triangulation.active_cell_iterators())
1738 *
if (cell->center()[0] > 203.)
1740 *
cell->set_refine_flag();
1743 *
triangulation.execute_coarsening_and_refinement();
1745 *
pcout <<
" setup_system" << std::endl;
1747 *
pcout <<
" assemble_system" << std::endl;
1748 *
assemble_system();
1749 *
pcout <<
" solve" << std::endl;
1753 * Calculation of the magnitude of the solution. For postprocessing, the
1754 * magnitude of the solutions corresponds to the real part and the imaginary
1758 *
calculate_magnitude();
1759 *
const auto sound_power_source_side_local = incident_sound_power();
1760 *
const auto sound_power_receiver_side_local = receiver_sound_power();
1761 *
const auto sound_power_source_side =
1762 * ::Utilities::MPI::sum(sound_power_source_side_local,
1763 *
mpi_communicator);
1764 *
const auto sound_power_receiver_side =
1765 * ::Utilities::MPI::sum(sound_power_receiver_side_local,
1766 *
mpi_communicator);
1769 *
10. * std::log10(sound_power_source_side / sound_power_receiver_side);
1770 *
pcout <<
" STL = " << stl <<
" dB" << std::endl;
1773 *
std::ofstream outfile(
"STL_result.txt", std::ios::app);
1774 *
outfile << frequency <<
" " << stl << std::endl;
1782 *
std::vector<std::string> solution_names_magnitude(dim,
"magnitude_u");
1783 *
solution_names_magnitude.push_back(
"magnitude_p");
1784 *
std::vector<std::string> solution_names(dim,
"u");
1785 *
solution_names.push_back(
"p");
1787 *
std::vector<DataComponentInterpretation::DataComponentInterpretation>
1788 *
interpretation = {
1793 *
data_out.add_data_vector(locally_relevant_solution,
1799 *
data_out.add_data_vector(locally_relevant_magnitude,
1800 *
solution_names_magnitude,
1806 * subdomain visualization (unchanged)
1810 *
for (
unsigned int i = 0; i < subdomain.size(); ++i)
1811 *
subdomain(i) = triangulation.locally_owned_subdomain();
1813 *
data_out.add_data_vector(subdomain,
"subdomain");
1815 *
data_out.build_patches();
1817 *
std::ostringstream ss;
1818 *
ss << std::fixed << std::setprecision(2) << frequency;
1819 *
std::filesystem::create_directories(
"./output/");
1820 *
data_out.write_vtu_with_pvtu_record(
1821 *
"./output/",
"solution_" + ss.str(), 0, mpi_communicator, 2, 8);
1827 *
main(
int argc,
char *argv[])
1831 *
using namespace dealii;
1832 *
const unsigned int dim = 3;
1835 *
unsigned int n = 0;
1838 *
while (f_c < 1000.)
1840 *
f_c = f0 *
std::pow(10.,
static_cast<double>(n) / 60.);
1842 *
VibroAcousticProblem::HarmonicResponse<dim> elastic_problem(omega);
1843 *
elastic_problem.run(
true);
1847 *
catch (std::exception &exc)
1849 *
std::cerr << std::endl
1851 *
<<
"----------------------------------------------------"
1853 *
std::cerr <<
"Exception on processing: " << std::endl
1854 *
<< exc.what() << std::endl
1855 *
<<
"Aborting!" << std::endl
1856 *
<<
"----------------------------------------------------"
1863 *
std::cerr << std::endl
1865 *
<<
"----------------------------------------------------"
1867 *
std::cerr <<
"Unknown exception!" << std::endl
1868 *
<<
"Aborting!" << std::endl
1869 *
<<
"----------------------------------------------------"
* * for(const auto &cell :triangulation.active_cell_iterators())
* * int main(int argc, char **argv)
* x_component_mask set(0, true)
* * * struct InterferenceTaperTransform *
std::vector< bool > component_mask
void attach_dof_handler(const DoFHandler< dim, spacedim > &)
const FEFaceValues< dim, spacedim > & get_present_fe_values() const
const unsigned int n_quadrature_points
const FEValues< dim, spacedim > & get_present_fe_values() const
virtual void gradient_list(const std::vector< Point< dim > > &points, std::vector< Tensor< 1, dim, RangeNumberType > > &gradients, const unsigned int component=0) const
virtual void value_list(const std::vector< Point< dim > > &points, std::vector< RangeNumberType > &values, const unsigned int component=0) const
virtual void vector_value(const Point< dim > &p, Vector< RangeNumberType > &values) const
void attach_triangulation(Triangulation< dim, spacedim > &tria)
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertThrow(cond, exc)
void make_hanging_node_constraints(const DoFHandler< dim, spacedim > &dof_handler, AffineConstraints< number > &constraints)
void make_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternBase &sparsity_pattern, const AffineConstraints< number > &constraints={}, const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
void make_flux_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternBase &sparsity_pattern)
@ update_values
Shape function values.
@ update_normal_vectors
Normal vectors.
@ update_JxW_values
Transformed quadrature weights.
@ update_gradients
Shape function gradients.
@ update_quadrature_points
Transformed quadrature points.
@ component_is_part_of_vector
void random(DoFHandler< dim, spacedim > &dof_handler)
@ matrix
Contents is actually a matrix.
constexpr types::blas_int one
void cell_matrix(FullMatrix< double > &M, const FEValuesBase< dim > &fe, const FEValuesBase< dim > &fetest, const ArrayView< const std::vector< double > > &velocity, const double factor=1.)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
* * if(update_pressure &update_flags) * compute_pressure(constitutive_request
* * * RotationFunction< dim, Number >::RotationFunction Number(dim)
* * * ThermoPlasticMaterial< dim, ViscoplasticYieldLaw, Number > ThermoPlasticMaterial * mu(mu)
* * * * std::vector< Number > ThermoPlasticMaterial< dim, ViscoplasticYieldLaw, Number >::get_state_parameters const
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
T broadcast(const MPI_Comm comm, const T &object_to_send, const unsigned int root_process=0)
void run(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &end, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length, const unsigned int chunk_size)
void assemble(const MeshWorker::DoFInfoBox< dim, DOFINFO > &dinfo, A *assembler)
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
::VectorizedArray< Number, width > exp(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > cos(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sin(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
inline ::VectorizedArray< Number, width > acos(const ::VectorizedArray< Number, width > &x)