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 time = 0.)
42 const param_float_t time = 0.)
50 const param_float_t time = 0.)
58 const param_float_t time = 0.)
66 const param_float_t time = 0.)
103 template <
unsigned int hyEdge_dimT,
104 unsigned int poly_deg,
105 unsigned int quad_deg,
106 template <
unsigned int,
typename>
typename parametersT = DiffusionParametersDefault,
107 typename lSol_float_t =
double>
140 std::array<lSol_float_t, 1U> summed_error;
141 summed_error.fill(0.);
149 for (
unsigned int k = 0; k < summed_error.size(); ++k)
150 summed_error[k] += new_error[k];
158 for (
unsigned int k = 0; k < summed_error.size(); ++k)
159 summed_error[k] = std::sqrt(summed_error[k]);
171 static constexpr
unsigned int hyEdge_dim() {
return hyEdge_dimT; }
225 template <
typename parameters>
228 return std::find(parameters::dirichlet_nodes.begin(), parameters::dirichlet_nodes.end(),
229 node_type) != parameters::dirichlet_nodes.end();
270 template <
typename hyEdgeT>
273 const lSol_float_t time)
const;
294 template <
typename hyEdgeT,
typename SmallMatT>
296 const SmallMatT& lambda_values,
297 hyEdgeT& hyper_edge)
const;
316 template <
typename hyEdgeT>
319 const lSol_float_t time)
const;
339 template <
typename hyEdgeT,
typename SmallVecT>
341 hyEdgeT& hyper_edge)
const;
353 template <
typename hyEdgeT,
typename SmallMatT>
355 const unsigned int solution_type,
357 const lSol_float_t time)
const
362 if (solution_type == 0)
364 else if (solution_type == 1)
368 hy_assert(0 == 1,
"This has not been implemented!");
374 <<
"This can happen if quadrature is too inaccurate!");
389 template <
typename hyEdgeT>
392 hyEdgeT& hyper_edge)
const;
404 template <
typename hyEdgeT>
407 hyEdgeT& hyper_edge)
const;
441 template <
typename hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
443 SmallMatOutT& lambda_values_out,
445 const lSol_float_t time = 0.)
const
447 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
448 lambda_values_in.size() == 2 * hyEdge_dimT,
449 "Both matrices must be of same size which corresponds to the number of faces!");
450 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
452 lambda_values_in[i].size() == lambda_values_out[i].size() &&
454 "Both matrices must be of same size which corresponds to the number of dofs per face!");
464 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
465 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
466 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
467 lambda_values_out[i][j] = 0.;
469 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
470 lambda_values_out[i][j] =
471 duals(i, j) +
tau_ * primals(i, j) -
472 tau_ * lambda_values_in[i][j] * hyper_edge.geometry.face_area(i);
474 return lambda_values_out;
479 template <
typename hyEdgeT>
480 std::array<unsigned int, 2 * hyEdge_dimT>
node_types(hyEdgeT& hyper_edge)
const
484 std::array<unsigned int, 2 * hyEdge_dimT> result;
487 for (
unsigned int i = 0; i < 2 * hyEdge_dimT; ++i)
488 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
505 template <
typename hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
507 SmallMatOutT& lambda_values_out,
509 const lSol_float_t time = 0.)
const
511 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
512 lambda_values_in.size() == 2 * hyEdge_dimT,
513 "Both matrices must be of same size which corresponds to the number of faces!");
514 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
516 lambda_values_in[i].size() == lambda_values_out[i].size() &&
518 "Both matrices must be of same size which corresponds to the number of dofs per face!");
528 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
530 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
531 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
532 lambda_values_out[i][j] = 0.;
534 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
535 lambda_values_out[i][j] =
536 duals(i, j) +
tau_ * primals(i, j) -
537 tau_ * lambda_values_in[i][j] * hyper_edge.geometry.face_area(i);
540 return lambda_values_out;
552 template <
typename hyEdgeT,
typename SmallMatT>
553 std::array<lSol_float_t, 1U>
errors(
const SmallMatT& lambda_values,
555 const lSol_float_t time = 0.)
const
557 hy_assert(lambda_values.size() == 2 * hyEdge_dimT,
"Matrix must have appropriate size!");
558 for (
unsigned int i = 0; i < lambda_values.size(); ++i)
560 "Matrix must have appropriate size!");
569 for (
unsigned int i = 0; i < n_shape_pp; ++i)
570 for (
unsigned int j = 0; j < n_shape_pp; ++j)
571 matrix(i, j) = integrator_pp::template integrate_vol_nablaphinablaphifunc<
580 for (
unsigned int i = 0; i < n_shape_pp; ++i)
583 grad_int_vec = integrator_pp::template integrate_vol_nablaphiphi<
585 i, j, hy_edge.geometry);
586 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
587 vector[i] -= coefficients[dim *
n_shape_fct_ + j] * grad_int_vec[dim];
592 sol = vector / matrix;
594 return std::array<lSol_float_t, 1U>({integrator_pp::template integrate_vol_diffsquare_discana<
612 template <
typename abscissa_float_t,
613 std::size_t abscissas_sizeT,
616 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
system_dim>
617 bulk_values(
const std::array<abscissa_float_t, abscissas_sizeT>& abscissas,
618 const input_array_t& lambda_values,
620 const lSol_float_t time = 0.)
const;
639 template <
unsigned int hyEdge_dimT,
640 unsigned int poly_deg,
641 unsigned int quad_deg,
642 template <
unsigned int,
typename>
643 typename parametersT,
644 typename lSol_float_t>
645 template <
typename hyEdgeT>
654 lSol_float_t vol_integral, face_integral, helper;
657 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
659 for (
unsigned int j = 0; j < n_shape_fct_; ++j)
662 vol_integral = integrator::template integrate_vol_phiphifunc<
664 parameters::inverse_diffusion_coeff,
Point<hyEdge_dimT, lSol_float_t> >(
669 integrator::template integrate_vol_nablaphiphi<SmallVec<hyEdge_dimT, lSol_float_t>,
671 i, j, hyper_edge.geometry);
675 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
677 helper = integrator::template integrate_bdr_phiphi<decltype(hyEdgeT::geometry)>(
678 i, j, face, hyper_edge.geometry);
679 face_integral += helper;
680 normal_int_vec += helper * hyper_edge.geometry.local_normal(face);
683 local_mat(hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) +=
684 tau_ * face_integral;
685 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
687 local_mat(dim * n_shape_fct_ + i, dim * n_shape_fct_ + j) += vol_integral;
688 local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) -= grad_int_vec[dim];
689 local_mat(dim * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) -= grad_int_vec[dim];
690 local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) += normal_int_vec[dim];
702 template <
unsigned int hyEdge_dimT,
703 unsigned int poly_deg,
704 unsigned int quad_deg,
705 template <
unsigned int,
typename>
706 typename parametersT,
707 typename lSol_float_t>
708 template <
typename hyEdgeT,
typename SmallMatT>
715 static_assert(std::is_same<typename SmallMatT::value_type::value_type, lSol_float_t>::value,
716 "Lambda values should have same floating point arithmetics as local solver!");
717 hy_assert(lambda_values.size() == 2 * hyEdge_dimT,
718 "The size of the lambda values should be twice the dimension of a hyperedge.");
719 for (
unsigned int i = 0; i < 2 * hyEdge_dimT; ++i)
720 hy_assert(lambda_values[i].size() == n_shape_bdr_,
721 "The size of lambda should be the amount of ansatz functions at boundary.");
724 lSol_float_t integral;
726 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
727 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
728 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
730 integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
731 i, j, face, hyper_edge.geometry);
732 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] += tau_ * lambda_values[face][j] * integral;
733 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
734 right_hand_side[dim * n_shape_fct_ + i] -=
735 hyper_edge.geometry.local_normal(face).operator[](dim) * lambda_values[face][j] *
739 return right_hand_side;
746 template <
unsigned int hyEdge_dimT,
747 unsigned int poly_deg,
748 unsigned int quad_deg,
749 template <
unsigned int,
typename>
750 typename parametersT,
751 typename lSol_float_t>
752 template <
typename hyEdgeT>
761 lSol_float_t integral;
762 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
764 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] = integrator::template integrate_vol_phifunc<
767 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
769 if (!is_dirichlet<parameters>(hyper_edge.node_descriptor[face]))
771 integral = integrator::template integrate_bdr_phifunc<
773 parameters::dirichlet_value,
Point<hyEdge_dimT, lSol_float_t> >(i, face,
775 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] += tau_ * integral;
776 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
777 right_hand_side[dim * n_shape_fct_ + i] -=
778 hyper_edge.geometry.local_normal(face).operator[](dim) * integral;
782 return right_hand_side;
789 template <
unsigned int hyEdge_dimT,
790 unsigned int poly_deg,
791 unsigned int quad_deg,
792 template <
unsigned int,
typename>
793 typename parametersT,
794 typename lSol_float_t>
795 template <
typename hyEdgeT,
typename SmallVecT>
803 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
804 for (
unsigned int j = 0; j < n_shape_fct_; ++j)
805 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] +=
806 coeffs[hyEdge_dimT * n_shape_fct_ + j] *
807 integrator::template integrate_vol_phiphi(i, j, hyper_edge.geometry);
809 return right_hand_side;
816 template <
unsigned int hyEdge_dimT,
817 unsigned int poly_deg,
818 unsigned int quad_deg,
819 template <
unsigned int,
typename>
820 typename parametersT,
821 typename lSol_float_t>
822 template <
typename hyEdgeT>
832 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
833 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
834 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
835 bdr_values(face, j) +=
836 coeffs[hyEdge_dimT * n_shape_fct_ + i] *
837 integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
838 i, j, face, hyper_edge.geometry);
847 template <
unsigned int hyEdge_dimT,
848 unsigned int poly_deg,
849 unsigned int quad_deg,
850 template <
unsigned int,
typename>
851 typename parametersT,
852 typename lSol_float_t>
853 template <
typename hyEdgeT>
860 hyEdgeT& hyper_edge)
const
863 lSol_float_t integral;
865 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
866 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
867 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
869 integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
870 i, j, face, hyper_edge.geometry);
871 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
872 bdr_values(face, j) += hyper_edge.geometry.local_normal(face).operator[](dim) * integral *
873 coeffs[dim * n_shape_fct_ + i];
883 template <
unsigned int hyEdge_dimT,
884 unsigned int poly_deg,
885 unsigned int quad_deg,
886 template <
unsigned int,
typename>
887 typename parametersT,
888 typename lSol_float_t>
889 template <
typename abscissa_float_t,
890 std::size_t abscissas_sizeT,
894 std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
897 const std::array<abscissa_float_t, abscissas_sizeT>& abscissas,
898 const input_array_t& lambda_values,
900 const lSol_float_t time)
const
903 solve_local_problem(lambda_values, 1U, hyper_edge, time);
908 std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
912 for (
unsigned int d = 0; d < system_dim; ++d)
914 for (
unsigned int i = 0; i < coeffs.
size(); ++i)
915 coeffs[i] = coefficients[d * n_shape_fct_ + i];
916 for (
unsigned int pt = 0; pt < Hypercube<hyEdge_dimT>::pow(abscissas_sizeT); ++pt)
917 point_vals[d][pt] = integrator::shape_fun_t::template lin_comb_fct_val<float>(