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.)
88 template <
unsigned int hyEdge_dimT,
89 unsigned int poly_deg,
90 unsigned int quad_deg,
91 template <
unsigned int,
typename>
typename parametersT = DiffusionParametersDefault,
92 typename lSol_float_t =
double>
125 std::array<lSol_float_t, 1U> summed_error;
126 summed_error.fill(0.);
134 for (
unsigned int k = 0; k < summed_error.size(); ++k)
135 summed_error[k] += new_error[k];
143 for (
unsigned int k = 0; k < summed_error.size(); ++k)
144 summed_error[k] = std::sqrt(summed_error[k]);
156 static constexpr
unsigned int hyEdge_dim() {
return hyEdge_dimT; }
210 template <
typename parameters>
213 return std::find(parameters::dirichlet_nodes.begin(), parameters::dirichlet_nodes.end(),
214 node_type) != parameters::dirichlet_nodes.end();
247 template <
typename hyEdgeT>
249 assemble_loc_matrix(
const lSol_float_t tau, hyEdgeT& hyper_edge,
const lSol_float_t eig)
const;
270 template <
typename hyEdgeT,
typename SmallMatT>
272 const SmallMatT& lambda_values,
273 hyEdgeT& hyper_edge)
const;
284 template <
typename hyEdgeT,
typename SmallMatT>
287 const lSol_float_t eig)
const
297 <<
"This can happen if quadrature is too inaccurate!");
312 template <
typename hyEdgeT>
313 inline std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT>
primal_at_boundary(
314 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
315 hyEdgeT& hyper_edge)
const;
327 template <
typename hyEdgeT>
328 inline std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT>
dual_at_boundary(
329 const std::array<lSol_float_t, (hyEdge_dimT + 1) *
n_shape_fct_>& coeffs,
330 hyEdgeT& hyper_edge)
const;
361 template <
typename hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
363 SmallMatOutT& lambda_values_out,
365 const lSol_float_t eig = 0.)
const
367 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
368 lambda_values_in.size() == 2 * hyEdge_dimT,
369 "Both matrices must be of same size which corresponds to the number of faces!");
370 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
372 lambda_values_in[i].size() == lambda_values_out[i].size() &&
374 "Both matrices must be of same size which corresponds to the number of dofs per face!");
377 std::array<lSol_float_t, n_loc_dofs_> coeffs =
380 std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT> primals(
384 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
385 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
386 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
387 lambda_values_out[i][j] = 0.;
389 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
390 lambda_values_out[i][j] =
391 duals[i][j] +
tau_ * primals[i][j] -
392 tau_ * lambda_values_in[i][j] * hyper_edge.geometry.face_area(i);
394 return lambda_values_out;
403 template <
class hyEdgeT>
404 std::array<unsigned int, 2 * hyEdge_dimT>
node_types(hyEdgeT& hyper_edge)
const
408 std::array<unsigned int, 2 * hyEdge_dimT> result;
411 for (
unsigned int i = 0; i < 2 * hyEdge_dimT; ++i)
412 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
427 template <
class hyEdgeT,
typename SmallMatT>
430 const lSol_float_t time = 0.)
const
434 for (
unsigned int i = 0; i < lambda_values.size(); ++i)
436 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
437 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
438 lambda_values[i][j] = 0.;
440 for (
unsigned int j = 0; j < lambda_values[i].size(); ++j)
441 lambda_values[i][j] = integrator::template integrate_bdrUni_psifunc<
444 j, i, hyper_edge.geometry, time);
447 return lambda_values;
466 template <
class hyEdgeT,
typename SmallMatInT,
typename SmallMatOutT>
468 SmallMatOutT& lambda_values_out,
469 const lSol_float_t eig,
470 const SmallMatInT& lambda_vals,
471 const lSol_float_t eig_val,
472 hyEdgeT& hyper_edge)
const
474 hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
475 lambda_values_in.size() == 2 * hyEdge_dimT,
476 "Both matrices must be of same size which corresponds to the number of faces!");
477 for (
unsigned int i = 0; i < lambda_values_in.size(); ++i)
479 lambda_values_in[i].size() == lambda_values_out[i].size() &&
481 "Both matrices must be of same size which corresponds to the number of dofs per face!");
484 std::array<lSol_float_t, n_loc_dofs_> coeffs =
487 std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT> primals(
491 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
492 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
493 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
494 lambda_values_out[i][j] = 0.;
496 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
497 lambda_values_out[i][j] =
498 duals[i][j] +
tau_ * primals[i][j] -
499 tau_ * lambda_values_in[i][j] * hyper_edge.geometry.face_area(i);
503 for (
unsigned int i = 0; i < hyEdge_dimT *
n_shape_fct_; ++i)
506 coeffs[hyEdge_dimT *
n_shape_fct_ + i] *= eig * hyper_edge.geometry.area();
508 coeffs = (
SmallVec<coeffs.
size(), lSol_float_t>(coeffs) /
515 for (
unsigned int i = 0; i < lambda_values_out.size(); ++i)
516 if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
517 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
518 lambda_values_out[i][j] += 0.;
520 for (
unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
521 lambda_values_out[i][j] += duals[i][j] +
tau_ * primals[i][j];
523 return lambda_values_out;
534 template <
class hyEdgeT>
536 const std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT>& lambda_values,
538 const lSol_float_t eig = 0.)
const
541 std::array<lSol_float_t, n_loc_dofs_> coefficients =
543 std::array<lSol_float_t, n_shape_fct_> coeffs;
544 for (
unsigned int i = 0; i < coeffs.size(); ++i)
545 coeffs[i] = coefficients[i + hyEdge_dimT *
n_shape_fct_];
546 return std::array<lSol_float_t, 1U>({integrator::template integrate_vol_diffsquare_discana<
564 template <
typename abscissa_float_t,
565 std::size_t abscissas_sizeT,
568 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
system_dim>
569 bulk_values(
const std::array<abscissa_float_t, abscissas_sizeT>& abscissas,
570 const input_array_t& lambda_values,
572 const lSol_float_t time = 0.)
const;
591 template <
unsigned int hyEdge_dimT,
592 unsigned int poly_deg,
593 unsigned int quad_deg,
594 template <
unsigned int,
typename>
595 typename parametersT,
596 typename lSol_float_t>
597 template <
typename hyEdgeT>
602 const lSol_float_t tau,
604 const lSol_float_t eig)
const
608 lSol_float_t vol_integral, face_integral, helper;
611 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
613 for (
unsigned int j = 0; j < n_shape_fct_; ++j)
616 vol_integral = integrator::template integrate_vol_phiphifunc<
618 parameters::inverse_diffusion_coeff,
Point<hyEdge_dimT, lSol_float_t> >(
623 integrator::template integrate_vol_nablaphiphi<SmallVec<hyEdge_dimT, lSol_float_t>,
625 i, j, hyper_edge.geometry);
629 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
631 helper = integrator::template integrate_bdr_phiphi<decltype(hyEdgeT::geometry)>(
632 i, j, face, hyper_edge.geometry);
633 face_integral += helper;
634 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
635 normal_int_vec[dim] += hyper_edge.geometry.local_normal(face).operator[](dim) * helper;
638 local_mat(hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) +=
640 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
642 local_mat(dim * n_shape_fct_ + i, dim * n_shape_fct_ + j) += vol_integral;
643 local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) -= grad_int_vec[dim];
644 local_mat(dim * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) -= grad_int_vec[dim];
645 local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) += normal_int_vec[dim];
648 local_mat(hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) -=
649 eig * integrator::template integrate_vol_phiphi<decltype(hyEdgeT::geometry)>(
650 i, j, hyper_edge.geometry);
661 template <
unsigned int hyEdge_dimT,
662 unsigned int poly_deg,
663 unsigned int quad_deg,
664 template <
unsigned int,
typename>
665 typename parametersT,
666 typename lSol_float_t>
667 template <
typename hyEdgeT,
typename SmallMatT>
672 const SmallMatT& lambda_values,
673 hyEdgeT& hyper_edge)
const
675 hy_assert(lambda_values.size() == 2 * hyEdge_dimT,
676 "The size of the lambda values should be twice the dimension of a hyperedge.");
677 for (
unsigned int i = 0; i < 2 * hyEdge_dimT; ++i)
678 hy_assert(lambda_values[i].size() == n_shape_bdr_,
679 "The size of lambda should be the amount of ansatz functions at boundary.");
682 lSol_float_t integral;
684 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
685 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
686 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
688 integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
689 i, j, face, hyper_edge.geometry);
690 right_hand_side[hyEdge_dimT * n_shape_fct_ + i] += tau_ * lambda_values[face][j] * integral;
691 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
692 right_hand_side[dim * n_shape_fct_ + i] -=
693 hyper_edge.geometry.local_normal(face).operator[](dim) * lambda_values[face][j] *
697 return right_hand_side;
704 template <
unsigned int hyEdge_dimT,
705 unsigned int poly_deg,
706 unsigned int quad_deg,
707 template <
unsigned int,
typename>
708 typename parametersT,
709 typename lSol_float_t>
710 template <
typename hyEdgeT>
717 const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
718 hyEdgeT& hyper_edge)
const
720 std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT> bdr_values;
722 for (
unsigned int dim_n = 0; dim_n < 2 * hyEdge_dimT; ++dim_n)
723 bdr_values[dim_n].fill(0.);
725 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
726 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
727 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
728 bdr_values[face][j] +=
729 coeffs[hyEdge_dimT * n_shape_fct_ + i] *
731 i, j, face, hyper_edge.geometry);
740 template <
unsigned int hyEdge_dimT,
741 unsigned int poly_deg,
742 unsigned int quad_deg,
743 template <
unsigned int,
typename>
744 typename parametersT,
745 typename lSol_float_t>
746 template <
typename hyEdgeT>
753 const std::array<lSol_float_t, (hyEdge_dimT + 1) * n_shape_fct_>& coeffs,
754 hyEdgeT& hyper_edge)
const
756 std::array<std::array<lSol_float_t, n_shape_bdr_>, 2 * hyEdge_dimT> bdr_values;
757 lSol_float_t integral;
759 for (
unsigned int dim_n = 0; dim_n < 2 * hyEdge_dimT; ++dim_n)
760 bdr_values[dim_n].fill(0.);
762 for (
unsigned int i = 0; i < n_shape_fct_; ++i)
763 for (
unsigned int j = 0; j < n_shape_bdr_; ++j)
764 for (
unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
766 integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
767 i, j, face, hyper_edge.geometry);
768 for (
unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
769 bdr_values[face][j] += hyper_edge.geometry.local_normal(face).operator[](dim) * integral *
770 coeffs[dim * n_shape_fct_ + i];
780 template <
unsigned int hyEdge_dimT,
781 unsigned int poly_deg,
782 unsigned int quad_deg,
783 template <
unsigned int,
typename>
784 typename parametersT,
785 typename lSol_float_t>
786 template <
typename abscissa_float_t,
787 std::size_t abscissas_sizeT,
790 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
793 const std::array<abscissa_float_t, abscissas_sizeT>& abscissas,
794 const input_array_t& lambda_values,
796 const lSol_float_t time)
const
799 solve_local_problem(lambda_values, hyper_edge, time);
803 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(abscissas_sizeT)>,
807 for (
unsigned int d = 0; d < system_dim; ++d)
809 for (
unsigned int i = 0; i < coeffs.
size(); ++i)
810 coeffs[i] = coefficients[d * n_shape_fct_ + i];
811 for (
unsigned int pt = 0; pt < Hypercube<hyEdge_dimT>::pow(abscissas_sizeT); ++pt)
812 point_vals[d][pt] = integrator::shape_fun_t::template lin_comb_fct_val<float>(