HyperHDG
elliptic.hxx
Go to the documentation of this file.
1 #pragma once // Ensure that file is included only once in a single compilation.
2 
6 #include <HyperHDG/hy_assert.hxx>
7 #include <HyperHDG/plot.hxx>
8 
9 #include <algorithm>
10 #include <array>
11 #include <cmath>
12 #include <vector>
13 
14 namespace GlobalLoop
15 {
16 /*!*************************************************************************************************
17  * \brief Combine local solver and global information for elliptic problems.
18  *
19  * \tparam TopologyT Class type containing topological information.
20  * \tparam GeometryT Class type containing geometrical information.
21  * \tparam NodeDescriptorT Class type containing the information of nodes of hyperedges.
22  * \tparam LocalSolverT Class type of the local solver.
23  * \tparam LargeVecT Clas type of large, global vector.
24  * \tparam dof_index_t Index type of hyperedges. Default is \c unsigned \c int.
25  *
26  * \authors Guido Kanschat, Heidelberg University, 2019--2020.
27  * \authors Andreas Rupp, Heidelberg University, 2019--2020.
28  **************************************************************************************************/
29 template <class TopologyT,
30  class GeometryT,
31  class NodeDescriptorT,
32  class LocalSolverT,
33  typename LargeVecT = std::vector<double>,
34  typename dof_index_t = unsigned int>
35 class Elliptic
36 {
37  private:
38  /*!***********************************************************************************************
39  * \brief Prepare struct to check for function to exist (cf. compile_time_tricks.hxx).
40  ************************************************************************************************/
41  HAS_MEMBER_FUNCTION(trace_to_flux, has_trace_to_flux);
42  /*!***********************************************************************************************
43  * \brief Prepare struct to check for function to exist (cf. compile_time_tricks.hxx).
44  ************************************************************************************************/
45  HAS_MEMBER_FUNCTION(residual_flux, has_residual_flux);
46  /*!***********************************************************************************************
47  * \brief Prepare struct to check for function to exist (cf. compile_time_tricks.hxx).
48  ************************************************************************************************/
49  HAS_MEMBER_FUNCTION(errors, has_errors);
50  /*!***********************************************************************************************
51  * \brief Some constant variable that might be helpful.
52  ************************************************************************************************/
53  static constexpr unsigned int hyEdge_dim = TopologyT::hyEdge_dim();
54  /*!***********************************************************************************************
55  * \brief Some constant variable that might be helpful.
56  ************************************************************************************************/
57  static constexpr unsigned int n_dofs_per_node = LocalSolverT::n_glob_dofs_per_node();
58 
59  /*!***********************************************************************************************
60  * \brief Floating type is determined by floating type of large vector's entries.
61  ************************************************************************************************/
62  using dof_value_t = typename LargeVecT::value_type;
63  /*!***********************************************************************************************
64  * \brief Instantiation of a hypergraph.
65  ************************************************************************************************/
66  HDGHyperGraph<LocalSolverT::n_glob_dofs_per_node(),
67  TopologyT,
68  GeometryT,
69  NodeDescriptorT,
70  typename LocalSolverT::data_type>
72  /*!***********************************************************************************************
73  * \brief Vector containing the indices of Dirichlet type nodes.
74  ************************************************************************************************/
75  std::vector<dof_index_t> dirichlet_indices_;
76  /*!***********************************************************************************************
77  * \brief Instantiation of a local solver.
78  ************************************************************************************************/
79  const LocalSolverT local_solver_;
80  /*!***********************************************************************************************
81  * \brief Struct encoding the options for plotting.
82  ************************************************************************************************/
84 
85  public:
86  /*!***********************************************************************************************
87  * \brief Abstract problem constructor.
88  *
89  * Constructor for class containing a HyperGraph and a local solver that solve a PDE on a
90  * hyperedge.
91  *
92  * \param construct_topo Information to construct a topology.
93  * \param construct_geom Information to construct a geometry.
94  * \param construct_loc_sol Information to construct a local solver.
95  ************************************************************************************************/
96  Elliptic(const typename TopologyT::constructor_value_type& construct_topo,
97  const typename GeometryT::constructor_value_type& construct_geom,
98  const typename LocalSolverT::constructor_value_type& construct_loc_sol)
99  : hyper_graph_(construct_topo, construct_geom), local_solver_(construct_loc_sol)
100  {
101  static_assert(TopologyT::hyEdge_dim() == GeometryT::hyEdge_dim(),
102  "Hyperedge dimension of topology and geometry must be equal!");
103  static_assert(TopologyT::space_dim() == GeometryT::space_dim(),
104  "Space dimension of topology and geometry must be equal!");
105  static_assert(TopologyT::hyEdge_dim() == LocalSolverT::hyEdge_dim(),
106  "Hyperedge dimension of hypergraph and local solver must be equal!");
107  }
108  /*!***********************************************************************************************
109  * \brief Abstract problem constructor.
110  *
111  * Constructor for class containing a HyperGraph and a local solver that solve a PDE on a
112  * hyperedge.
113  *
114  * \param construct_topo Information to construct a topology.
115  * \param construct_loc_sol Information to construct a local solver.
116  ************************************************************************************************/
117  Elliptic(const typename TopologyT::constructor_value_type& construct_topo,
118  const typename LocalSolverT::constructor_value_type& construct_loc_sol)
119  : hyper_graph_(construct_topo), local_solver_(construct_loc_sol)
120  {
121  static_assert(TopologyT::hyEdge_dim() == GeometryT::hyEdge_dim(),
122  "Hyperedge dimension of topology and geometry must be equal!");
123  static_assert(TopologyT::space_dim() == GeometryT::space_dim(),
124  "Space dimension of topology and geometry must be equal!");
125  static_assert(TopologyT::hyEdge_dim() == LocalSolverT::hyEdge_dim(),
126  "Hyperedge dimension of hypergraph and local solver must be equal!");
127  }
128  /*!***********************************************************************************************
129  * \brief Abstract problem constructor.
130  *
131  * Constructor for class containing a HyperGraph and a local solver that solve a PDE on a
132  * hyperedge.
133  *
134  * \param construct_topo Information to construct a topology.
135  ************************************************************************************************/
136  Elliptic(const typename TopologyT::constructor_value_type& construct_topo)
137  : hyper_graph_(construct_topo)
138  {
139  static_assert(TopologyT::hyEdge_dim() == GeometryT::hyEdge_dim(),
140  "Hyperedge dimension of topology and geometry must be equal!");
141  static_assert(TopologyT::space_dim() == GeometryT::space_dim(),
142  "Space dimension of topology and geometry must be equal!");
143  static_assert(TopologyT::hyEdge_dim() == LocalSolverT::hyEdge_dim(),
144  "Hyperedge dimension of hypergraph and local solver must be equal!");
145  }
146  /*!***********************************************************************************************
147  * \brief Read indices of Dirichlet type hypernodes/faces.
148  *
149  * Read the indices ot the hypernodes/faces that are of Dirichlet type and therefore do not
150  * contain degrees of freedom that are allowed to change within iterations of the iterative
151  * solver and other processes. In contrast, these degrees of freedom are set by the user.
152  *
153  * The user creates a vector that contains the coefficients of the corresponding degrees of
154  * freedom (read by this function) and defines the Dirichlet values by this choice. The
155  * remaining elements of the global vector of unknowns (which is \b not the vector \c indices
156  * are supposed to be zero).
157  *
158  * \param indices A vector containing the (global) indices of Dirichlet type hypernodes.
159  ************************************************************************************************/
160  void read_dirichlet_indices(const std::vector<unsigned int>& indices)
161  {
162  dirichlet_indices_.resize(indices.size());
163  for (unsigned int i = 0; i < indices.size(); ++i)
164  {
165  hy_assert(
166  (dof_index_t)indices[i] >= 0 && (dof_index_t)indices[i] < hyper_graph_.n_global_dofs(),
167  "All indices of Dirichlet nodes need to be larger than or equal to zero and "
168  << "smaller than the total amount of degrees of freedom." << std::endl
169  << "In this case, the index is " << indices[i] << " and the total amount of "
170  << "hypernodes is " << hyper_graph_.n_global_dofs() << ".");
171  dirichlet_indices_[i] = (dof_index_t)indices[i];
172  }
173  std::sort(dirichlet_indices_.begin(), dirichlet_indices_.end());
174  auto last = std::unique(dirichlet_indices_.begin(), dirichlet_indices_.end());
175  dirichlet_indices_.erase(last, dirichlet_indices_.end());
176  }
177  /*!***********************************************************************************************
178  * \brief Returns vector of appropriate size for the predefined problem.
179  *
180  * Returns a vector containing only the value zero, but of the size \f$n\f$ which is also the
181  * number which is returned if \c size_of_system() is evaluated.
182  *
183  * \retval zero A vector of the correct size for the unknowns of the given problem.
184  ************************************************************************************************/
185  LargeVecT zero_vector() const { return LargeVecT(hyper_graph_.n_global_dofs(), 0.); }
186  /*!***********************************************************************************************
187  * \brief Evaluate condensed matrix-vector product.
188  *
189  * Function that evaluates the condensed, matrix-free version of the matrix-vector product
190  * \f$A x = y\f$, where \f$A\f$ is the condensed matrix of the LDG-H method, \f$x\f$ is the
191  * vector of parameters to define the skeletal variable \f$\lambda\f$, and \f$y\f$ is the
192  * resulting vector, which has the same size as the input vector \f$x\f$.
193  *
194  * \tparam hyNode_index_t Typename of the hypernode index. Defaults to \c unsigned \c int.
195  * \param x_vec A vector containing the input vector \f$x\f$.
196  * \param time Time at which given analyitic functions will be evaluated.
197  * \retval y_vec A vector containing the product \f$y = Ax\f$.
198  ************************************************************************************************/
199  template <typename hyNode_index_t = dof_index_t>
200  LargeVecT trace_to_flux(const LargeVecT& x_vec, const dof_value_t time = 0.)
201  {
202  auto vec_Ax = prototype_mat_vec_multiply(trace_to_flux, has_trace_to_flux);
203 
204  // Set all Dirichlet values to zero.
205  for (dof_index_t i = 0; i < dirichlet_indices_.size(); ++i)
206  {
208  "All indices of Dirichlet nodes need to be larger than or equal to zero and "
209  << "smaller than the total amount of degrees of freedom." << std::endl
210  << "In this case, the index is " << dirichlet_indices_[i] << " and the total "
211  << "amount of hypernodes is " << hyper_graph_.n_global_dofs() << ".");
212  vec_Ax[dirichlet_indices_[i]] = 0.;
213  }
214 
215  return vec_Ax;
216  }
217  /*!***********************************************************************************************
218  * \brief Evaluate condensed matrix-vector product containing data.
219  *
220  * Function that evaluates the condensed, matrix-free version of the matrix-vector product
221  * \f$A x - f = y\f$, where \f$A\f$ is the condensed matrix of the LDG-H method, \f$x\f$ is the
222  * vector of parameters to define the skeletal variable \f$\lambda\f$, \f$f\f$ is the right-hand
223  * side of the problem and \f$y\f$ is the resulting vector, which has the same size as the input
224  * vector \f$x\f$.
225  *
226  * \tparam hyNode_index_t Typename of the hypernode index. Defaults to \c unsigned \c int.
227  * \param x_vec A vector containing the input vector \f$x\f$.
228  * \param time Time at which analytical functions will be evaluated.
229  * \retval y_vec A vector containing the product \f$y = Ax\f$.
230  ************************************************************************************************/
231  template <typename hyNode_index_t = dof_index_t>
232  LargeVecT residual_flux(const LargeVecT& x_vec, const dof_value_t time = 0.)
233  {
234  auto vec_Ax = prototype_mat_vec_multiply(residual_flux, has_residual_flux);
235 
236  // Set all Dirichlet values to zero.
237  for (dof_index_t i = 0; i < dirichlet_indices_.size(); ++i)
238  {
240  "All indices of Dirichlet nodes need to be larger than or equal to zero and "
241  << "smaller than the total amount of degrees of freedom." << std::endl
242  << "In this case, the index is " << dirichlet_indices_[i] << " and the total "
243  << "amount of hypernodes is " << hyper_graph_.n_global_dofs() << ".");
244  vec_Ax[dirichlet_indices_[i]] = 0.;
245  }
246 
247  return vec_Ax;
248  }
249  /*!***********************************************************************************************
250  * \brief Calculate L2 error of approximated function.
251  *
252  * \tparam hyNode_index_t Typename of the hypernode index. Defaults to \c unsigned \c int.
253  * \param x_vec A vector containing the input vector \f$x\f$.
254  * \param time Time at which analytical functions will be evaluated.
255  * \retval error A vector containing the errors.
256  ************************************************************************************************/
257  template <typename hyNode_index_t = dof_index_t>
258  std::vector<dof_value_t> errors(const LargeVecT& x_vec, const dof_value_t time = 0.)
259  {
260  auto result = prototype_errors(errors, has_errors);
261  return std::vector<dof_value_t>(result.begin(), result.end());
262  }
263  /*!***********************************************************************************************
264  * \brief Determine size of condensed system for the skeletal unknowns.
265  *
266  * Function that returns the size \f$n\f$ of the \f$n \times n\f$ linear, sparse system
267  * \f$Ax = b\f$ that is solved by the program in a matrix-free fashion.
268  *
269  * This function is needed to define a \c LinearOperator from Python's \c scipy.sparse.linalg
270  * package which can be used to define iterative solvers for sparse systems.
271  *
272  * \retval n Size of the condensed (square) system of equations.
273  ************************************************************************************************/
274  dof_index_t size_of_system() const { return hyper_graph_.n_global_dofs(); }
275  /*!***********************************************************************************************
276  * \brief Set plot option and return old plot option.
277  *
278  * Function to set and / or read the current plot option.
279  *
280  * \param option A \c std::string containing the plot option to be considered.
281  * \param value A \c std::string containing the new value of the considered option.
282  * If empty, the old value is kept.
283  * \retval opt_value A \c std::string containing the value of the plot option.
284  ************************************************************************************************/
285  std::string plot_option(const std::string& option, std::string value = "")
286  {
287  return set_plot_option(plot_options, option, value);
288  }
289  /*!***********************************************************************************************
290  * \brief Plot solution in vtu format.
291  *
292  * Function that plots the solution of the problem to a predefined file.
293  *
294  * \param lambda A vector of unknowns containing the data vector.
295  * \param time Time at which analytical functions are evaluated.
296  * \retval file A file in the output directory.
297  ************************************************************************************************/
298  void plot_solution(const LargeVecT& lambda, const dof_value_t time = 0.)
299  {
300  plot(hyper_graph_, local_solver_, lambda, plot_options, time);
301  }
302  /*!***********************************************************************************************
303  * \brief Return refinement level.
304  ************************************************************************************************/
305  unsigned int get_refinement() { return hyper_graph_.get_refinement(); }
306  /*!***********************************************************************************************
307  * \brief Set refinement level.
308  ************************************************************************************************/
309  void set_refinement(unsigned int level) { hyper_graph_.set_refinement(level); }
310 }; // end of class Elliptic
311 
312 } // end of namespace GlobalLoop
GlobalLoop::Elliptic::set_refinement
void set_refinement(unsigned int level)
Set refinement level.
Definition: elliptic.hxx:309
compile_time_tricks.hxx
hy_assert.hxx
This file provides the function hy_assert.
HDGHyperGraph::n_global_dofs
const dof_index_t n_global_dofs() const
Returns the total amount of degrees of freedom in the considered hypergraph.
Definition: hdg_hypergraph.hxx:514
HDGHyperGraph::get_refinement
unsigned int get_refinement() const
Return the refinement level of the hypergraph.
Definition: hdg_hypergraph.hxx:521
plot.hxx
HDGHyperGraph::set_refinement
void set_refinement(unsigned int level)
Set the refinement level of the hypergraph.
Definition: hdg_hypergraph.hxx:525
GlobalLoop::Elliptic::hyper_graph_
HDGHyperGraph< LocalSolverT::n_glob_dofs_per_node(), TopologyT, GeometryT, NodeDescriptorT, typename LocalSolverT::data_type > hyper_graph_
Instantiation of a hypergraph.
Definition: elliptic.hxx:71
GlobalLoop::Elliptic::plot_option
std::string plot_option(const std::string &option, std::string value="")
Set plot option and return old plot option.
Definition: elliptic.hxx:285
prototype_errors
#define prototype_errors(fun_name, has_fun_name)
Macro that allows to use an implemented error evaluation.
Definition: prototype.hxx:71
PlotOptions
A class storing options for plotting.
Definition: plot.hxx:20
GlobalLoop::Elliptic::get_refinement
unsigned int get_refinement()
Return refinement level.
Definition: elliptic.hxx:305
HDGHyperGraph
The class template uniting topology and geometry of a hypergraph with the topology of the skeleton sp...
Definition: hdg_hypergraph.hxx:51
GlobalLoop::Elliptic::zero_vector
LargeVecT zero_vector() const
Returns vector of appropriate size for the predefined problem.
Definition: elliptic.hxx:185
GlobalLoop::Elliptic::Elliptic
Elliptic(const typename TopologyT::constructor_value_type &construct_topo)
Abstract problem constructor.
Definition: elliptic.hxx:136
GlobalLoop::Elliptic::dof_value_t
typename LargeVecT::value_type dof_value_t
Floating type is determined by floating type of large vector's entries.
Definition: elliptic.hxx:62
GlobalLoop::Elliptic::dirichlet_indices_
std::vector< dof_index_t > dirichlet_indices_
Vector containing the indices of Dirichlet type nodes.
Definition: elliptic.hxx:75
GlobalLoop::Elliptic::trace_to_flux
LargeVecT trace_to_flux(const LargeVecT &x_vec, const dof_value_t time=0.)
Evaluate condensed matrix-vector product.
Definition: elliptic.hxx:200
GlobalLoop::Elliptic::Elliptic
Elliptic(const typename TopologyT::constructor_value_type &construct_topo, const typename LocalSolverT::constructor_value_type &construct_loc_sol)
Abstract problem constructor.
Definition: elliptic.hxx:117
GlobalLoop::Elliptic::local_solver_
const LocalSolverT local_solver_
Instantiation of a local solver.
Definition: elliptic.hxx:79
GlobalLoop::Elliptic::HAS_MEMBER_FUNCTION
HAS_MEMBER_FUNCTION(trace_to_flux, has_trace_to_flux)
Prepare struct to check for function to exist (cf. compile_time_tricks.hxx).
GlobalLoop::Elliptic::size_of_system
dof_index_t size_of_system() const
Determine size of condensed system for the skeletal unknowns.
Definition: elliptic.hxx:274
prototype.hxx
GlobalLoop::Elliptic::plot_options
PlotOptions plot_options
Struct encoding the options for plotting.
Definition: elliptic.hxx:83
plot
void plot(HyperGraphT &hyper_graph, const LocalSolverT &local_solver, const LargeVecT &lambda, PlotOptions &plot_options, const floatT time=0.)
Function plotting the solution of an equation on a hypergraph in vtu format.
Definition: plot.hxx:778
GlobalLoop::Elliptic::read_dirichlet_indices
void read_dirichlet_indices(const std::vector< unsigned int > &indices)
Read indices of Dirichlet type hypernodes/faces.
Definition: elliptic.hxx:160
hy_assert
#define hy_assert(Expr, Msg)
The assertion to be used within HyperHDG — deactivate using -DNDEBUG compile flag.
Definition: hy_assert.hxx:38
GlobalLoop::Elliptic::residual_flux
LargeVecT residual_flux(const LargeVecT &x_vec, const dof_value_t time=0.)
Evaluate condensed matrix-vector product containing data.
Definition: elliptic.hxx:232
GlobalLoop::Elliptic::Elliptic
Elliptic(const typename TopologyT::constructor_value_type &construct_topo, const typename GeometryT::constructor_value_type &construct_geom, const typename LocalSolverT::constructor_value_type &construct_loc_sol)
Abstract problem constructor.
Definition: elliptic.hxx:96
GlobalLoop::Elliptic::n_dofs_per_node
static constexpr unsigned int n_dofs_per_node
Some constant variable that might be helpful.
Definition: elliptic.hxx:57
set_plot_option
std::string set_plot_option(PlotOptions &plot_options, const std::string &option, std::string value="")
Set a plot option and return the new value of this option as std::string.
Definition: plot.hxx:122
hdg_hypergraph.hxx
GlobalLoop::Elliptic::plot_solution
void plot_solution(const LargeVecT &lambda, const dof_value_t time=0.)
Plot solution in vtu format.
Definition: elliptic.hxx:298
prototype_mat_vec_multiply
#define prototype_mat_vec_multiply(fun_name, has_fun_name)
Macro that allows to use an implemented a matrix–vector multpilication.
Definition: prototype.hxx:18
GlobalLoop::Elliptic
Combine local solver and global information for elliptic problems.
Definition: elliptic.hxx:35
GlobalLoop
A namespace for global loops.
Definition: elliptic.hxx:14
GlobalLoop::Elliptic::hyEdge_dim
static constexpr unsigned int hyEdge_dim
Some constant variable that might be helpful.
Definition: elliptic.hxx:53
GlobalLoop::Elliptic::errors
std::vector< dof_value_t > errors(const LargeVecT &x_vec, const dof_value_t time=0.)
Calculate L2 error of approximated function.
Definition: elliptic.hxx:258