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