deal.II version GIT relicensing-6750-g1dc21bc838 2026-09-15 17:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
Parallel_Vibro-Acoustic_Solver.h
Go to the documentation of this file.
1
240 *  
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>
246 *  
247 *   #include <deal.II/dofs/dof_handler.h>
248 *   #include <deal.II/dofs/dof_tools.h>
249 *  
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>
254 *  
255 *   #include <deal.II/grid/grid_in.h>
256 *   #include <deal.II/grid/grid_out.h>
257 *   #include <deal.II/grid/grid_tools.h>
258 *  
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>
264 *  
265 *   #include <deal.II/numerics/data_out.h>
266 *   #include <deal.II/numerics/vector_tools.h>
267 *  
268 *   #include <filesystem>
269 *   #include <fstream>
270 *   #include <iostream>
271 *   #include <random>
272 *   #include <vector>
273 *  
274 *   namespace VibroAcousticProblem
275 *   {
276 *   using namespace dealii;
277 * @endcode
278 *
279 * geometric tolerance
280 *
281 * @code
282 *   constexpr double geom_tol = 1e-10;
283 *  
284 *   enum class SurfaceID : ::types::boundary_id
285 *   {
286 * @endcode
287 *
288 * By default, boundary indicators are 0
289 *
290 * @code
291 *   Default,
292 *   SourceSide,
293 *   ReceiverSide,
294 *   FixedBoundary,
295 *   ZeroPressure
296 *   };
297 *  
298 *   enum class MaterialID : ::types::material_id
299 *   {
300 *   Concrete,
301 *   Air
302 *   };
303 *  
304 * @endcode
305 *
306 * return the isotropic loss factor
307 *
308 * @code
309 *   std::complex<double>
310 *   get_iso_loss()
311 *   {
312 *   return std::complex<double>{1., 0.01};
313 *   }
314 *  
315 * @endcode
316 *
317 * calculation of the linear strain tensor
318 *
319 * @code
320 *   template <int dim>
322 *   get_strain(const FEValues<dim> &fe_values,
323 *   const unsigned int shape_func,
324 *   const unsigned int q_point)
325 *   {
327 *  
328 *   for (unsigned int i = 0; i < dim; ++i)
329 *   tmp[i][i] = fe_values.shape_grad_component(shape_func, q_point, i)[i];
330 *  
331 *   for (unsigned int i = 0; i < dim; ++i)
332 *   for (unsigned int j = i + 1; j < dim; ++j)
333 *   tmp[i][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]) /
336 *   2;
337 *  
338 *   return tmp;
339 *   }
340 *  
341 * @endcode
342 *
343 * Returning the stiffness tensor of the wall
344 *
345 * @code
346 *   template <int dim>
348 *   get_stiffness_tensor()
349 *   {
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;
354 *  
355 *   SymmetricTensor<4, dim> stiffness_tensor;
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;
365 *   }
366 *  
367 * @endcode
368 *
369 * Returning the density of the wall
370 *
371 * @code
372 *   double
373 *   get_density_structure()
374 *   {
375 *   return 2.275 * 1e-3;
376 *   }
377 *  
378 * @endcode
379 *
380 * Returning the density of air
381 *
382 * @code
383 *   double
384 *   get_density_air()
385 *   {
386 *   return 1.204 * 1e-6;
387 *   }
388 *  
389 * @endcode
390 *
391 * Returning the speed of sound
392 *
393 * @code
394 *   double
395 *   get_sound_speed()
396 *   {
397 *   return 343. * 1e3;
398 *   }
399 *  
400 * @endcode
401 *
402 * Implementation of a perfectly matched layer
403 *
404 * @code
405 *   template <int dim>
406 *   class PML : public Function<dim, std::complex<double>>
407 *   {
408 *   public:
409 *   explicit PML(double omega)
410 *   : omega(omega)
411 *   , b_pos{}
412 *   , b_neg{}
413 *   , t_pos{}
414 *   , t_neg{}
415 *   , pml_coeff_degree(2.0)
416 *   , pml_coeff(1.e4 / omega)
417 *   {
418 *   Assert(dim == 3, ExcNotImplemented());
419 *  
420 * @endcode
421 *
422 * x-direction
423 *
424 * @code
425 *   b_pos[0] = 812.0;
426 *   b_neg[0] = std::numeric_limits<double>::lowest();
427 *   t_pos[0] = 500.0;
428 *   t_neg[0] = 500.0;
429 *  
430 * @endcode
431 *
432 * y-direction
433 *
434 * @code
435 *   b_pos[1] = 1826.0;
436 *   b_neg[1] = -1826.0;
437 *   t_pos[1] = 500.0;
438 *   t_neg[1] = 500.0;
439 *  
440 * @endcode
441 *
442 * z-direction
443 *
444 * @code
445 *   b_pos[2] = 2591.0;
446 *   b_neg[2] = -2591.0;
447 *   t_pos[2] = 500.0;
448 *   t_neg[2] = 500.0;
449 *   }
450 *  
451 * @endcode
452 *
453 * calculates the value of the complex coordinate stretch
454 *
455 * @code
456 *   void
457 *   vector_value(const Point<dim> &p,
458 *   Vector<std::complex<double>> &value) const override;
459 *  
460 *   private:
461 *   double omega;
462 *  
463 *   std::array<double, dim> b_pos, b_neg;
464 *   std::array<double, dim> t_pos, t_neg;
465 *  
466 *   double pml_coeff_degree;
467 *   double pml_coeff;
468 *   };
469 *  
470 *   template <int dim>
471 *   void
472 *   PML<dim>::vector_value(const Point<dim> &p,
473 *   Vector<std::complex<double>> &value) const
474 *   {
475 *   value.reinit(dim);
476 *  
477 *   for (unsigned int d = 0; d < dim; ++d)
478 *   {
479 *   double coeff = 0.0;
480 *  
481 *   if (p[d] > b_pos[d])
482 *   {
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);
487 *   }
488 *   else if (p[d] < b_neg[d])
489 *   {
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);
494 *   }
495 *  
496 * @endcode
497 *
498 * complex coordinate stretching: s = 1 + i * sigma(x)
499 *
500 * @code
501 *   value[d] = std::complex<double>(1.0, coeff);
502 *   }
503 *   }
504 *  
505 * @endcode
506 *
507 * Creation of a diffuse sound field for excitation of the wall on the source
508 * side
509 *
510 * @code
511 *   template <int dim>
512 *   class DiffuseSoundField : public Function<dim, std::complex<double>>
513 *   {
514 *   public:
515 *   DiffuseSoundField(unsigned int N, double omega, MPI_Comm mpi_communicator)
517 *   , N(N)
518 *   , dist_0_2PI(0.0, 2. * numbers::PI)
519 *   , dist_0_1(0.0, 1.)
520 *   , generator(static_cast<int>(omega))
521 *   , omega(omega)
522 *   {
523 * @endcode
524 *
525 * Only let one rank 0 create the random variables of the diffuse sound
526 * field...
527 *
528 * @code
529 *   const unsigned int rank =
530 *   Utilities::MPI::this_mpi_process(mpi_communicator);
531 *   if (rank == 0)
532 *   {
533 *   phi.resize(N);
534 *   Phi.resize(N);
535 *   phase.resize(N);
536 *   for (unsigned int n = 0; n < N; ++n)
537 *   {
538 *   phi[n] = dist_0_2PI(generator);
539 *   Phi[n] = std::acos(dist_0_1(generator));
540 *   phase[n] = dist_0_2PI(generator);
541 *   }
542 *   }
543 * @endcode
544 *
545 * ... and broadcast from rank 0 to all ranks.
546 *
547 * @code
548 *   phi = Utilities::MPI::broadcast(mpi_communicator, phi, 0);
549 *   Phi = Utilities::MPI::broadcast(mpi_communicator, Phi, 0);
550 *   phase = Utilities::MPI::broadcast(mpi_communicator, phase, 0);
551 *  
552 * @endcode
553 *
554 * Generation of kn on all ranks
555 *
556 * @code
557 *   for (unsigned int n = 0; n < N; n++)
558 *   {
559 *   double scale = (omega / get_sound_speed());
560 *   Tensor<1, dim> k;
561 *   k[0] = std::cos(Phi[n]) * scale;
562 *   k[1] = std::sin(Phi[n]) * std::cos(phi[n]) * scale;
563 *   k[2] = std::sin(Phi[n]) * std::sin(phi[n]) * scale;
564 *   k_vector.push_back(k);
565 *   }
566 *   }
567 * @endcode
568 *
569 * Calculation of the total pressure on the source side
570 *
571 * @code
572 *   virtual void
573 *   value_list(const std::vector<Point<dim>> &points,
574 *   std::vector<std::complex<double>> &values,
575 *   const unsigned int component = 0) const override;
576 *  
577 * @endcode
578 *
579 * Calculation of the gradient of the total pressure on the source side
580 *
581 * @code
582 *   virtual void
583 *   gradient_list(const std::vector<Point<dim>> &points,
584 *   std::vector<Tensor<1, dim, std::complex<double>>> &gradients,
585 *   const unsigned int component = 0) const override;
586 *  
587 * @endcode
588 *
589 * Calculation of the incident sound pressure on the source side
590 *
591 * @code
592 *   void
593 *   value_list_incidence(const std::vector<Point<dim>> &points,
594 *   std::vector<std::complex<double>> &values,
595 *   const unsigned int component = 0) const;
596 *  
597 *   private:
598 * @endcode
599 *
600 * Number of plane waves
601 *
602 * @code
603 *   unsigned int N;
604 * @endcode
605 *
606 * For randmoness
607 *
608 * @code
609 *   std::uniform_real_distribution<double> dist_0_2PI;
610 *   std::uniform_real_distribution<double> dist_0_1;
611 *   std::mt19937 generator;
612 *  
613 * @endcode
614 *
615 * variables of the diffuse field
616 *
617 * @code
618 *   std::vector<double> phi, Phi, phase, kn_x, kn_y, kn_z;
619 *   std::vector<Tensor<1, dim, double>> k_vector;
620 *  
621 * @endcode
622 *
623 * angular velocity
624 *
625 * @code
626 *   double omega;
627 *   };
628 *  
629 *   template <int dim>
630 *   void
631 *   DiffuseSoundField<dim>::value_list(const std::vector<Point<dim>> &points,
632 *   std::vector<std::complex<double>> &values,
633 *   const unsigned int component) const
634 *   {
635 *   AssertThrow(component == 0, ExcMessage("only component 0 is implemented"));
636 *   values.resize(points.size());
637 *   std::complex<double> j{0., 1.};
638 *  
639 *   for (unsigned int q = 0; q < points.size(); ++q)
640 *   {
641 *   const auto &q_p = points[q];
642 *   values[q] = {0., 0.};
643 *   for (unsigned int n = 0; n < N; n++)
644 *   {
645 * @endcode
646 *
647 * sound waves traveling towards the wall...
648 *
649 * @code
650 *   double dot_towards = 0.;
651 *   double dot_reflection = 0.;
652 *  
653 *   for (unsigned int d = 0; d < dim; d++)
654 *   {
655 * @endcode
656 *
657 * sound waves traveling towards the wall...
658 *
659 * @code
660 *   dot_towards += k_vector[n][d] * q_p[d];
661 * @endcode
662 *
663 * ... and reflections.
664 *
665 * @code
666 *   if (d == 0)
667 *   {
668 *   dot_reflection -= k_vector[n][d] * q_p[d];
669 *   }
670 *   else
671 *   {
672 *   dot_reflection += k_vector[n][d] * q_p[d];
673 *   }
674 *   }
675 * @endcode
676 *
677 * sound waves traveling towards the wall...
678 *
679 * @code
680 *   values[q] += std::exp(-j * (dot_towards) + j * phase[n]);
681 * @endcode
682 *
683 * ... and reflections.
684 *
685 * @code
686 *   values[q] += std::exp(-j * (dot_reflection) + j * phase[n]);
687 *   }
688 *   values[q] *= 1. / (std::sqrt(2. * static_cast<double>(N))) * 1.e6;
689 *   }
690 *   }
691 *  
692 *   template <int dim>
693 *   void
694 *   DiffuseSoundField<dim>::value_list_incidence(
695 *   const std::vector<Point<dim>> &points,
696 *   std::vector<std::complex<double>> &values,
697 *   const unsigned int component) const
698 *   {
699 *   AssertThrow(component == 0, ExcMessage("only component 0 is implemented"));
700 *  
701 *   values.resize(points.size());
702 *   std::complex<double> j{0., 1.};
703 *   for (unsigned int q = 0; q < points.size(); ++q)
704 *   {
705 *   const auto &q_p = points[q];
706 *   values[q] = {0., 0.};
707 *   for (unsigned int n = 0; n < N; n++)
708 *   {
709 * @endcode
710 *
711 * Only sound waves traveling towards the wall.
712 *
713 * @code
714 *   double dot_towards = 0.;
715 *   for (unsigned int d = 0; d < dim; d++)
716 *   {
717 * @endcode
718 *
719 * Sound waves traveling towards the wall.
720 *
721 * @code
722 *   dot_towards += k_vector[n][d] * q_p[d];
723 *   }
724 * @endcode
725 *
726 * Only sound waves traveling towards the wall.
727 *
728 * @code
729 *   values[q] += std::exp(-j * (dot_towards) + j * phase[n]);
730 *   }
731 *   values[q] *= 1. / (std::sqrt(2. * static_cast<double>(N))) * 1.e6;
732 *   }
733 *   }
734 *  
735 *   template <int dim>
736 *   void
737 *   DiffuseSoundField<dim>::gradient_list(
738 *   const std::vector<Point<dim>> &points,
739 *   std::vector<Tensor<1, dim, std::complex<double>>> &gradients,
740 *   const unsigned int component) const
741 *   {
742 *   AssertThrow(component == 0, ExcMessage("only component 0 is implemented"));
743 *  
744 *   gradients.resize(points.size());
745 *   const std::complex<double> j{0.0, 1.0};
746 *   for (unsigned int q = 0; q < points.size(); ++q)
747 *   {
748 *   const auto &q_p = points[q];
749 *   for (unsigned int d = 0; d < dim; ++d)
750 *   gradients[q][d] = 0.;
751 *  
752 *   for (unsigned int n = 0; n < N; ++n)
753 *   {
754 *   double dot = 0.;
755 *   for (unsigned int d = 0; d < dim; ++d)
756 *   dot += k_vector[n][d] * q_p[d];
757 *  
758 *   const std::complex<double> exp_term =
759 *   std::exp(-j * dot + j * phase[n]);
760 *  
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))) *
764 *   1.e6;
765 *   }
766 *   }
767 *   }
768 *  
769 *   template <int dim>
770 *   class HarmonicResponse
771 *   {
772 *   public:
773 *   HarmonicResponse(double omega);
774 *   void
775 *   run(bool write_output = false);
776 *  
777 *   private:
778 *   void
779 *   setup_system();
780 *   void
781 *   assemble_system();
782 *   void
783 *   solve();
784 *  
785 * @endcode
786 *
787 * calculate the magnitude of u and p
788 *
789 * @code
790 *   void
791 *   calculate_magnitude();
792 *  
793 * @endcode
794 *
795 * calculation of sound power at receiver side for one cell
796 *
797 * @code
798 *   double
799 *   cell_receiver_sound_power(
800 *   const FEFaceValuesBase<dim> &elasticity_fe_face_values,
801 *   const FEFaceValuesBase<dim> &air_fe_face_values,
802 *   const double &omega);
803 *  
804 * @endcode
805 *
806 * calculation of sound power at sender side
807 *
808 * @code
809 *   double
810 *   incident_sound_power();
811 * @endcode
812 *
813 * calculation of sound power at receiver side
814 *
815 * @code
816 *   double
817 *   receiver_sound_power();
818 * @endcode
819 *
820 * Assemble the air-structure coupling terms
821 * This function implements the assembly of the air-structure interface.
822 *
823 * @code
824 *   void
825 *   assemble_air_structure_interface_term(
826 *   const FEFaceValuesBase<dim> &elasticity_fe_face_values,
827 *   const FEFaceValuesBase<dim> &air_fe_face_values,
828 *   FullMatrix<std::complex<double>> &local_interface_matrix,
829 *   const double &omega);
830 *   MPI_Comm mpi_communicator;
832 *  
833 *   const FESystem<dim> fe_structure, fe_air;
834 *   const QGauss<dim> quadrature_formula_structure, quadrature_formula_air;
835 *   const QGauss<dim - 1> face_quadrature_formula_structure,
836 *   face_quadrature_formula_air;
837 *  
838 *   hp::FECollection<dim> fe_collection;
839 *   hp::QCollection<dim> q_collection;
840 *   hp::QCollection<dim - 1> q_face_collection;
841 *  
842 *   DoFHandler<dim> dof_handler;
843 *   IndexSet locally_owned_dofs;
844 *   IndexSet locally_relevant_dofs;
847 *   LinearAlgebraPETSc::MPI::Vector locally_relevant_solution;
848 *   LinearAlgebraPETSc::MPI::Vector locally_relevant_magnitude;
850 *  
851 *   ConditionalOStream pcout;
852 *   const double omega;
853 *   DiffuseSoundField<dim> field;
854 *   PML<dim> pml;
855 *   };
856 *  
857 *   template <int dim>
858 *   HarmonicResponse<dim>::HarmonicResponse(double omega)
859 *   : mpi_communicator(MPI_COMM_WORLD)
860 *   , triangulation(mpi_communicator,
864 *   , fe_structure(FE_Q<dim>(2), dim, FE_Nothing<dim>(), 1)
865 *   , fe_air(FE_Nothing<dim>(), dim, FE_Q<dim>(1), 1)
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)
871 *   , pcout(std::cout,
872 *   (Utilities::MPI::this_mpi_process(mpi_communicator) == 0))
873 *   , omega(omega)
874 *   , field(1.e3, omega, mpi_communicator)
875 *   , pml(omega)
876 *   {
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);
885 *   }
886 *  
887 *   template <int dim>
888 *   void
889 *   HarmonicResponse<dim>::setup_system()
890 *   {
891 * @endcode
892 *
893 * Set material id and active FE indices.
894 *
895 * @code
896 *   for (const auto &cell : dof_handler.cell_iterators())
897 *   {
898 *   cell->set_material_id(static_cast<unsigned int>(MaterialID::Concrete));
899 *  
900 *   if ((cell->center()[0] - 203.) > 0.)
901 *   {
902 *   cell->set_material_id(static_cast<unsigned int>(MaterialID::Air));
903 *   }
904 *   }
905 *   for (const auto &cell : dof_handler.active_cell_iterators())
906 *   {
907 *   if (cell->is_locally_owned())
908 *   {
909 *   cell->set_active_fe_index(
910 *   static_cast<unsigned int>(MaterialID::Concrete));
911 *   }
912 *   if ((cell->center()[0] - 203.) > 0.)
913 *   {
914 *   if (cell->is_locally_owned())
915 *   {
916 *   cell->set_active_fe_index(
917 *   static_cast<unsigned int>(MaterialID::Air));
918 *   }
919 *   }
920 *   }
921 * @endcode
922 *
923 * Definition of FE space
924 *
925 * @code
926 *   dof_handler.distribute_dofs(fe_collection);
927 *   pcout << " Number of degrees of freedom = " << dof_handler.n_dofs()
928 *   << std::endl;
929 *  
930 *   locally_owned_dofs = dof_handler.locally_owned_dofs();
931 *   locally_relevant_dofs.clear();
932 *   DoFTools::extract_locally_relevant_dofs(dof_handler, locally_relevant_dofs);
933 *  
934 *   locally_relevant_solution.reinit(locally_owned_dofs,
935 *   locally_relevant_dofs,
936 *   mpi_communicator);
937 *   locally_relevant_magnitude.reinit(locally_owned_dofs, mpi_communicator);
938 *   system_rhs.reinit(locally_owned_dofs, mpi_communicator);
939 *  
940 * @endcode
941 *
942 * set up contraints
943 *
944 * @code
945 *   constraints.clear();
946 *   constraints.reinit(locally_owned_dofs, locally_relevant_dofs);
947 *   DoFTools::make_hanging_node_constraints(dof_handler, constraints);
948 *  
949 * @endcode
950 *
951 * Set boundary ids
952 *
953 * @code
954 *   for (const auto &cell : dof_handler.active_cell_iterators())
955 *   {
956 *   if (cell->is_locally_owned())
957 *   {
958 *   for (unsigned int f = 0; f < cell->n_faces(); ++f)
959 *   {
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)))
965 *   {
966 *   cell->face(f)->set_user_index(
967 *   static_cast<unsigned int>(SurfaceID::ReceiverSide));
968 *   }
969 *   if (std::abs(p[0]) < geom_tol)
970 *   {
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)));
975 *   }
976 *   if (cell->face(f)->at_boundary())
977 *   {
978 *   if ((p[0] + geom_tol) < 203. && p[0] > geom_tol)
979 *   {
980 *   cell->face(f)->set_boundary_id(
981 *   static_cast<unsigned int>(SurfaceID::FixedBoundary));
982 *   }
983 *   if (std::abs(p[0] - 1312.) < geom_tol &&
984 *   cell->material_id() ==
985 *   static_cast<unsigned int>(MaterialID::Air))
986 *   {
987 *   cell->face(f)->set_boundary_id(
988 *   static_cast<unsigned int>(SurfaceID::ZeroPressure));
989 *   }
990 *   }
991 *   }
992 *   }
993 *   }
994 * @endcode
995 *
996 * The wall is fixed at its outer boundary
997 *
998 * @code
999 *   const FEValuesExtractors::Vector displacement(0);
1000 *   ComponentMask component_mask_displacement =
1001 *   fe_collection.component_mask(displacement);
1003 *   dof_handler,
1004 *   static_cast<unsigned int>(SurfaceID::FixedBoundary),
1005 *   Functions::ZeroFunction<dim, std::complex<double>>(4),
1006 *   constraints,
1007 *   component_mask_displacement);
1008 *   constraints.close();
1009 *  
1010 *   DynamicSparsityPattern dsp(locally_relevant_dofs);
1011 *   DoFTools::make_sparsity_pattern(dof_handler, dsp, constraints, true);
1012 *   DoFTools::make_flux_sparsity_pattern(dof_handler, dsp, constraints);
1014 *   locally_owned_dofs,
1015 *   mpi_communicator,
1016 *   locally_relevant_dofs);
1017 *   system_matrix.reinit(locally_owned_dofs,
1018 *   locally_owned_dofs,
1019 *   dsp,
1020 *   mpi_communicator);
1021 *   }
1022 *  
1023 *   template <int dim>
1024 *   void
1025 *   HarmonicResponse<dim>::assemble_system()
1026 *   {
1027 * @endcode
1028 *
1029 * FE values for volume integration
1030 *
1031 * @code
1032 *   hp::FEValues<dim> hp_fe_values(fe_collection,
1033 *   q_collection,
1037 *   hp::FEFaceValues<dim> hp_fe_face_values(fe_collection,
1038 *   q_face_collection,
1042 *  
1043 * @endcode
1044 *
1045 * Common face quadrature
1046 *
1047 * @code
1048 *   const QGauss<dim - 1> common_face_quadrature(fe_collection.max_degree() +
1049 *   1);
1050 * @endcode
1051 *
1052 * FE face values for surface integration
1053 *
1054 * @code
1055 *   FEFaceValues<dim> air_fe_face_values(fe_air,
1056 *   common_face_quadrature,
1060 *   FEFaceValues<dim> elasticity_fe_face_values(fe_structure,
1061 *   common_face_quadrature,
1062 *   update_values |
1066 *   FESubfaceValues<dim> air_fe_sub_face_values(fe_air,
1067 *   common_face_quadrature,
1068 *   update_values |
1072 *   FESubfaceValues<dim> elasticity_fe_sub_face_values(
1073 *   fe_structure,
1074 *   common_face_quadrature,
1077 *  
1078 * @endcode
1079 *
1080 * Local element matrix for a cell
1081 *
1082 * @code
1084 * @endcode
1085 *
1086 * Local interface matrix between air and structure DoFs
1087 *
1088 * @code
1089 *   FullMatrix<std::complex<double>> local_interface_matrix(
1090 *   fe_air.n_dofs_per_cell(), fe_structure.n_dofs_per_cell());
1091 *  
1092 * @endcode
1093 *
1094 * Right-hand side
1095 *
1096 * @code
1097 *   Vector<std::complex<double>> cell_rhs;
1098 *   std::vector<types::global_dof_index> local_dof_indices;
1099 *   std::vector<types::global_dof_index> neighbor_dof_indices;
1100 *   const FEValuesExtractors::Vector displacement(0);
1101 *   const FEValuesExtractors::Scalar pressure(dim);
1102 *  
1103 *   for (const auto &cell : dof_handler.active_cell_iterators())
1104 *   {
1105 *   if (cell->is_locally_owned())
1106 *   {
1107 * @endcode
1108 *
1109 * Assemble air cells contributions
1110 *
1111 * @code
1112 *   if (cell->material_id() ==
1113 *   static_cast<unsigned int>(MaterialID::Air))
1114 *   {
1115 *   cell_matrix = 0;
1116 *   cell_rhs = 0;
1117 *   hp_fe_values.reinit(cell);
1118 *   const FEValues<dim> &fe_values =
1119 *   hp_fe_values.get_present_fe_values();
1120 *  
1121 *   const unsigned int dofs_per_cell = fe_air.n_dofs_per_cell();
1122 *   const unsigned int n_q_points = fe_values.n_quadrature_points;
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();
1128 *  
1129 * @endcode
1130 *
1131 * Wave number k
1132 *
1133 * @code
1134 *   const std::complex<double> k = (omega / sound_speed);
1135 *  
1136 *   for (unsigned int q = 0; q < n_q_points; ++q)
1137 *   {
1138 *   const auto JxW = fe_values.JxW(q);
1139 *   const Point<dim> &q_point = fe_values.quadrature_point(q);
1140 * @endcode
1141 *
1142 * calucalte lambda and J for PML
1143 *
1144 * @code
1146 *   pml.vector_value(q_point, lambda);
1147 *   const std::complex<double> J =
1148 *   lambda[0] * lambda[1] * lambda[2];
1149 *  
1150 *   for (unsigned int i = 0; i < dofs_per_cell; ++i)
1151 *   {
1152 *   const double phi_i = fe_values[pressure].value(i, q);
1153 *  
1154 * @endcode
1155 *
1156 * Gradient of phi_i, which is multiplied by 1/lambda
1157 *
1158 * @code
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];
1163 *  
1164 *   for (unsigned int j = 0; j < dofs_per_cell; ++j)
1165 *   {
1166 *   const double phi_j =
1167 *   fe_values[pressure].value(j, q);
1168 *  
1169 * @endcode
1170 *
1171 * Gradient of phi_j, which is multiplied by
1172 * 1/lambda
1173 *
1174 * @code
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];
1179 *  
1180 *   cell_matrix[i][j] += phi_i_i * phi_j_j * JxW * J;
1181 *   cell_matrix[i][j] -= Utilities::fixed_power<2>(k) *
1182 *   phi_i * phi_j * JxW * J;
1183 *   }
1184 *   }
1185 *   }
1186 * @endcode
1187 *
1188 * assemble local system to global system.
1189 *
1190 * @code
1191 *   cell->get_dof_indices(local_dof_indices);
1192 *   constraints.distribute_local_to_global(cell_matrix,
1193 *   cell_rhs,
1194 *   local_dof_indices,
1195 *   system_matrix,
1196 *   system_rhs);
1197 *  
1198 * @endcode
1199 *
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.
1204 *
1205 * @code
1206 *   for (const auto f : cell->face_indices())
1207 *   {
1208 *   if (!cell->at_boundary(f))
1209 *   {
1210 *   const auto neighbor = cell->neighbor(f);
1211 *   if (neighbor->material_id() ==
1212 *   static_cast<unsigned int>(MaterialID::Concrete))
1213 *  
1214 * @endcode
1215 *
1216 * if (neighbor->center()[0]<203.)
1217 *
1218 * @code
1219 *   {
1220 * @endcode
1221 *
1222 * The neighbor is at the same refinement level and
1223 * has no children.
1224 *
1225 * @code
1226 *   if ((cell->neighbor(f)->level() == cell->level()) &&
1227 *   (cell->neighbor(f)->has_children() == false))
1228 *   {
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,
1237 *   omega);
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,
1244 *   system_matrix);
1245 *   }
1246 * @endcode
1247 *
1248 * The neighbor has children.
1249 *
1250 * @code
1251 *   else if ((cell->neighbor(f)->level() ==
1252 *   cell->level()) &&
1253 *   (cell->neighbor(f)->has_children() ==
1254 *   true))
1255 *   {
1256 *   for (unsigned int subface = 0;
1257 *   subface < cell->face(f)->n_children();
1258 *   ++subface)
1259 *   {
1260 *   air_fe_sub_face_values.reinit(cell,
1261 *   f,
1262 *   subface);
1263 *   elasticity_fe_face_values.reinit(
1264 *   cell->neighbor_child_on_subface(f,
1265 *   subface),
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,
1271 *   omega);
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,
1278 *   system_matrix);
1279 *   }
1280 *   }
1281 * @endcode
1282 *
1283 * The neighbor is coarser.
1284 *
1285 * @code
1286 *   else if (cell->neighbor_is_coarser(f))
1287 *   {
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,
1297 *   omega);
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,
1304 *   system_matrix);
1305 *   }
1306 *   }
1307 *   }
1308 *   }
1309 *   }
1310 * @endcode
1311 *
1312 * Assemble structure cells contributions
1313 *
1314 * @code
1315 *   else if (cell->is_locally_owned() &&
1316 *   cell->material_id() ==
1317 *   static_cast<unsigned int>(MaterialID::Concrete))
1318 *   {
1319 *   cell_matrix = 0;
1320 *   cell_rhs = 0;
1321 *   hp_fe_values.reinit(cell);
1322 *   const FEValues<dim> &fe_values =
1323 *   hp_fe_values.get_present_fe_values();
1324 *  
1325 *   const unsigned int dofs_per_cell =
1326 *   fe_structure.n_dofs_per_cell();
1327 *   const unsigned int n_q_points = fe_values.n_quadrature_points;
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());
1332 *  
1333 *   const SymmetricTensor<4, dim> stiffness_tensor =
1334 *   get_stiffness_tensor<dim>();
1335 *   const double density = get_density_structure();
1336 *   const std::complex<double> iso_loss = get_iso_loss();
1337 *  
1338 *   for (unsigned int q = 0; q < n_q_points; ++q)
1339 *   {
1340 *   const auto JxW = fe_values.JxW(q);
1341 *   for (unsigned int i = 0; i < dofs_per_cell; ++i)
1342 *   {
1343 *   const Tensor<1, dim> phi_i =
1344 *   fe_values[displacement].value(i, q);
1345 *   for (unsigned int j = 0; j < dofs_per_cell; ++j)
1346 *   {
1347 *   const Tensor<1, dim> phi_j =
1348 *   fe_values[displacement].value(j, q);
1349 *   const SymmetricTensor<2, dim> eps_phi_i =
1350 *   get_strain(fe_values, i, q);
1351 *   const SymmetricTensor<2, dim> eps_phi_j =
1352 *   get_strain(fe_values, j, q);
1353 *   cell_matrix[i][j] += eps_phi_i * stiffness_tensor *
1354 *   iso_loss * eps_phi_j * JxW;
1355 *   cell_matrix[i][j] -=
1356 *   Utilities::fixed_power<2>(omega) * phi_j * phi_i *
1357 *   density * JxW;
1358 *   }
1359 *   }
1360 *   }
1361 * @endcode
1362 *
1363 * Here the diffuse sound field is considered on the source side
1364 * of the wall.
1365 *
1366 * @code
1367 *   for (const auto face_no : cell->face_indices())
1368 *   {
1369 *   if (cell->face(face_no)->user_index() ==
1370 *   static_cast<unsigned int>(SurfaceID::SourceSide))
1371 *   {
1372 *   hp_fe_face_values.reinit(cell, face_no);
1373 *   const FEFaceValues<dim> &fe_face_values =
1374 *   hp_fe_face_values.get_present_fe_values();
1375 *   const unsigned int n_face_q_points =
1376 *   fe_face_values.n_quadrature_points;
1377 *   for (unsigned int i = 0; i < dofs_per_cell; ++i)
1378 *   {
1379 *   if (fe_structure.has_support_on_face(i, face_no))
1380 *   {
1381 *   std::vector<std::complex<double>> pressure(
1382 *   n_face_q_points);
1383 *   const auto face_quadrature_points =
1384 *   fe_face_values.get_quadrature_points();
1385 *   field.value_list(face_quadrature_points,
1386 *   pressure);
1387 *  
1388 *   for (unsigned int q = 0; q < n_face_q_points;
1389 *   ++q)
1390 *   {
1391 *   const auto JxW = fe_face_values.JxW(q);
1392 *   const Tensor<1, dim> phi_i =
1393 *   fe_face_values[displacement].value(i, q);
1394 *   const Tensor<1, dim, double> NormalVector =
1395 *   -fe_face_values.normal_vector(q);
1396 *   cell_rhs[i] += pressure[q] *
1397 *   (NormalVector * phi_i) * JxW;
1398 *   }
1399 *   }
1400 *   }
1401 *   }
1402 *   }
1403 *   cell->get_dof_indices(local_dof_indices);
1404 *   constraints.distribute_local_to_global(cell_matrix,
1405 *   cell_rhs,
1406 *   local_dof_indices,
1407 *   system_matrix,
1408 *   system_rhs);
1409 *   }
1410 *   }
1411 *   }
1412 *   system_matrix.compress(VectorOperation::add);
1413 *   system_rhs.compress(VectorOperation::add);
1414 *   }
1415 *  
1416 *   template <int dim>
1417 *   void
1418 *   HarmonicResponse<dim>::assemble_air_structure_interface_term(
1419 *   const FEFaceValuesBase<dim> &elasticity_fe_face_values,
1420 *   const FEFaceValuesBase<dim> &air_fe_face_values,
1421 *   FullMatrix<std::complex<double>> &local_interface_matrix,
1422 *   const double &omega)
1423 *   {
1424 *   const FEValuesExtractors::Vector displacement(0);
1425 *   const FEValuesExtractors::Scalar pressure(dim);
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;
1430 *  
1431 *   for (unsigned int q = 0; q < n_face_quadrature_points; ++q)
1432 *   {
1433 *   const Tensor<1, dim, double> normalVectorStructure =
1434 *   -air_fe_face_values.normal_vector(q);
1435 *   for (unsigned int i = 0; i < air_fe_face_values.dofs_per_cell; ++i)
1436 *   {
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;
1440 *   ++j)
1441 *   {
1442 *   const Tensor<1, dim> phi_j =
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);
1450 *   }
1451 *   }
1452 *   }
1453 *   }
1454 *  
1455 * @endcode
1456 *
1457 * calculation of incident sound power on the source side
1458 *
1459 * @code
1460 *   template <int dim>
1461 *   double
1462 *   HarmonicResponse<dim>::incident_sound_power()
1463 *   {
1464 *   FEFaceValues<dim> structure_fe_face_values(
1465 *   fe_structure,
1466 *   face_quadrature_formula_structure,
1469 *   std::vector<types::global_dof_index> local_dof_indices;
1470 *   const FEValuesExtractors::Vector displacement(0);
1471 *   double sound_power = 0.;
1472 *   const double density_air = get_density_air();
1473 *   for (const auto &cell : dof_handler.active_cell_iterators())
1474 *   {
1475 *   if (cell->is_locally_owned())
1476 *   {
1477 *   for (const auto face_no : cell->face_indices())
1478 *   {
1479 *   if (cell->face(face_no)->at_boundary() &&
1480 *   (cell->face(face_no)->user_index() ==
1481 *   static_cast<unsigned int>(SurfaceID::SourceSide)) &&
1482 *   (cell->material_id() ==
1483 *   static_cast<unsigned int>(MaterialID::Concrete)))
1484 *   {
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,
1492 *   pressure);
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)
1498 *   {
1499 *   const Tensor<1, dim, double> NormalVector =
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.) *
1504 *   density_air)) *
1505 *   (pressure_gradients[q] * NormalVector);
1506 *   sound_power +=
1507 *   0.5 * std::real(pressure[q] * std::conj(v_n) * JxW);
1508 *   }
1509 *   }
1510 *   }
1511 *   }
1512 *   }
1513 *   return sound_power;
1514 *   }
1515 *  
1516 * @endcode
1517 *
1518 * Calculating the sound power on the receiver side
1519 *
1520 * @code
1521 *   template <int dim>
1522 *   double
1523 *   HarmonicResponse<dim>::receiver_sound_power()
1524 *   {
1525 * @endcode
1526 *
1527 * Common face quadrature
1528 *
1529 * @code
1530 *   const QGauss<dim - 1> common_face_quadrature(fe_collection.max_degree() +
1531 *   1);
1532 * @endcode
1533 *
1534 * FE face values for surface integration
1535 *
1536 * @code
1537 *   FEFaceValues<dim> air_fe_face_values(fe_air,
1538 *   common_face_quadrature,
1543 *   FEFaceValues<dim> elasticity_fe_face_values(fe_structure,
1544 *   common_face_quadrature,
1545 *   update_values |
1550 *   FESubfaceValues<dim> air_fe_sub_face_values(fe_air,
1551 *   common_face_quadrature,
1552 *   update_values |
1557 *   FESubfaceValues<dim> elasticity_fe_sub_face_values(
1558 *   fe_structure,
1559 *   common_face_quadrature,
1562 *  
1563 *   double sound_power = 0.;
1564 *   for (const auto &cell : dof_handler.active_cell_iterators())
1565 *   {
1566 *   if (cell->is_locally_owned())
1567 *   {
1568 *   for (const auto f : cell->face_indices())
1569 *   {
1570 *   if ((cell->face(f)->user_index() ==
1571 *   static_cast<unsigned int>(SurfaceID::ReceiverSide)) &&
1572 *   !cell->at_boundary(f) &&
1573 *   (cell->material_id() ==
1574 *   static_cast<unsigned int>(MaterialID::Concrete)))
1575 *   {
1576 *   const auto neighbor = cell->neighbor(f);
1577 * @endcode
1578 *
1579 * The neighbor is at the same refinement level and has no
1580 * children.
1581 *
1582 * @code
1583 *   if ((neighbor->level() == cell->level()) &&
1584 *   (neighbor->has_children() == false) &&
1585 *   (neighbor->material_id() ==
1586 *   static_cast<unsigned int>(MaterialID::Air)))
1587 *   {
1588 *   elasticity_fe_face_values.reinit(cell, f);
1589 *   air_fe_face_values.reinit(
1590 *   neighbor, cell->neighbor_of_neighbor(f));
1591 *   sound_power +=
1592 *   cell_receiver_sound_power(elasticity_fe_face_values,
1593 *   air_fe_face_values,
1594 *   omega);
1595 *   }
1596 * @endcode
1597 *
1598 * The neighbor has children.
1599 *
1600 * @code
1601 *   else if ((neighbor->level() == cell->level()) &&
1602 *   (neighbor->has_children() == true))
1603 *   {
1604 *   for (unsigned int subface = 0;
1605 *   subface < cell->face(f)->n_children();
1606 *   ++subface)
1607 *   {
1608 *   elasticity_fe_sub_face_values.reinit(cell,
1609 *   f,
1610 *   subface);
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,
1617 *   omega);
1618 *   }
1619 *   }
1620 * @endcode
1621 *
1622 * The neighbor is coarser.
1623 *
1624 * @code
1625 *   else if (cell->neighbor_is_coarser(f))
1626 *   {
1627 *   elasticity_fe_face_values.reinit(cell, f);
1628 *   air_fe_sub_face_values.reinit(
1629 *   neighbor,
1630 *   cell->neighbor_of_coarser_neighbor(f).first,
1631 *   cell->neighbor_of_coarser_neighbor(f).second);
1632 *   sound_power +=
1633 *   cell_receiver_sound_power(elasticity_fe_face_values,
1634 *   air_fe_sub_face_values,
1635 *   omega);
1636 *   }
1637 *   }
1638 *   }
1639 *   }
1640 *   }
1641 *   return sound_power;
1642 *   }
1643 *  
1644 *   template <int dim>
1645 *   double
1646 *   HarmonicResponse<dim>::cell_receiver_sound_power(
1647 *   const FEFaceValuesBase<dim> &elasticity_fe_face_values,
1648 *   const FEFaceValuesBase<dim> &air_fe_face_values,
1649 *   const double &omega)
1650 *   {
1651 *   std::vector<types::global_dof_index> local_dof_indices;
1652 *   const FEValuesExtractors::Vector displacement(0);
1653 *   const FEValuesExtractors::Scalar pressure(dim);
1654 *   const unsigned int n_q_points = air_fe_face_values.n_quadrature_points;
1655 *   double sound_power = 0.;
1656 *   ;
1657 *  
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);
1662 *  
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)
1668 *   {
1669 *   const Tensor<1, dim, double> NormalVector =
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;
1675 *   sound_power +=
1676 *   0.5 *
1677 *   std::real(local_dof_values_pressure[q] * std::conj(normal_velocity)) *
1678 *   JxW;
1679 *   }
1680 *   return sound_power;
1681 *   }
1682 *  
1683 *   template <int dim>
1684 *   void
1685 *   HarmonicResponse<dim>::solve()
1686 *   {
1687 *   LinearAlgebraPETSc::MPI::Vector completely_distributed_solution(
1688 *   locally_owned_dofs, mpi_communicator);
1689 *   SolverControl solver_control;
1690 *   PETScWrappers::SparseDirectMUMPS solver(solver_control, 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;
1694 *   }
1695 *  
1696 *   template <int dim>
1697 *   void
1698 *   HarmonicResponse<dim>::calculate_magnitude()
1699 *   {
1700 *   for (const auto i : locally_owned_dofs)
1701 *   {
1702 *   const std::complex<double> value = locally_relevant_solution[i];
1703 * @endcode
1704 *
1705 * For postprocessing, the real part represents the magnitude, while the
1706 * imaginary part vanishes.
1707 *
1708 * @code
1709 *   locally_relevant_magnitude[i] = std::abs(value);
1710 *   }
1711 *   }
1712 *  
1713 *   template <int dim>
1714 *   void
1715 *   HarmonicResponse<dim>::run(bool write_output)
1716 *   {
1717 *   static bool mode_output = false;
1718 *   if (!mode_output)
1719 *   {
1720 *   #ifdef DEBUG
1721 *   pcout << "Debug mode" << std::endl;
1722 *   #else
1723 *   pcout << "Release mode" << std::endl;
1724 *   #endif
1725 *   mode_output = true;
1726 *   }
1727 *  
1728 *   const double frequency = omega / (numbers::PI * 2.); // frequency in Hz
1729 *   pcout << std::endl << "Frequency = " << frequency << " Hz" << std::endl;
1730 *  
1731 *   GridIn<dim> grid_in;
1732 *   grid_in.attach_triangulation(triangulation);
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())
1737 *   {
1738 *   if (cell->center()[0] > 203.)
1739 *   {
1740 *   cell->set_refine_flag();
1741 *   }
1742 *   }
1743 *   triangulation.execute_coarsening_and_refinement();
1744 *  
1745 *   pcout << " setup_system" << std::endl;
1746 *   setup_system();
1747 *   pcout << " assemble_system" << std::endl;
1748 *   assemble_system();
1749 *   pcout << " solve" << std::endl;
1750 *   solve();
1751 * @endcode
1752 *
1753 * Calculation of the magnitude of the solution. For postprocessing, the
1754 * magnitude of the solutions corresponds to the real part and the imaginary
1755 * part vaishes.
1756 *
1757 * @code
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);
1767 *  
1768 *   const auto stl =
1769 *   10. * std::log10(sound_power_source_side / sound_power_receiver_side);
1770 *   pcout << " STL = " << stl << " dB" << std::endl;
1771 *   if (Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0)
1772 *   {
1773 *   std::ofstream outfile("STL_result.txt", std::ios::app);
1774 *   outfile << frequency << " " << stl << std::endl;
1775 *   }
1776 *  
1777 *   if (write_output)
1778 *   {
1779 *   DataOut<dim> data_out;
1780 *   data_out.attach_dof_handler(dof_handler);
1781 *  
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");
1786 *  
1787 *   std::vector<DataComponentInterpretation::DataComponentInterpretation>
1788 *   interpretation = {
1793 *   data_out.add_data_vector(locally_relevant_solution,
1794 *   solution_names,
1796 *   interpretation);
1797 *  
1798 *  
1799 *   data_out.add_data_vector(locally_relevant_magnitude,
1800 *   solution_names_magnitude,
1802 *   interpretation);
1803 *  
1804 * @endcode
1805 *
1806 * subdomain visualization (unchanged)
1807 *
1808 * @code
1809 *   Vector<float> subdomain(triangulation.n_active_cells());
1810 *   for (unsigned int i = 0; i < subdomain.size(); ++i)
1811 *   subdomain(i) = triangulation.locally_owned_subdomain();
1812 *  
1813 *   data_out.add_data_vector(subdomain, "subdomain");
1814 *  
1815 *   data_out.build_patches();
1816 *  
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);
1822 *   }
1823 *   }
1824 *   } // namespace VibroAcousticProblem
1825 *  
1826 *   int
1827 *   main(int argc, char *argv[])
1828 *   {
1829 *   try
1830 *   {
1831 *   using namespace dealii;
1832 *   const unsigned int dim = 3;
1833 *   Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);
1834 *   double f0 = 50.; // starting frequency in Hz
1835 *   unsigned int n = 0; // number of frequency steps
1836 *   double f_c = f0; // evaluation frequency
1837 *  
1838 *   while (f_c < 1000.)
1839 *   {
1840 *   f_c = f0 * std::pow(10., static_cast<double>(n) / 60.);
1841 *   double omega = f_c * 2. * numbers::PI;
1842 *   VibroAcousticProblem::HarmonicResponse<dim> elastic_problem(omega);
1843 *   elastic_problem.run(true);
1844 *   n++;
1845 *   }
1846 *   }
1847 *   catch (std::exception &exc)
1848 *   {
1849 *   std::cerr << std::endl
1850 *   << std::endl
1851 *   << "----------------------------------------------------"
1852 *   << std::endl;
1853 *   std::cerr << "Exception on processing: " << std::endl
1854 *   << exc.what() << std::endl
1855 *   << "Aborting!" << std::endl
1856 *   << "----------------------------------------------------"
1857 *   << std::endl;
1858 *  
1859 *   return 1;
1860 *   }
1861 *   catch (...)
1862 *   {
1863 *   std::cerr << std::endl
1864 *   << std::endl
1865 *   << "----------------------------------------------------"
1866 *   << std::endl;
1867 *   std::cerr << "Unknown exception!" << std::endl
1868 *   << "Aborting!" << std::endl
1869 *   << "----------------------------------------------------"
1870 *   << std::endl;
1871 *   return 1;
1872 *   }
1873 *  
1874 *   return 0;
1875 *   } * @endcode
1876
1877
1878*/
*  *  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
Definition fe_q.h:552
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)
Definition grid_in.cc:155
Definition point.h:111
unsigned int level
Definition grid_out.cc:4642
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.
void random(DoFHandler< dim, spacedim > &dof_handler)
IndexSet extract_locally_relevant_dofs(const DoFHandler< dim, spacedim > &dof_handler)
void scale(const double scaling_factor, Triangulation< dim, spacedim > &triangulation)
double volume(const Triangulation< dim, spacedim > &tria)
@ matrix
Contents is actually a matrix.
constexpr char N
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.)
Definition advection.h:72
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
void distribute_sparsity_pattern(DynamicSparsityPattern &dsp, const IndexSet &locally_owned_rows, const MPI_Comm mpi_comm, const IndexSet &locally_relevant_rows)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
Definition mpi.cc:118
T broadcast(const MPI_Comm comm, const T &object_to_send, const unsigned int root_process=0)
void interpolate_boundary_values(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const std::map< types::boundary_id, const Function< spacedim, number > * > &function_map, std::map< types::global_dof_index, number > &boundary_values, const ComponentMask &component_mask={})
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)
Definition loop.h:68
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
constexpr double E
Definition numbers.h:215
constexpr double PI
Definition numbers.h:240
STL namespace.
::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)
unsigned int material_id
Definition types.h:182