1 #pragma once // Ensure that file is included only once in a single compilation.
19 template <
unsigned int space_dimT,
typename param_
float_t =
double>
20 struct Bilaplacian_parameters_default
33 static constexpr std::array<unsigned int, 0U>
neumann_nodes{};
42 const param_float_t = 0.)
50 const param_float_t = 0.)
58 const param_float_t = 0.)
66 const param_float_t = 0.)
74 const param_float_t = 0.)
82 const param_float_t = 0.)
90 const param_float_t = 0.)
113 template <
unsigned int hyEdge_dimT,
114 unsigned int poly_deg,
115 unsigned int quad_deg,
116 template <
unsigned int,
typename>
117 typename parametersT,
118 typename lSol_float_t =
double>
129 static constexpr
unsigned int hyEdge_dim() {
return hyEdge_dimT; }
183 template <
typename parameters>
186 return std::find(parameters::dirichlet_nodes.begin(), parameters::dirichlet_nodes.end(),
187 node_type) != parameters::dirichlet_nodes.end();
189 template <
typename parameters>
192 return std::find(parameters::dirichlet_laplacian_nodes.begin(),
193 parameters::dirichlet_laplacian_nodes.end(),
194 node_type) != parameters::dirichlet_laplacian_nodes.end();
235 template <
typename hyEdgeT>
237 assemble_loc_matrix(
const lSol_float_t tau, hyEdgeT& hyper_edge,
const lSol_float_t time)
const;
258 template <
typename hyEdgeT,
typename SmallMatT>
260 const SmallMatT& lambda_values,
261 hyEdgeT& hyper_edge)
const;
280 template <
typename hyEdgeT>
283 const lSol_float_t time)
const;
302 template <
typename hyEdgeT>
304 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
305 hyEdgeT& hyper_edge)
const;
317 template <
typename hyEdgeT,
typename SmallMatT>
319 const unsigned int solution_type,
321 const lSol_float_t time)
const
326 if (solution_type == 0)
328 else if (solution_type == 1)
332 hy_assert(0 == 1,
"This has not been implemented!");
338 <<
"This can happen if quadrature is too inaccurate!");
353 template <
typename hyEdgeT>
354 inline std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT>
primal_at_boundary(
355 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
356 hyEdgeT& hyper_edge)
const;
368 template <
typename hyEdgeT>
369 inline std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT>
dual_at_boundary(
370 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
371 hyEdgeT& hyper_edge)
const;
383 std::array<lSol_float_t, n_loc_dofs_>
coeffs;
408 std::array<lSol_float_t, 1U> summed_error;
409 summed_error.fill(0.);
417 for (
unsigned int k = 0; k < summed_error.size(); ++k)
418 summed_error[k] += new_error[k];
426 for (
unsigned int k = 0; k < summed_error.size(); ++k)
427 summed_error[k] = std::sqrt(summed_error[k]);
461 template <
typename hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
463 SmallMatOutT& lambda_values_out,
465 const lSol_float_t time = 0.)
const
467 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
468 lambda_values_in.size() == 2 * hyEdge_dimT,
469 "Both matrices must be of same size which corresponds to the number of faces!");
470 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
472 lambda_values_in[i].size() == lambda_values_out[i].size() &&
474 "Both matrices must be of same size which corresponds to the number of dofs per face!");
477 std::array<lSol_float_t, n_loc_dofs_> coeffs =
480 std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> primals(
484 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
486 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
487 lambda_values_out[i][j] =
488 duals[i][j] +
tau_ * primals[i][j] -
490 hyper_edge.geometry.face_area(i);
491 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
492 for (
unsigned int j = 0; j < lambda_values_out[i].size() / 2; ++j)
493 lambda_values_out[i][j] = 0.;
494 if (is_dirichlet_laplacian<parameters>(hyper_edge.node_descriptor[i]))
495 for (
unsigned int j = lambda_values_out[i].size() / 2; j < lambda_values_out[i].size(); ++j)
496 lambda_values_out[i][j] = 0.;
499 return lambda_values_out;
518 template <
class hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
520 SmallMatOutT& lambda_values_out,
522 const lSol_float_t time = 0.)
const
524 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
525 lambda_values_in.size() == 2 * hyEdge_dimT,
526 "Both matrices must be of same size which corresponds to the number of faces!");
527 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
529 lambda_values_in[i].size() == lambda_values_out[i].size() &&
531 "Both matrices must be of same size which corresponds to the number of dofs per face!");
534 std::array<lSol_float_t, n_loc_dofs_> coeffs =
537 std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> primals(
541 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
543 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
544 lambda_values_out[i][j] = duals[i][j] +
tau_ * primals[i][j] -
545 tau_ * lambda_values_in[i][j] * hyper_edge.geometry.face_area(i);
546 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
547 for (
unsigned int j = 0; j < lambda_values_out[i].size() / 2; ++j)
548 lambda_values_out[i][j] = 0.;
549 if (is_dirichlet_laplacian<parameters>(hyper_edge.node_descriptor[i]))
550 for (
unsigned int j = lambda_values_out[i].size() / 2; j < lambda_values_out[i].size(); ++j)
551 lambda_values_out[i][j] = 0.;
554 return lambda_values_out;
564 template <
class hyEdgeT>
566 const std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT>& lambda_values,
568 const lSol_float_t time = 0.)
const
570 std::array<lSol_float_t, n_loc_dofs_> coeffs =
573 hyper_edge.data.coeffs = coeffs;
585 template <
class hyEdgeT,
typename SmallMatT>
588 const lSol_float_t time = 0.)
const
592 for (
unsigned int i = 0; i < lambda_values.size(); ++i)
594 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
595 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
596 lambda_values[i][j] = 0.;
599 for (
unsigned int j = 0; j < lambda_values[i].size() / 2; ++j)
600 lambda_values[i][j] = integrator::template integrate_bdrUni_psifunc<
603 i, j, hyper_edge.geometry, time);
604 for (
unsigned int j = lambda_values[i].size() / 2; j < lambda_values[i].size(); ++j)
605 lambda_values[i][j] = integrator::template integrate_bdrUni_psifunc<
614 integrator::template integrate_volUni_phifunc<
617 i, hyper_edge.geometry, time);
619 return lambda_values;
631 template <
class hyEdgeT,
typename SmallMatT>
632 std::array<lSol_float_t, 1U>
errors(SmallMatT& lambda_values,
634 const lSol_float_t time = 0.)
const
638 for (
unsigned int i = 0; i < lambda_values.size(); ++i)
639 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
640 hy_assert(lambda_values[i][j] == lambda_values[i][j],
641 "Lambda value wit index " << i <<
"," << j <<
" is NaN!");
643 std::array<lSol_float_t, n_loc_dofs_> coefficients =
645 std::array<lSol_float_t, n_shape_fct_> coeffs;
646 for (
unsigned int i = 0; i < coeffs.size(); ++i)
647 coeffs[i] = coefficients[i + hyEdge_dimT *
n_shape_fct_];
649 for (
unsigned int i = 0; i < coeffs.size(); ++i)
650 hy_assert(coeffs[i] == coeffs[i],
"The " << i <<
"-th coeff is NaN!");
652 lSol_float_t result = integrator::template integrate_vol_diffsquare_discana<
656 hy_assert(result >= 0.,
"The squared error must be non-negative, but was " << result);
657 return std::array<lSol_float_t, 1U>({result});
672 template <
typename abscissa_
float_t, std::
size_t sizeT,
class input_array_t,
class hyEdgeT>
674 const std::array<abscissa_float_t, sizeT>& abscissas,
675 const input_array_t& lambda_values,
677 const lSol_float_t time = 0.)
const;
697 template <
unsigned int hyEdge_dimT,
698 unsigned int poly_deg,
699 unsigned int quad_deg,
700 template <
unsigned int,
typename>
701 typename parametersT,
702 typename lSol_float_t>
703 template <
typename hyEdgeT>
708 const lSol_float_t tau,
710 const lSol_float_t time)
const
713 constexpr
unsigned int n_dofs_lap = n_loc_dofs_ / 2;
716 lSol_float_t vol_integral, vol_func_integral, face_integral, helper;
719 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
721 for (
unsigned int j = 0; j < n_shape_fct_; ++j)
724 vol_integral = integrator::template integrate_vol_phiphi(i, j, hyper_edge.geometry);
725 vol_func_integral = integrator::template integrate_vol_phiphifunc<
727 parameters::inverse_bilaplacian_coefficient,
Point<hyEdge_dimT, lSol_float_t>>(
732 integrator::template integrate_vol_nablaphiphi<SmallVec<hyEdge_dimT, lSol_float_t>,
734 i, j, hyper_edge.geometry);
738 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
740 helper = integrator::template integrate_bdr_phiphi<decltype(hyEdgeT::geometry)>(
741 i, j, face, hyper_edge.geometry);
742 face_integral += helper;
743 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
744 normal_int_vec[dim] += hyper_edge.geometry.local_normal(face).operator[](dim) * helper;
747 local_mat(hyEdge_dimT * n_shape_fct_ + i, n_dofs_lap + hyEdge_dimT * n_shape_fct_ + j) -=
750 local_mat(hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) +=
752 local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
753 n_dofs_lap + hyEdge_dimT * n_shape_fct_ + j) +=
754 tau * theta_ * delta_t_ * face_integral;
756 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
758 local_mat(dim * n_shape_fct_ + i, dim * n_shape_fct_ + j) += vol_integral;
759 local_mat(n_dofs_lap + dim * n_shape_fct_ + i, n_dofs_lap + dim * n_shape_fct_ + j) +=
762 local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) -= grad_int_vec[dim];
763 local_mat(dim * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) -= grad_int_vec[dim];
764 local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
765 n_dofs_lap + dim * n_shape_fct_ + j) -= theta_ * delta_t_ * grad_int_vec[dim];
766 local_mat(n_dofs_lap + dim * n_shape_fct_ + i,
767 n_dofs_lap + hyEdge_dimT * n_shape_fct_ + j) -= grad_int_vec[dim];
769 local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) += normal_int_vec[dim];
770 local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
771 n_dofs_lap + dim * n_shape_fct_ + j) += theta_ * delta_t_ * normal_int_vec[dim];
774 local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) +=
775 integrator::template integrate_vol_phiphi<decltype(hyEdgeT::geometry)>(i, j,
776 hyper_edge.geometry);
787 template <
unsigned int hyEdge_dimT,
788 unsigned int poly_deg,
789 unsigned int quad_deg,
790 template <
unsigned int,
typename>
791 typename parametersT,
792 typename lSol_float_t>
793 template <
typename hyEdgeT,
typename SmallMatT>
800 constexpr
unsigned int n_dofs_lap = n_loc_dofs_ / 2;
801 hy_assert(lambda_values.size() == 2 * hyEdge_dimT,
802 "The size of the lambda values should be twice the dimension of a hyperedge.");
803 for (
unsigned int i = 0; i < 2 * hyEdge_dimT; ++i)
804 hy_assert(lambda_values[i].size() == 2 * n_shape_bdr_,
805 "The size of lambda should be the amount of ansatz functions at boundary.");
808 lSol_float_t integral;
810 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
811 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
812 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
814 integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
815 i, j, face, hyper_edge.geometry);
816 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] += tau_ * lambda_values[face][j] * integral;
817 right_hand_side[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] +=
818 tau_ * theta_ * delta_t_ * lambda_values[face][n_shape_bdr_ + j] * integral;
820 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
822 right_hand_side[dim * n_shape_fct_ + i] -=
823 hyper_edge.geometry.local_normal(face).operator[](dim) * lambda_values[face][j] *
825 right_hand_side[n_dofs_lap + dim * n_shape_fct_ + i] -=
826 hyper_edge.geometry.local_normal(face).operator[](dim) *
827 lambda_values[face][n_shape_bdr_ + j] * integral;
831 return right_hand_side;
838 template <
unsigned int hyEdge_dimT,
839 unsigned int poly_deg,
840 unsigned int quad_deg,
841 template <
unsigned int,
typename>
842 typename parametersT,
843 typename lSol_float_t>
844 template <
typename hyEdgeT>
852 constexpr
unsigned int n_dofs_lap = n_loc_dofs_ / 2;
854 lSol_float_t integral;
855 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
857 right_hand_side[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] =
859 integrator::template integrate_vol_phifunc<
862 Point<hyEdge_dimT, lSol_float_t>>(i, hyper_edge.
geometry, time) +
863 (1 - theta_) * delta_t_ *
864 integrator::template integrate_vol_phifunc<
865 Point<decltype(hyEdgeT::
geometry)::space_dim(), lSol_float_t>,
867 Point<hyEdge_dimT, lSol_float_t>>(i, hyper_edge.
geometry, time - delta_t_);
871 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
873 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[face]))
875 integral = integrator::template integrate_bdr_phifunc<
878 Point<hyEdge_dimT, lSol_float_t>>(i, face, hyper_edge.
geometry, time);
879 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] += tau_ * integral;
880 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
881 right_hand_side[dim * n_shape_fct_ + i] -=
882 hyper_edge.geometry.local_normal(face).operator[](dim) * integral;
884 if (is_dirichlet_laplacian<parameters>(hyper_edge.node_descriptor[face]))
886 integral = integrator::template integrate_bdr_phifunc<
889 Point<hyEdge_dimT, lSol_float_t>>(i, face, hyper_edge.
geometry, time);
890 right_hand_side[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] +=
891 tau_ * theta_ * delta_t_ * integral;
892 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
893 right_hand_side[n_dofs_lap + dim * n_shape_fct_ + i] -=
894 hyper_edge.geometry.local_normal(face).operator[](dim) * integral;
898 return right_hand_side + assemble_rhs_from_coeffs(hyper_edge.data.coeffs, hyper_edge);
905 template <
unsigned int hyEdge_dimT,
906 unsigned int poly_deg,
907 unsigned int quad_deg,
908 template <
unsigned int,
typename>
909 typename parametersT,
910 typename lSol_float_t>
911 template <
typename hyEdgeT>
921 hyEdgeT& hyper_edge)
const
924 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
925 for (
unsigned int j = 0; j < n_shape_fct_; ++j)
927 right_hand_side[n_loc_dofs_ / 2 + hyEdge_dimT * n_shape_fct_ + i] +=
928 coeffs[hyEdge_dimT * n_shape_fct_ + j] *
929 integrator::template integrate_vol_phiphi(i, j, hyper_edge.geometry);
932 return right_hand_side;
939 template <
unsigned int hyEdge_dimT,
940 unsigned int poly_deg,
941 unsigned int quad_deg,
942 template <
unsigned int,
typename>
943 typename parametersT,
944 typename lSol_float_t>
945 template <
typename hyEdgeT>
952 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
953 hyEdgeT& hyper_edge)
const
955 constexpr
unsigned int n_dofs_lap = n_loc_dofs_ / 2;
956 std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> bdr_values;
958 for (
unsigned int dim_n = 0; dim_n < 2 * hyEdge_dimT; ++dim_n)
959 bdr_values[dim_n].fill(0.);
961 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
962 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
963 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
965 bdr_values[face][n_shape_bdr_ + j] +=
966 coeffs[hyEdge_dimT * n_shape_fct_ + i] *
967 integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
968 i, j, face, hyper_edge.geometry);
970 bdr_values[face][j] +=
971 coeffs[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] *
972 integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
973 i, j, face, hyper_edge.geometry);
983 template <
unsigned int hyEdge_dimT,
984 unsigned int poly_deg,
985 unsigned int quad_deg,
986 template <
unsigned int,
typename>
987 typename parametersT,
988 typename lSol_float_t>
989 template <
typename hyEdgeT>
996 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
997 hyEdgeT& hyper_edge)
const
999 constexpr
unsigned int n_dofs_lap = n_loc_dofs_ / 2;
1000 std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> bdr_values;
1001 lSol_float_t integral;
1003 for (
unsigned int dim_n = 0; dim_n < 2 * hyEdge_dimT; ++dim_n)
1004 bdr_values[dim_n].fill(0.);
1006 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
1007 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
1008 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
1010 integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
1011 i, j, face, hyper_edge.geometry);
1012 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
1014 bdr_values[face][n_shape_bdr_ + j] +=
1015 hyper_edge.geometry.local_normal(face).operator[](dim) * integral *
1016 coeffs[dim * n_shape_fct_ + i];
1018 bdr_values[face][j] += hyper_edge.geometry.local_normal(face).operator[](dim) * integral *
1019 coeffs[n_dofs_lap + dim * n_shape_fct_ + i];
1030 template <
unsigned int hyEdge_dimT,
1031 unsigned int poly_deg,
1032 unsigned int quad_deg,
1033 template <
unsigned int,
typename>
1034 typename parametersT,
1035 typename lSol_float_t>
1036 template <
typename abscissa_
float_t, std::
size_t sizeT,
class input_array_t,
typename hyEdgeT>
1037 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(sizeT)>,
1040 const std::array<abscissa_float_t, sizeT>& abscissas,
1041 const input_array_t& lambda_values,
1042 hyEdgeT& hyper_edge,
1043 const lSol_float_t time)
const
1046 solve_local_problem(lambda_values, 1U, hyper_edge, time);
1051 std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(sizeT)>,
1055 for (
unsigned int d = 0; d < system_dim; ++d)
1057 for (
unsigned int i = 0; i < coeffs.
size(); ++i)
1058 coeffs[i] = coefficients[d * n_shape_fct_ + i];
1059 for (
unsigned int pt = 0; pt < Hypercube<hyEdge_dimT>::pow(sizeT); ++pt)
1060 point_vals[d][pt] = integrator::shape_fun_t::template lin_comb_fct_val<float>(