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 DiffusionParametersDefault
29 static constexpr std::array<unsigned int, 0U>
neumann_nodes{};
34 const param_float_t = 0.)
42 const param_float_t = 0.)
50 const param_float_t = 0.)
58 const param_float_t = 0.)
66 const param_float_t = 0.)
101 template <
unsigned int hyEdge_dimT,
102 unsigned int poly_deg,
103 unsigned int quad_deg,
104 template <
unsigned int,
typename>
typename parametersT = DiffusionParametersDefault,
105 typename lSol_float_t =
double>
116 static constexpr
unsigned int hyEdge_dim() {
return hyEdge_dimT; }
170 template <
typename parameters>
173 return std::find(parameters::dirichlet_nodes.begin(), parameters::dirichlet_nodes.end(),
174 node_type) != parameters::dirichlet_nodes.end();
215 template <
typename hyEdgeT>
217 assemble_loc_matrix(
const lSol_float_t tau, hyEdgeT& hyper_edge,
const lSol_float_t time)
const;
238 template <
typename hyEdgeT,
typename SmallMatT>
240 const SmallMatT& lambda_values,
241 hyEdgeT& hyper_edge)
const;
260 template <
typename hyEdgeT>
263 const lSol_float_t time)
const;
282 template <
typename hyEdgeT>
284 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
285 hyEdgeT& hyper_edge)
const;
297 template <
typename hyEdgeT,
typename SmallMatT>
299 const unsigned int solution_type,
301 const lSol_float_t time)
const
306 if (solution_type == 0)
308 else if (solution_type == 1)
312 hy_assert(0 == 1,
"This has not been implemented!");
318 <<
"This can happen if quadrature is too inaccurate!");
333 template <
typename hyEdgeT>
334 inline std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT>
primal_at_boundary(
335 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
336 hyEdgeT& hyper_edge)
const;
348 template <
typename hyEdgeT>
349 inline std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT>
dual_at_boundary(
350 const std::array<lSol_float_t, (hyEdge_dimT + 1) *
n_shape_fct_>& coeffs,
351 hyEdgeT& hyper_edge)
const;
389 std::array<lSol_float_t, 1U> summed_error;
390 summed_error.fill(0.);
398 for (
unsigned int k = 0; k < summed_error.size(); ++k)
399 summed_error[k] += new_error[k];
407 for (
unsigned int k = 0; k < summed_error.size(); ++k)
408 summed_error[k] = std::sqrt(summed_error[k]);
442 template <
typename hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
444 SmallMatOutT& lambda_values_out,
446 const lSol_float_t time = 0.)
const
448 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
449 lambda_values_in.size() == 2 * hyEdge_dimT,
450 "Both matrices must be of same size which corresponds to the number of faces!");
451 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
453 lambda_values_in[i].size() == lambda_values_out[i].size() &&
455 "Both matrices must be of same size which corresponds to the number of dofs per face!");
458 std::array<lSol_float_t, n_loc_dofs_> coeffs =
461 std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT> primals(
465 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
466 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
467 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
468 lambda_values_out[i][j] = 0.;
470 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
472 lambda_values_out[i][j] =
473 duals[i][j] +
tau_ * primals[i][j] -
474 tau_ * lambda_values_in[i][j] * hyper_edge.geometry.face_area(i);
475 lambda_values_out[i][j] *=
theta_;
478 return lambda_values_out;
497 template <
typename hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
499 SmallMatOutT& lambda_values_out,
501 const lSol_float_t time = 0.)
const
503 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
504 lambda_values_in.size() == 2 * hyEdge_dimT,
505 "Both matrices must be of same size which corresponds to the number of faces!");
506 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
508 lambda_values_in[i].size() == lambda_values_out[i].size() &&
510 "Both matrices must be of same size which corresponds to the number of dofs per face!");
513 std::array<lSol_float_t, n_loc_dofs_> coeffs =
516 std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT> primals(
520 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
522 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
523 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
524 lambda_values_out[i][j] = 0.;
526 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
528 lambda_values_out[i][j] =
529 duals[i][j] +
tau_ * primals[i][j] -
530 tau_ * lambda_values_in[i][j] * hyper_edge.geometry.face_area(i);
531 lambda_values_out[i][j] *=
theta_;
532 lambda_values_out[i][j] += (1. -
theta_) * hyper_edge.data.boundary_flux_old(j, i);
536 return lambda_values_out;
546 template <
class hyEdgeT>
548 const std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT>& lambda_values,
550 const lSol_float_t time = 0.)
const
554 std::array<lSol_float_t, n_loc_dofs_> coeffs =
558 hyper_edge.data.u_old[i] = coeffs[hyEdge_dimT *
n_shape_fct_ + i];
561 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
570 hyper_edge.
data.flux_old[i] = integrator::template integrate_vol_phifunc<
572 parameters::right_hand_side>(i, hyper_edge.geometry, time);
576 integrator::template integrate_vol_nablaphiphi<Point<hyEdge_dimT, lSol_float_t>,
578 i, j, hyper_edge.geometry);
579 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
580 hyper_edge.
data.flux_old[i] += q_components[dim][j] * grad_int_vec[dim];
581 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
583 helper = integrator::template integrate_bdr_phiphi<decltype(hyEdgeT::geometry)>(
584 i, j, face, hyper_edge.geometry);
585 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
586 hyper_edge.data.flux_old[i] -= q_components[dim][j] *
587 hyper_edge.geometry.local_normal(face).operator[](dim) *
589 hyper_edge.data.flux_old[i] -=
tau_ * hyper_edge.data.u_old[j] * helper;
593 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
594 hyper_edge.data.flux_old[i] +=
595 tau_ * lambda_values[face][j] *
597 i, j, face, hyper_edge.geometry);
600 std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT> primals(
604 for (
unsigned int i = 0; i < lambda_values.size(); ++i)
606 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
607 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
608 hyper_edge.data.boundary_flux_old(j, i) = 0.;
610 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
611 hyper_edge.data.boundary_flux_old(j, i) =
612 duals[i][j] +
tau_ * primals[i][j] -
613 tau_ * lambda_values[i][j] * hyper_edge.geometry.face_area(i);
626 template <
class hyEdgeT,
typename SmallMatT>
629 const lSol_float_t time = 0.)
const
634 for (
unsigned int i = 0; i < lambda_values.size(); ++i)
636 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
637 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
638 lambda_values[i][j] = 0.;
640 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
641 lambda_values[i][j] = integrator::template integrate_bdrUni_psifunc<
643 decltype(
hyEdgeT::geometry), parameters::initial>(j, i, hyper_edge.geometry, time);
648 hyper_edge.data.u_old[i] = integrator::template integrate_volUni_phifunc<
650 parameters::initial>(i, hyper_edge.geometry, time);
656 mass_flux(i, j) = integrator::template integrate_vol_phiphifunc<
659 i, j, hyper_edge.geometry, time);
662 std::array<SmallVec<n_shape_fct_, lSol_float_t>, hyEdge_dimT> q_components;
665 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
669 local_rhs[i] = integrator::template integrate_vol_derphifunc<
672 i, dim, hyper_edge.geometry, time);
673 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
675 integrator::template integrate_bdr_phifunc<
678 i, face, hyper_edge.geometry, time) *
679 hyper_edge.geometry.local_normal(face).operator[](dim);
681 q_components[dim] = local_rhs / mass_mat;
689 hyper_edge.
data.flux_old[i] = integrator::template integrate_vol_phifunc<
696 integrator::template integrate_vol_nablaphiphi<Point<hyEdge_dimT, lSol_float_t>,
698 i, j, hyper_edge.geometry);
699 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
700 hyper_edge.
data.flux_old[i] += q_components[dim][j] * grad_int_vec[dim];
701 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
703 helper = integrator::template integrate_bdr_phiphi<decltype(hyEdgeT::geometry)>(
704 i, j, face, hyper_edge.geometry);
705 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
706 hyper_edge.data.flux_old[i] -= q_components[dim][j] *
707 hyper_edge.geometry.local_normal(face).operator[](dim) *
709 hyper_edge.data.flux_old[i] -=
tau_ * hyper_edge.data.u_old[j] * helper;
713 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
714 hyper_edge.data.flux_old[i] +=
715 tau_ * lambda_values[face][j] *
717 i, j, face, hyper_edge.geometry);
720 std::array<lSol_float_t, n_loc_dofs_> coeffs;
721 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
725 coeffs[hyEdge_dimT *
n_shape_fct_ + i] = hyper_edge.data.u_old[i];
726 std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT> primals(
730 for (
unsigned int i = 0; i < lambda_values.size(); ++i)
732 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
733 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
734 hyper_edge.data.boundary_flux_old(j, i) = 0.;
736 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
737 hyper_edge.data.boundary_flux_old(j, i) =
738 duals[i][j] +
tau_ * primals[i][j] -
739 tau_ * lambda_values[i][j] * hyper_edge.geometry.face_area(i);
742 return lambda_values;
753 template <
class hyEdgeT>
754 std::array<lSol_float_t, 1U>
errors(
const std::array<std::array<lSol_float_t, n_shape_bdr_>,
755 2 * hyEdge_dimT>&
UNUSED(lambda_values),
757 const lSol_float_t time = 0.)
const
761 return std::array<lSol_float_t, 1U>({integrator::template integrate_vol_diffsquare_discana<
764 hy_edge.geometry, time)});
779 template <
typename abscissa_float_t,
780 std::size_t abscissas_sizeT,
783 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
system_dim>
784 bulk_values(
const std::array<abscissa_float_t, abscissas_sizeT>& abscissas,
785 const input_array_t& lambda_values,
787 const lSol_float_t time = 0.)
const;
807 template <
unsigned int hyEdge_dimT,
808 unsigned int poly_deg,
809 unsigned int quad_deg,
810 template <
unsigned int,
typename>
811 typename parametersT,
812 typename lSol_float_t>
813 template <
typename hyEdgeT>
818 const lSol_float_t tau,
820 const lSol_float_t time)
const
824 lSol_float_t vol_integral, face_integral, helper;
827 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
829 for (
unsigned int j = 0; j < n_shape_fct_; ++j)
832 vol_integral = integrator::template integrate_vol_phiphifunc<
834 parameters::inverse_diffusion_coeff,
Point<hyEdge_dimT, lSol_float_t> >(
839 integrator::template integrate_vol_nablaphiphi<SmallVec<hyEdge_dimT, lSol_float_t>,
841 i, j, hyper_edge.geometry);
845 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
847 helper = integrator::template integrate_bdr_phiphi<decltype(hyEdgeT::geometry)>(
848 i, j, face, hyper_edge.geometry);
849 face_integral += helper;
850 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
851 normal_int_vec[dim] += hyper_edge.geometry.local_normal(face).operator[](dim) * helper;
854 local_mat(hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) +=
855 tau * theta_ * delta_t_ * face_integral;
856 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
858 local_mat(dim * n_shape_fct_ + i, dim * n_shape_fct_ + j) += vol_integral;
859 local_mat(dim * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) -= grad_int_vec[dim];
860 local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) -=
861 theta_ * delta_t_ * grad_int_vec[dim];
862 local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) +=
863 theta_ * delta_t_ * normal_int_vec[dim];
866 local_mat(hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) +=
867 integrator::template integrate_vol_phiphi<decltype(hyEdgeT::geometry)>(i, j,
868 hyper_edge.geometry);
879 template <
unsigned int hyEdge_dimT,
880 unsigned int poly_deg,
881 unsigned int quad_deg,
882 template <
unsigned int,
typename>
883 typename parametersT,
884 typename lSol_float_t>
885 template <
typename hyEdgeT,
typename SmallMatT>
892 hy_assert(lambda_values.size() == 2 * hyEdge_dimT,
893 "The size of the lambda values should be twice the dimension of a hyperedge.");
894 for (
unsigned int i = 0; i < 2 * hyEdge_dimT; ++i)
895 hy_assert(lambda_values[i].size() == n_shape_bdr_,
896 "The size of lambda should be the amount of ansatz functions at boundary.");
899 lSol_float_t integral;
901 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
902 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
903 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
905 integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
906 i, j, face, hyper_edge.geometry);
907 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] +=
908 tau_ * theta_ * delta_t_ * lambda_values[face][j] * integral;
909 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
910 right_hand_side[dim * n_shape_fct_ + i] -=
911 hyper_edge.geometry.local_normal(face).operator[](dim) * lambda_values[face][j] *
915 return right_hand_side;
922 template <
unsigned int hyEdge_dimT,
923 unsigned int poly_deg,
924 unsigned int quad_deg,
925 template <
unsigned int,
typename>
926 typename parametersT,
927 typename lSol_float_t>
928 template <
typename hyEdgeT>
937 lSol_float_t integral;
938 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
940 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] =
942 integrator::template integrate_vol_phifunc<
947 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
949 if (!is_dirichlet<parameters>(hyper_edge.node_descriptor[face]))
951 integral = integrator::template integrate_bdr_phifunc<
953 parameters::dirichlet_value,
Point<hyEdge_dimT, lSol_float_t> >(i, face,
955 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] +=
956 tau_ * theta_ * delta_t_ * integral +
957 tau_ * (1. - theta_) * delta_t_ *
958 integrator::template integrate_bdr_phifunc<
961 Point<hyEdge_dimT, lSol_float_t> >(i, face, hyper_edge.
geometry, time - delta_t_);
962 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
963 right_hand_side[dim * n_shape_fct_ + i] -=
964 hyper_edge.geometry.local_normal(face).operator[](dim) * integral;
968 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
969 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] +=
970 hyper_edge.data.u_old[i] * hyper_edge.geometry.area() +
971 delta_t_ * (1. - theta_) * hyper_edge.data.flux_old[i];
973 return right_hand_side;
980 template <
unsigned int hyEdge_dimT,
981 unsigned int poly_deg,
982 unsigned int quad_deg,
983 template <
unsigned int,
typename>
984 typename parametersT,
985 typename lSol_float_t>
986 template <
typename hyEdgeT>
996 hyEdgeT& hyper_edge)
const
999 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
1000 for (
unsigned int j = 0; j < n_shape_fct_; ++j)
1001 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] +=
1002 coeffs[hyEdge_dimT * n_shape_fct_ + j] *
1003 integrator::template integrate_vol_phiphi(i, j, hyper_edge.geometry);
1005 return right_hand_side;
1012 template <
unsigned int hyEdge_dimT,
1013 unsigned int poly_deg,
1014 unsigned int quad_deg,
1015 template <
unsigned int,
typename>
1016 typename parametersT,
1017 typename lSol_float_t>
1018 template <
typename hyEdgeT>
1025 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
1026 hyEdgeT& hyper_edge)
const
1028 std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT> bdr_values;
1030 for (
unsigned int dim_n = 0; dim_n < 2 * hyEdge_dimT; ++dim_n)
1031 bdr_values[dim_n].fill(0.);
1033 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
1034 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
1035 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
1036 bdr_values[face][j] +=
1037 coeffs[hyEdge_dimT * n_shape_fct_ + i] *
1039 i, j, face, hyper_edge.geometry);
1048 template <
unsigned int hyEdge_dimT,
1049 unsigned int poly_deg,
1050 unsigned int quad_deg,
1051 template <
unsigned int,
typename>
1052 typename parametersT,
1053 typename lSol_float_t>
1054 template <
typename hyEdgeT>
1061 const std::array<lSol_float_t, (hyEdge_dimT + 1) * n_shape_fct_>& coeffs,
1062 hyEdgeT& hyper_edge)
const
1064 std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT> bdr_values;
1065 lSol_float_t integral;
1067 for (
unsigned int dim_n = 0; dim_n < 2 * hyEdge_dimT; ++dim_n)
1068 bdr_values[dim_n].fill(0.);
1070 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
1071 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
1072 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
1074 integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
1075 i, j, face, hyper_edge.geometry);
1076 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
1077 bdr_values[face][j] += hyper_edge.geometry.local_normal(face).operator[](dim) * integral *
1078 coeffs[dim * n_shape_fct_ + i];
1088 template <
unsigned int hyEdge_dimT,
1089 unsigned int poly_deg,
1090 unsigned int quad_deg,
1091 template <
unsigned int,
typename>
1092 typename parametersT,
1093 typename lSol_float_t>
1094 template <
typename abscissa_float_t,
1095 std::size_t abscissas_sizeT,
1096 class input_array_t,
1098 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
1101 const std::array<abscissa_float_t, abscissas_sizeT>& abscissas,
1102 const input_array_t& lambda_values,
1103 hyEdgeT& hyper_edge,
1104 const lSol_float_t time)
const
1107 solve_local_problem(lambda_values, 1U, hyper_edge, time);
1111 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
1115 for (
unsigned int d = 0; d < system_dim; ++d)
1117 for (
unsigned int i = 0; i < coeffs.
size(); ++i)
1118 coeffs[i] = coefficients[d * n_shape_fct_ + i];
1119 for (
unsigned int pt = 0; pt < Hypercube<hyEdge_dimT>::pow(abscissas_sizeT); ++pt)
1120 point_vals[d][pt] = integrator::shape_fun_t::template lin_comb_fct_val<float>(