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>
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,
typename hyEdge_t>
172 const unsigned int face,
173 const lSol_float_t time)
175 const unsigned int node_type = edge.node_descriptor[face];
176 if (std::find(parameters::dirichlet_nodes.begin(), parameters::dirichlet_nodes.end(),
177 node_type) != parameters::dirichlet_nodes.end())
180 std::find(parameters::boundary_nodes.begin(), parameters::boundary_nodes.end(), node_type);
181 if (node == parameters::boundary_nodes.end())
184 parameters::velocity(edge.geometry.face_barycenter(face), time)) <= 0.;
187 template <
typename parameters,
typename hyEdge_t>
189 const unsigned int face,
190 const lSol_float_t time)
192 const unsigned int node_type = edge.node_descriptor[face];
193 if (std::find(parameters::outflow_nodes.begin(), parameters::outflow_nodes.end(), node_type) !=
194 parameters::outflow_nodes.end())
197 std::find(parameters::boundary_nodes.begin(), parameters::boundary_nodes.end(), node_type);
198 if (node == parameters::boundary_nodes.end())
201 parameters::velocity(edge.geometry.face_barycenter(face), time)) > 0.;
241 template <
typename hyEdgeT>
244 const lSol_float_t time)
const;
266 template <
typename hyEdgeT,
typename SmallMatT>
268 const SmallMatT& lambda_values,
270 const lSol_float_t time)
const;
289 template <
typename hyEdgeT>
292 const lSol_float_t time)
const;
304 template <
typename hyEdgeT,
typename SmallMatT>
306 const unsigned int solution_type,
308 const lSol_float_t time)
const
313 if (solution_type == 0)
315 else if (solution_type == 1)
319 hy_assert(0 == 1,
"This has not been implemented!");
325 <<
"This can happen if quadrature is too inaccurate!");
341 template <
typename SmallMatT,
typename hyEdgeT>
342 inline std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT>
flux_at_boundary(
343 const SmallMatT& lambda_values,
344 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
347 const lSol_float_t time)
const;
385 std::array<lSol_float_t, 1U> summed_error;
386 summed_error.fill(0.);
394 for (
unsigned int k = 0; k < summed_error.size(); ++k)
395 summed_error[k] += new_error[k];
403 for (
unsigned int k = 0; k < summed_error.size(); ++k)
404 summed_error[k] = std::sqrt(summed_error[k]);
438 template <
typename hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
440 SmallMatOutT& lambda_values_out,
442 const lSol_float_t time = 0.)
const
444 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
445 lambda_values_in.size() == 2 * hyEdge_dimT,
446 "Both matrices must be of same size which corresponds to the number of faces!");
447 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
449 lambda_values_in[i].size() == lambda_values_out[i].size() &&
451 "Both matrices must be of same size which corresponds to the number of dofs per face!");
454 std::array<lSol_float_t, n_loc_dofs_> coeffs =
457 std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT> primals(
460 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
461 if (is_dirichlet<parameters>(hyper_edge, i, time))
462 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
463 lambda_values_out[i][j] = 0.;
465 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
466 lambda_values_out[i][j] = primals[i][j];
468 return lambda_values_out;
487 template <
typename hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
489 SmallMatOutT& lambda_values_out,
491 const lSol_float_t time = 0.)
const
493 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
494 lambda_values_in.size() == 2 * hyEdge_dimT,
495 "Both matrices must be of same size which corresponds to the number of faces!");
496 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
498 lambda_values_in[i].size() == lambda_values_out[i].size() &&
500 "Both matrices must be of same size which corresponds to the number of dofs per face!");
503 std::array<lSol_float_t, n_loc_dofs_> coeffs =
506 std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT> primals(
509 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
511 if (is_dirichlet<parameters>(hyper_edge, i, time))
512 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
513 lambda_values_out[i][j] = 0.;
515 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
516 lambda_values_out[i][j] = primals[i][j];
519 return lambda_values_out;
529 template <
class hyEdgeT>
531 const std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT>& lambda_values,
533 const lSol_float_t time = 0.)
const
540 hyper_edge.data.boundary_flux_old = 0.;
543 hyper_edge.data.flux_old[i] = integrator::template integrate_vol_phifunc<
549 hyper_edge.
data.flux_old[i] +=
550 integrator::template integrate_vol_nablaphiphivecfunc<
553 i, j, hyper_edge.geometry, time) *
554 hyper_edge.
data.u_old[j];
555 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
556 hyper_edge.data.flux_old[i] -=
557 hyper_edge.data.u_old[j] *
558 (integrator::template integrate_bdr_phiphinuvecfunc_cutwind<
561 i, j, face, hyper_edge.geometry, time) +
562 tau_ * integrator::template integrate_bdr_phiphi_cutwind<
567 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
568 if (!is_dirichlet<parameters>(hyper_edge, face, time))
570 hyper_edge.data.flux_old[i] -=
571 lambda_values[face][j] *
572 (integrator::template integrate_bdr_phipsinuvecfunc_cutwind<
576 tau_ * integrator::template integrate_bdr_phipsi_cutdownwind<
581 hyper_edge.data.flux_old[i] -=
582 integrator::template integrate_bdr_phifuncnuvecfunc_cutwind<
589 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
591 if (!is_outflow<parameters>(hyper_edge, face, time))
593 hyper_edge.
data.boundary_flux_old(i, face) +=
594 hyper_edge.data.u_old[j] *
595 (integrator::template integrate_bdr_psiphinuvecfunc_cutwind<
599 tau_ * integrator::template integrate_bdr_psiphi_cutwind<
605 hyper_edge.data.boundary_flux_old(i, face) +=
606 tau_ * hyper_edge.data.u_old[j] *
607 integrator::template integrate_bdr_psiphi_cutwind<
612 if (!is_outflow<parameters>(hyper_edge, face, time))
614 hyper_edge.
data.boundary_flux_old(i, face) +=
615 lambda_values[face][j] *
616 (integrator::template integrate_bdr_psipsinuvecfunc_cutwind<
620 tau_ * integrator::template integrate_bdr_psipsi_cutdownwind<
626 hyper_edge.data.boundary_flux_old(i, face) -=
627 lambda_values[face][j] *
tau_ *
628 integrator::template integrate_bdr_psipsi_cutdownwind<
644 template <
class hyEdgeT,
typename SmallMatT>
647 const lSol_float_t time = 0.)
const
652 for (
unsigned int i = 0; i < lambda_values.size(); ++i)
654 if (is_dirichlet<parameters>(hyper_edge, i, time))
655 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
656 lambda_values[i][j] = 0.;
658 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
659 lambda_values[i][j] = integrator::template integrate_bdrUni_psifunc<
662 j, i, hyper_edge.geometry, time);
667 hyper_edge.
data.u_old[i] = integrator::template integrate_volUni_phifunc<
672 hyper_edge.
data.boundary_flux_old = 0.;
675 hyper_edge.data.flux_old[i] = integrator::template integrate_vol_phifunc<
681 hyper_edge.
data.flux_old[i] +=
682 integrator::template integrate_vol_nablaphiphivecfunc<
685 i, j, hyper_edge.geometry, time) *
686 hyper_edge.
data.u_old[j];
687 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
688 hyper_edge.data.flux_old[i] -=
689 hyper_edge.data.u_old[j] *
690 (integrator::template integrate_bdr_phiphinuvecfunc_cutwind<
693 i, j, face, hyper_edge.geometry, time) +
694 tau_ * integrator::template integrate_bdr_phiphi_cutwind<
699 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
700 if (!is_dirichlet<parameters>(hyper_edge, face, time))
702 hyper_edge.data.flux_old[i] -=
703 lambda_values[face][j] *
704 (integrator::template integrate_bdr_phipsinuvecfunc_cutwind<
708 tau_ * integrator::template integrate_bdr_phipsi_cutdownwind<
713 hyper_edge.data.flux_old[i] -=
714 integrator::template integrate_bdr_phifuncnuvecfunc_cutwind<
721 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
723 if (!is_outflow<parameters>(hyper_edge, face, time))
725 hyper_edge.
data.boundary_flux_old(i, face) +=
726 hyper_edge.data.u_old[j] *
727 (integrator::template integrate_bdr_psiphinuvecfunc_cutwind<
731 tau_ * integrator::template integrate_bdr_psiphi_cutwind<
737 hyper_edge.data.boundary_flux_old(i, face) +=
738 tau_ * hyper_edge.data.u_old[j] *
739 integrator::template integrate_bdr_psiphi_cutwind<
744 if (!is_outflow<parameters>(hyper_edge, face, time))
746 hyper_edge.
data.boundary_flux_old(i, face) +=
747 lambda_values[face][j] *
748 (integrator::template integrate_bdr_psipsinuvecfunc_cutwind<
752 tau_ * integrator::template integrate_bdr_psipsi_cutdownwind<
758 hyper_edge.data.boundary_flux_old(i, face) -=
759 lambda_values[face][j] *
tau_ *
760 integrator::template integrate_bdr_psipsi_cutdownwind<
766 return lambda_values;
777 template <
class hyEdgeT>
778 std::array<lSol_float_t, 1U>
errors(
const std::array<std::array<lSol_float_t, n_shape_bdr_>,
779 2 * hyEdge_dimT>&
UNUSED(lambda_values),
781 const lSol_float_t time = 0.)
const
785 return std::array<lSol_float_t, 1U>({integrator::template integrate_vol_diffsquare_discana<
788 hy_edge.geometry, time)});
802 template <
typename abscissa_float_t,
803 std::size_t abscissas_sizeT,
806 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
system_dim>
807 bulk_values(
const std::array<abscissa_float_t, abscissas_sizeT>& abscissas,
808 const input_array_t&,
810 const lSol_float_t
UNUSED(time) = 0.)
const;
830 template <
unsigned int hyEdge_dimT,
831 unsigned int poly_deg,
832 unsigned int quad_deg,
833 template <
unsigned int,
typename>
834 typename parametersT,
835 typename lSol_float_t>
836 template <
typename hyEdgeT>
842 const lSol_float_t time)
const
847 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
849 for (
unsigned int j = 0; j < n_shape_fct_; ++j)
851 local_mat(i, j) += integrator::template integrate_vol_phiphi<decltype(hyEdgeT::geometry)>(
852 i, j, hyper_edge.geometry);
856 integrator::template integrate_vol_nablaphiphivecfunc<
861 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
865 (integrator::template integrate_bdr_phiphinuvecfunc_cutwind<
868 i, j, face, hyper_edge.
geometry, time) +
870 integrator::template integrate_bdr_phiphi_cutwind<
871 Point<decltype(hyEdgeT::
geometry)::space_dim(), lSol_float_t>,
873 i, j, face, hyper_edge.
geometry, time));
885 template <
unsigned int hyEdge_dimT,
886 unsigned int poly_deg,
887 unsigned int quad_deg,
888 template <
unsigned int,
typename>
889 typename parametersT,
890 typename lSol_float_t>
891 template <
typename hyEdgeT,
typename SmallMatT>
898 const lSol_float_t time)
const
902 hy_assert(lambda_values.size() == 2 * hyEdge_dimT,
903 "The size of the lambda values should be twice the dimension of a hyperedge.");
904 for (
unsigned int i = 0; i < 2 * hyEdge_dimT; ++i)
905 hy_assert(lambda_values[i].size() == n_shape_bdr_,
906 "The size of lambda should be the amount of ansatz functions at boundary.");
910 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
911 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
912 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
913 right_hand_side[i] -=
914 theta_ * delta_t_ * lambda_values[face][j] *
915 (integrator::template integrate_bdr_phipsinuvecfunc_cutwind<
918 i, j, face, hyper_edge.geometry, time) -
920 integrator::template integrate_bdr_phipsi_cutdownwind<
923 i, j, face, hyper_edge.geometry, time));
925 return right_hand_side;
932 template <
unsigned int hyEdge_dimT,
933 unsigned int poly_deg,
934 unsigned int quad_deg,
935 template <
unsigned int,
typename>
936 typename parametersT,
937 typename lSol_float_t>
938 template <
typename hyEdgeT>
948 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
952 integrator::template integrate_vol_phifunc<
957 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
959 if (is_dirichlet<parameters>(hyper_edge, face, time))
960 right_hand_side[i] -=
962 integrator::template integrate_bdr_phifuncnuvecfunc_cutwind<
965 Point<hyEdge_dimT, lSol_float_t>>(i, face, hyper_edge.
geometry, time);
969 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
970 right_hand_side[i] += 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 SmallMatT,
typename hyEdgeT>
993 const SmallMatT& lambda_values,
994 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
997 const lSol_float_t time)
const
1000 std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT> bdr_values;
1002 for (
unsigned int dim_n = 0; dim_n < 2 * hyEdge_dimT; ++dim_n)
1003 bdr_values[dim_n].fill(0.);
1005 for (
unsigned int i = 0; i < n_shape_bdr_; ++i)
1006 for (
unsigned int j = 0; j < n_shape_fct_; ++j)
1007 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
1008 if (!is_outflow<parameters>(hyper_edge, face, time))
1009 bdr_values[face][i] +=
1011 (integrator::template integrate_bdr_psiphinuvecfunc_cutwind<
1014 SmallVec<hyEdge_dimT, lSol_float_t>>(i, j, face, hyper_edge.
geometry, time) +
1015 tau_ * integrator::template integrate_bdr_psiphi_cutwind<
1016 Point<decltype(hyEdgeT::
geometry)::space_dim(), lSol_float_t>,
1018 SmallVec<hyEdge_dimT, lSol_float_t>>(i, j, face, hyper_edge.
geometry, time));
1020 bdr_values[face][i] +=
1022 integrator::template integrate_bdr_psiphi_cutwind<
1025 SmallVec<hyEdge_dimT, lSol_float_t>>(i, j, face, hyper_edge.
geometry, time);
1027 for (
unsigned int i = 0; i < n_shape_bdr_; ++i)
1028 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
1029 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
1030 if (!is_outflow<parameters>(hyper_edge, face, time))
1031 bdr_values[face][i] +=
1032 lambda_values[face][j] *
1033 (integrator::template integrate_bdr_psipsinuvecfunc_cutwind<
1036 SmallVec<hyEdge_dimT, lSol_float_t>>(i, j, face, hyper_edge.
geometry, time) -
1037 tau_ * integrator::template integrate_bdr_psipsi_cutdownwind<
1038 Point<decltype(hyEdgeT::
geometry)::space_dim(), lSol_float_t>,
1040 SmallVec<hyEdge_dimT, lSol_float_t>>(i, j, face, hyper_edge.
geometry, time));
1042 bdr_values[face][i] -=
1043 lambda_values[face][j] * tau_ *
1044 integrator::template integrate_bdr_psipsi_cutdownwind<
1047 SmallVec<hyEdge_dimT, lSol_float_t>>(i, j, face, hyper_edge.
geometry, time);
1049 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
1050 for (
unsigned int i = 0; i < n_shape_bdr_; ++i)
1052 bdr_values[face][i] *= theta_;
1054 bdr_values[face][i] += (1. - theta_) * hyper_edge.
data.boundary_flux_old(i, face);
1063 template <
unsigned int hyEdge_dimT,
1064 unsigned int poly_deg,
1065 unsigned int quad_deg,
1066 template <
unsigned int,
typename>
1067 typename parametersT,
1068 typename lSol_float_t>
1069 template <
typename abscissa_float_t,
1070 std::size_t abscissas_sizeT,
1071 class input_array_t,
1073 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
1076 const std::array<abscissa_float_t, abscissas_sizeT>& abscissas,
1077 const input_array_t&,
1078 hyEdgeT& hyper_edge,
1079 const lSol_float_t)
const
1083 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
1087 for (
unsigned int d = 0; d < system_dim; ++d)
1089 for (
unsigned int pt = 0; pt < Hypercube<hyEdge_dimT>::pow(abscissas_sizeT); ++pt)
1090 point_vals[d][pt] = integrator::shape_fun_t::template lin_comb_fct_val<float>(
1091 hyper_edge.data.u_old,