HyperHDG
shifted_inverse_eigenvalue.hxx
Go to the documentation of this file.
1 #pragma once // Ensure that file is included only once in a single compilation.
2 
5 #include <HyperHDG/hy_assert.hxx>
6 #include <HyperHDG/plot.hxx>
7 #include <algorithm>
8 #include <array>
9 #include <cmath>
10 
11 namespace GlobalLoop
12 {
13 /*!*************************************************************************************************
14  * \brief Combine local solver and global information for eigenvalue problems with shifted inverse
15  * approach.
16  *
17  * \tparam TopologyT Class type containing topological information.
18  * \tparam GeometryT Class type containing geometrical information.
19  * \tparam NodeDescriptorT Class type containing the information of nodes of hyperedges.
20  * \tparam LocalSolverT Class type of the local solver.
21  * \tparam LargeVecT Clas type of large, global vector.
22  * \tparam dof_index_t Index type of hyperedges. Default is \c unsigned \c int.
23  *
24  * \authors Guido Kanschat, Heidelberg University, 2019--2020.
25  * \authors Andreas Rupp, Heidelberg University, 2019--2020.
26  **************************************************************************************************/
27 template <class TopologyT,
28  class GeometryT,
29  class NodeDescriptorT,
30  class LocalSolverT,
31  typename LargeVecT = std::vector<double>,
32  typename dof_index_t = unsigned int>
34 {
35  /*!***********************************************************************************************
36  * \brief Prepare struct to check for function to exist (cf. compile_time_tricks.hxx).
37  ************************************************************************************************/
38  HAS_MEMBER_FUNCTION(trace_to_flux, has_trace_to_flux);
39 
40  /*!***********************************************************************************************
41  * \brief Floating type is determined by floating type of large vector's entries.
42  ************************************************************************************************/
43  using dof_value_t = typename LargeVecT::value_type;
44 
45  private:
46  /*!***********************************************************************************************
47  * \brief Instantiation of a hypergraph.
48  ************************************************************************************************/
49  HDGHyperGraph<LocalSolverT::n_glob_dofs_per_node(),
50  TopologyT,
51  GeometryT,
52  NodeDescriptorT,
53  typename LocalSolverT::data_type>
55  /*!***********************************************************************************************
56  * \brief Vector containing the indices of Dirichlet type nodes.
57  ************************************************************************************************/
58  std::vector<dof_index_t> dirichlet_indices_;
59  /*!***********************************************************************************************
60  * \brief Instantiation of a local solver.
61  ************************************************************************************************/
62  const LocalSolverT local_solver_;
63  /*!***********************************************************************************************
64  * \brief Struct encoding the options for plotting.
65  ************************************************************************************************/
67 
68  public:
69  /*!***********************************************************************************************
70  * \brief Abstract problem constructor.
71  *
72  * Constructor for class containing a HyperGraph and a local solver that solve a PDE on a
73  * hyperedge.
74  *
75  * \param construct_topo Information to construct a topology.
76  * \param construct_geom Information to construct a geometry.
77  * \param construct_loc_sol Information to construct a local solver.
78  ************************************************************************************************/
79  ShiftedInverseEigenvalue(const typename TopologyT::constructor_value_type& construct_topo,
80  const typename GeometryT::constructor_value_type& construct_geom,
81  const typename LocalSolverT::constructor_value_type& construct_loc_sol)
82  : hyper_graph_(construct_topo, construct_geom), local_solver_(construct_loc_sol)
83  {
84  static_assert(TopologyT::hyEdge_dim() == GeometryT::hyEdge_dim(),
85  "Hyperedge dimension of topology and geometry must be equal!");
86  static_assert(TopologyT::space_dim() == GeometryT::space_dim(),
87  "Space dimension of topology and geometry must be equal!");
88  static_assert(TopologyT::hyEdge_dim() == LocalSolverT::hyEdge_dim(),
89  "Hyperedge dimension of hypergraph and local solver must be equal!");
90  }
91  /*!***********************************************************************************************
92  * \brief Abstract problem constructor.
93  *
94  * Constructor for class containing a HyperGraph and a local solver that solve a PDE on a
95  * hyperedge.
96  *
97  * \param construct_topo Information to construct a topology.
98  * \param construct_loc_sol Information to construct a local solver.
99  ************************************************************************************************/
100  ShiftedInverseEigenvalue(const typename TopologyT::constructor_value_type& construct_topo,
101  const typename LocalSolverT::constructor_value_type& construct_loc_sol)
102  : hyper_graph_(construct_topo), local_solver_(construct_loc_sol)
103  {
104  static_assert(TopologyT::hyEdge_dim() == GeometryT::hyEdge_dim(),
105  "Hyperedge dimension of topology and geometry must be equal!");
106  static_assert(TopologyT::space_dim() == GeometryT::space_dim(),
107  "Space dimension of topology and geometry must be equal!");
108  static_assert(TopologyT::hyEdge_dim() == LocalSolverT::hyEdge_dim(),
109  "Hyperedge dimension of hypergraph and local solver must be equal!");
110  }
111  /*!***********************************************************************************************
112  * \brief Abstract problem constructor.
113  *
114  * Constructor for class containing a HyperGraph and a local solver that solve a PDE on a
115  * hyperedge.
116  *
117  * \param construct_topo Information to construct a topology.
118  ************************************************************************************************/
119  ShiftedInverseEigenvalue(const typename TopologyT::constructor_value_type& construct_topo)
120  : hyper_graph_(construct_topo)
121  {
122  static_assert(TopologyT::hyEdge_dim() == GeometryT::hyEdge_dim(),
123  "Hyperedge dimension of topology and geometry must be equal!");
124  static_assert(TopologyT::space_dim() == GeometryT::space_dim(),
125  "Space dimension of topology and geometry must be equal!");
126  static_assert(TopologyT::hyEdge_dim() == LocalSolverT::hyEdge_dim(),
127  "Hyperedge dimension of hypergraph and local solver must be equal!");
128  }
129  /*!***********************************************************************************************
130  * \brief Return indices of Dirichlet degrees of freedom.
131  *
132  * \tparam hyNode_index_t Typename of the index type for hypernodes.
133  * \retval dirichlet_indices_ Vector containing all dirichlet dof indices.
134  ************************************************************************************************/
135  template <typename hyNode_index_t = dof_index_t>
136  std::vector<unsigned int> dirichlet_indices()
137  {
138  constexpr unsigned int hyEdge_dim = TopologyT::hyEdge_dim();
139 
140  std::array<dof_index_t, LocalSolverT::n_glob_dofs_per_node()> dof_indices;
142  std::array<unsigned int, 2 * hyEdge_dim> hyNode_types;
143 
144  std::for_each(hyper_graph_.begin(), hyper_graph_.end(), [&](auto hyper_edge) {
145  hyNode_types = local_solver_.node_types(hyper_edge);
146  hyEdge_hyNodes = hyper_edge.topology.get_hyNode_indices();
147 
148  for (unsigned int i = 0; i < hyNode_types.size(); ++i)
149  if (hyNode_types[i] == 1)
150  {
151  hyper_graph_.hyNode_factory().get_dof_indices(hyEdge_hyNodes[i], dof_indices);
152  for (unsigned int j = 0; j < dof_indices.size(); ++j)
153  dirichlet_indices_.push_back(dof_indices[j]);
154  }
155  });
156 
157  std::sort(dirichlet_indices_.begin(), dirichlet_indices_.end());
158  auto last = std::unique(dirichlet_indices_.begin(), dirichlet_indices_.end());
159  dirichlet_indices_.erase(last, dirichlet_indices_.end());
160 
161  return dirichlet_indices_;
162  }
163  /*!***********************************************************************************************
164  * \brief Evaluate condensed matrix-vector product.
165  *
166  * Evaluate \f$ (A - \sigma M) x = y\f$.
167  *
168  * \param x_vec A vector containing the input vector \f$x\f$.
169  * \param sigma Approximation to eigenvalue / shifting parameter.
170  * \retval y_vec A vector containing the product \f$y = Ax\f$.
171  ************************************************************************************************/
172  template <typename hyNode_index_t = dof_index_t>
173  LargeVecT trace_to_flux(const LargeVecT& x_vec, const dof_value_t sigma = 0.)
174  {
175  constexpr unsigned int hyEdge_dim = TopologyT::hyEdge_dim();
176  constexpr unsigned int n_dofs_per_node = LocalSolverT::n_glob_dofs_per_node();
177 
178  LargeVecT vec_Ax(x_vec.size(), 0.);
180  std::array<std::array<dof_value_t, n_dofs_per_node>, 2 * hyEdge_dim> hyEdge_dofs_old,
181  hyEdge_dofs_new;
182 
183  // Do matrix--vector multiplication by iterating over all hyperedges.
184  std::for_each(hyper_graph_.begin(), hyper_graph_.end(), [&](auto hyper_edge) {
185  // Fill x_vec's degrees of freedom of a hyperedge into hyEdge_dofs array.
186  hyEdge_hyNodes = hyper_edge.topology.get_hyNode_indices();
187  for (unsigned int hyNode = 0; hyNode < hyEdge_hyNodes.size(); ++hyNode)
188  {
189  hyper_graph_.hyNode_factory().get_dof_values(hyEdge_hyNodes[hyNode], x_vec,
190  hyEdge_dofs_old[hyNode]);
191  hyEdge_dofs_new[hyNode].fill(0.);
192  }
193 
194  // Turn degrees of freedom of x_vec that have been stored locally into those of vec_Ax.
195  if constexpr (
196  has_trace_to_flux<
197  LocalSolverT,
198  std::array<std::array<dof_value_t, n_dofs_per_node>, 2 * TopologyT::hyEdge_dim()>&(
199  std::array<std::array<dof_value_t, n_dofs_per_node>, 2 * TopologyT::hyEdge_dim()>&,
200  std::array<std::array<dof_value_t, n_dofs_per_node>, 2 * TopologyT::hyEdge_dim()>&,
201  dof_value_t)>::value)
202  local_solver_.trace_to_flux(hyEdge_dofs_old, hyEdge_dofs_new, sigma);
203  else if constexpr (
204  has_trace_to_flux<
205  LocalSolverT,
206  std::array<std::array<dof_value_t, n_dofs_per_node>, 2 * TopologyT::hyEdge_dim()>&(
207  std::array<std::array<dof_value_t, n_dofs_per_node>, 2 * TopologyT::hyEdge_dim()>&,
208  std::array<std::array<dof_value_t, n_dofs_per_node>, 2 * TopologyT::hyEdge_dim()>&,
209  decltype(hyper_edge)&, dof_value_t)>::value)
210  local_solver_.trace_to_flux(hyEdge_dofs_old, hyEdge_dofs_new, hyper_edge, sigma);
211  else
212  hy_assert(false, "Function seems not to be implemented!");
213 
214  // Fill hyEdge_dofs array degrees of freedom into vec_Ax.
215  for (unsigned int hyNode = 0; hyNode < hyEdge_hyNodes.size(); ++hyNode)
216  hyper_graph_.hyNode_factory().add_to_dof_values(hyEdge_hyNodes[hyNode], vec_Ax,
217  hyEdge_dofs_new[hyNode]);
218  });
219 
220  return vec_Ax;
221  }
222  /*!***********************************************************************************************
223  * \brief Determine size of condensed system for the skeletal unknowns.
224  *
225  * Function that returns the size \f$n\f$ of the \f$n \times n\f$ linear, sparse system
226  * \f$Ax = b\f$ that is solved by the program in a matrix-free fashion.
227  *
228  * This function is needed to define a \c LinearOperator from Python's \c scipy.sparse.linalg
229  * package which can be used to define iterative solvers for sparse systems.
230  *
231  * \retval n Size of condensed global system of equations.
232  ************************************************************************************************/
233  dof_index_t size_of_system() const { return hyper_graph_.n_global_dofs(); }
234  /*!***********************************************************************************************
235  * \brief Set plot option and return old plot option.
236  *
237  * Function to set and / or read the current plot option.
238  *
239  * \param option A \c std::string containing the plot option to be considered.
240  * \param value A \c std::string containing the new value of the considered option.
241  * If empty, the old value is kept.
242  * \retval opt_value A \c std::string containing the value of the plot option.
243  ************************************************************************************************/
244  std::string plot_option(const std::string& option, std::string value = "")
245  {
246  return set_plot_option(plot_options, option, value);
247  }
248  /*!***********************************************************************************************
249  * \brief Plot solution in vtu format.
250  *
251  * Function that plots the solution of the problem to a predefined file.
252  *
253  * \param lambda A vector of unknowns containing the data vector.
254  * \param time Time at which analytic functions are evaluated.
255  * \retval file A file in the output directory.
256  ************************************************************************************************/
257  void plot_solution(const std::vector<dof_value_t>& lambda, const dof_value_t time = 0.)
258  {
259  plot(hyper_graph_, local_solver_, lambda, plot_options, time);
260  }
261  /*!***********************************************************************************************
262  * \brief Return refinement level.
263  ************************************************************************************************/
264  unsigned int get_refinement() { return hyper_graph_.get_refinement(); }
265  /*!***********************************************************************************************
266  * \brief Set refinement level.
267  ************************************************************************************************/
268  void set_refinement(unsigned int level) { hyper_graph_.set_refinement(level); }
269 }; // end of class ShiftedInverseEigenvalue
270 
271 } // end of namespace GlobalLoop
GlobalLoop::ShiftedInverseEigenvalue::local_solver_
const LocalSolverT local_solver_
Instantiation of a local solver.
Definition: shifted_inverse_eigenvalue.hxx:62
compile_time_tricks.hxx
hy_assert.hxx
This file provides the function hy_assert.
GlobalLoop::ShiftedInverseEigenvalue
Combine local solver and global information for eigenvalue problems with shifted inverse approach.
Definition: shifted_inverse_eigenvalue.hxx:33
plot.hxx
GlobalLoop::ShiftedInverseEigenvalue::get_refinement
unsigned int get_refinement()
Return refinement level.
Definition: shifted_inverse_eigenvalue.hxx:264
PlotOptions
A class storing options for plotting.
Definition: plot.hxx:20
GlobalLoop::ShiftedInverseEigenvalue::dof_value_t
typename LargeVecT::value_type dof_value_t
Floating type is determined by floating type of large vector's entries.
Definition: shifted_inverse_eigenvalue.hxx:43
HDGHyperGraph::end
HDGHyperGraph< n_dofs_per_nodeT, TopoT, GeomT, NodeT, DataT, hyEdge_index_t >::iterator end()
Return iterator to the end of hyEdge list.
Definition: hdg_hypergraph.hxx:433
HDGHyperGraph
The class template uniting topology and geometry of a hypergraph with the topology of the skeleton sp...
Definition: hdg_hypergraph.hxx:51
GlobalLoop::ShiftedInverseEigenvalue::dirichlet_indices_
std::vector< dof_index_t > dirichlet_indices_
Vector containing the indices of Dirichlet type nodes.
Definition: shifted_inverse_eigenvalue.hxx:58
GlobalLoop::ShiftedInverseEigenvalue::plot_option
std::string plot_option(const std::string &option, std::string value="")
Set plot option and return old plot option.
Definition: shifted_inverse_eigenvalue.hxx:244
SmallMat::size
static constexpr unsigned int size()
Return size a SmallMat.
Definition: dense_la.hxx:54
GlobalLoop::ShiftedInverseEigenvalue::plot_options
PlotOptions plot_options
Struct encoding the options for plotting.
Definition: shifted_inverse_eigenvalue.hxx:66
GlobalLoop::ShiftedInverseEigenvalue::dirichlet_indices
std::vector< unsigned int > dirichlet_indices()
Return indices of Dirichlet degrees of freedom.
Definition: shifted_inverse_eigenvalue.hxx:136
GlobalLoop::ShiftedInverseEigenvalue::ShiftedInverseEigenvalue
ShiftedInverseEigenvalue(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: shifted_inverse_eigenvalue.hxx:79
GlobalLoop::ShiftedInverseEigenvalue::plot_solution
void plot_solution(const std::vector< dof_value_t > &lambda, const dof_value_t time=0.)
Plot solution in vtu format.
Definition: shifted_inverse_eigenvalue.hxx:257
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
hy_assert
#define hy_assert(Expr, Msg)
The assertion to be used within HyperHDG — deactivate using -DNDEBUG compile flag.
Definition: hy_assert.hxx:38
HDGHyperGraph::begin
HDGHyperGraph< n_dofs_per_nodeT, TopoT, GeomT, NodeT, DataT, hyEdge_index_t >::iterator begin()
Return iterator to first hyEdge of HDGHyperGraph.
Definition: hdg_hypergraph.hxx:417
GlobalLoop::ShiftedInverseEigenvalue::trace_to_flux
LargeVecT trace_to_flux(const LargeVecT &x_vec, const dof_value_t sigma=0.)
Evaluate condensed matrix-vector product.
Definition: shifted_inverse_eigenvalue.hxx:173
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
GlobalLoop::ShiftedInverseEigenvalue::ShiftedInverseEigenvalue
ShiftedInverseEigenvalue(const typename TopologyT::constructor_value_type &construct_topo, const typename LocalSolverT::constructor_value_type &construct_loc_sol)
Abstract problem constructor.
Definition: shifted_inverse_eigenvalue.hxx:100
hdg_hypergraph.hxx
GlobalLoop::ShiftedInverseEigenvalue::ShiftedInverseEigenvalue
ShiftedInverseEigenvalue(const typename TopologyT::constructor_value_type &construct_topo)
Abstract problem constructor.
Definition: shifted_inverse_eigenvalue.hxx:119
GlobalLoop::ShiftedInverseEigenvalue::set_refinement
void set_refinement(unsigned int level)
Set refinement level.
Definition: shifted_inverse_eigenvalue.hxx:268
GlobalLoop
A namespace for global loops.
Definition: elliptic.hxx:14
GlobalLoop::ShiftedInverseEigenvalue::size_of_system
dof_index_t size_of_system() const
Determine size of condensed system for the skeletal unknowns.
Definition: shifted_inverse_eigenvalue.hxx:233
GlobalLoop::ShiftedInverseEigenvalue::hyper_graph_
HDGHyperGraph< LocalSolverT::n_glob_dofs_per_node(), TopologyT, GeometryT, NodeDescriptorT, typename LocalSolverT::data_type > hyper_graph_
Instantiation of a hypergraph.
Definition: shifted_inverse_eigenvalue.hxx:54
SmallMat
This class implements a small/dense matrix.
Definition: dense_la.hxx:34
GlobalLoop::ShiftedInverseEigenvalue::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).