HyperHDG
bilaplacian_parab_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 Default parameters for the diffusion equation, cf. below.
15  *
16  * \authors Guido Kanschat, Heidelberg University, 2019--2020.
17  * \authors Andreas Rupp, Heidelberg University, 2019--2020.
18  **************************************************************************************************/
19 template <unsigned int space_dimT, typename param_float_t = double>
20 struct Bilaplacian_parameters_default
21 {
22  /*!***********************************************************************************************
23  * \brief Array containing hypernode types corresponding to Dirichlet boundary.
24  ************************************************************************************************/
25  static constexpr std::array<unsigned int, 0U> dirichlet_nodes{};
26  /*!***********************************************************************************************
27  * \brief Array containing hypernode types corresponding to Dirichlet boundary of Laplacian.
28  ************************************************************************************************/
29  static constexpr std::array<unsigned int, 0U> dirichlet_laplacian_nodes{};
30  /*!***********************************************************************************************
31  * \brief Array containing hypernode types corresponding to Neumann boundary.
32  ************************************************************************************************/
33  static constexpr std::array<unsigned int, 0U> neumann_nodes{};
34  /*!***********************************************************************************************
35  * \brief Array containing hypernode types corresponding to Neumann boundary of Laplacian.
36  ************************************************************************************************/
37  static constexpr std::array<unsigned int, 0U> neumann_laplacian_nodes{};
38  /*!***********************************************************************************************
39  * \brief Inverse bilaplacian coefficient in PDE as analytic function.
40  ************************************************************************************************/
42  const param_float_t = 0.)
43  {
44  return 1.;
45  }
46  /*!***********************************************************************************************
47  * \brief Right-hand side in PDE as analytic function.
48  ************************************************************************************************/
50  const param_float_t = 0.)
51  {
52  return 0.;
53  }
54  /*!***********************************************************************************************
55  * \brief Dirichlet values of solution as analytic function.
56  ************************************************************************************************/
58  const param_float_t = 0.)
59  {
60  return 0.;
61  }
62  /*!***********************************************************************************************
63  * \brief Dirichlet values of solution's Laplacian as analytic function.
64  ************************************************************************************************/
66  const param_float_t = 0.)
67  {
68  return 0.;
69  }
70  /*!***********************************************************************************************
71  * \brief Neumann values of solution as analytic function.
72  ************************************************************************************************/
73  static param_float_t neumann_value(const Point<space_dimT, param_float_t>&,
74  const param_float_t = 0.)
75  {
76  return 0.;
77  }
78  /*!***********************************************************************************************
79  * \brief Neumann values of solution's Laplacian as analytic function.
80  ************************************************************************************************/
82  const param_float_t = 0.)
83  {
84  return 0.;
85  }
86  /*!***********************************************************************************************
87  * \brief Analytic result of PDE (for convergence tests).
88  ************************************************************************************************/
90  const param_float_t = 0.)
91  {
92  return 0.;
93  }
94 }; // end of struct Bilaplacian_parameters_default
95 
96 /*!*************************************************************************************************
97  * \brief Local solver for bilaplacian equation on uniform hypergraph.
98  *
99  * \note Theta must be one, since only implicit Euler has been implemented at the moment.
100  *
101  * \tparam hyEdge_dimT Dimension of a hyperedge, i.e., 1 is for PDEs defined on graphs, 2 is for
102  * PDEs defined on surfaces, and 3 is for PDEs defined on volumes.
103  * \tparam poly_deg The polynomial degree of test and trial functions.
104  * \tparam quad_deg The order of the quadrature rule.
105  * \tparam parametersT Struct depending on templates \c space_dimTP and \c lSol_float_TP that
106  * contains static parameter functions.
107  * Defaults to above functions included in \c DiffusionParametersDefault.
108  * \tparam lSol_float_t The floating point type calculations are executed in. Defaults to double.
109  *
110  * \authors Guido Kanschat, Heidelberg University, 2019--2020.
111  * \authors Andreas Rupp, Heidelberg University, 2019--2020.
112  **************************************************************************************************/
113 template <unsigned int hyEdge_dimT,
114  unsigned int poly_deg,
115  unsigned int quad_deg,
116  template <unsigned int, typename>
117  typename parametersT,
118  typename lSol_float_t = double>
120 {
121  public:
122  // -----------------------------------------------------------------------------------------------
123  // Public, static constexpr functions
124  // -----------------------------------------------------------------------------------------------
125 
126  /*!***********************************************************************************************
127  * \brief Dimension of hyper edge type that this object solves on.
128  ************************************************************************************************/
129  static constexpr unsigned int hyEdge_dim() { return hyEdge_dimT; }
130  /*!***********************************************************************************************
131  * \brief Evaluate amount of global degrees of freedom per hypernode.
132  *
133  * This number must be equal to HyperNodeFactory::n_dofs_per_node() of the HyperNodeFactory
134  * cooperating with this object.
135  *
136  * \retval n_dofs Number of global degrees of freedom per hypernode.
137  ************************************************************************************************/
138  static constexpr unsigned int n_glob_dofs_per_node()
139  {
140  return 2 * Hypercube<hyEdge_dimT - 1>::pow(poly_deg + 1);
141  }
142  /*!***********************************************************************************************
143  * \brief Dimension of of the solution evaluated with respect to a hyperedge.
144  ************************************************************************************************/
145  static constexpr unsigned int system_dimension() { return hyEdge_dimT + 1; }
146  /*!***********************************************************************************************
147  * \brief Dimension of of the solution evaluated with respect to a hypernode.
148  ************************************************************************************************/
149  static constexpr unsigned int node_system_dimension() { return 1; }
150 
151  private:
152  // -----------------------------------------------------------------------------------------------
153  // Private, static constexpr functions
154  // -----------------------------------------------------------------------------------------------
155 
156  /*!***********************************************************************************************
157  * \brief Number of local shape functions (with respect to all spatial dimensions).
158  ************************************************************************************************/
159  static constexpr unsigned int n_shape_fct_ = n_glob_dofs_per_node() * (poly_deg + 1) / 2;
160  /*!***********************************************************************************************
161  * \brief Number oflocal shape functions (with respect to a face / hypernode).
162  ************************************************************************************************/
163  static constexpr unsigned int n_shape_bdr_ = n_glob_dofs_per_node() / 2;
164  /*!***********************************************************************************************
165  * \brief Number of (local) degrees of freedom per hyperedge.
166  ************************************************************************************************/
167  static constexpr unsigned int n_loc_dofs_ = 2 * (hyEdge_dimT + 1) * n_shape_fct_;
168  /*!***********************************************************************************************
169  * \brief Dimension of of the solution evaluated with respect to a hypernode.
170  *
171  * This allows to the use of this quantity as template parameter in member functions.
172  ************************************************************************************************/
173  static constexpr unsigned int system_dim = system_dimension();
174  /*!***********************************************************************************************
175  * \brief Dimension of of the solution evaluated with respect to a hypernode.
176  *
177  * This allows to the use of this quantity as template parameter in member functions.
178  ************************************************************************************************/
179  static constexpr unsigned int node_system_dim = node_system_dimension();
180  /*!***********************************************************************************************
181  * \brief Find out whether a node is of Dirichlet type.
182  ************************************************************************************************/
183  template <typename parameters>
184  static constexpr bool is_dirichlet(const unsigned int node_type)
185  {
186  return std::find(parameters::dirichlet_nodes.begin(), parameters::dirichlet_nodes.end(),
187  node_type) != parameters::dirichlet_nodes.end();
188  }
189  template <typename parameters>
190  static constexpr bool is_dirichlet_laplacian(const unsigned int node_type)
191  {
192  return std::find(parameters::dirichlet_laplacian_nodes.begin(),
193  parameters::dirichlet_laplacian_nodes.end(),
194  node_type) != parameters::dirichlet_laplacian_nodes.end();
195  }
196 
197  // -----------------------------------------------------------------------------------------------
198  // Private, const members: Parameters and auxiliaries that help assembling matrices, etc.
199  // -----------------------------------------------------------------------------------------------
200 
201  /*!***********************************************************************************************
202  * \brief (Globally constant) penalty parameter for HDG scheme.
203  ************************************************************************************************/
204  const lSol_float_t tau_;
205  /*!***********************************************************************************************
206  * \brief Parameter theta that defines the one-step theta scheme.
207  ************************************************************************************************/
208  const lSol_float_t theta_;
209  /*!***********************************************************************************************
210  * \brief Time step size.
211  ************************************************************************************************/
212  const lSol_float_t delta_t_;
213  /*!***********************************************************************************************
214  * \brief An integrator helps to easily evaluate integrals (e.g. via quadrature).
215  ************************************************************************************************/
219  lSol_float_t>
221 
222  // -----------------------------------------------------------------------------------------------
223  // Private, internal functions for the local solver
224  // -----------------------------------------------------------------------------------------------
225 
226  /*!***********************************************************************************************
227  * \brief Assemble local matrix for the local solver.
228  *
229  * \tparam hyEdgeT The geometry type / typename of the considered hyEdge's geometry.
230  * \param tau Penalty parameter.
231  * \param hyper_edge The geometry of the considered hyperedge (of typename GeomT).
232  * \param time Time, when the local matrix is evaluated.
233  * \retval loc_mat Matrix of the local solver.
234  ************************************************************************************************/
235  template <typename hyEdgeT>
237  assemble_loc_matrix(const lSol_float_t tau, hyEdgeT& hyper_edge, const lSol_float_t time) const;
238  /*!***********************************************************************************************
239  * \brief Assemble local right-hand for the local solver (from skeletal).
240  *
241  * The right hand side needs the values of the global degrees of freedom. Note that we basically
242  * follow the lines of
243  *
244  * B. Cockburn, J. Gopalakrishnan, and R. Lazarov.
245  * Unified hybridization of discontinuous Galerkin, mixed, and continuous Galerkin methods for
246  * second order elliptic problems. SIAM Journal on Numerical Analysis, 47(2):1319–1365, 2009
247  *
248  * and discriminate between local solvers with respect to the skeletal variable and with respect
249  * to the global right-hand side. This assembles the local right-hand side with respect to the
250  * skeletal variable.
251  *
252  * \tparam hyEdgeT The geometry type / typename of the considered hyEdge's geometry.
253  * \tparam SmallMatT The data type of \c lambda_values.
254  * \param lambda_values Global degrees of freedom associated to the hyperedge.
255  * \param hyper_edge The geometry of the considered hyperedge (of typename GeomT).
256  * \retval loc_rhs Local right hand side of the locasl solver.
257  ************************************************************************************************/
258  template <typename hyEdgeT, typename SmallMatT>
260  const SmallMatT& lambda_values,
261  hyEdgeT& hyper_edge) const;
262  /*!***********************************************************************************************
263  * \brief Assemble local right-hand for the local solver (from global right-hand side).
264  *
265  * Note that we basically follow the lines of
266  *
267  * B. Cockburn, J. Gopalakrishnan, and R. Lazarov.
268  * Unified hybridization of discontinuous Galerkin, mixed, and continuous Galerkin methods for
269  * second order elliptic problems. SIAM Journal on Numerical Analysis, 47(2):1319–1365, 2009
270  *
271  * and discriminate between local solvers with respect to the skeletal variable and with respect
272  * to the global right-hand side. This assembles the local right-hand side with respect to the
273  * global right-hand side. This function implicitly uses the parameters.
274  *
275  * \tparam hyEdgeT The geometry type / typename of the considered hyEdge's geometry.
276  * \param hyper_edge The geometry of the considered hyperedge (of typename GeomT).
277  * \param time Point of time, rhs is evaluated at
278  * \retval loc_rhs Local right hand side of the locasl solver.
279  ************************************************************************************************/
280  template <typename hyEdgeT>
282  hyEdgeT& hyper_edge,
283  const lSol_float_t time) const;
284  /*!***********************************************************************************************
285  * \brief Assemble local right-hand for the local solver (from function coefficients).
286  *
287  * Note that we basically follow the lines of
288  *
289  * B. Cockburn, J. Gopalakrishnan, and R. Lazarov.
290  * Unified hybridization of discontinuous Galerkin, mixed, and continuous Galerkin methods for
291  * second order elliptic problems. SIAM Journal on Numerical Analysis, 47(2):1319–1365, 2009
292  *
293  * and discriminate between local solvers with respect to the skeletal variable and with respect
294  * to the global right-hand side. This assembles the local right-hand side with respect to the
295  * global right-hand side. This function implicitly uses the parameters.
296  *
297  * \tparam hyEdgeT The geometry type / typename of the considered hyEdge's geometry.
298  * \param coeffs Local coefficients of bulk variable u.
299  * \param hyper_edge The geometry of the considered hyperedge (of typename GeomT).
300  * \retval loc_rhs Local right hand side of the locasl solver.
301  ************************************************************************************************/
302  template <typename hyEdgeT>
304  const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
305  hyEdgeT& hyper_edge) const;
306  /*!***********************************************************************************************
307  * \brief Solve local problem (with right-hand side from skeletal).
308  *
309  * \tparam hyEdgeT The geometry type / typename of the considered hyEdge's geometry.
310  * \tparam SmallMatT The data type of \c lambda_values.
311  * \param lambda_values Global degrees of freedom associated to the hyperedge.
312  * \param solution_type Type of local problem that is to be solved.
313  * \param hyper_edge The geometry of the considered hyperedge (of typename GeomT).
314  * \param time Point of time the problem is solved.
315  * \retval loc_sol Solution of the local problem.
316  ************************************************************************************************/
317  template <typename hyEdgeT, typename SmallMatT>
318  inline std::array<lSol_float_t, n_loc_dofs_> solve_local_problem(const SmallMatT& lambda_values,
319  const unsigned int solution_type,
320  hyEdgeT& hyper_edge,
321  const lSol_float_t time) const
322  {
323  try
324  {
326  if (solution_type == 0)
327  rhs = assemble_rhs_from_lambda(lambda_values, hyper_edge);
328  else if (solution_type == 1)
329  rhs = assemble_rhs_from_lambda(lambda_values, hyper_edge) +
330  assemble_rhs_from_global_rhs(hyper_edge, time);
331  else
332  hy_assert(0 == 1, "This has not been implemented!");
333  return (rhs / assemble_loc_matrix(tau_, hyper_edge, time)).data();
334  }
335  catch (Wrapper::LAPACKexception& exc)
336  {
337  hy_assert(0 == 1, exc.what() << std::endl
338  << "This can happen if quadrature is too inaccurate!");
339  throw exc;
340  }
341  }
342  /*!***********************************************************************************************
343  * \brief Evaluate primal variable at boundary.
344  *
345  * Function to evaluate primal variable of the solution. This function is needed to calculate
346  * the local numerical fluxes.
347  *
348  * \tparam hyEdgeT The geometry type / typename of the considered hyEdge's geometry.
349  * \param coeffs Coefficients of the local solution.
350  * \param hyper_edge The geometry of the considered hyperedge (of typename GeomT).
351  * \retval bdr_coeffs Coefficients of respective (dim-1) dimensional function at boundaries.
352  ************************************************************************************************/
353  template <typename hyEdgeT>
354  inline std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> primal_at_boundary(
355  const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
356  hyEdgeT& hyper_edge) const;
357  /*!***********************************************************************************************
358  * \brief Evaluate dual variable at boundary.
359  *
360  * Function to evaluate dual variable of the solution. This function is needed to calculate the
361  * local numerical fluxes.
362  *
363  * \tparam hyEdgeT The geometry type / typename of the considered hyEdge's geometry.
364  * \param coeffs Coefficients of the local solution.
365  * \param hyper_edge The geometry of the considered hyperedge (of typename GeomT).
366  * \retval bdr_coeffs Coefficients of respective (dim-1) dimensional function at boundaries.
367  ************************************************************************************************/
368  template <typename hyEdgeT>
369  inline std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> dual_at_boundary(
370  const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
371  hyEdgeT& hyper_edge) const;
372 
373  public:
374  // -----------------------------------------------------------------------------------------------
375  // Public functions (and one typedef) to be utilized by external functions.
376  // -----------------------------------------------------------------------------------------------
377 
378  /*!***********************************************************************************************
379  * \brief Define type of (hyperedge related) data that is stored in HyDataContainer.
380  ************************************************************************************************/
381  struct data_type
382  {
383  std::array<lSol_float_t, n_loc_dofs_> coeffs;
384  };
385  /*!***********************************************************************************************
386  * \brief Define type of node elements, especially with respect to nodal shape functions.
387  ************************************************************************************************/
389  {
390  typedef std::tuple<TPP::ShapeFunction<
393  };
394  /*!***********************************************************************************************
395  * \brief Define how errors are evaluated.
396  ************************************************************************************************/
397  struct error_def
398  {
399  /*!*********************************************************************************************
400  * \brief Define the typename returned by function errors.
401  **********************************************************************************************/
402  typedef std::array<lSol_float_t, 1U> error_t;
403  /*!*********************************************************************************************
404  * \brief Define how initial error is generated.
405  **********************************************************************************************/
407  {
408  std::array<lSol_float_t, 1U> summed_error;
409  summed_error.fill(0.);
410  return summed_error;
411  }
412  /*!*********************************************************************************************
413  * \brief Define how local errors should be accumulated.
414  **********************************************************************************************/
415  static error_t sum_error(error_t& summed_error, const error_t& new_error)
416  {
417  for (unsigned int k = 0; k < summed_error.size(); ++k)
418  summed_error[k] += new_error[k];
419  return summed_error;
420  }
421  /*!*********************************************************************************************
422  * \brief Define how global errors should be postprocessed.
423  **********************************************************************************************/
424  static error_t postprocess_error(error_t& summed_error)
425  {
426  for (unsigned int k = 0; k < summed_error.size(); ++k)
427  summed_error[k] = std::sqrt(summed_error[k]);
428  return summed_error;
429  }
430  };
431  /*!***********************************************************************************************
432  * \brief Class is constructed using a single double indicating the penalty parameter.
433  ************************************************************************************************/
434  typedef std::vector<lSol_float_t> constructor_value_type;
435  /*!***********************************************************************************************
436  * \brief Constructor for local solver.
437  *
438  * \param constru Constructor object.
439  ************************************************************************************************/
440  BilaplacianParab(const constructor_value_type& constru = std::vector(3, 1.))
441  : tau_(constru[0]), theta_(constru[1]), delta_t_(constru[2])
442  {
443  }
444  /*!***********************************************************************************************
445  * \brief Evaluate local contribution to matrix--vector multiplication.
446  *
447  * Execute matrix--vector multiplication y = A * x, where x represents the vector containing the
448  * skeletal variable (adjacent to one hyperedge), and A is the condensed matrix arising from the
449  * HDG discretization. This function does this multiplication (locally) for one hyperedge. The
450  * hyperedge is no parameter, since all hyperedges are assumed to have the same properties.
451  *
452  * \tparam hyEdgeT The geometry type / typename of the considered hyEdge's geometry.
453  * \tparam SmallMatInT Data type of \c lambda_values_in.
454  * \tparam SmallMatOutT Data type of \c lambda_values_out.
455  * \param lambda_values_in Local part of vector x.
456  * \param lambda_values_out Local part that will be added to A * x.
457  * \param hyper_edge The geometry of the considered hyperedge (of typename GeomT).
458  * \param time Time at which time step ends.
459  * \retval vecAx Local part of vector A * x.
460  ************************************************************************************************/
461  template <typename hyEdgeT, typename SmallMatInT, typename SmallMatOutT>
462  SmallMatOutT& trace_to_flux(const SmallMatInT& lambda_values_in,
463  SmallMatOutT& lambda_values_out,
464  hyEdgeT& hyper_edge,
465  const lSol_float_t time = 0.) const
466  {
467  hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
468  lambda_values_in.size() == 2 * hyEdge_dimT,
469  "Both matrices must be of same size which corresponds to the number of faces!");
470  for (unsigned int i = 0; i < lambda_values_in.size(); ++i)
471  hy_assert(
472  lambda_values_in[i].size() == lambda_values_out[i].size() &&
473  lambda_values_in[i].size() == n_glob_dofs_per_node(),
474  "Both matrices must be of same size which corresponds to the number of dofs per face!");
475 
476  using parameters = parametersT<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>;
477  std::array<lSol_float_t, n_loc_dofs_> coeffs =
478  solve_local_problem(lambda_values_in, 0U, hyper_edge, time);
479 
480  std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> primals(
481  primal_at_boundary(coeffs, hyper_edge)),
482  duals(dual_at_boundary(coeffs, hyper_edge));
483 
484  for (unsigned int i = 0; i < lambda_values_out.size(); ++i)
485  {
486  for (unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
487  lambda_values_out[i][j] =
488  duals[i][j] + tau_ * primals[i][j] -
489  tau_ * lambda_values_in[i][j < n_shape_bdr_ ? j + n_shape_bdr_ : j - n_shape_bdr_] *
490  hyper_edge.geometry.face_area(i);
491  if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
492  for (unsigned int j = 0; j < lambda_values_out[i].size() / 2; ++j)
493  lambda_values_out[i][j] = 0.;
494  if (is_dirichlet_laplacian<parameters>(hyper_edge.node_descriptor[i]))
495  for (unsigned int j = lambda_values_out[i].size() / 2; j < lambda_values_out[i].size(); ++j)
496  lambda_values_out[i][j] = 0.;
497  }
498 
499  return lambda_values_out;
500  }
501  /*!***********************************************************************************************
502  * \brief Evaluate local contribution to residual.
503  *
504  * Execute residual evaluation y = A * x - b, where x represents the vector containing the
505  * skeletal variable (adjacent to one hyperedge), and A is the condensed matrix arising from the
506  * HDG discretization. This function does this multiplication (locally) for one hyperedge. The
507  * hyperedge is no parameter, since all hyperedges are assumed to have the same properties.
508  *
509  * \tparam hyEdgeT The geometry type / typename of the considered hyEdge's geometry.
510  * \tparam SmallMatInT Data type of \c lambda_values_in.
511  * \tparam SmallMatOutT Data type of \c lambda_values_out.
512  * \param lambda_values_in Local part of vector x.
513  * \param lambda_values_out Local part that will be added to A * x.
514  * \param hyper_edge The geometry of the considered hyperedge (of typename GeomT).
515  * \param time Time at which time step ends.
516  * \retval vecAx Local part of vector A * x.
517  ************************************************************************************************/
518  template <class hyEdgeT, typename SmallMatInT, typename SmallMatOutT>
519  SmallMatOutT& residual_flux(const SmallMatInT& lambda_values_in,
520  SmallMatOutT& lambda_values_out,
521  hyEdgeT& hyper_edge,
522  const lSol_float_t time = 0.) const
523  {
524  hy_assert(lambda_values_in.size() == lambda_values_out.size() &&
525  lambda_values_in.size() == 2 * hyEdge_dimT,
526  "Both matrices must be of same size which corresponds to the number of faces!");
527  for (unsigned int i = 0; i < lambda_values_in.size(); ++i)
528  hy_assert(
529  lambda_values_in[i].size() == lambda_values_out[i].size() &&
530  lambda_values_in[i].size() == n_glob_dofs_per_node(),
531  "Both matrices must be of same size which corresponds to the number of dofs per face!");
532 
533  using parameters = parametersT<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>;
534  std::array<lSol_float_t, n_loc_dofs_> coeffs =
535  solve_local_problem(lambda_values_in, 1U, hyper_edge, time);
536 
537  std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> primals(
538  primal_at_boundary(coeffs, hyper_edge)),
539  duals(dual_at_boundary(coeffs, hyper_edge));
540 
541  for (unsigned int i = 0; i < lambda_values_out.size(); ++i)
542  {
543  for (unsigned int j = 0; j < lambda_values_out[i].size(); ++j)
544  lambda_values_out[i][j] = duals[i][j] + tau_ * primals[i][j] -
545  tau_ * lambda_values_in[i][j] * hyper_edge.geometry.face_area(i);
546  if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
547  for (unsigned int j = 0; j < lambda_values_out[i].size() / 2; ++j)
548  lambda_values_out[i][j] = 0.;
549  if (is_dirichlet_laplacian<parameters>(hyper_edge.node_descriptor[i]))
550  for (unsigned int j = lambda_values_out[i].size() / 2; j < lambda_values_out[i].size(); ++j)
551  lambda_values_out[i][j] = 0.;
552  }
553 
554  return lambda_values_out;
555  }
556  /*!***********************************************************************************************
557  * \brief Set data into data container to be used for next time step.
558  *
559  * \tparam hyEdgeT The geometry type / typename of the considered hyEdge's geometry.
560  * \param lambda_values Local part of vector x.
561  * \param hyper_edge The geometry of the considered hyperedge (of typename GeomT).
562  * \param time Time at which the old time step ended.
563  ************************************************************************************************/
564  template <class hyEdgeT>
565  void set_data(
566  const std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT>& lambda_values,
567  hyEdgeT& hyper_edge,
568  const lSol_float_t time = 0.) const
569  {
570  std::array<lSol_float_t, n_loc_dofs_> coeffs =
571  solve_local_problem(lambda_values, 1U, hyper_edge, time);
572 
573  hyper_edge.data.coeffs = coeffs;
574  }
575  /*!***********************************************************************************************
576  * \brief L2 project initial data to skeletal and fill data container.
577  *
578  * \tparam hyEdgeT The geometry type / typename of the considered hyEdge's geometry.
579  * \tparam SmallMatT The data type of the \c lambda_values.
580  * \param lambda_values Local part of vector x.
581  * \param hyper_edge The geometry of the considered hyperedge (of typename GeomT).
582  * \param time Initial time of parabolic problem.
583  * \retval vecAx L2 projected initial datum.
584  ************************************************************************************************/
585  template <class hyEdgeT, typename SmallMatT>
586  SmallMatT& make_initial(SmallMatT& lambda_values,
587  hyEdgeT& hyper_edge,
588  const lSol_float_t time = 0.) const
589  {
590  using parameters = parametersT<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>;
591 
592  for (unsigned int i = 0; i < lambda_values.size(); ++i)
593  {
594  if (is_dirichlet<parameters>(hyper_edge.node_descriptor[i]))
595  for (unsigned int j = 0; j < lambda_values[i].size(); ++j)
596  lambda_values[i][j] = 0.;
597  else
598  {
599  for (unsigned int j = 0; j < lambda_values[i].size() / 2; ++j)
600  lambda_values[i][j] = integrator::template integrate_bdrUni_psifunc<
601  Point<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>,
602  decltype(hyEdgeT::geometry), parameters::initial, Point<hyEdge_dimT, lSol_float_t>>(
603  i, j, hyper_edge.geometry, time);
604  for (unsigned int j = lambda_values[i].size() / 2; j < lambda_values[i].size(); ++j)
605  lambda_values[i][j] = integrator::template integrate_bdrUni_psifunc<
606  Point<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>,
607  decltype(hyEdgeT::geometry), parameters::initial_laplace,
608  Point<hyEdge_dimT, lSol_float_t>>(i, j, hyper_edge.geometry, time);
609  }
610  }
611 
612  for (unsigned int i = 0; i < n_shape_fct_; ++i)
613  hyper_edge.data.coeffs[hyEdge_dimT * n_shape_fct_ + i] =
614  integrator::template integrate_volUni_phifunc<
615  Point<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>,
616  decltype(hyEdgeT::geometry), parameters::initial, Point<hyEdge_dimT, lSol_float_t>>(
617  i, hyper_edge.geometry, time);
618 
619  return lambda_values;
620  }
621  /*!***********************************************************************************************
622  * \brief Evaluate squared local L2 error.
623  *
624  * \tparam hyEdgeT The geometry type / typename of the considered hyEdge's geometry.
625  * \tparam SmallMatT The typename of \c lambda_values.
626  * \param lambda_values The values of the skeletal variable's coefficients.
627  * \param hy_edge The geometry of the considered hyperedge (of typename GeomT).
628  * \param time Time at which error is evaluated.
629  * \retval err Local squared L2 error.
630  ************************************************************************************************/
631  template <class hyEdgeT, typename SmallMatT>
632  std::array<lSol_float_t, 1U> errors(SmallMatT& lambda_values,
633  hyEdgeT& hy_edge,
634  const lSol_float_t time = 0.) const
635  {
636  using parameters = parametersT<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>;
637 
638  for (unsigned int i = 0; i < lambda_values.size(); ++i)
639  for (unsigned int j = 0; j < lambda_values[i].size(); ++j)
640  hy_assert(lambda_values[i][j] == lambda_values[i][j],
641  "Lambda value wit index " << i << "," << j << " is NaN!");
642 
643  std::array<lSol_float_t, n_loc_dofs_> coefficients =
644  solve_local_problem(lambda_values, 1U, hy_edge, time);
645  std::array<lSol_float_t, n_shape_fct_> coeffs;
646  for (unsigned int i = 0; i < coeffs.size(); ++i)
647  coeffs[i] = coefficients[i + hyEdge_dimT * n_shape_fct_];
648 
649  for (unsigned int i = 0; i < coeffs.size(); ++i)
650  hy_assert(coeffs[i] == coeffs[i], "The " << i << "-th coeff is NaN!");
651 
652  lSol_float_t result = integrator::template integrate_vol_diffsquare_discana<
653  Point<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>, decltype(hyEdgeT::geometry),
654  parameters::analytic_result, Point<hyEdge_dimT, lSol_float_t>>(coeffs, hy_edge.geometry,
655  time);
656  hy_assert(result >= 0., "The squared error must be non-negative, but was " << result);
657  return std::array<lSol_float_t, 1U>({result});
658  }
659  /*!***********************************************************************************************
660  * \brief Evaluate local local reconstruction at tensorial products of abscissas.
661  *
662  * \tparam abscissa_float_t Floating type for the abscissa values.
663  * \tparam abscissas_sizeT Size of the array of array of abscissas.
664  * \tparam input_array_t Input array type.
665  * \tparam hyEdgeT The geometry type / typename of the considered hyEdge's geometry.
666  * \param abscissas Abscissas of the supporting points.
667  * \param lambda_values The values of the skeletal variable's coefficients.
668  * \param hyper_edge The geometry of the considered hyperedge (of typename GeomT).
669  * \param time Time at which function is plotted.
670  * \retval func_vals Array of function values.
671  ************************************************************************************************/
672  template <typename abscissa_float_t, std::size_t sizeT, class input_array_t, class hyEdgeT>
673  std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(sizeT)>, system_dim> bulk_values(
674  const std::array<abscissa_float_t, sizeT>& abscissas,
675  const input_array_t& lambda_values,
676  hyEdgeT& hyper_edge,
677  const lSol_float_t time = 0.) const;
678 
679 }; // end of class BilaplacianParab
680 
681 // -------------------------------------------------------------------------------------------------
683 // -------------------------------------------------------------------------------------------------
684 
685 // -------------------------------------------------------------------------------------------------
686 // -------------------------------------------------------------------------------------------------
687 //
688 // IMPLEMENTATION OF MEMBER FUNCTIONS OF BilaplacianParab
689 //
690 // -------------------------------------------------------------------------------------------------
691 // -------------------------------------------------------------------------------------------------
692 
693 // -------------------------------------------------------------------------------------------------
694 // assemble_loc_matrix
695 // -------------------------------------------------------------------------------------------------
696 
697 template <unsigned int hyEdge_dimT,
698  unsigned int poly_deg,
699  unsigned int quad_deg,
700  template <unsigned int, typename>
701  typename parametersT,
702  typename lSol_float_t>
703 template <typename hyEdgeT>
704 inline SmallSquareMat<
706  lSol_float_t>
708  const lSol_float_t tau,
709  hyEdgeT& hyper_edge,
710  const lSol_float_t time) const
711 {
712  using parameters = parametersT<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>;
713  constexpr unsigned int n_dofs_lap = n_loc_dofs_ / 2;
714 
716  lSol_float_t vol_integral, vol_func_integral, face_integral, helper;
717  SmallVec<hyEdge_dimT, lSol_float_t> grad_int_vec, normal_int_vec;
718 
719  for (unsigned int i = 0; i < n_shape_fct_; ++i)
720  {
721  for (unsigned int j = 0; j < n_shape_fct_; ++j)
722  {
723  // Integral_element phi_i phi_j dx in diagonal blocks
724  vol_integral = integrator::template integrate_vol_phiphi(i, j, hyper_edge.geometry);
725  vol_func_integral = integrator::template integrate_vol_phiphifunc<
726  Point<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>, decltype(hyEdgeT::geometry),
727  parameters::inverse_bilaplacian_coefficient, Point<hyEdge_dimT, lSol_float_t>>(
728  i, j, hyper_edge.geometry, time);
729  // Integral_element - nabla phi_i \vec phi_j dx
730  // = Integral_element - div \vec phi_i phi_j dx in right upper and left lower blocks
731  grad_int_vec =
732  integrator::template integrate_vol_nablaphiphi<SmallVec<hyEdge_dimT, lSol_float_t>,
733  decltype(hyEdgeT::geometry)>(
734  i, j, hyper_edge.geometry);
735 
736  face_integral = 0.;
737  normal_int_vec = 0.;
738  for (unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
739  {
740  helper = integrator::template integrate_bdr_phiphi<decltype(hyEdgeT::geometry)>(
741  i, j, face, hyper_edge.geometry);
742  face_integral += helper;
743  for (unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
744  normal_int_vec[dim] += hyper_edge.geometry.local_normal(face).operator[](dim) * helper;
745  }
746 
747  local_mat(hyEdge_dimT * n_shape_fct_ + i, n_dofs_lap + hyEdge_dimT * n_shape_fct_ + j) -=
748  vol_func_integral;
749 
750  local_mat(hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) +=
751  tau * face_integral;
752  local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
753  n_dofs_lap + hyEdge_dimT * n_shape_fct_ + j) +=
754  tau * theta_ * delta_t_ * face_integral;
755 
756  for (unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
757  {
758  local_mat(dim * n_shape_fct_ + i, dim * n_shape_fct_ + j) += vol_integral;
759  local_mat(n_dofs_lap + dim * n_shape_fct_ + i, n_dofs_lap + dim * n_shape_fct_ + j) +=
760  vol_integral;
761 
762  local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) -= grad_int_vec[dim];
763  local_mat(dim * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) -= grad_int_vec[dim];
764  local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
765  n_dofs_lap + dim * n_shape_fct_ + j) -= theta_ * delta_t_ * grad_int_vec[dim];
766  local_mat(n_dofs_lap + dim * n_shape_fct_ + i,
767  n_dofs_lap + hyEdge_dimT * n_shape_fct_ + j) -= grad_int_vec[dim];
768 
769  local_mat(hyEdge_dimT * n_shape_fct_ + i, dim * n_shape_fct_ + j) += normal_int_vec[dim];
770  local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i,
771  n_dofs_lap + dim * n_shape_fct_ + j) += theta_ * delta_t_ * normal_int_vec[dim];
772  }
773 
774  local_mat(n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i, hyEdge_dimT * n_shape_fct_ + j) +=
775  integrator::template integrate_vol_phiphi<decltype(hyEdgeT::geometry)>(i, j,
776  hyper_edge.geometry);
777  }
778  }
779 
780  return local_mat;
781 } // end of BilaplacianParab::assemble_loc_matrix
782 
783 // -------------------------------------------------------------------------------------------------
784 // assemble_rhs_from_lambda
785 // -------------------------------------------------------------------------------------------------
786 
787 template <unsigned int hyEdge_dimT,
788  unsigned int poly_deg,
789  unsigned int quad_deg,
790  template <unsigned int, typename>
791  typename parametersT,
792  typename lSol_float_t>
793 template <typename hyEdgeT, typename SmallMatT>
794 inline SmallVec<
796  lSol_float_t>
798  assemble_rhs_from_lambda(const SmallMatT& lambda_values, hyEdgeT& hyper_edge) const
799 {
800  constexpr unsigned int n_dofs_lap = n_loc_dofs_ / 2;
801  hy_assert(lambda_values.size() == 2 * hyEdge_dimT,
802  "The size of the lambda values should be twice the dimension of a hyperedge.");
803  for (unsigned int i = 0; i < 2 * hyEdge_dimT; ++i)
804  hy_assert(lambda_values[i].size() == 2 * n_shape_bdr_,
805  "The size of lambda should be the amount of ansatz functions at boundary.");
806 
807  SmallVec<n_loc_dofs_, lSol_float_t> right_hand_side;
808  lSol_float_t integral;
809 
810  for (unsigned int i = 0; i < n_shape_fct_; ++i)
811  for (unsigned int j = 0; j < n_shape_bdr_; ++j)
812  for (unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
813  {
814  integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
815  i, j, face, hyper_edge.geometry);
816  right_hand_side[hyEdge_dimT * n_shape_fct_ + i] += tau_ * lambda_values[face][j] * integral;
817  right_hand_side[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] +=
818  tau_ * theta_ * delta_t_ * lambda_values[face][n_shape_bdr_ + j] * integral;
819 
820  for (unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
821  {
822  right_hand_side[dim * n_shape_fct_ + i] -=
823  hyper_edge.geometry.local_normal(face).operator[](dim) * lambda_values[face][j] *
824  integral;
825  right_hand_side[n_dofs_lap + dim * n_shape_fct_ + i] -=
826  hyper_edge.geometry.local_normal(face).operator[](dim) *
827  lambda_values[face][n_shape_bdr_ + j] * integral;
828  }
829  }
830 
831  return right_hand_side;
832 } // end of BilaplacianParab::assemble_rhs_from_lambda
833 
834 // -------------------------------------------------------------------------------------------------
835 // assemble_rhs_from_global_rhs
836 // -------------------------------------------------------------------------------------------------
837 
838 template <unsigned int hyEdge_dimT,
839  unsigned int poly_deg,
840  unsigned int quad_deg,
841  template <unsigned int, typename>
842  typename parametersT,
843  typename lSol_float_t>
844 template <typename hyEdgeT>
845 inline SmallVec<
847  lSol_float_t>
849  assemble_rhs_from_global_rhs(hyEdgeT& hyper_edge, const lSol_float_t time) const
850 {
851  using parameters = parametersT<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>;
852  constexpr unsigned int n_dofs_lap = n_loc_dofs_ / 2;
853  SmallVec<n_loc_dofs_, lSol_float_t> right_hand_side;
854  lSol_float_t integral;
855  for (unsigned int i = 0; i < n_shape_fct_; ++i)
856  {
857  right_hand_side[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] =
858  theta_ * delta_t_ *
859  integrator::template integrate_vol_phifunc<
860  Point<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>,
861  decltype(hyEdgeT::geometry), parameters::right_hand_side,
862  Point<hyEdge_dimT, lSol_float_t>>(i, hyper_edge.geometry, time) +
863  (1 - theta_) * delta_t_ *
864  integrator::template integrate_vol_phifunc<
865  Point<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>,
866  decltype(hyEdgeT::geometry), parameters::right_hand_side,
867  Point<hyEdge_dimT, lSol_float_t>>(i, hyper_edge.geometry, time - delta_t_);
868 
869  // THIS HAS TO BE EXTENDED FOR THETA != 1
870 
871  for (unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
872  {
873  if (is_dirichlet<parameters>(hyper_edge.node_descriptor[face]))
874  {
875  integral = integrator::template integrate_bdr_phifunc<
876  Point<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>,
877  decltype(hyEdgeT::geometry), parameters::dirichlet_value,
878  Point<hyEdge_dimT, lSol_float_t>>(i, face, hyper_edge.geometry, time);
879  right_hand_side[hyEdge_dimT * n_shape_fct_ + i] += tau_ * integral;
880  for (unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
881  right_hand_side[dim * n_shape_fct_ + i] -=
882  hyper_edge.geometry.local_normal(face).operator[](dim) * integral;
883  }
884  if (is_dirichlet_laplacian<parameters>(hyper_edge.node_descriptor[face]))
885  {
886  integral = integrator::template integrate_bdr_phifunc<
887  Point<decltype(hyEdgeT::geometry)::space_dim(), lSol_float_t>,
888  decltype(hyEdgeT::geometry), parameters::dirichlet_laplace_value,
889  Point<hyEdge_dimT, lSol_float_t>>(i, face, hyper_edge.geometry, time);
890  right_hand_side[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] +=
891  tau_ * theta_ * delta_t_ * integral;
892  for (unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
893  right_hand_side[n_dofs_lap + dim * n_shape_fct_ + i] -=
894  hyper_edge.geometry.local_normal(face).operator[](dim) * integral;
895  }
896  }
897  }
898  return right_hand_side + assemble_rhs_from_coeffs(hyper_edge.data.coeffs, hyper_edge);
899 } // end of BilaplacianParab::assemble_rhs_from_global_rhs
900 
901 // -------------------------------------------------------------------------------------------------
902 // assemble_rhs_from_coeffs
903 // -------------------------------------------------------------------------------------------------
904 
905 template <unsigned int hyEdge_dimT,
906  unsigned int poly_deg,
907  unsigned int quad_deg,
908  template <unsigned int, typename>
909  typename parametersT,
910  typename lSol_float_t>
911 template <typename hyEdgeT>
912 inline SmallVec<
914  lSol_float_t>
917  const std::array<
918  lSol_float_t,
920  coeffs,
921  hyEdgeT& hyper_edge) const
922 {
923  SmallVec<n_loc_dofs_, lSol_float_t> right_hand_side;
924  for (unsigned int i = 0; i < n_shape_fct_; ++i)
925  for (unsigned int j = 0; j < n_shape_fct_; ++j)
926  {
927  right_hand_side[n_loc_dofs_ / 2 + hyEdge_dimT * n_shape_fct_ + i] +=
928  coeffs[hyEdge_dimT * n_shape_fct_ + j] *
929  integrator::template integrate_vol_phiphi(i, j, hyper_edge.geometry);
930  }
931 
932  return right_hand_side;
933 } // end of Diffusion::assemble_rhs_from_coeffs
934 
935 // -------------------------------------------------------------------------------------------------
936 // primal_at_boundary
937 // -------------------------------------------------------------------------------------------------
938 
939 template <unsigned int hyEdge_dimT,
940  unsigned int poly_deg,
941  unsigned int quad_deg,
942  template <unsigned int, typename>
943  typename parametersT,
944  typename lSol_float_t>
945 template <typename hyEdgeT>
946 inline std::array<
947  std::array<
948  lSol_float_t,
950  2 * hyEdge_dimT>
952  const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
953  hyEdgeT& hyper_edge) const
954 {
955  constexpr unsigned int n_dofs_lap = n_loc_dofs_ / 2;
956  std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> bdr_values;
957 
958  for (unsigned int dim_n = 0; dim_n < 2 * hyEdge_dimT; ++dim_n)
959  bdr_values[dim_n].fill(0.);
960 
961  for (unsigned int i = 0; i < n_shape_fct_; ++i)
962  for (unsigned int j = 0; j < n_shape_bdr_; ++j)
963  for (unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
964  {
965  bdr_values[face][n_shape_bdr_ + j] +=
966  coeffs[hyEdge_dimT * n_shape_fct_ + i] *
967  integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
968  i, j, face, hyper_edge.geometry);
969 
970  bdr_values[face][j] +=
971  coeffs[n_dofs_lap + hyEdge_dimT * n_shape_fct_ + i] *
972  integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
973  i, j, face, hyper_edge.geometry);
974  }
975 
976  return bdr_values;
977 } // end of BilaplacianParab::primal_at_boundary
978 
979 // -------------------------------------------------------------------------------------------------
980 // dual_at_boundary
981 // -------------------------------------------------------------------------------------------------
982 
983 template <unsigned int hyEdge_dimT,
984  unsigned int poly_deg,
985  unsigned int quad_deg,
986  template <unsigned int, typename>
987  typename parametersT,
988  typename lSol_float_t>
989 template <typename hyEdgeT>
990 inline std::array<
991  std::array<
992  lSol_float_t,
994  2 * hyEdge_dimT>
996  const std::array<lSol_float_t, n_loc_dofs_>& coeffs,
997  hyEdgeT& hyper_edge) const
998 {
999  constexpr unsigned int n_dofs_lap = n_loc_dofs_ / 2;
1000  std::array<std::array<lSol_float_t, 2 * n_shape_bdr_>, 2 * hyEdge_dimT> bdr_values;
1001  lSol_float_t integral;
1002 
1003  for (unsigned int dim_n = 0; dim_n < 2 * hyEdge_dimT; ++dim_n)
1004  bdr_values[dim_n].fill(0.);
1005 
1006  for (unsigned int i = 0; i < n_shape_fct_; ++i)
1007  for (unsigned int j = 0; j < n_shape_bdr_; ++j)
1008  for (unsigned int face = 0; face < 2 * hyEdge_dimT; ++face)
1009  {
1010  integral = integrator::template integrate_bdr_phipsi<decltype(hyEdgeT::geometry)>(
1011  i, j, face, hyper_edge.geometry);
1012  for (unsigned int dim = 0; dim < hyEdge_dimT; ++dim)
1013  {
1014  bdr_values[face][n_shape_bdr_ + j] +=
1015  hyper_edge.geometry.local_normal(face).operator[](dim) * integral *
1016  coeffs[dim * n_shape_fct_ + i];
1017 
1018  bdr_values[face][j] += hyper_edge.geometry.local_normal(face).operator[](dim) * integral *
1019  coeffs[n_dofs_lap + dim * n_shape_fct_ + i];
1020  }
1021  }
1022 
1023  return bdr_values;
1024 } // end of BilaplacianParab::dual_at_boundary
1025 
1026 // -------------------------------------------------------------------------------------------------
1027 // bulk_values
1028 // -------------------------------------------------------------------------------------------------
1029 
1030 template <unsigned int hyEdge_dimT,
1031  unsigned int poly_deg,
1032  unsigned int quad_deg,
1033  template <unsigned int, typename>
1034  typename parametersT,
1035  typename lSol_float_t>
1036 template <typename abscissa_float_t, std::size_t sizeT, class input_array_t, typename hyEdgeT>
1037 std::array<std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(sizeT)>,
1040  const std::array<abscissa_float_t, sizeT>& abscissas,
1041  const input_array_t& lambda_values,
1042  hyEdgeT& hyper_edge,
1043  const lSol_float_t time) const
1044 {
1046  solve_local_problem(lambda_values, 1U, hyper_edge, time);
1048  SmallVec<static_cast<unsigned int>(sizeT), abscissa_float_t> helper(abscissas);
1049 
1050  std::array<
1051  std::array<lSol_float_t, Hypercube<hyEdge_dimT>::pow(sizeT)>,
1053  point_vals;
1054 
1055  for (unsigned int d = 0; d < system_dim; ++d)
1056  {
1057  for (unsigned int i = 0; i < coeffs.size(); ++i)
1058  coeffs[i] = coefficients[d * n_shape_fct_ + i];
1059  for (unsigned int pt = 0; pt < Hypercube<hyEdge_dimT>::pow(sizeT); ++pt)
1060  point_vals[d][pt] = integrator::shape_fun_t::template lin_comb_fct_val<float>(
1061  coeffs, Hypercube<hyEdge_dimT>::template tensorial_pt<Point<hyEdge_dimT>>(pt, helper));
1062  }
1063 
1064  return point_vals;
1065 } // end of BilaplacianParab::bulk_values
1066 
1067 // -------------------------------------------------------------------------------------------------
1069 // -------------------------------------------------------------------------------------------------
1070 
1071 } // namespace LocalSolver
LocalSolver::BilaplacianParab::assemble_rhs_from_global_rhs
SmallVec< n_loc_dofs_, lSol_float_t > assemble_rhs_from_global_rhs(hyEdgeT &hyper_edge, const lSol_float_t time) const
Assemble local right-hand for the local solver (from global right-hand side).
LocalSolver::BilaplacianParab::data_type
Define type of (hyperedge related) data that is stored in HyDataContainer.
Definition: bilaplacian_parab_ldgh.hxx:381
LocalSolver::Bilaplacian_parameters_default::inverse_bilaplacian_coefficient
static param_float_t inverse_bilaplacian_coefficient(const Point< space_dimT, param_float_t > &, const param_float_t=0.)
Inverse bilaplacian coefficient in PDE as analytic function.
Definition: bilaplacian_parab_ldgh.hxx:41
shape_function.hxx
LocalSolver::Bilaplacian_parameters_default::dirichlet_laplacian_nodes
static constexpr std::array< unsigned int, 0U > dirichlet_laplacian_nodes
Array containing hypernode types corresponding to Dirichlet boundary of Laplacian.
Definition: bilaplacian_eigs_ldgh.hxx:29
LocalSolver::BilaplacianParab::error_def::postprocess_error
static error_t postprocess_error(error_t &summed_error)
Define how global errors should be postprocessed.
Definition: bilaplacian_parab_ldgh.hxx:424
LocalSolver::BilaplacianParab::assemble_rhs_from_lambda
SmallVec< n_loc_dofs_, lSol_float_t > assemble_rhs_from_lambda(const SmallMatT &lambda_values, hyEdgeT &hyper_edge) const
Assemble local right-hand for the local solver (from skeletal).
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
diffusion_uniform.geometry
geometry
Definition: diffusion_uniform.py:19
LocalSolver::Bilaplacian_parameters_default::dirichlet_nodes
static constexpr std::array< unsigned int, 0U > dirichlet_nodes
Array containing hypernode types corresponding to Dirichlet boundary.
Definition: bilaplacian_eigs_ldgh.hxx:25
LocalSolver::BilaplacianParab::error_def
Define how errors are evaluated.
Definition: bilaplacian_parab_ldgh.hxx:397
LocalSolver::BilaplacianParab::errors
std::array< lSol_float_t, 1U > errors(SmallMatT &lambda_values, hyEdgeT &hy_edge, const lSol_float_t time=0.) const
Evaluate squared local L2 error.
Definition: bilaplacian_parab_ldgh.hxx:632
LocalSolver::BilaplacianParab::assemble_rhs_from_coeffs
SmallVec< n_loc_dofs_, lSol_float_t > assemble_rhs_from_coeffs(const std::array< lSol_float_t, n_loc_dofs_ > &coeffs, hyEdgeT &hyper_edge) const
Assemble local right-hand for the local solver (from function coefficients).
LocalSolver::BilaplacianParab::system_dim
static constexpr unsigned int system_dim
Dimension of of the solution evaluated with respect to a hypernode.
Definition: bilaplacian_parab_ldgh.hxx:173
LocalSolver::Bilaplacian_parameters_default::neumann_laplacian_nodes
static constexpr std::array< unsigned int, 0U > neumann_laplacian_nodes
Array containing hypernode types corresponding to Neumann boundary of Laplacian.
Definition: bilaplacian_eigs_ldgh.hxx:37
TPP::Quadrature::GaussLegendre
Gauss–Legendre quadrature points and weights in one spatial dimension.
Definition: one_dimensional.hxx:19
LocalSolver::Bilaplacian_parameters_default::dirichlet_value
static param_float_t dirichlet_value(const Point< space_dimT, param_float_t > &, const param_float_t=0.)
Dirichlet values of solution as analytic function.
Definition: bilaplacian_parab_ldgh.hxx:57
SmallMat::size
static constexpr unsigned int size()
Return size a SmallMat.
Definition: dense_la.hxx:54
LocalSolver::Bilaplacian_parameters_default::neumann_nodes
static constexpr std::array< unsigned int, 0U > neumann_nodes
Array containing hypernode types corresponding to Neumann boundary.
Definition: bilaplacian_eigs_ldgh.hxx:33
LocalSolver::BilaplacianParab::node_system_dimension
static constexpr unsigned int node_system_dimension()
Dimension of of the solution evaluated with respect to a hypernode.
Definition: bilaplacian_parab_ldgh.hxx:149
LocalSolver::Bilaplacian_parameters_default::dirichlet_laplace_value
static param_float_t dirichlet_laplace_value(const Point< space_dimT, param_float_t > &, const param_float_t=0.)
Dirichlet values of solution's Laplacian as analytic function.
Definition: bilaplacian_parab_ldgh.hxx:65
LocalSolver::BilaplacianParab::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, hyEdgeT &hyper_edge) const
Evaluate primal variable at boundary.
TPP::ShapeType::Tensorial
Struct that handles the evaluation of tensorial shape functions.
Definition: tensorial.hxx:22
LocalSolver::BilaplacianParab::hyEdge_dim
static constexpr unsigned int hyEdge_dim()
Dimension of hyper edge type that this object solves on.
Definition: bilaplacian_parab_ldgh.hxx:129
LocalSolver::BilaplacianParab::make_initial
SmallMatT & make_initial(SmallMatT &lambda_values, hyEdgeT &hyper_edge, const lSol_float_t time=0.) const
L2 project initial data to skeletal and fill data container.
Definition: bilaplacian_parab_ldgh.hxx:586
TPP::ShapeFunction
Struct that handles different types of evaluation of shape functions.
Definition: shape_function.hxx:15
LocalSolver::BilaplacianParab::error_def::initial_error
static error_t initial_error()
Define how initial error is generated.
Definition: bilaplacian_parab_ldgh.hxx:406
LocalSolver::BilaplacianParab::trace_to_flux
SmallMatOutT & trace_to_flux(const SmallMatInT &lambda_values_in, SmallMatOutT &lambda_values_out, hyEdgeT &hyper_edge, const lSol_float_t time=0.) const
Evaluate local contribution to matrix–vector multiplication.
Definition: bilaplacian_parab_ldgh.hxx:462
LocalSolver::BilaplacianParab::system_dimension
static constexpr unsigned int system_dimension()
Dimension of of the solution evaluated with respect to a hyperedge.
Definition: bilaplacian_parab_ldgh.hxx:145
TPP::Quadrature::Tensorial
General integrator class on tensorial hypergraphs.
Definition: tensorial.hxx:24
LocalSolver::BilaplacianParab::error_def::error_t
std::array< lSol_float_t, 1U > error_t
Define the typename returned by function errors.
Definition: bilaplacian_parab_ldgh.hxx:402
LocalSolver::BilaplacianParab::theta_
const lSol_float_t theta_
Parameter theta that defines the one-step theta scheme.
Definition: bilaplacian_parab_ldgh.hxx:208
LocalSolver::BilaplacianParab::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, hyEdgeT &hyper_edge, const lSol_float_t time=0.) const
Evaluate local local reconstruction at tensorial products of abscissas.
SmallMat::data
std::array< mat_entry_t, size()> & data()
Return data array that allows to manipulate the SmallMat.
Definition: dense_la.hxx:190
LocalSolver::BilaplacianParab::assemble_loc_matrix
SmallSquareMat< n_loc_dofs_, lSol_float_t > assemble_loc_matrix(const lSol_float_t tau, hyEdgeT &hyper_edge, const lSol_float_t time) const
Assemble local matrix for the local solver.
LocalSolver::BilaplacianParab::tau_
const lSol_float_t tau_
(Globally constant) penalty parameter for HDG scheme.
Definition: bilaplacian_parab_ldgh.hxx:204
hypercube.hxx
LocalSolver::BilaplacianParab::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_parab_ldgh.hxx:415
LocalSolver::BilaplacianParab::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_parab_ldgh.hxx:138
Wrapper::LAPACKexception
Exception to be thrown if LAPACK's solve fails.
Definition: lapack.hxx:25
LocalSolver::BilaplacianParab::delta_t_
const lSol_float_t delta_t_
Time step size.
Definition: bilaplacian_parab_ldgh.hxx:212
LocalSolver::BilaplacianParab::constructor_value_type
std::vector< lSol_float_t > constructor_value_type
Class is constructed using a single double indicating the penalty parameter.
Definition: bilaplacian_parab_ldgh.hxx:434
LocalSolver::BilaplacianParab::data_type::coeffs
std::array< lSol_float_t, n_loc_dofs_ > coeffs
Definition: bilaplacian_parab_ldgh.hxx:383
Hypercube::pow
static constexpr unsigned int pow(unsigned int base)
Return n to the power dim.
Definition: hypercube.hxx:25
LocalSolver::Bilaplacian_parameters_default::analytic_result
static param_float_t analytic_result(const Point< space_dimT, param_float_t > &, const param_float_t=0.)
Analytic result of PDE (for convergence tests).
Definition: bilaplacian_parab_ldgh.hxx:89
LocalSolver::BilaplacianParab::is_dirichlet_laplacian
static constexpr bool is_dirichlet_laplacian(const unsigned int node_type)
Definition: bilaplacian_parab_ldgh.hxx:190
LocalSolver::BilaplacianParab::residual_flux
SmallMatOutT & residual_flux(const SmallMatInT &lambda_values_in, SmallMatOutT &lambda_values_out, hyEdgeT &hyper_edge, const lSol_float_t time=0.) const
Evaluate local contribution to residual.
Definition: bilaplacian_parab_ldgh.hxx:519
LocalSolver::BilaplacianParab::BilaplacianParab
BilaplacianParab(const constructor_value_type &constru=std::vector(3, 1.))
Constructor for local solver.
Definition: bilaplacian_parab_ldgh.hxx:440
parameters
the intent is to exercise the right to control the distribution of derivative or collective works based on the Library In mere aggregation of another work not based on the Library with the you must alter all the notices that refer to this so that they refer to the ordinary GNU General Public instead of to this it is irreversible for that so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy This option is useful when you wish to copy part of the code of the Library into a program that is not a library You may copy and distribute the which must be distributed under the terms of Sections and above on a medium customarily used for software interchange If distribution of object code is made by offering access to copy from a designated then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source even though third parties are not compelled to copy the source along with the object code A program that contains no derivative of any portion of the but is designed to work with the Library by being compiled or linked with is called a work that uses the Library Such a in is not a derivative work of the and therefore falls outside the scope of this License linking a work that uses the Library with the Library creates an executable that is a derivative of the rather than a work that uses the library The executable is therefore covered by this License Section states terms for distribution of such executables When a work that uses the Library uses material from a header file that is part of the the object code for the work may be a derivative work of the Library even though the source code is not Whether this is true is especially significant if the work can be linked without the or if the work is itself a library The threshold for this to be true is not precisely defined by law If such an object file uses only numerical parameters
Definition: License.txt:259
LocalSolver::Bilaplacian_parameters_default::neumann_laplace_value
static param_float_t neumann_laplace_value(const Point< space_dimT, param_float_t > &, const param_float_t=0.)
Neumann values of solution's Laplacian as analytic function.
Definition: bilaplacian_parab_ldgh.hxx:81
LocalSolver::BilaplacianParab::node_element
Define type of node elements, especially with respect to nodal shape functions.
Definition: bilaplacian_parab_ldgh.hxx:388
hy_assert
#define hy_assert(Expr, Msg)
The assertion to be used within HyperHDG — deactivate using -DNDEBUG compile flag.
Definition: hy_assert.hxx:38
LocalSolver::BilaplacianParab::n_loc_dofs_
static constexpr unsigned int n_loc_dofs_
Number of (local) degrees of freedom per hyperedge.
Definition: bilaplacian_parab_ldgh.hxx:167
dense_la.hxx
LocalSolver::BilaplacianParab::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_parab_ldgh.hxx:220
LocalSolver::BilaplacianParab
Local solver for bilaplacian equation on uniform hypergraph.
Definition: bilaplacian_parab_ldgh.hxx:119
LocalSolver::BilaplacianParab::node_element::functions
std::tuple< TPP::ShapeFunction< TPP::ShapeType::Tensorial< TPP::ShapeType::Legendre< poly_deg >, hyEdge_dimT - 1 > > > functions
Definition: bilaplacian_parab_ldgh.hxx:392
LocalSolver::BilaplacianParab::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, n_loc_dofs_ > &coeffs, hyEdgeT &hyper_edge) const
Evaluate dual variable at boundary.
LocalSolver::BilaplacianParab::solve_local_problem
std::array< lSol_float_t, n_loc_dofs_ > solve_local_problem(const SmallMatT &lambda_values, const unsigned int solution_type, hyEdgeT &hyper_edge, const lSol_float_t time) const
Solve local problem (with right-hand side from skeletal).
Definition: bilaplacian_parab_ldgh.hxx:318
LocalSolver::Bilaplacian_parameters_default::neumann_value
static param_float_t neumann_value(const Point< space_dimT, param_float_t > &, const param_float_t=0.)
Neumann values of solution as analytic function.
Definition: bilaplacian_parab_ldgh.hxx:73
LocalSolver::BilaplacianParab::node_system_dim
static constexpr unsigned int node_system_dim
Dimension of of the solution evaluated with respect to a hypernode.
Definition: bilaplacian_parab_ldgh.hxx:179
LocalSolver::BilaplacianParab::n_shape_fct_
static constexpr unsigned int n_shape_fct_
Number of local shape functions (with respect to all spatial dimensions).
Definition: bilaplacian_parab_ldgh.hxx:159
LocalSolver::Bilaplacian_parameters_default::right_hand_side
static param_float_t right_hand_side(const Point< space_dimT, param_float_t > &, const param_float_t=0.)
Right-hand side in PDE as analytic function.
Definition: bilaplacian_parab_ldgh.hxx:49
LocalSolver::BilaplacianParab::n_shape_bdr_
static constexpr unsigned int n_shape_bdr_
Number oflocal shape functions (with respect to a face / hypernode).
Definition: bilaplacian_parab_ldgh.hxx:163
SmallMat
This class implements a small/dense matrix.
Definition: dense_la.hxx:34
LocalSolver::BilaplacianParab::set_data
void set_data(const std::array< std::array< lSol_float_t, 2 *n_shape_bdr_ >, 2 *hyEdge_dimT > &lambda_values, hyEdgeT &hyper_edge, const lSol_float_t time=0.) const
Set data into data container to be used for next time step.
Definition: bilaplacian_parab_ldgh.hxx:565
LocalSolver::BilaplacianParab::is_dirichlet
static constexpr bool is_dirichlet(const unsigned int node_type)
Find out whether a node is of Dirichlet type.
Definition: bilaplacian_parab_ldgh.hxx:184
Hypercube
Helper class containing numbers and functions related to hypercubes.
Definition: hypercube.hxx:12