HyperHDG
hypernodefactory.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/hy_assert.hxx>
4 
5 /*!*************************************************************************************************
6  * \brief This class is responsible for the mapping of hypernodes to global degrees of freedom.
7  *
8  * This class administrates the mapping of topological information (i.e. a hypernode) to information
9  * related to the approximation of solutions to PDEs. Thus, it is capable of mapping an hypernode
10  * index to the indices and values of degrees of freedom. It is the only class to manage the access
11  * to the global vectors comprising degrees of freedom and is universal to (almost) all kinds of
12  * possible equations.
13  *
14  * \tparam n_dofs_per_nodeT Amount of degrees of freedom associated to an hypernode. This is the
15  * number of local trial functions for the skeletal variable.
16  * \tparam hyNode_index_t Unsigned integer type specification. Default is unsigned int.
17  *
18  * \authors Andreas Rupp, Heidelberg University, 2019--2020.
19  **************************************************************************************************/
20 template <unsigned int n_dofs_per_nodeT, typename hyNode_index_t = unsigned int>
22 {
23  public:
24  /*!***********************************************************************************************
25  * \brief Return the template parameter representing the amount of dofs per node.
26  *
27  * \retval n_dofs_per_node The amount of degrees of freedom per node.
28  ************************************************************************************************/
29  static constexpr unsigned int n_dofs_per_node() { return n_dofs_per_nodeT; }
30 
31  private:
32  /*!***********************************************************************************************
33  * \brief Amount of hypernodes within hypergraph.
34  *
35  * The number of hypernodes within the considered hypergraph is needed to construct vectors of
36  * the correct size, to check whether a vector has the appropriate size, and to check whether a
37  * degree of freedom has a valid index.
38  ************************************************************************************************/
39  hyNode_index_t n_hyNodes_;
40 
41  public:
42  /*!***********************************************************************************************
43  * \brief Construct HyperNodeFactory from total number of hypernodes.
44  *
45  * \param n_hyNodes Total number of hypernodes.
46  ************************************************************************************************/
47  HyperNodeFactory(const hyNode_index_t n_hyNodes) : n_hyNodes_(n_hyNodes) {}
48  /*!***********************************************************************************************
49  * \brief Copy constructot for HypernodeFactory.
50  *
51  * Function that evaluates the condensed, matrix-free version of the matrix-vector product
52  * \f$A x = y\f$, where \f$A\f$ is the condensed matrix of the LDG-H method, \f$x\f$ is the
53  * vector of parameters to define the skeletal variable \f$\lambda\f$, and \f$y\f$ is the
54  * resulting vector, which has the same size as the input vector \f$x\f$.
55  *
56  * \param hnf A \c HyperNodeFactory to be copied.
57  ************************************************************************************************/
59  /*!***********************************************************************************************
60  * \brief Copy assignment.
61  ************************************************************************************************/
63  {
64  n_hyNodes_ = other.n_hyNodes_;
65  return *this;
66  }
67  /*!***********************************************************************************************
68  * \brief Move assignment.
69  ************************************************************************************************/
71  {
72  n_hyNodes_ = other.n_hyNodes_;
73  return *this;
74  }
75  /*!***********************************************************************************************
76  * \brief Returns the total amount of hypernodes in the considered hypergraph.
77  *
78  * \retval n_hypernodes The total amount of hypernodes in the considered hypergraph.
79  ************************************************************************************************/
80  hyNode_index_t n_hyNodes() const { return n_hyNodes_; }
81  /*!***********************************************************************************************
82  * \brief Returns the total amount of degrees of freedom in the considered hypergraph.
83  *
84  * \tparam dof_index_t Unsigned integer type specification. Default is \c hyNode_index_t.
85  * \retval n_global_dofs The total amount of degreees of freedom in the considered
86  * hypergraph.
87  ************************************************************************************************/
88  template <typename dof_index_t = hyNode_index_t>
89  dof_index_t n_global_dofs() const
90  {
91  return n_hyNodes_ * n_dofs_per_nodeT;
92  }
93  /*!***********************************************************************************************
94  * \brief Calculate global indices of degrees of freedom related to a hypernode.
95  *
96  * \tparam SmallVecT The typename of a small vector to be filled. Needs to provide the
97  * operator [] for random access and sizes().
98  * \param hyNode_index Index of the considered hypernode.
99  * \param dof_indices Reference to small vector to be filled.
100  * \retval dof_indices Reference to small vector containing the global indices of related
101  * degrees of freedom.
102  ************************************************************************************************/
103  template <typename SmallVecT>
104  SmallVecT& get_dof_indices(const hyNode_index_t hyNode_index, SmallVecT& dof_indices) const
105  {
106  const typename SmallVecT::value_type initial_dof_index = hyNode_index * n_dofs_per_nodeT;
107  hy_assert(dof_indices.size() == n_dofs_per_nodeT,
108  "The size of the local dof vector is "
109  << dof_indices.size()
110  << ", but should be equal to the amount of local dofs, which is "
111  << n_dofs_per_nodeT << ".");
112  if constexpr (n_dofs_per_nodeT > 0)
113  for (unsigned int i = 0; i < n_dofs_per_nodeT; ++i)
114  dof_indices[i] = initial_dof_index + i;
115  return dof_indices;
116  }
117  /*!***********************************************************************************************
118  * \brief Calculate index of hypernode holding a special degree of freedom.
119  *
120  * \tparam dof_index_t Unsigned integer type specification. Default is unsigned int.
121  * \param dof_index Global index of related degree of freedom.
122  * \retval hyNode_index Index of the considered hypernode.
123  ************************************************************************************************/
124  template <typename dof_index_t>
125  hyNode_index_t get_hyNode_from_dof_index(const dof_index_t dof_index) const
126  {
127  hy_assert(0 <= dof_index && dof_index < n_global_dofs(), "No valid dof index.");
128  return dof_index / n_dofs_per_nodeT;
129  }
130  /*!***********************************************************************************************
131  * \brief Evaluate values of degrees of freedom related to a hypernode.
132  *
133  * \tparam dof_index_t Unsigned integer type specification. Default is hyNode_index_t.
134  * \tparam SmallVecT The typename of a small vector to be filled. Needs to provide the
135  * operator [] for random access and size().
136  * \tparam LargeVecT The typename of a large vector to be filled. Needs to provide the
137  * operator [] for random access and size().
138  * \param hyNode_index Index of the considered hypernode.
139  * \param global_dof_vector Global vector of degrees of freedom.
140  * \param local_dof_values Reference to small vector to be filled.
141  * \retval local_dof_values Reference to small vector containing the values of related degrees
142  * of freedom.
143  ************************************************************************************************/
144  template <typename dof_index_t = hyNode_index_t, typename SmallVecT, typename LargeVecT>
145  SmallVecT& get_dof_values(const hyNode_index_t hyNode_index,
146  const LargeVecT& global_dof_vector,
147  SmallVecT& local_dof_values) const
148  {
149  using dof_value_t = typename LargeVecT::value_type;
150  static_assert(std::is_same<typename SmallVecT::value_type, dof_value_t>::value,
151  "Both vectors must have same type!");
152  hy_assert(local_dof_values.size() == n_dofs_per_nodeT,
153  "The size of the local dof vector is "
154  << local_dof_values.size()
155  << ", but should be equal to the amount of local dofs, which is "
156  << n_dofs_per_nodeT << ".");
157  dof_index_t initial_dof_index = hyNode_index * n_dofs_per_nodeT;
158  hy_assert(initial_dof_index >= 0 &&
159  initial_dof_index + n_dofs_per_nodeT <= global_dof_vector.size(),
160  "The initial dof index = "
161  << initial_dof_index << ", should be non-negative. "
162  << " Moreover, the final index = " << initial_dof_index + n_dofs_per_nodeT
163  << " must not exceed the size of the vector of global degrees of freedom.");
164  if constexpr (n_dofs_per_nodeT > 0)
165  for (unsigned int index = 0; index < n_dofs_per_nodeT; ++index)
166  local_dof_values[index] = global_dof_vector[initial_dof_index + index];
167  return local_dof_values;
168  }
169  /*!***********************************************************************************************
170  * \brief Add different values to values of degrees of freedom related to a hypernode.
171  *
172  * Add local values of the small vector \c local_dof_vector to the respective values of the large
173  * vector \c global_dof_vector comprising all degrees of freedom.
174  *
175  * \tparam dof_index_t Unsigned integer type specification. Default is hyNode_index_t.
176  * \tparam SmallVecT The typename of a small vector to be filled. Needs to provide the
177  * operator [] for random access and size().
178  * \tparam LargeVecT The typename of a large vector to be filled. Needs to provide the
179  * operator [] for random access and size().
180  * \param hyNode_index Index of the considered hypernode.
181  * \param global_dof_vector Large vector containing the values of all degrees of freedom.
182  * \param local_dof_vector Small vector containing the local values to be added to the
183  * global ones.
184  * \retval global_dof_vector Large vector containing the values of all degrees of freedom.
185  ************************************************************************************************/
186  template <typename dof_index_t = hyNode_index_t, typename SmallVecT, typename LargeVecT>
187  LargeVecT& add_to_dof_values(const hyNode_index_t hyNode_index,
188  LargeVecT& global_dof_vector,
189  const SmallVecT& local_dof_vector) const
190  {
191  static_assert(
192  std::is_same<typename SmallVecT::value_type, typename LargeVecT::value_type>::value,
193  "Both vectors must have same type!");
194  dof_index_t initial_dof_index = hyNode_index * n_dofs_per_nodeT;
195  hy_assert(local_dof_vector.size() == n_dofs_per_nodeT,
196  "The size of the local dof vector is "
197  << local_dof_vector.size() << ", but should"
198  << " be equal to the amount of local dofs, which is " << n_dofs_per_nodeT << ".");
199  hy_assert(initial_dof_index >= 0 &&
200  initial_dof_index + n_dofs_per_nodeT <= global_dof_vector.size(),
201  "The initial dof index = "
202  << initial_dof_index << "should be non-negative. "
203  << "Moreover, the final index = " << initial_dof_index + n_dofs_per_nodeT
204  << " must not exceed the size of the vector of global degrees of freedom.");
205 
206  if constexpr (n_dofs_per_nodeT > 0)
207  for (unsigned int index = 0; index < n_dofs_per_nodeT; ++index)
208  global_dof_vector[initial_dof_index + index] += local_dof_vector[index];
209  return global_dof_vector;
210  }
211  /*!***********************************************************************************************
212  * \brief Set different values of degrees of freedom related to a hypernode.
213  *
214  * Set local values of the \c std::array \c local_dof_vector as the respective values of the
215  * \c std::vector \c global_dof_vector comprising all degrees of freedom.
216  *
217  * \tparam dof_index_t Unsigned integer type specification. Default is hyNode_index_t.
218  * \tparam SmallVecT The typename of a small vector to be filled. Needs to provide the
219  * operator [] for random access and size().
220  * \tparam LargeVecT The typename of a large vector to be filled. Needs to provide the
221  * operator [] for random access and size().
222  * \param hyNode_index Index of the considered hypernode.
223  * \param global_dof_vector Large vector containing the values of all degrees of freedom.
224  * \param local_dof_vector Small vector containing the local values to be set at the
225  * global ones.
226  * \retval global_dof_vector Large vector containing the values of all degrees of freedom.
227  ************************************************************************************************/
228  template <typename dof_index_t = hyNode_index_t, typename SmallVecT, typename LargeVecT>
229  LargeVecT& set_dof_values(const hyNode_index_t hyNode_index,
230  LargeVecT& global_dof_vector,
231  const SmallVecT& local_dof_vector) const
232  {
233  static_assert(
234  std::is_same<typename SmallVecT::value_type, typename LargeVecT::value_type>::value,
235  "Both vectors must have same type!");
236  dof_index_t initial_dof_index = hyNode_index * n_dofs_per_nodeT;
237  hy_assert(local_dof_vector.size() == n_dofs_per_nodeT,
238  "The size of the local dof vector is "
239  << local_dof_vector.size() << ", but should"
240  << " be equal to the amount of local dofs, which is " << n_dofs_per_nodeT << ".");
241  hy_assert(initial_dof_index >= 0 &&
242  initial_dof_index + n_dofs_per_nodeT <= global_dof_vector.size(),
243  "The initial dof index = "
244  << initial_dof_index << "should be non-negative. "
245  << "Moreover, the final index = " << initial_dof_index + n_dofs_per_nodeT
246  << " must not exceed the size of the vector of global degrees of freedom.");
247  if constexpr (n_dofs_per_nodeT > 0)
248  for (unsigned int index = 0; index < n_dofs_per_nodeT; ++index)
249  global_dof_vector[initial_dof_index + index] = local_dof_vector[index];
250  return global_dof_vector;
251  }
252  /*!***********************************************************************************************
253  * \brief Set all values of degrees of freedom of a hypernode to a predefined value.
254  *
255  * \tparam dof_index_t Unsigned integer type specification. Default is hyNode_index_t.
256  * \tparam LargeVecT The typename of a large vector to be filled. Needs to provide the
257  * operator [] for random access and size().
258  * \param hyNode_index Index of the considered hypernode.
259  * \param global_dof_vector Large vector containing the values of all degrees of freedom.
260  * \param value The future value of related degrees of freedom.
261  * \retval global_dof_vector Large vector containing the values of all degrees of freedom.
262  ************************************************************************************************/
263  template <typename dof_index_t = hyNode_index_t, typename LargeVecT>
264  LargeVecT& set_dof_values(const hyNode_index_t hyNode_index,
265  LargeVecT& global_dof_vector,
266  const typename LargeVecT::value_type value) const
267  {
268  dof_index_t initial_dof_index = hyNode_index * n_dofs_per_nodeT;
269  hy_assert(initial_dof_index >= 0 &&
270  initial_dof_index + n_dofs_per_nodeT <= global_dof_vector.size(),
271  "The initial dof index = "
272  << initial_dof_index << "should be non-negative. "
273  << "Moreover, the final index = " << initial_dof_index + n_dofs_per_nodeT
274  << " must not exceed the size of the vector of global degrees of freedom.");
275  if constexpr (n_dofs_per_nodeT > 0)
276  for (unsigned int index = 0; index < n_dofs_per_nodeT; ++index)
277  global_dof_vector[initial_dof_index + index] = value;
278  return global_dof_vector;
279  }
280 }; // end of class HyperNodeFactory
HyperNodeFactory::operator=
HyperNodeFactory< n_dofs_per_nodeT > & operator=(const HyperNodeFactory< n_dofs_per_nodeT > &other)
Copy assignment.
Definition: hypernodefactory.hxx:62
hy_assert.hxx
This file provides the function hy_assert.
check_push_test.index
index
Definition: check_push_test.py:10
HyperNodeFactory::get_dof_values
SmallVecT & get_dof_values(const hyNode_index_t hyNode_index, const LargeVecT &global_dof_vector, SmallVecT &local_dof_values) const
Evaluate values of degrees of freedom related to a hypernode.
Definition: hypernodefactory.hxx:145
HyperNodeFactory::n_hyNodes_
hyNode_index_t n_hyNodes_
Amount of hypernodes within hypergraph.
Definition: hypernodefactory.hxx:39
HyperNodeFactory::HyperNodeFactory
HyperNodeFactory(const HyperNodeFactory< n_dofs_per_nodeT > &hnf)
Copy constructot for HypernodeFactory.
Definition: hypernodefactory.hxx:58
HyperNodeFactory::n_global_dofs
dof_index_t n_global_dofs() const
Returns the total amount of degrees of freedom in the considered hypergraph.
Definition: hypernodefactory.hxx:89
HyperNodeFactory::get_dof_indices
SmallVecT & get_dof_indices(const hyNode_index_t hyNode_index, SmallVecT &dof_indices) const
Calculate global indices of degrees of freedom related to a hypernode.
Definition: hypernodefactory.hxx:104
HyperNodeFactory
This class is responsible for the mapping of hypernodes to global degrees of freedom.
Definition: hypernodefactory.hxx:21
HyperNodeFactory::add_to_dof_values
LargeVecT & add_to_dof_values(const hyNode_index_t hyNode_index, LargeVecT &global_dof_vector, const SmallVecT &local_dof_vector) const
Add different values to values of degrees of freedom related to a hypernode.
Definition: hypernodefactory.hxx:187
HyperNodeFactory::HyperNodeFactory
HyperNodeFactory(const hyNode_index_t n_hyNodes)
Construct HyperNodeFactory from total number of hypernodes.
Definition: hypernodefactory.hxx:47
HyperNodeFactory::n_hyNodes
hyNode_index_t n_hyNodes() const
Returns the total amount of hypernodes in the considered hypergraph.
Definition: hypernodefactory.hxx:80
HyperNodeFactory::operator=
HyperNodeFactory< n_dofs_per_nodeT > & operator=(HyperNodeFactory< n_dofs_per_nodeT > &&other) noexcept
Move assignment.
Definition: hypernodefactory.hxx:70
HyperNodeFactory::set_dof_values
LargeVecT & set_dof_values(const hyNode_index_t hyNode_index, LargeVecT &global_dof_vector, const typename LargeVecT::value_type value) const
Set all values of degrees of freedom of a hypernode to a predefined value.
Definition: hypernodefactory.hxx:264
hy_assert
#define hy_assert(Expr, Msg)
The assertion to be used within HyperHDG — deactivate using -DNDEBUG compile flag.
Definition: hy_assert.hxx:38
HyperNodeFactory::set_dof_values
LargeVecT & set_dof_values(const hyNode_index_t hyNode_index, LargeVecT &global_dof_vector, const SmallVecT &local_dof_vector) const
Set different values of degrees of freedom related to a hypernode.
Definition: hypernodefactory.hxx:229
HyperNodeFactory::get_hyNode_from_dof_index
hyNode_index_t get_hyNode_from_dof_index(const dof_index_t dof_index) const
Calculate index of hypernode holding a special degree of freedom.
Definition: hypernodefactory.hxx:125
HyperNodeFactory::n_dofs_per_node
static constexpr unsigned int n_dofs_per_node()
Return the template parameter representing the amount of dofs per node.
Definition: hypernodefactory.hxx:29