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.)
43 const param_float_t = 0.)
51 const param_float_t = 0.)
59 const param_float_t = 0.)
67 const param_float_t = 0.)
75 const param_float_t = 0.)
83 const param_float_t = 0.)
121 template <
unsigned int hyEdge_dimT,
122 unsigned int poly_deg,
123 unsigned int quad_deg,
124 template <
unsigned int,
typename>
typename parametersT =
125 DiffusionAdvectionReactionParametersDefault,
126 typename lSol_float_t =
double>
159 std::array<lSol_float_t, 1U> summed_error;
160 summed_error.fill(0.);
168 for (
unsigned int k = 0; k < summed_error.size(); ++k)
169 summed_error[k] += new_error[k];
177 for (
unsigned int k = 0; k < summed_error.size(); ++k)
178 summed_error[k] = std::sqrt(summed_error[k]);
190 static constexpr
unsigned int hyEdge_dim() {
return hyEdge_dimT; }
244 template <
typename parameters>
247 return std::find(parameters::dirichlet_nodes.begin(), parameters::dirichlet_nodes.end(),
248 node_type) != parameters::dirichlet_nodes.end();
281 template <
typename hyEdgeT>
283 assemble_loc_matrix(
const lSol_float_t tau, hyEdgeT& hyper_edge,
const lSol_float_t time)
const;
304 template <
typename hyEdgeT,
typename SmallMatT>
306 const SmallMatT& lambda_values,
307 hyEdgeT& hyper_edge)
const;
326 template <
typename hyEdgeT>
329 const lSol_float_t time)
const;
349 template <
typename hyEdgeT,
typename SmallVecT>
351 hyEdgeT& hyper_edge)
const;
363 template <
typename hyEdgeT,
typename SmallMatT>
365 const unsigned int solution_type,
367 const lSol_float_t time)
const
372 if (solution_type == 0)
374 else if (solution_type == 1)
378 hy_assert(0 == 1,
"This has not been implemented!");
384 <<
"This can happen if quadrature is too inaccurate!");
400 template <
typename hyEdgeT,
typename SmallMatT>
403 const lSol_float_t time)
const
413 <<
"This can happen if quadrature is too inaccurate!");
422 template <
typename hyEdgeT,
typename SmallMatT,
typename SmallVecT>
424 const SmallVecT& coeffs,
426 const lSol_float_t delta_time,
427 const lSol_float_t time)
const
440 <<
"This can happen if quadrature is too inaccurate!");
455 template <
typename hyEdgeT>
458 hyEdgeT& hyper_edge)
const;
470 template <
typename hyEdgeT>
473 hyEdgeT& hyper_edge)
const;
507 template <
typename hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
509 SmallMatOutT& lambda_values_out,
511 const lSol_float_t time = 0.)
const
513 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
514 lambda_values_in.size() == 2 * hyEdge_dimT,
515 "Both matrices must be of same size which corresponds to the number of faces!");
516 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
518 lambda_values_in[i].size() == lambda_values_out[i].size() &&
520 "Both matrices must be of same size which corresponds to the number of dofs per face!");
530 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
531 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
532 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
533 lambda_values_out[i][j] = 0.;
535 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
536 lambda_values_out[i][j] =
537 duals(i, j) +
tau_ * primals(i, j) -
538 tau_ * lambda_values_in[i][j] * hyper_edge.geometry.face_area(i);
540 return lambda_values_out;
545 template <
typename hyEdgeT>
546 std::array<unsigned int, 2 * hyEdge_dimT>
node_types(hyEdgeT& hyper_edge)
const
550 std::array<unsigned int, 2 * hyEdge_dimT> result;
553 for (
unsigned int i = 0; i < 2 * hyEdge_dimT; ++i)
554 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
571 template <
typename hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
573 SmallMatOutT& lambda_values_out,
575 const lSol_float_t time = 0.)
const
577 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
578 lambda_values_in.size() == 2 * hyEdge_dimT,
579 "Both matrices must be of same size which corresponds to the number of faces!");
580 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
582 lambda_values_in[i].size() == lambda_values_out[i].size() &&
584 "Both matrices must be of same size which corresponds to the number of dofs per face!");
594 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
596 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
597 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
598 lambda_values_out[i][j] = 0.;
600 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
601 lambda_values_out[i][j] =
602 duals(i, j) +
tau_ * primals(i, j) -
603 tau_ * lambda_values_in[i][j] * hyper_edge.geometry.face_area(i);
606 return lambda_values_out;
620 template <
typename hyEdgeT,
typename SmallMatT>
623 const lSol_float_t time = 0.)
const
625 hy_assert(lambda_values.size() == 2 * hyEdge_dimT,
"Matrix must have appropriate size!");
626 for (
unsigned int i = 0; i < lambda_values.size(); ++i)
628 "Matrix must have appropriate size!");
631 for (
unsigned int i = 0; i < lambda_values.size(); ++i)
633 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
634 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
635 lambda_values[i][j] = 0.;
637 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
638 lambda_values[i][j] =
640 parameters::initial>(
641 j, i, hyper_edge.geometry, time);
644 return lambda_values;
736 template <
typename hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
738 SmallMatOutT& lambda_values_out,
740 const lSol_float_t time = 0.)
const
742 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
743 lambda_values_in.size() == 2 * hyEdge_dimT,
744 "Both matrices must be of same size which corresponds to the number of faces!");
745 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
747 lambda_values_in[i].size() == lambda_values_out[i].size() &&
749 "Both matrices must be of same size which corresponds to the number of dofs per face!");
760 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
762 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
763 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
764 lambda_values_out[i][j] = 0.;
766 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
767 lambda_values_out[i][j] = duals(i, j) +
tau_ * primals(i, j);
770 return lambda_values_out;
786 template <
typename hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
788 SmallMatOutT& lambda_values_out,
790 const lSol_float_t time = 0.)
const
792 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
793 lambda_values_in.size() == 2 * hyEdge_dimT,
794 "Both matrices must be of same size which corresponds to the number of faces!");
795 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
797 lambda_values_in[i].size() == lambda_values_out[i].size() &&
799 "Both matrices must be of same size which corresponds to the number of dofs per face!");
810 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
812 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
813 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
814 lambda_values_out[i][j] = 0.;
816 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
817 lambda_values_out[i][j] = duals(i, j) +
tau_ * primals(i, j);
820 return lambda_values_out;
832 template <
typename hyEdgeT,
typename SmallMatT>
833 std::array<lSol_float_t, 1U>
errors(
const SmallMatT& lambda_values,
835 const lSol_float_t time = 0.)
const
837 hy_assert(lambda_values.size() == 2 * hyEdge_dimT,
"Matrix must have appropriate size!");
838 for (
unsigned int i = 0; i < lambda_values.size(); ++i)
840 "Matrix must have appropriate size!");
845 std::array<lSol_float_t, n_shape_fct_> coeffs;
846 for (
unsigned int i = 0; i < coeffs.size(); ++i)
847 coeffs[i] = coefficients[i + hyEdge_dimT *
n_shape_fct_];
848 return std::array<lSol_float_t, 1U>({integrator::template integrate_vol_diffsquare_discana<
867 template <
typename hyEdgeT,
typename SmallMatT>
869 const SmallMatT& lambda_values_old,
871 const lSol_float_t delta_t,
872 const lSol_float_t time)
const
874 hy_assert(lambda_values_new.size() == lambda_values_old.size() &&
875 lambda_values_new.size() == 2 * hyEdge_dimT,
876 "Both matrices must be of same size which corresponds to the number of faces!");
877 for (
unsigned int i = 0; i < lambda_values_new.size(); ++i)
879 lambda_values_new[i].size() == lambda_values_old[i].size() &&
881 "Both matrices must be of same size which corresponds to the number of dofs per face!");
889 for (
unsigned int i = 0; i < coeffs_old.
size(); ++i)
890 coeffs_old[i] = (coeffs_old[i] - coeffs_new[i]) / delta_t;
894 std::array<lSol_float_t, n_shape_fct_> coeffs;
895 for (
unsigned int i = 0; i < coeffs.size(); ++i)
896 coeffs[i] = coefficients[i + hyEdge_dimT *
n_shape_fct_];
897 return integrator::template integrate_vol_diffsquare_discana<decltype(
hyEdgeT::geometry),
898 parameters::analytic_result>(
899 coeffs, hy_edge.geometry, time);
914 template <
typename abscissa_float_t,
915 std::size_t abscissas_sizeT,
918 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
system_dim>
919 bulk_values(
const std::array<abscissa_float_t, abscissas_sizeT>& abscissas,
920 const input_array_t& lambda_values,
922 const lSol_float_t time = 0.)
const;
941 template <
unsigned int hyEdge_dimT,
942 unsigned int poly_deg,
943 unsigned int quad_deg,
944 template <
unsigned int,
typename>
945 typename parametersT,
946 typename lSol_float_t>
947 template <
typename hyEdgeT>
949 DiffusionAdvectionReaction<hyEdge_dimT, poly_deg, quad_deg, parametersT, lSol_float_t>::
953 assemble_loc_matrix(
const lSol_float_t tau, hyEdgeT& hyper_edge,
const lSol_float_t time)
const
957 lSol_float_t vol_integral, face_integral, helper;
960 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
962 for (
unsigned int j = 0; j < n_shape_fct_; ++j)
965 vol_integral = integrator::template integrate_vol_phiphifunc<
967 parameters::inverse_diffusion_coeff,
Point<hyEdge_dimT, lSol_float_t> >(
972 integrator::template integrate_vol_nablaphiphi<SmallVec<hyEdge_dimT, lSol_float_t>,
974 i, j, hyper_edge.geometry);
978 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
980 helper = integrator::template integrate_bdr_phiphi<decltype(hyEdgeT::geometry)>(
981 i, j, face, hyper_edge.geometry);
982 face_integral += helper;
983 normal_int_vec += helper * hyper_edge.geometry.local_normal(face);
986 local_mat(hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) +=
987 tau * face_integral + integrator::template integrate_vol_phiphifunc<
990 Point<hyEdge_dimT, lSol_float_t> >(i, j, hyper_edge.
geometry, time);
991 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
993 local_mat(dim * n_shape_fct_ + i, dim * n_shape_fct_ + j) += vol_integral;
994 local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) -= grad_int_vec[dim];
995 local_mat(dim * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) -= grad_int_vec[dim];
996 local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) += normal_int_vec[dim];
997 local_mat(dim * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) -=
998 integrator::template integrate_vol_phiphivecfunc<
1001 Point<hyEdge_dimT, lSol_float_t> >(i, j, dim, hyper_edge.
geometry);
1013 template <
unsigned int hyEdge_dimT,
1014 unsigned int poly_deg,
1015 unsigned int quad_deg,
1016 template <
unsigned int,
typename>
1017 typename parametersT,
1018 typename lSol_float_t>
1019 template <
typename hyEdgeT,
typename SmallMatT>
1021 DiffusionAdvectionReaction<hyEdge_dimT, poly_deg, quad_deg, parametersT, lSol_float_t>::
1027 static_assert(std::is_same<typename SmallMatT::value_type::value_type, lSol_float_t>::value,
1028 "Lambda values should have same floating point arithmetics as local solver!");
1029 hy_assert(lambda_values.size() == 2 * hyEdge_dimT,
1030 "The size of the lambda values should be twice the dimension of a hyperedge.");
1031 for (
unsigned int i = 0; i < 2 * hyEdge_dimT; ++i)
1032 hy_assert(lambda_values[i].size() == n_shape_bdr_,
1033 "The size of lambda should be the amount of ansatz functions at boundary.");
1036 lSol_float_t integral;
1038 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
1039 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
1040 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
1042 integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
1043 i, j, face, hyper_edge.geometry);
1044 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] += tau_ * lambda_values[face][j] * integral;
1045 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
1046 right_hand_side[dim * n_shape_fct_ + i] -=
1047 hyper_edge.geometry.local_normal(face).operator[](dim) * lambda_values[face][j] *
1051 return right_hand_side;
1058 template <
unsigned int hyEdge_dimT,
1059 unsigned int poly_deg,
1060 unsigned int quad_deg,
1061 template <
unsigned int,
typename>
1062 typename parametersT,
1063 typename lSol_float_t>
1064 template <
typename hyEdgeT>
1066 DiffusionAdvectionReaction<hyEdge_dimT, poly_deg, quad_deg, parametersT, lSol_float_t>::
1074 lSol_float_t integral;
1075 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
1077 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] = integrator::template integrate_vol_phifunc<
1080 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
1082 if (!is_dirichlet<parameters>(hyper_edge.node_descriptor[face]))
1084 integral = integrator::template integrate_bdr_phifunc<
1086 parameters::dirichlet_value,
Point<hyEdge_dimT, lSol_float_t> >(i, face,
1088 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] += tau_ * integral;
1089 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
1090 right_hand_side[dim * n_shape_fct_ + i] -=
1091 hyper_edge.geometry.local_normal(face).operator[](dim) * integral;
1095 return right_hand_side;
1102 template <
unsigned int hyEdge_dimT,
1103 unsigned int poly_deg,
1104 unsigned int quad_deg,
1105 template <
unsigned int,
typename>
1106 typename parametersT,
1107 typename lSol_float_t>
1108 template <
typename hyEdgeT,
typename SmallVecT>
1110 DiffusionAdvectionReaction<hyEdge_dimT, poly_deg, quad_deg, parametersT, lSol_float_t>::
1117 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
1118 for (
unsigned int j = 0; j < n_shape_fct_; ++j)
1119 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] +=
1120 coeffs[hyEdge_dimT * n_shape_fct_ + j] *
1121 integrator::template integrate_vol_phiphi(i, j, hyper_edge.geometry);
1123 return right_hand_side;
1130 template <
unsigned int hyEdge_dimT,
1131 unsigned int poly_deg,
1132 unsigned int quad_deg,
1133 template <
unsigned int,
typename>
1134 typename parametersT,
1135 typename lSol_float_t>
1136 template <
typename hyEdgeT>
1139 DiffusionAdvectionReaction<hyEdge_dimT, poly_deg, quad_deg, parametersT, lSol_float_t>::
1147 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
1148 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
1149 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
1150 bdr_values(face, j) +=
1151 coeffs[hyEdge_dimT * n_shape_fct_ + i] *
1152 integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
1153 i, j, face, hyper_edge.geometry);
1162 template <
unsigned int hyEdge_dimT,
1163 unsigned int poly_deg,
1164 unsigned int quad_deg,
1165 template <
unsigned int,
typename>
1166 typename parametersT,
1167 typename lSol_float_t>
1168 template <
typename hyEdgeT>
1171 DiffusionAdvectionReaction<hyEdge_dimT, poly_deg, quad_deg, parametersT, lSol_float_t>::
1178 lSol_float_t integral;
1180 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
1181 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
1182 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
1184 integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
1185 i, j, face, hyper_edge.geometry);
1186 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
1187 bdr_values(face, j) += hyper_edge.geometry.local_normal(face).operator[](dim) * integral *
1188 coeffs[dim * n_shape_fct_ + i];
1198 template <
unsigned int hyEdge_dimT,
1199 unsigned int poly_deg,
1200 unsigned int quad_deg,
1201 template <
unsigned int,
typename>
1202 typename parametersT,
1203 typename lSol_float_t>
1204 template <
typename abscissa_float_t,
1205 std::size_t abscissas_sizeT,
1206 class input_array_t,
1208 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
1209 DiffusionAdvectionReaction<hyEdge_dimT, poly_deg, quad_deg, parametersT, lSol_float_t>::
1212 const std::array<abscissa_float_t, abscissas_sizeT>& abscissas,
1213 const input_array_t& lambda_values,
1214 hyEdgeT& hyper_edge,
1215 const lSol_float_t time)
const
1218 solve_local_problem(lambda_values, 1U, hyper_edge, time);
1222 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
1223 DiffusionAdvectionReaction<hyEdge_dimT, poly_deg, quad_deg, parametersT,
1224 lSol_float_t>::system_dim>
1227 for (
unsigned int d = 0; d < system_dim; ++d)
1229 for (
unsigned int i = 0; i < coeffs.
size(); ++i)
1230 coeffs[i] = coefficients[d * n_shape_fct_ + i];
1231 for (
unsigned int pt = 0; pt < Hypercube<hyEdge_dimT>::pow(abscissas_sizeT); ++pt)
1232 point_vals[d][pt] = integrator::shape_fun_t::template lin_comb_fct_val<float>(