HyperHDG
bilaplacian_uniform_ldgh.hxx
Go to the documentation of this file.
1 #pragma once // Ensure that file is included only once in a single compilation.
2 
3 #include <HyperHDG/dense_la.hxx>
4 #include <HyperHDG/hypercube.hxx>
7 
8 #include <algorithm>
9 #include <tuple>
10 
11 namespace LocalSolver
12 {
13 /*!*************************************************************************************************
14  * \brief Local solver for bilaplacian equation on uniform hypergraph.
15  *
16  * \tparam hyEdge_dimT Dimension of a hyperedge, i.e., 1 is for PDEs defined on graphs, 2 is for
17  * PDEs defined on surfaces, and 3 is for PDEs defined on volumes.
18  * \tparam poly_deg The polynomial degree of test and trial functions.
19  * \tparam quad_deg The order of the quadrature rule.
20  * \tparam lSol_float_t The floating point type calculations are executed in. Defaults to double.
21  *
22  * \authors Guido Kanschat, Heidelberg University, 2019--2020.
23  * \authors Andreas Rupp, Heidelberg University, 2019--2020.
24  **************************************************************************************************/
25 template <unsigned int hyEdge_dimT,
26  unsigned int poly_deg,
27  unsigned int quad_deg,
28  typename lSol_float_t = double>
30 {
31  public:
32  /*!***********************************************************************************************
33  * \brief Define type of (hyperedge related) data that is stored in HyDataContainer.
34  ************************************************************************************************/
35  struct data_type
36  {
37  };
38  /*!***********************************************************************************************
39  * \brief Define type of node elements, especially with respect to nodal shape functions.
40  ************************************************************************************************/
41  struct node_element
42  {
43  typedef std::tuple<TPP::ShapeFunction<
46  };
47  /*!***********************************************************************************************
48  * \brief Define how errors are evaluated.
49  ************************************************************************************************/
50  struct error_def
51  {
52  /*!*********************************************************************************************
53  * \brief Define the typename returned by function errors.
54  **********************************************************************************************/
55  typedef std::array<lSol_float_t, 1U> error_t;
56  /*!*********************************************************************************************
57  * \brief Define how initial error is generated.
58  **********************************************************************************************/
60  {
61  std::array<lSol_float_t, 1U> summed_error;
62  summed_error.fill(0.);
63  return summed_error;
64  }
65  /*!*********************************************************************************************
66  * \brief Define how local errors should be accumulated.
67  **********************************************************************************************/
68  static error_t sum_error(error_t& summed_error, const error_t& new_error)
69  {
70  for (unsigned int k = 0; k < summed_error.size(); ++k)
71  summed_error[k] += new_error[k];
72  return summed_error;
73  }
74  /*!*********************************************************************************************
75  * \brief Define how global errors should be postprocessed.
76  **********************************************************************************************/
77  static error_t postprocess_error(error_t& summed_error)
78  {
79  for (unsigned int k = 0; k < summed_error.size(); ++k)
80  summed_error[k] = std::sqrt(summed_error[k]);
81  return summed_error;
82  }
83  };
84 
85  // -----------------------------------------------------------------------------------------------
86  // Public, static constexpr functions
87  // -----------------------------------------------------------------------------------------------
88 
89  /*!***********************************************************************************************
90  * \brief Dimension of hyper edge type that this object solves on.
91  ************************************************************************************************/
92  static constexpr unsigned int hyEdge_dim() { return hyEdge_dimT; }
93  /*!***********************************************************************************************
94  * \brief Evaluate amount of global degrees of freedom per hypernode.
95  *
96  * This number must be equal to HyperNodeFactory::n_dofs_per_node() of the HyperNodeFactory
97  * cooperating with this object.
98  *
99  * \retval n_dofs Number of global degrees of freedom per hypernode.
100  ************************************************************************************************/
101  static constexpr unsigned int n_glob_dofs_per_node()
102  {
103  return 2 * Hypercube<hyEdge_dimT - 1>::pow(poly_deg + 1);
104  }
105  /*!***********************************************************************************************
106  * \brief Dimension of of the solution evaluated with respect to a hyperedge.
107  ************************************************************************************************/
108  static constexpr unsigned int system_dimension() { return hyEdge_dimT + 1; }
109  /*!***********************************************************************************************
110  * \brief Dimension of of the solution evaluated with respect to a hypernode.
111  ************************************************************************************************/
112  static constexpr unsigned int node_system_dimension() { return 1; }
113 
114  private:
115  // -----------------------------------------------------------------------------------------------
116  // Private, static constexpr functions
117  // -----------------------------------------------------------------------------------------------
118 
119  /*!***********************************************************************************************
120  * \brief Number of local shape functions (with respect to all spatial dimensions).
121  ************************************************************************************************/
122  static constexpr unsigned int n_shape_fct_ = Hypercube<hyEdge_dimT>::pow(poly_deg + 1);
123  /*!***********************************************************************************************
124  * \brief Number oflocal shape functions (with respect to a face / hypernode).
125  ************************************************************************************************/
126  static constexpr unsigned int n_shape_bdr_ = Hypercube<hyEdge_dimT - 1>::pow(poly_deg + 1);
127  /*!***********************************************************************************************
128  * \brief Number of (local) degrees of freedom per hyperedge.
129  ************************************************************************************************/
130  static constexpr unsigned int n_loc_dofs_ = 2 * (hyEdge_dimT + 1) * n_shape_fct_;
131  /*!***********************************************************************************************
132  * \brief Dimension of of the solution evaluated with respect to a hypernode.
133  *
134  * This allows to the use of this quantity as template parameter in member functions.
135  ************************************************************************************************/
136  static constexpr unsigned int system_dim = system_dimension();
137  /*!***********************************************************************************************
138  * \brief Dimension of of the solution evaluated with respect to a hypernode.
139  *
140  * This allows to the use of this quantity as template parameter in member functions.
141  ************************************************************************************************/
142  static constexpr unsigned int node_system_dim = node_system_dimension();
143  /*!***********************************************************************************************
144  * \brief Assemble local matrix for the local solver.
145  *
146  * The local solver neither depends on the geometry, nor on global functions. Thus, its local
147  * matrix is the same for all hyperedges and can be assembled once in the constructor. This is
148  * done in this function.
149  *
150  * The function is static, since it is used in the constructor's initializer list.
151  *
152  * \param tau Penalty parameter for HDG.
153  * \retval loc_mat Matrix of the local solver.
154  ************************************************************************************************/
155  static SmallSquareMat<n_loc_dofs_, lSol_float_t> assemble_loc_matrix(const lSol_float_t tau);
156  /*!***********************************************************************************************
157  * \brief (Globally constant) penalty parameter for HDG scheme.
158  ************************************************************************************************/
159  const lSol_float_t tau_;
160  /*!***********************************************************************************************
161  * \brief Local matrix for the local solver.
162  ************************************************************************************************/
164  /*!***********************************************************************************************
165  * \brief An integrator helps to easily evaluate integrals (e.g. via quadrature).
166  ************************************************************************************************/
170  lSol_float_t>
172 
173  // -----------------------------------------------------------------------------------------------
174  // Private, internal functions for the local solver
175  // -----------------------------------------------------------------------------------------------
176 
177  /*!***********************************************************************************************
178  * \brief Assemble local right hand for the local solver.
179  *
180  * The right hand side needs the values of the global degrees of freedom. Thus, it needs to be
181  * constructed individually for every hyperedge.
182  *
183  * \tparam SmallMatT The cata type of the \c lambda_values.
184  * \param lambda_values Global degrees of freedom associated to the hyperedge.
185  * \retval loc_rhs Local right hand side of the locasl solver.
186  ************************************************************************************************/
187  template <typename SmallMatT>
188  inline SmallVec<n_loc_dofs_, lSol_float_t> assemble_rhs(const SmallMatT& lambda_values) const;
189  /*!***********************************************************************************************
190  * \brief Solve local problem.
191  *
192  * \tparam SmallMatT The cata type of the \c lambda_values.
193  * \param lambda_values Global degrees of freedom associated to the hyperedge.
194  * \retval loc_sol Solution of the local problem.
195  ************************************************************************************************/
196  template <typename SmallMatT>
197  inline std::array<lSol_float_t, n_loc_dofs_> solve_local_problem(
198  const SmallMatT& lambda_values) const
199  {
200  try
201  {
202  return (assemble_rhs(lambda_values) / loc_mat_).data();
203  }
204  catch (Wrapper::LAPACKexception& exc)
205  {
206  hy_assert(0 == 1, exc.what() << std::endl
207  << "This can happen if quadrature is too inaccurate!");
208  throw exc;
209  }
210  }
211  /*!***********************************************************************************************
212  * \brief Evaluate primal variable at boundary.
213  *
214  * Function to evaluate primal variable of the solution. This function is needed to calculate
215  * the local numerical fluxes.
216  *
217  * \param coeffs Coefficients of the local solution.
218  * \retval bdr_coeffs Coefficients of respective (dim-1) dimensional function at boundaries.
219  ************************************************************************************************/
220  inline std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> primal_at_boundary(
221  const std::array<lSol_float_t, n_loc_dofs_>& coeffs) const;
222  /*!***********************************************************************************************
223  * \brief Evaluate dual variable at boundary.
224  *
225  * Function to evaluate dual variable of the solution. This function is needed to calculate the
226  * local numerical fluxes.
227  *
228  * \param coeffs Coefficients of the local solution.
229  * \retval bdr_coeffs Coefficients of respective (dim-1) dimensional function at boundaries.
230  ************************************************************************************************/
231  inline std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> dual_at_boundary(
232  const std::array<lSol_float_t, 2 * (hyEdge_dimT + 1) * n_shape_fct_>& coeffs) const;
233 
234  public:
235  /*!***********************************************************************************************
236  * \brief Class is constructed using a single double indicating the penalty parameter.
237  ************************************************************************************************/
238  typedef lSol_float_t constructor_value_type;
239  /*!***********************************************************************************************
240  * \brief Constructor for local solver.
241  *
242  * \param tau Penalty parameter of HDG scheme.
243  ************************************************************************************************/
245  : tau_(tau), loc_mat_(assemble_loc_matrix(tau))
246  {
247  }
248  /*!***********************************************************************************************
249  * \brief Evaluate local contribution to matrix--vector multiplication.
250  *
251  * Execute matrix--vector multiplication y = A * x, where x represents the vector containing the
252  * skeletal variable (adjacent to one hyperedge), and A is the condensed matrix arising from the
253  * HDG discretization. This function does this multiplication (locally) for one hyperedge. The
254  * hyperedge is no parameter, since all hyperedges are assumed to have the same properties.
255  *
256  * \tparam SmallMatInT Data type of \c lambda_values_in.
257  * \tparam SmallMatOutT Data type of \c lambda_values_out.
258  * \param lambda_values_in Local part of vector x.
259  * \param lambda_values_out Local part that will be added to A * x.
260  * \param time Time --- this parameter is redundant for this local solver.
261  * \retval vecAx Local part of vector A * x.
262  ************************************************************************************************/
263  template <typename SmallMatInT, typename SmallMatOutT>
264  SmallMatOutT& trace_to_flux(const SmallMatInT& lambda_values_in,
265  SmallMatOutT& lambda_values_out,
266  const lSol_float_t UNUSED(time) = 0.) const
267  {
268  hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
269  lambda_values_in.size() == 2 * hyEdge_dimT,
270  "Both matrices must be of same size which corresponds to the number of faces!");
271  for (unsigned int i = 0; i < lambda_values_in.size(); ++i)
272  hy_assert(
273  lambda_values_in[i].size() == lambda_values_out[i].size() &&
274  lambda_values_in[i].size() == n_glob_dofs_per_node(),
275  "Both matrices must be of same size which corresponds to the number of dofs per face!");
276 
277  std::array<lSol_float_t, n_loc_dofs_> coeffs = solve_local_problem(lambda_values_in);
278 
279  std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> primals(
280  primal_at_boundary(coeffs)),
281  duals(dual_at_boundary(coeffs));
282 
283  for (unsigned int i = 0; i < lambda_values_out.size(); ++i)
284  for (unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
285  lambda_values_out[i][j] = duals[i][j] + tau_ * (primals[i][j] - lambda_values_in[i][j]);
286 
287  return lambda_values_out;
288  }
289  /*!***********************************************************************************************
290  * \brief Evaluate local contribution to matrix--vector residual.
291  *
292  * \tparam SmallMatInT Data type of \c lambda_values_in.
293  * \tparam SmallMatOutT Data type of \c lambda_values_out.
294  * \param lambda_values_in Local part of vector x.
295  * \param lambda_values_out Local part that will be added to A * x.
296  * \param time Time --- this parameter is redundant for this local solver.
297  * \retval vecAx Local part of vector A * x.
298  ************************************************************************************************/
299  template <typename SmallMatInT, typename SmallMatOutT>
300  SmallMatOutT& residual_flux(const SmallMatInT& lambda_values_in,
301  SmallMatOutT& lambda_values_out,
302  const lSol_float_t UNUSED(time) = 0.) const
303  {
304  return lambda_values_out = trace_to_flux(lambda_values_in, lambda_values_out);
305  }
306  /*!***********************************************************************************************
307  * \brief Evaluate local squared L2 error.
308  *
309  * \param lambda_values The values of the skeletal variable's coefficients.
310  * \param time Time --- this parameter is redundant for this local solver.
311  * \retval vec_b Local part of vector b.
312  ************************************************************************************************/
313  template <typename SmallMatT>
314  std::array<lSol_float_t, 1U> errors(const SmallMatT& UNUSED(lambda_values),
315  const lSol_float_t UNUSED(time) = 0.) const
316  {
317  return std::array<lSol_float_t, 1U>({0.});
318  }
319  /*!***********************************************************************************************
320  * \brief Evaluate local reconstruction at tensorial products of abscissas.
321  *
322  * \tparam absc_float_t Floating type for the abscissa values.
323  * \tparam abscissas_sizeT Size of the array of array of abscissas.
324  * \tparam input_array_t Type of input array.
325  * \param abscissas Abscissas of the supporting points.
326  * \param lambda_values The values of the skeletal variable's coefficients.
327  * \param time Time --- this parameter is redundant for this local solver.
328  * \retval function_values Function values at quadrature points.
329  ************************************************************************************************/
330  template <typename abscissa_float_t, std::size_t sizeT, class input_array_t>
331  std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(sizeT)>, system_dim> bulk_values(
332  const std::array<abscissa_float_t, sizeT>& abscissas,
333  const input_array_t& lambda_values,
334  const lSol_float_t UNUSED(time) = 0.) const;
335 
336 }; // end of class BilaplacianUniform
337 
338 // -------------------------------------------------------------------------------------------------
340 // -------------------------------------------------------------------------------------------------
341 
342 // -------------------------------------------------------------------------------------------------
343 // -------------------------------------------------------------------------------------------------
344 //
345 // IMPLEMENTATION OF MEMBER FUNCTIONS OF BilaplacianUniform
346 //
347 // -------------------------------------------------------------------------------------------------
348 // -------------------------------------------------------------------------------------------------
349 
350 // -------------------------------------------------------------------------------------------------
351 // assemble_loc_matrix
352 // -------------------------------------------------------------------------------------------------
353 
354 template <unsigned int hyEdge_dimT,
355  unsigned int poly_deg,
356  unsigned int quad_deg,
357  typename lSol_float_t>
359  lSol_float_t>
361  const lSol_float_t tau)
362 {
363  constexpr unsigned int n_dofs_lap = n_loc_dofs_ / 2;
364  lSol_float_t integral;
365 
367 
368  for (unsigned int i = 0; i < n_shape_fct_; ++i)
369  {
370  for (unsigned int j = 0; j < n_shape_fct_; ++j)
371  {
372  // Integral_element phi_i phi_j dx in diagonal blocks
373  integral = integrator::integrate_vol_phiphi(i, j);
374  local_mat(hyEdge_dimT * n_shape_fct_ + i, n_dofs_lap + hyEdge_dimT * n_shape_fct_ + j) -=
375  integral;
376  for (unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
377  {
378  local_mat(dim * n_shape_fct_ + i, dim * n_shape_fct_ + j) += integral;
379  local_mat(n_dofs_lap + dim * n_shape_fct_ + i, n_dofs_lap + dim * n_shape_fct_ + j) +=
380  integral;
381  }
382 
383  for (unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
384  {
385  // Integral_element - nabla phi_i \vec phi_j dx
386  // = Integral_element - div \vec phi_i phi_j dx in right upper and left lower blocks
387  integral = integrator::integrate_vol_Dphiphi(i, j, dim);
388  local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) -= integral;
389  local_mat(dim * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) -= integral;
390  local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
391  n_dofs_lap + dim * n_shape_fct_ + j) -= integral;
392  local_mat(n_dofs_lap + dim * n_shape_fct_ + i,
393  n_dofs_lap + hyEdge_dimT * n_shape_fct_ + j) -= integral;
394 
395  // Corresponding boundary integrals from integration by parts in left lower blocks
396  integral = integrator::integrate_bdr_phiphi(i, j, 2 * dim + 1);
397  local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) += integral;
398  local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
399  n_dofs_lap + dim * n_shape_fct_ + j) +=
400  integral; // Removing to enforce Neumann zero!
401  // and from the penalty in the lower right diagonal block
402  local_mat(hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) += tau * integral;
403  local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
404  n_dofs_lap + hyEdge_dimT * n_shape_fct_ + j) += tau * integral;
405  // Corresponding boundary integrals from integration by parts in left lower blocks
406  integral = integrator::integrate_bdr_phiphi(i, j, 2 * dim + 0);
407  local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) -= integral;
408  local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
409  n_dofs_lap + dim * n_shape_fct_ + j) -=
410  integral; // Removing to enforce Neumann zero!
411  // and from the penalty in the lower right diagonal block
412  local_mat(hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) += tau * integral;
413  local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
414  n_dofs_lap + hyEdge_dimT * n_shape_fct_ + j) += tau * integral;
415  }
416  }
417  }
418 
419  return local_mat;
420 } // end of BernoulliBendingBeam::assemble_loc_matrix
421 
422 // -------------------------------------------------------------------------------------------------
423 // assemble_rhs
424 // -------------------------------------------------------------------------------------------------
425 
426 template <unsigned int hyEdge_dimT,
427  unsigned int poly_deg,
428  unsigned int quad_deg,
429  typename lSol_float_t>
430 template <typename SmallMatT>
432  lSol_float_t>
434  const SmallMatT& lambda_values) const
435 {
436  constexpr unsigned int n_dofs_lap = n_loc_dofs_ / 2;
437  lSol_float_t integral;
438  SmallVec<n_loc_dofs_, lSol_float_t> right_hand_side;
439 
440  hy_assert(lambda_values.size() == 2 * hyEdge_dimT,
441  "The size of the lambda values should be twice the dimension of a hyperedge.");
442  for (unsigned int i = 0; i < 2 * hyEdge_dimT; ++i)
443  hy_assert(lambda_values[i].size() == 2 * n_shape_bdr_,
444  "The size of lambda should be the amount of ansatz functions at boundary.");
445 
446  for (unsigned int i = 0; i < n_shape_fct_; ++i)
447  {
448  for (unsigned int j = 0; j < n_shape_bdr_; ++j)
449  {
450  for (unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
451  {
452  integral = integrator::integrate_bdr_phipsi(i, j, 2 * dim + 0);
453  right_hand_side[dim * n_shape_fct_ + i] += lambda_values[2 * dim + 0][j] * integral;
454  right_hand_side[hyEdge_dimT * n_shape_fct_ + i] +=
455  tau_ * lambda_values[2 * dim + 0][j] * integral;
456  right_hand_side[n_dofs_lap + dim * n_shape_fct_ + i] +=
457  lambda_values[2 * dim + 0][n_shape_bdr_ + j] * integral;
458  right_hand_side[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] +=
459  tau_ * lambda_values[2 * dim + 0][n_shape_bdr_ + j] * integral;
460 
461  integral = integrator::integrate_bdr_phipsi(i, j, 2 * dim + 1);
462  right_hand_side[dim * n_shape_fct_ + i] -= lambda_values[2 * dim + 1][j] * integral;
463  right_hand_side[hyEdge_dimT * n_shape_fct_ + i] +=
464  tau_ * lambda_values[2 * dim + 1][j] * integral;
465  right_hand_side[n_dofs_lap + dim * n_shape_fct_ + i] -=
466  lambda_values[2 * dim + 1][n_shape_bdr_ + j] * integral;
467  right_hand_side[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] +=
468  tau_ * lambda_values[2 * dim + 1][n_shape_bdr_ + j] * integral;
469  }
470  }
471  }
472 
473  return right_hand_side;
474 } // end of BernoulliBendingBeam::assemble_rhs
475 
476 // -------------------------------------------------------------------------------------------------
477 // primal_at_boundary
478 // -------------------------------------------------------------------------------------------------
479 
480 template <unsigned int hyEdge_dimT,
481  unsigned int poly_deg,
482  unsigned int quad_deg,
483  typename lSol_float_t>
484 inline std::array<
485  std::array<lSol_float_t,
487  2 * hyEdge_dimT>
489  const std::array<lSol_float_t, n_loc_dofs_>& coeffs) const
490 {
491  constexpr unsigned int n_dofs_lap = n_loc_dofs_ / 2;
492  std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> bdr_values;
493  lSol_float_t integral;
494 
495  for (unsigned int dim_n = 0; dim_n < 2 * hyEdge_dimT; ++dim_n)
496  bdr_values[dim_n].fill(0.);
497 
498  for (unsigned int i = 0; i < n_shape_fct_; ++i)
499  {
500  for (unsigned int j = 0; j < n_shape_bdr_; ++j)
501  {
502  for (unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
503  {
504  integral = integrator::integrate_bdr_phipsi(i, j, 2 * dim + 0);
505  bdr_values[2 * dim + 0][j] += coeffs[hyEdge_dimT * n_shape_fct_ + i] * integral;
506  bdr_values[2 * dim + 0][n_shape_bdr_ + j] +=
507  coeffs[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] * integral;
508 
509  integral = integrator::integrate_bdr_phipsi(i, j, 2 * dim + 1);
510  bdr_values[2 * dim + 1][j] += coeffs[hyEdge_dimT * n_shape_fct_ + i] * integral;
511  bdr_values[2 * dim + 1][n_shape_bdr_ + j] +=
512  coeffs[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] * integral;
513  }
514  }
515  }
516 
517  return bdr_values;
518 } // end of BilaplacianUniform::primal_at_boundary
519 
520 // -------------------------------------------------------------------------------------------------
521 // dual_at_boundary
522 // -------------------------------------------------------------------------------------------------
523 
524 template <unsigned int hyEdge_dimT,
525  unsigned int poly_deg,
526  unsigned int quad_deg,
527  typename lSol_float_t>
528 inline std::array<
529  std::array<lSol_float_t,
531  2 * hyEdge_dimT>
533  const std::array<lSol_float_t, 2 * (hyEdge_dimT + 1) * n_shape_fct_>& coeffs) const
534 {
535  constexpr unsigned int n_dofs_lap = n_loc_dofs_ / 2;
536  std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> bdr_values;
537  lSol_float_t integral;
538 
539  for (unsigned int dim_n = 0; dim_n < 2 * hyEdge_dimT; ++dim_n)
540  bdr_values[dim_n].fill(0.);
541 
542  for (unsigned int i = 0; i < n_shape_fct_; ++i)
543  {
544  for (unsigned int j = 0; j < n_shape_bdr_; ++j)
545  {
546  for (unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
547  {
548  integral = integrator::integrate_bdr_phipsi(i, j, 2 * dim + 0);
549  bdr_values[2 * dim + 0][j] -= coeffs[dim * n_shape_fct_ + i] * integral;
550  bdr_values[2 * dim + 0][n_shape_bdr_ + j] -=
551  coeffs[n_dofs_lap + dim * n_shape_fct_ + i] * integral;
552 
553  integral = integrator::integrate_bdr_phipsi(i, j, 2 * dim + 1);
554  bdr_values[2 * dim + 1][j] += coeffs[dim * n_shape_fct_ + i] * integral;
555  bdr_values[2 * dim + 1][n_shape_bdr_ + j] +=
556  coeffs[n_dofs_lap + dim * n_shape_fct_ + i] * integral;
557  }
558  }
559  }
560 
561  return bdr_values;
562 } // end of BilaplacianUniform::dual_at_boundary
563 
564 // -------------------------------------------------------------------------------------------------
565 // bulk_values
566 // -------------------------------------------------------------------------------------------------
567 
568 template <unsigned int hyEdge_dimT,
569  unsigned int poly_deg,
570  unsigned int quad_deg,
571  typename lSol_float_t>
572 template <typename abscissa_float_t, std::size_t sizeT, class input_array_t>
573 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(sizeT)>,
576  const std::array<abscissa_float_t, sizeT>& abscissas,
577  const input_array_t& lambda_values,
578  const lSol_float_t) const
579 {
580  SmallVec<n_loc_dofs_, lSol_float_t> coefficients = solve_local_problem(lambda_values);
582  SmallVec<static_cast<unsigned int>(sizeT), abscissa_float_t> helper(abscissas);
583 
584  std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(sizeT)>,
586  point_vals;
587 
588  for (unsigned int d = 0; d < system_dim; ++d)
589  {
590  for (unsigned int i = 0; i < coeffs.size(); ++i)
591  coeffs[i] = coefficients[d * n_shape_fct_ + i];
592  for (unsigned int pt = 0; pt < Hypercube<hyEdge_dimT>::pow(sizeT); ++pt)
593  point_vals[d][pt] = integrator::shape_fun_t::template lin_comb_fct_val<float>(
594  coeffs, Hypercube<hyEdge_dimT>::template tensorial_pt<Point<hyEdge_dimT> >(pt, helper));
595  }
596 
597  return point_vals;
598 } // end of BilaplacianUniform::bulk_values
599 
600 // -------------------------------------------------------------------------------------------------
602 // -------------------------------------------------------------------------------------------------
603 
604 } // namespace LocalSolver
LocalSolver::BilaplacianUniform::system_dimension
static constexpr unsigned int system_dimension()
Dimension of of the solution evaluated with respect to a hyperedge.
Definition: bilaplacian_uniform_ldgh.hxx:108
LocalSolver::BilaplacianUniform::primal_at_boundary
std::array< std::array< lSol_float_t, 2 *n_shape_bdr_ >, 2 *hyEdge_dimT > primal_at_boundary(const std::array< lSol_float_t, n_loc_dofs_ > &coeffs) const
Evaluate primal variable at boundary.
shape_function.hxx
LocalSolver::BilaplacianUniform::assemble_loc_matrix
static SmallSquareMat< n_loc_dofs_, lSol_float_t > assemble_loc_matrix(const lSol_float_t tau)
Assemble local matrix for the local solver.
Wrapper::LAPACKexception::what
const char * what() const
Definition: lapack.hxx:27
LocalSolver
A namespace for local solvers.
Definition: advection_parab_ldgh.hxx:11
tensorial.hxx
LocalSolver::BilaplacianUniform::errors
std::array< lSol_float_t, 1U > errors(const SmallMatT &UNUSED(lambda_values), const lSol_float_t UNUSED(time)=0.) const
Evaluate local squared L2 error.
Definition: bilaplacian_uniform_ldgh.hxx:314
LocalSolver::BilaplacianUniform::node_system_dimension
static constexpr unsigned int node_system_dimension()
Dimension of of the solution evaluated with respect to a hypernode.
Definition: bilaplacian_uniform_ldgh.hxx:112
LocalSolver::BilaplacianUniform
Local solver for bilaplacian equation on uniform hypergraph.
Definition: bilaplacian_uniform_ldgh.hxx:29
LocalSolver::BilaplacianUniform::BilaplacianUniform
BilaplacianUniform(const constructor_value_type &tau=1.)
Constructor for local solver.
Definition: bilaplacian_uniform_ldgh.hxx:244
LocalSolver::BilaplacianUniform::tau_
const lSol_float_t tau_
(Globally constant) penalty parameter for HDG scheme.
Definition: bilaplacian_uniform_ldgh.hxx:159
LocalSolver::BilaplacianUniform::hyEdge_dim
static constexpr unsigned int hyEdge_dim()
Dimension of hyper edge type that this object solves on.
Definition: bilaplacian_uniform_ldgh.hxx:92
LocalSolver::BilaplacianUniform::node_system_dim
static constexpr unsigned int node_system_dim
Dimension of of the solution evaluated with respect to a hypernode.
Definition: bilaplacian_uniform_ldgh.hxx:142
TPP::Quadrature::GaussLegendre
Gauss–Legendre quadrature points and weights in one spatial dimension.
Definition: one_dimensional.hxx:19
SmallMat::size
static constexpr unsigned int size()
Return size a SmallMat.
Definition: dense_la.hxx:54
LocalSolver::BilaplacianUniform::n_shape_bdr_
static constexpr unsigned int n_shape_bdr_
Number oflocal shape functions (with respect to a face / hypernode).
Definition: bilaplacian_uniform_ldgh.hxx:126
TPP::ShapeType::Tensorial
Struct that handles the evaluation of tensorial shape functions.
Definition: tensorial.hxx:22
LocalSolver::BilaplacianUniform::error_def::initial_error
static error_t initial_error()
Define how initial error is generated.
Definition: bilaplacian_uniform_ldgh.hxx:59
LocalSolver::BilaplacianUniform::dual_at_boundary
std::array< std::array< lSol_float_t, 2 *n_shape_bdr_ >, 2 *hyEdge_dimT > dual_at_boundary(const std::array< lSol_float_t, 2 *(hyEdge_dimT+1) *n_shape_fct_ > &coeffs) const
Evaluate dual variable at boundary.
LocalSolver::BilaplacianUniform::bulk_values
std::array< std::array< lSol_float_t, Hypercube< hyEdge_dimT >::pow(sizeT)>, system_dim > bulk_values(const std::array< abscissa_float_t, sizeT > &abscissas, const input_array_t &lambda_values, const lSol_float_t UNUSED(time)=0.) const
Evaluate local reconstruction at tensorial products of abscissas.
LocalSolver::BilaplacianUniform::n_shape_fct_
static constexpr unsigned int n_shape_fct_
Number of local shape functions (with respect to all spatial dimensions).
Definition: bilaplacian_uniform_ldgh.hxx:122
TPP::ShapeFunction
Struct that handles different types of evaluation of shape functions.
Definition: shape_function.hxx:15
LocalSolver::BilaplacianUniform::system_dim
static constexpr unsigned int system_dim
Dimension of of the solution evaluated with respect to a hypernode.
Definition: bilaplacian_uniform_ldgh.hxx:136
LocalSolver::BilaplacianUniform::trace_to_flux
SmallMatOutT & trace_to_flux(const SmallMatInT &lambda_values_in, SmallMatOutT &lambda_values_out, const lSol_float_t UNUSED(time)=0.) const
Evaluate local contribution to matrix–vector multiplication.
Definition: bilaplacian_uniform_ldgh.hxx:264
TPP::Quadrature::Tensorial
General integrator class on tensorial hypergraphs.
Definition: tensorial.hxx:24
LocalSolver::BilaplacianUniform::constructor_value_type
lSol_float_t constructor_value_type
Class is constructed using a single double indicating the penalty parameter.
Definition: bilaplacian_uniform_ldgh.hxx:238
LocalSolver::BilaplacianUniform::n_loc_dofs_
static constexpr unsigned int n_loc_dofs_
Number of (local) degrees of freedom per hyperedge.
Definition: bilaplacian_uniform_ldgh.hxx:130
hypercube.hxx
LocalSolver::BilaplacianUniform::node_element
Define type of node elements, especially with respect to nodal shape functions.
Definition: bilaplacian_uniform_ldgh.hxx:41
Wrapper::LAPACKexception
Exception to be thrown if LAPACK's solve fails.
Definition: lapack.hxx:25
LocalSolver::BilaplacianUniform::error_def::postprocess_error
static error_t postprocess_error(error_t &summed_error)
Define how global errors should be postprocessed.
Definition: bilaplacian_uniform_ldgh.hxx:77
LocalSolver::BilaplacianUniform::node_element::functions
std::tuple< TPP::ShapeFunction< TPP::ShapeType::Tensorial< TPP::ShapeType::Legendre< poly_deg >, hyEdge_dimT - 1 > > > functions
Definition: bilaplacian_uniform_ldgh.hxx:45
Hypercube::pow
static constexpr unsigned int pow(unsigned int base)
Return n to the power dim.
Definition: hypercube.hxx:25
LocalSolver::BilaplacianUniform::error_def
Define how errors are evaluated.
Definition: bilaplacian_uniform_ldgh.hxx:50
hy_assert
#define hy_assert(Expr, Msg)
The assertion to be used within HyperHDG — deactivate using -DNDEBUG compile flag.
Definition: hy_assert.hxx:38
dense_la.hxx
LocalSolver::BilaplacianUniform::integrator
TPP::Quadrature::Tensorial< TPP::Quadrature::GaussLegendre< quad_deg >, TPP::ShapeFunction< TPP::ShapeType::Tensorial< TPP::ShapeType::Legendre< poly_deg >, hyEdge_dimT > >, lSol_float_t > integrator
An integrator helps to easily evaluate integrals (e.g. via quadrature).
Definition: bilaplacian_uniform_ldgh.hxx:171
LocalSolver::BilaplacianUniform::solve_local_problem
std::array< lSol_float_t, n_loc_dofs_ > solve_local_problem(const SmallMatT &lambda_values) const
Solve local problem.
Definition: bilaplacian_uniform_ldgh.hxx:197
LocalSolver::BilaplacianUniform::residual_flux
SmallMatOutT & residual_flux(const SmallMatInT &lambda_values_in, SmallMatOutT &lambda_values_out, const lSol_float_t UNUSED(time)=0.) const
Evaluate local contribution to matrix–vector residual.
Definition: bilaplacian_uniform_ldgh.hxx:300
UNUSED
#define UNUSED(x)
Unused parametes will neither result in g++, nor in doxygen warnings if wrapped by this.
Definition: compile_time_tricks.hxx:10
LocalSolver::BilaplacianUniform::assemble_rhs
SmallVec< n_loc_dofs_, lSol_float_t > assemble_rhs(const SmallMatT &lambda_values) const
Assemble local right hand for the local solver.
LocalSolver::BilaplacianUniform::n_glob_dofs_per_node
static constexpr unsigned int n_glob_dofs_per_node()
Evaluate amount of global degrees of freedom per hypernode.
Definition: bilaplacian_uniform_ldgh.hxx:101
LocalSolver::BilaplacianUniform::error_def::sum_error
static error_t sum_error(error_t &summed_error, const error_t &new_error)
Define how local errors should be accumulated.
Definition: bilaplacian_uniform_ldgh.hxx:68
LocalSolver::BilaplacianUniform::loc_mat_
const SmallSquareMat< n_loc_dofs_, lSol_float_t > loc_mat_
Local matrix for the local solver.
Definition: bilaplacian_uniform_ldgh.hxx:163
LocalSolver::BilaplacianUniform::data_type
Define type of (hyperedge related) data that is stored in HyDataContainer.
Definition: bilaplacian_uniform_ldgh.hxx:35
SmallMat
This class implements a small/dense matrix.
Definition: dense_la.hxx:34
LocalSolver::BilaplacianUniform::error_def::error_t
std::array< lSol_float_t, 1U > error_t
Define the typename returned by function errors.
Definition: bilaplacian_uniform_ldgh.hxx:55
Hypercube
Helper class containing numbers and functions related to hypercubes.
Definition: hypercube.hxx:12