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>
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.)
112 template <
unsigned int hyEdge_dimT,
113 unsigned int poly_deg,
114 unsigned int quad_deg,
115 template <
unsigned int,
typename>
116 typename parametersT,
117 typename lSol_float_t =
double>
150 std::array<lSol_float_t, 1U> summed_error;
151 summed_error.fill(0.);
159 for (
unsigned int k = 0; k < summed_error.size(); ++k)
160 summed_error[k] += new_error[k];
168 for (
unsigned int k = 0; k < summed_error.size(); ++k)
169 summed_error[k] = std::sqrt(summed_error[k]);
181 static constexpr
unsigned int hyEdge_dim() {
return hyEdge_dimT; }
235 template <
typename parameters>
238 return std::find(parameters::dirichlet_nodes.begin(), parameters::dirichlet_nodes.end(),
239 node_type) != parameters::dirichlet_nodes.end();
241 template <
typename parameters>
244 return std::find(parameters::dirichlet_laplacian_nodes.begin(),
245 parameters::dirichlet_laplacian_nodes.end(),
246 node_type) != parameters::dirichlet_laplacian_nodes.end();
279 template <
typename hyEdgeT>
281 assemble_loc_matrix(
const lSol_float_t tau, hyEdgeT& hyper_edge,
const lSol_float_t eig)
const;
302 template <
typename hyEdgeT,
typename SmallMatT>
304 const SmallMatT& lambda_values,
305 hyEdgeT& hyper_edge)
const;
316 template <
typename hyEdgeT,
typename SmallMatT>
319 const lSol_float_t eig)
const
329 <<
"This can happen if quadrature is too inaccurate!");
344 template <
typename hyEdgeT>
345 inline std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT>
primal_at_boundary(
346 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
347 hyEdgeT& hyper_edge)
const;
359 template <
typename hyEdgeT>
360 inline std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT>
dual_at_boundary(
361 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
362 hyEdgeT& hyper_edge)
const;
393 template <
class hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
395 SmallMatOutT& lambda_values_out,
397 const lSol_float_t eig)
const
399 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
400 lambda_values_in.size() == 2 * hyEdge_dimT,
401 "Both matrices must be of same size which corresponds to the number of faces!");
402 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
404 lambda_values_in[i].size() == lambda_values_out[i].size() &&
406 "Both matrices must be of same size which corresponds to the number of dofs per face!");
409 std::array<lSol_float_t, n_loc_dofs_> coeffs =
412 std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> primals(
416 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
418 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
419 lambda_values_out[i][j] =
420 duals[i][j] +
tau_ * primals[i][j] -
422 hyper_edge.geometry.face_area(i);
423 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
424 for (
unsigned int j = 0; j < lambda_values_out[i].size() / 2; ++j)
425 lambda_values_out[i][j] = 0.;
426 if (is_dirichlet_laplacian<parameters>(hyper_edge.node_descriptor[i]))
427 for (
unsigned int j = lambda_values_out[i].size() / 2; j < lambda_values_out[i].size(); ++j)
428 lambda_values_out[i][j] = 0.;
431 return lambda_values_out;
440 template <
class hyEdgeT>
441 std::array<unsigned int, 2 * hyEdge_dimT>
node_types(hyEdgeT& hyper_edge)
const
445 std::array<unsigned int, 2 * hyEdge_dimT> result;
448 for (
unsigned int i = 0; i < 2 * hyEdge_dimT; ++i)
449 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
464 template <
class hyEdgeT,
typename SmallMatT>
467 const lSol_float_t time = 0.)
const
471 for (
unsigned int i = 0; i < lambda_values.size(); ++i)
473 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
474 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
475 lambda_values[i][j] = 0.;
478 for (
unsigned int j = 0; j < lambda_values[i].size() / 2; ++j)
479 lambda_values[i][j] = integrator::template integrate_bdrUni_psifunc<
482 j, i, hyper_edge.geometry, time);
483 for (
unsigned int j = lambda_values[i].size() / 2; j < lambda_values[i].size(); ++j)
484 lambda_values[i][j] = integrator::template integrate_bdrUni_psifunc<
491 return lambda_values;
510 template <
class hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
512 SmallMatOutT& lambda_values_out,
513 const lSol_float_t eig,
514 const SmallMatInT& lambda_vals,
515 const lSol_float_t eig_val,
516 hyEdgeT& hyper_edge)
const
518 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
519 lambda_values_in.size() == 2 * hyEdge_dimT,
520 "Both matrices must be of same size which corresponds to the number of faces!");
521 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
523 lambda_values_in[i].size() == lambda_values_out[i].size() &&
525 "Both matrices must be of same size which corresponds to the number of dofs per face!");
528 std::array<lSol_float_t, n_loc_dofs_> coeffs =
531 std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> primals(
535 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
537 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
538 lambda_values_out[i][j] =
539 duals[i][j] +
tau_ * primals[i][j] -
541 hyper_edge.geometry.face_area(i);
542 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
543 for (
unsigned int j = 0; j < lambda_values_out[i].size() / 2; ++j)
544 lambda_values_out[i][j] = 0.;
545 if (is_dirichlet_laplacian<parameters>(hyper_edge.node_descriptor[i]))
546 for (
unsigned int j = lambda_values_out[i].size() / 2; j < lambda_values_out[i].size(); ++j)
547 lambda_values_out[i][j] = 0.;
558 eig * coeffs[hyEdge_dimT *
n_shape_fct_ + i] * hyper_edge.geometry.area();
562 coeffs = (
SmallVec<coeffs.
size(), lSol_float_t>(coeffs) /
569 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
571 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
572 lambda_values_out[i][j] += duals[i][j] +
tau_ * primals[i][j];
573 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
574 for (
unsigned int j = 0; j < lambda_values_out[i].size() / 2; ++j)
575 lambda_values_out[i][j] = 0.;
576 if (is_dirichlet_laplacian<parameters>(hyper_edge.node_descriptor[i]))
577 for (
unsigned int j = lambda_values_out[i].size() / 2; j < lambda_values_out[i].size(); ++j)
578 lambda_values_out[i][j] = 0.;
581 return lambda_values_out;
593 template <
class hyEdgeT,
typename SmallMatT>
594 std::array<lSol_float_t, 1U>
errors(SmallMatT& lambda_values,
596 const lSol_float_t eig = 0.)
const
600 for (
unsigned int i = 0; i < lambda_values.size(); ++i)
601 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
602 hy_assert(lambda_values[i][j] == lambda_values[i][j],
603 "Lambda value wit index " << i <<
"," << j <<
" is NaN!");
605 std::array<lSol_float_t, n_loc_dofs_> coefficients =
607 std::array<lSol_float_t, n_shape_fct_> coeffs;
608 for (
unsigned int i = 0; i < coeffs.size(); ++i)
609 coeffs[i] = coefficients[i + hyEdge_dimT *
n_shape_fct_];
611 for (
unsigned int i = 0; i < coeffs.size(); ++i)
612 hy_assert(coeffs[i] == coeffs[i],
"The " << i <<
"-th coeff is NaN!");
614 lSol_float_t result = integrator::template integrate_vol_diffsquare_discana<
618 hy_assert(result >= 0.,
"The squared error must be non-negative, but was " << result);
619 return std::array<lSol_float_t, 1U>({result});
635 template <
typename abscissa_
float_t, std::
size_t sizeT,
class input_array_t,
class hyEdgeT>
637 const std::array<abscissa_float_t, sizeT>& abscissas,
638 const input_array_t& lambda_values,
640 const lSol_float_t time = 0.)
const;
659 template <
unsigned int hyEdge_dimT,
660 unsigned int poly_deg,
661 unsigned int quad_deg,
662 template <
unsigned int,
typename>
663 typename parametersT,
664 typename lSol_float_t>
665 template <
typename hyEdgeT>
670 const lSol_float_t tau,
672 const lSol_float_t eig)
const
675 constexpr
unsigned int n_dofs_lap = n_loc_dofs_ / 2;
678 lSol_float_t vol_integral, vol_func_integral, face_integral, helper;
681 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
683 for (
unsigned int j = 0; j < n_shape_fct_; ++j)
686 vol_integral = integrator::template integrate_vol_phiphi(i, j, hyper_edge.geometry);
687 vol_func_integral = integrator::template integrate_vol_phiphifunc<
689 parameters::inverse_bilaplacian_coefficient,
Point<hyEdge_dimT, lSol_float_t> >(
694 integrator::template integrate_vol_nablaphiphi<SmallVec<hyEdge_dimT, lSol_float_t>,
696 i, j, hyper_edge.geometry);
700 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
702 helper = integrator::template integrate_bdr_phiphi<decltype(hyEdgeT::geometry)>(
703 i, j, face, hyper_edge.geometry);
704 face_integral += helper;
705 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
706 normal_int_vec[dim] += hyper_edge.geometry.local_normal(face).operator[](dim) * helper;
709 local_mat(hyEdge_dimT * n_shape_fct_ + i, n_dofs_lap + hyEdge_dimT * n_shape_fct_ + j) -=
712 local_mat(hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) +=
714 local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
715 n_dofs_lap + hyEdge_dimT * n_shape_fct_ + j) += tau * face_integral;
717 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
719 local_mat(dim * n_shape_fct_ + i, dim * n_shape_fct_ + j) += vol_integral;
720 local_mat(n_dofs_lap + dim * n_shape_fct_ + i, n_dofs_lap + dim * n_shape_fct_ + j) +=
723 local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) -= grad_int_vec[dim];
724 local_mat(dim * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) -= grad_int_vec[dim];
725 local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
726 n_dofs_lap + dim * n_shape_fct_ + j) -= grad_int_vec[dim];
727 local_mat(n_dofs_lap + dim * n_shape_fct_ + i,
728 n_dofs_lap + hyEdge_dimT * n_shape_fct_ + j) -= grad_int_vec[dim];
730 local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) += normal_int_vec[dim];
731 local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
732 n_dofs_lap + dim * n_shape_fct_ + j) += normal_int_vec[dim];
735 local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) -=
736 eig * integrator::template integrate_vol_phiphi<decltype(hyEdgeT::geometry)>(
737 i, j, hyper_edge.geometry);
748 template <
unsigned int hyEdge_dimT,
749 unsigned int poly_deg,
750 unsigned int quad_deg,
751 template <
unsigned int,
typename>
752 typename parametersT,
753 typename lSol_float_t>
754 template <
typename hyEdgeT,
typename SmallMatT>
761 constexpr
unsigned int n_dofs_lap = n_loc_dofs_ / 2;
762 hy_assert(lambda_values.size() == 2 * hyEdge_dimT,
763 "The size of the lambda values should be twice the dimension of a hyperedge.");
764 for (
unsigned int i = 0; i < 2 * hyEdge_dimT; ++i)
765 hy_assert(lambda_values[i].size() == 2 * n_shape_bdr_,
766 "The size of lambda should be the amount of ansatz functions at boundary.");
769 lSol_float_t integral;
771 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
772 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
773 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
775 integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
776 i, j, face, hyper_edge.geometry);
777 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] += tau_ * lambda_values[face][j] * integral;
778 right_hand_side[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] +=
779 tau_ * lambda_values[face][n_shape_bdr_ + j] * integral;
781 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
783 right_hand_side[dim * n_shape_fct_ + i] -=
784 hyper_edge.geometry.local_normal(face).operator[](dim) * lambda_values[face][j] *
786 right_hand_side[n_dofs_lap + dim * n_shape_fct_ + i] -=
787 hyper_edge.geometry.local_normal(face).operator[](dim) *
788 lambda_values[face][n_shape_bdr_ + j] * integral;
792 return right_hand_side;
799 template <
unsigned int hyEdge_dimT,
800 unsigned int poly_deg,
801 unsigned int quad_deg,
802 template <
unsigned int,
typename>
803 typename parametersT,
804 typename lSol_float_t>
805 template <
typename hyEdgeT>
812 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
813 hyEdgeT& hyper_edge)
const
815 constexpr
unsigned int n_dofs_lap = n_loc_dofs_ / 2;
816 std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> bdr_values;
818 for (
unsigned int dim_n = 0; dim_n < 2 * hyEdge_dimT; ++dim_n)
819 bdr_values[dim_n].fill(0.);
821 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
822 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
823 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
825 bdr_values[face][n_shape_bdr_ + j] +=
826 coeffs[hyEdge_dimT * n_shape_fct_ + i] *
827 integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
828 i, j, face, hyper_edge.geometry);
830 bdr_values[face][j] +=
831 coeffs[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] *
832 integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
833 i, j, face, hyper_edge.geometry);
843 template <
unsigned int hyEdge_dimT,
844 unsigned int poly_deg,
845 unsigned int quad_deg,
846 template <
unsigned int,
typename>
847 typename parametersT,
848 typename lSol_float_t>
849 template <
typename hyEdgeT>
856 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
857 hyEdgeT& hyper_edge)
const
859 constexpr
unsigned int n_dofs_lap = n_loc_dofs_ / 2;
860 std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> bdr_values;
861 lSol_float_t integral;
863 for (
unsigned int dim_n = 0; dim_n < 2 * hyEdge_dimT; ++dim_n)
864 bdr_values[dim_n].fill(0.);
866 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
867 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
868 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
870 integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
871 i, j, face, hyper_edge.geometry);
872 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
874 bdr_values[face][n_shape_bdr_ + j] +=
875 hyper_edge.geometry.local_normal(face).operator[](dim) * integral *
876 coeffs[dim * n_shape_fct_ + i];
878 bdr_values[face][j] += hyper_edge.geometry.local_normal(face).operator[](dim) * integral *
879 coeffs[n_dofs_lap + dim * n_shape_fct_ + i];
890 template <
unsigned int hyEdge_dimT,
891 unsigned int poly_deg,
892 unsigned int quad_deg,
893 template <
unsigned int,
typename>
894 typename parametersT,
895 typename lSol_float_t>
896 template <
typename abscissa_
float_t, std::
size_t sizeT,
class input_array_t,
typename hyEdgeT>
897 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(sizeT)>,
900 const std::array<abscissa_float_t, sizeT>& abscissas,
901 const input_array_t& lambda_values,
903 const lSol_float_t time)
const
906 solve_local_problem(lambda_values, hyper_edge, time);
911 std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(sizeT)>,
915 for (
unsigned int d = 0; d < system_dim; ++d)
917 for (
unsigned int i = 0; i < coeffs.
size(); ++i)
918 coeffs[i] = coefficients[d * n_shape_fct_ + i];
919 for (
unsigned int pt = 0; pt < Hypercube<hyEdge_dimT>::pow(sizeT); ++pt)
920 point_vals[d][pt] = integrator::shape_fun_t::template lin_comb_fct_val<float>(