HyperHDG
read_domain.hxx
Go to the documentation of this file.
1 #pragma once // Ensure that file is included only once in a single compilation.
2 
4 #include <HyperHDG/hy_assert.hxx>
5 
6 #include <algorithm>
7 #include <array>
8 #include <filesystem>
9 #include <fstream>
10 #include <sstream>
11 
12 /*!*************************************************************************************************
13  * \brief Check whether a \c std::vector does not contain duplicate entries.
14  *
15  * This function returns true if the \c std::vector \c vec does not contain duplicates, and false if
16  * it contains duplicates.
17  *
18  * \tparam vectorT Class template for vector.
19  * \param vec General vector to be checked for duplicates.
20  * \retval is_unique True if vector does not contain duplicates and false otherwise.
21  *
22  * \authors Guido Kanschat, Heidelberg University, 2020.
23  * \authors Andreas Rupp, Heidelberg University, 2020.
24  **************************************************************************************************/
25 template <typename vectorT>
26 bool is_unique(const vectorT& vec)
27 {
28  vectorT x(vec); // Copy vector enabling reorder.
29  std::sort(x.begin(), x.end()); // Sort vector in O(N log N).
30  return (std::adjacent_find(x.begin(), x.end()) == x.end()); // Check for duplicates in O(n).
31 }
32 
33 /*!*************************************************************************************************
34  * \brief Hold all topological and geometrical information of a hypergraph.
35  *
36  * This struct holds all topological and geometrical information of a hypergraph that has been read
37  * from a file. Here, the hyperedges are supposed to be hypercuboids, i.e., we do not allow for
38  * simplicial structures here. These have not yet been implemented.
39  *
40  * \tparam hyEdge_dim The local dimension of a hyperedge.
41  * \tparam space_dim The dimension of the surrounding space.
42  * \tparam vectorT The typename of a large vector holding e.g. all points.
43  * \tparam pointT The typename of a point.
44  * \tparam hyEdge_index_t The index type for hyperedges. Default is \c unsigned \c int.
45  * \tparam hyNode_index_t The index type for hypernodes. Default is hyEdge_index_t.
46  * \tparam pt_index_t The index type for points. Default is hyNode_index_t.
47  *
48  * \authors Guido Kanschat, Heidelberg University, 2020.
49  * \authors Andreas Rupp, Heidelberg University, 2020.
50  **************************************************************************************************/
51 template <unsigned int hyEdge_dim,
52  unsigned int space_dim,
53  template <typename...>
54  typename vectorT,
55  typename pointT,
56  typename hyEdge_index_t = unsigned int,
57  typename hyNode_index_t = hyEdge_index_t,
58  typename pt_index_t = hyNode_index_t>
59 struct DomainInfo
60 {
61  /*!***********************************************************************************************
62  * \brief Total amount of hyperedges.
63  ************************************************************************************************/
64  hyEdge_index_t n_hyEdges;
65  /*!***********************************************************************************************
66  * \brief Total amount of hypernodes.
67  ************************************************************************************************/
68  hyNode_index_t n_hyNodes;
69  /*!***********************************************************************************************
70  * \brief Total amount of points.
71  ************************************************************************************************/
72  pt_index_t n_points;
73  /*!***********************************************************************************************
74  * \brief Vector containing points.
75  ************************************************************************************************/
76  vectorT<pointT> points;
77  /*!***********************************************************************************************
78  * \brief Vector containing hypernode indices per hyperedge.
79  ************************************************************************************************/
80  vectorT<std::array<hyNode_index_t, 2 * hyEdge_dim> > hyNodes_hyEdge, hyFaces_hyEdge;
81  /*!***********************************************************************************************
82  * \brief Vector containing vertex indices per hyperedge.
83  ************************************************************************************************/
84  vectorT<std::array<pt_index_t, 1 << hyEdge_dim> > points_hyEdge; // 2 ^ hyEdge_dim
85  /*!***********************************************************************************************
86  * \brief Constructor of DomainInfo struct.
87  ************************************************************************************************/
88  DomainInfo(const pt_index_t n_points,
89  const hyEdge_index_t n_hyEdge,
90  const hyNode_index_t n_hyNode,
91  const pt_index_t n_point)
92  : n_hyEdges(n_hyEdge),
93  n_hyNodes(n_hyNode),
94  n_points(n_point),
99  {
100  }
101  /*!***********************************************************************************************
102  * \brief Check, whether DomainInfo is in a consistent state.
103  ************************************************************************************************/
105  {
106  bool consistent = true;
107 
108  std::for_each(hyNodes_hyEdge.begin(), hyNodes_hyEdge.end(),
109  [&](std::array<hyNode_index_t, 2 * hyEdge_dim> hyEdge) {
110  for (unsigned int i = 0; i < hyEdge.size(); ++i)
111  {
112  consistent = (hyEdge[i] < n_hyNodes && hyEdge[i] >= 0);
113  hy_assert(consistent, "At least one hypernode index is invalid!");
114  }
115  });
116 
117  std::for_each(points_hyEdge.begin(), points_hyEdge.end(),
118  [&](std::array<pt_index_t, 1 << hyEdge_dim> hyEdge) {
119  for (unsigned int i = 0; i < hyEdge.size(); ++i)
120  {
121  consistent = (hyEdge[i] < n_points && hyEdge[i] >= 0);
122  hy_assert(consistent, "At least one point index is invalid!");
123  }
124  });
125 
126  consistent = is_unique(points);
127  hy_assert(consistent, "DomainInfo.points contains duplicate points!");
128  if (!consistent)
129  return false;
130 
131  consistent = is_unique(hyNodes_hyEdge);
132  hy_assert(consistent, "DomainInfo.hyNodes_hyEdge contains duplicate hypernode!");
133  if (!consistent)
134  return false;
135 
136  consistent = is_unique(points_hyEdge);
137  hy_assert(consistent, "DomainInfo.points_hyEdge contains duplicate points!");
138  if (!consistent)
139  return false;
140 
141  return true;
142  } // end of check_consistency
143 }; // end of struct DomainInfo
144 
145 /*!*************************************************************************************************
146  * \brief Function to read geo file.
147  *
148  * Function to read self-defined .geo files are supported. These files are supposed to comprise
149  * hypergraphs consisting of hypercuboids only. Other versions have not yet been implemented.
150  *
151  * \tparam hyEdge_dim The local dimension of a hyperedge.
152  * \tparam space_dim The dimension of the surrounding space.
153  * \tparam vectorT The typename of a large vector holding e.g. all points.
154  * \tparam pointT The typename of a point.
155  * \tparam hyEdge_index_t The index type for hyperedges. Default is \c unsigned \c int.
156  * \tparam hyNode_index_t The index type for hypernodes. Default is hyEdge_index_t.
157  * \tparam pt_index_t The index type for points. Default is hyNode_index_t.
158  *
159  * \param filename Name of the .geo file to be read.
160  * \retval domain_info Topological and geometrical information of hypergraph.
161  *
162  * \authors Guido Kanschat, Heidelberg University, 2020.
163  * \authors Andreas Rupp, Heidelberg University, 2020.
164  **************************************************************************************************/
165 template <unsigned int hyEdge_dim,
166  unsigned int space_dim,
167  template <typename...> typename vectorT = std::vector,
168  typename pointT = Point<space_dim, float>,
169  typename hyEdge_index_t = unsigned int,
170  typename hyNode_index_t = hyEdge_index_t,
171  typename pt_index_t = hyNode_index_t>
173 read_domain_geo(const std::string& filename)
174 {
175  hy_assert(filename.substr(filename.size() - 4, filename.size()) == ".geo",
176  "The given file needs to be a .geo file for this function to be applicable!");
177 
178  std::ifstream infile(filename);
179  std::istringstream linestream;
180  std::string line, keyword, equal_sign;
181 
182  unsigned int Space_Dim, HyperEdge_Dim;
183  pt_index_t N_Points = 0, pt_iter;
184  hyEdge_index_t N_HyperEdges = 0, hyEdge_iter;
185  hyNode_index_t N_HyperNodes = 0;
186  pointT pt;
187 
188  while (keyword != "Space_Dim" && std::getline(infile, line))
189  {
190  linestream = std::istringstream(line);
191  linestream >> keyword;
192  }
193  linestream >> equal_sign >> Space_Dim;
194 
195  hy_assert(keyword == "Space_Dim",
196  "The keyword Space_Dim has not been found in the file " << filename << "!");
197  hy_assert(equal_sign == "=", "The keyword " << keyword << " has not been followd by = symbol!");
198  hy_assert(Space_Dim == space_dim, "Space_Dim in " << filename << " is " << Space_Dim
199  << ", but should be " << space_dim << "!");
200 
201  while (keyword != "HyperEdge_Dim" && std::getline(infile, line))
202  {
203  linestream = std::istringstream(line);
204  linestream >> keyword;
205  }
206  linestream >> equal_sign >> HyperEdge_Dim;
207 
208  hy_assert(keyword == "HyperEdge_Dim",
209  "The keyword HyperEdge_Dim has not been found in the file " << filename << "!");
210  hy_assert(equal_sign == "=", "The keyword " << keyword << " has not been followd by = symbol!");
211  hy_assert(HyperEdge_Dim == hyEdge_dim, "HyperEdge_Dim in " << filename << " is " << Space_Dim
212  << ", but should be " << hyEdge_dim
213  << "!");
214 
215  while (keyword != "N_Points" && std::getline(infile, line))
216  {
217  linestream = std::istringstream(line);
218  linestream >> keyword;
219  }
220  linestream >> equal_sign >> N_Points;
221 
222  hy_assert(keyword == "N_Points",
223  "The keyword N_Points has not been found in the file " << filename << "!");
224  hy_assert(equal_sign == "=", "The keyword " << keyword << " has not been followd by = symbol!");
225  hy_assert(N_Points != 0, "The value of N_Points has not been set correctly!");
226 
227  while (keyword != "N_HyperNodes" && std::getline(infile, line))
228  {
229  linestream = std::istringstream(line);
230  linestream >> keyword;
231  }
232  linestream >> equal_sign >> N_HyperNodes;
233 
234  hy_assert(keyword == "N_HyperNodes",
235  "The keyword N_Points has not been found in the file " << filename << "!");
236  hy_assert(equal_sign == "=", "The keyword " << keyword << " has not been followd by = symbol!");
237  hy_assert(N_HyperNodes != 0, "The value of N_HyperNodes has not been set correctly!");
238 
239  while (keyword != "N_HyperEdges" && std::getline(infile, line))
240  {
241  linestream = std::istringstream(line);
242  linestream >> keyword;
243  }
244  linestream >> equal_sign >> N_HyperEdges;
245 
246  hy_assert(keyword == "N_HyperEdges",
247  "The keyword N_Points has not been found in the file " << filename << "!");
248  hy_assert(equal_sign == "=", "The keyword " << keyword << " has not been followd by = symbol!");
249  hy_assert(N_HyperEdges != 0, "The value of N_HyperEdges has not been set correctly!");
250 
252  domain_info(N_Points, N_HyperEdges, N_HyperNodes, N_Points);
253 
254  while (keyword != "POINTS:" && std::getline(infile, line))
255  {
256  linestream = std::istringstream(line);
257  linestream >> keyword;
258  }
259 
260  hy_assert(keyword == "POINTS:",
261  "The keyword 'POINTS:' has not been found in the file " << filename << "!");
262 
263  for (pt_iter = 0; pt_iter < N_Points && std::getline(infile, line); ++pt_iter)
264  {
265  linestream = std::istringstream(line);
266  for (unsigned int dim = 0; dim < space_dim; ++dim)
267  linestream >> pt[dim];
268  domain_info.points[pt_iter] = pt;
269  }
270 
271  hy_assert(pt_iter == N_Points, "Not all points have been added to the list!");
272 
273  while (keyword != "HYPERNODES_OF_HYPEREDGES:" && std::getline(infile, line))
274  {
275  linestream = std::istringstream(line);
276  linestream >> keyword;
277  }
278 
279  hy_assert(
280  keyword == "HYPERNODES_OF_HYPEREDGES:",
281  "The keyword 'HYPERNODES_OF_HYPEREDGES:' has not been found in the file " << filename << "!");
282 
283  for (hyEdge_iter = 0; hyEdge_iter < N_HyperEdges && std::getline(infile, line); ++hyEdge_iter)
284  {
285  linestream = std::istringstream(line);
286  for (unsigned int i = 0; i < domain_info.hyNodes_hyEdge[hyEdge_iter].size(); ++i)
287  linestream >> domain_info.hyNodes_hyEdge[hyEdge_iter][i];
288  }
289 
290  hy_assert(hyEdge_iter == N_HyperEdges, "Not all hyperedges have been added to the list!");
291 
292  while (keyword != "TYPES_OF_HYPERFACES:" && std::getline(infile, line))
293  {
294  linestream = std::istringstream(line);
295  linestream >> keyword;
296  }
297 
298  hy_assert(
299  keyword == "TYPES_OF_HYPERFACES:",
300  "The keyword 'TYPES_OF_HYPERFACES:' has not been found in the file " << filename << "!");
301 
302  for (hyEdge_iter = 0; hyEdge_iter < N_HyperEdges && std::getline(infile, line); ++hyEdge_iter)
303  {
304  linestream = std::istringstream(line);
305  for (unsigned int i = 0; i < domain_info.hyFaces_hyEdge[hyEdge_iter].size(); ++i)
306  linestream >> domain_info.hyFaces_hyEdge[hyEdge_iter][i];
307  }
308 
309  hy_assert(hyEdge_iter == N_HyperEdges, "Not all hyperedges have been added to the list!");
310 
311  while (keyword != "POINTS_OF_HYPEREDGES:" && std::getline(infile, line))
312  {
313  linestream = std::istringstream(line);
314  linestream >> keyword;
315  }
316 
317  hy_assert(
318  keyword == "POINTS_OF_HYPEREDGES:",
319  "The keyword 'POINTS_OF_HYPEREDGES:' has not been found in the file " << filename << "!");
320 
321  for (hyEdge_iter = 0; hyEdge_iter < N_HyperEdges && std::getline(infile, line); ++hyEdge_iter)
322  {
323  linestream = std::istringstream(line);
324  for (unsigned int i = 0; i < domain_info.points_hyEdge[hyEdge_iter].size(); ++i)
325  linestream >> domain_info.points_hyEdge[hyEdge_iter][i];
326  }
327 
328  hy_assert(hyEdge_iter == N_HyperEdges, "Not all hyperedges have been added to the list!");
329 
330  infile.close();
331  return domain_info;
332 } // end of read_domain_geo
333 
334 /*!*************************************************************************************************
335  * \brief General Function to read domain from input file.
336  *
337  * At the moment, only self-defined .geo files are supported. These files are supposed to comprise
338  * hypergraphs consisting of hypercuboids only. Other versions have not yet been implemented.
339  *
340  * \tparam hyEdge_dim The local dimension of a hyperedge.
341  * \tparam space_dim The dimension of the surrounding space.
342  * \tparam vectorT The typename of a large vector holding e.g. all points.
343  * \tparam pointT The typename of a point.
344  * \tparam hyEdge_index_t The index type for hyperedges. Default is \c unsigned \c int.
345  * \tparam hyNode_index_t The index type for hypernodes. Default is hyEdge_index_t.
346  * \tparam pt_index_t The index type for points. Default is hyNode_index_t.
347  *
348  * \param filename Name of the .geo file to be read.
349  * \retval domain_info Topological and geometrical information of hypergraph.
350  *
351  * \authors Guido Kanschat, Heidelberg University, 2020.
352  * \authors Andreas Rupp, Heidelberg University, 2020.
353  **************************************************************************************************/
354 template <unsigned int hyEdge_dim,
355  unsigned int space_dim,
356  template <typename...> typename vectorT = std::vector,
357  typename pointT = Point<space_dim, float>,
358  typename hyEdge_index_t = unsigned int,
359  typename hyNode_index_t = hyEdge_index_t,
360  typename pt_index_t = hyNode_index_t>
362 read_domain(std::string filename)
363 {
364  hy_assert(std::filesystem::exists(filename), "File does not exist.");
365 
366  if (filename.substr(filename.size() - 4, filename.size()) == ".pts")
367  {
368  hy_assert(hyEdge_dim == 1, "This only works for graphs, so far!");
369  make_epsilon_neighborhood_graph<space_dim, vectorT, pointT, hyEdge_index_t>(filename);
370  }
371 
372  hy_assert(filename.substr(filename.size() - 4, filename.size()) == ".geo",
373  "The given file needs to be a .geo file, since no other input file types are currently"
374  << " implemented.");
375 
377  domain_info = read_domain_geo<hyEdge_dim, space_dim, vectorT, pointT, hyEdge_index_t,
378  hyNode_index_t, pt_index_t>(filename);
379 
380  hy_assert(domain_info.check_consistency(),
381  "Domain info appears to be inconsistent!"
382  << std::endl
383  << "This assertion is never to be thrown since it can only be caused by internal "
384  << "assertions of DomainInfo.check_consistency()!");
385 
386  return domain_info;
387 } // end of read_domain
hy_assert.hxx
This file provides the function hy_assert.
DomainInfo::hyNodes_hyEdge
vectorT< std::array< hyNode_index_t, 2 *hyEdge_dim > > hyNodes_hyEdge
Vector containing hypernode indices per hyperedge.
Definition: read_domain.hxx:80
DomainInfo::check_consistency
bool check_consistency()
Check, whether DomainInfo is in a consistent state.
Definition: read_domain.hxx:104
DomainInfo::n_hyEdges
hyEdge_index_t n_hyEdges
Total amount of hyperedges.
Definition: read_domain.hxx:64
DomainInfo::n_hyNodes
hyNode_index_t n_hyNodes
Total amount of hypernodes.
Definition: read_domain.hxx:68
epsilon_neighborhood_graph.hxx
read_domain_geo
DomainInfo< hyEdge_dim, space_dim, vectorT, pointT, hyEdge_index_t, hyNode_index_t, pt_index_t > read_domain_geo(const std::string &filename)
Function to read geo file.
Definition: read_domain.hxx:173
DomainInfo::DomainInfo
DomainInfo(const pt_index_t n_points, const hyEdge_index_t n_hyEdge, const hyNode_index_t n_hyNode, const pt_index_t n_point)
Constructor of DomainInfo struct.
Definition: read_domain.hxx:88
DomainInfo::points
vectorT< pointT > points
Vector containing points.
Definition: read_domain.hxx:76
read_domain
DomainInfo< hyEdge_dim, space_dim, vectorT, pointT, hyEdge_index_t, hyNode_index_t, pt_index_t > read_domain(std::string filename)
General Function to read domain from input file.
Definition: read_domain.hxx:362
DomainInfo::n_points
pt_index_t n_points
Total amount of points.
Definition: read_domain.hxx:72
DomainInfo::hyFaces_hyEdge
vectorT< std::array< hyNode_index_t, 2 *hyEdge_dim > > hyFaces_hyEdge
Definition: read_domain.hxx:80
hy_assert
#define hy_assert(Expr, Msg)
The assertion to be used within HyperHDG — deactivate using -DNDEBUG compile flag.
Definition: hy_assert.hxx:38
is_unique
bool is_unique(const vectorT &vec)
Check whether a std::vector does not contain duplicate entries.
Definition: read_domain.hxx:26
DomainInfo::points_hyEdge
vectorT< std::array< pt_index_t, 1<< hyEdge_dim > > points_hyEdge
Vector containing vertex indices per hyperedge.
Definition: read_domain.hxx:84
HyperHDG.config.consistent
def consistent(conf)
Check that config is consistent.
Definition: config.py:19
DomainInfo
Hold all topological and geometrical information of a hypergraph.
Definition: read_domain.hxx:59
SmallMat
This class implements a small/dense matrix.
Definition: dense_la.hxx:34