ug4
undirected.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2022: G-CSC, Goethe University Frankfurt
3  * Author: Felix Salfelder, 2022
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef UG_GRAPH_INTERFACE_UNDIRECTED_H
34 #define UG_GRAPH_INTERFACE_UNDIRECTED_H
35 
36 //#include "trace.h"
37 #include "sparsematrix_boost.h"
38 #include <boost/geometry/iterators/concatenate_iterator.hpp>
39 #include <boost/graph/adjacency_list.hpp>
41 
42 #ifndef NDEBUG
43 #include "common/stopwatch.h"
44 #endif
45 
46 namespace ug{
47 
48 // Symmetrify matrix stencil
49 template<class T>
51  typedef typename T::const_row_iterator const_row_iterator;
52 public: // types
53  typedef typename T::value_type value_type;
54  typedef boost::adjacency_list<boost::vecS, boost::vecS> G;
55  typedef typename boost::graph_traits<T>::adjacency_iterator T_adj_it;
56  typedef typename boost::graph_traits<G>::adjacency_iterator G_adj_it;
57  class edge : public std::pair<int, int>{
58  public:
59  explicit edge() : std::pair<int, int>(){ untested();
60  }
61  edge(int a, int b) : std::pair<int, int>(a, b) {
62  }
64  incomplete();
65  }
66  edge(boost::graph_traits<G>::edge_descriptor){ untested();
67  incomplete();
68  }
69  };
70  typedef boost::geometry::concatenate_iterator<
72  G_adj_it,
73  int, int> adjacency_iterator;
74 
75 public:
76  explicit UndirectedMatrix(T const* m=nullptr)
77  : _matrix(m) {
78  if(m){
79  refresh();
80  }else{ untested();
81  }
82  }
86  }
88  _matrix = o._matrix;
90  return *this;
91  }
92 
93 public: // interface
94  void refresh();
95 
96  int num_rows() const {
97  return std::max(_matrix->num_rows(), _matrix->num_cols());
98  }
99  int num_cols() const { untested();
100  return num_rows();
101  }
102  int out_degree(int v) const {
103  // could call in_degree?
104  return in_degree(v);
105  }
106  int in_degree(int v) const {
107  return boost::out_degree(v, *_matrix)
109  }
110  int degree(int v) const {
111  return out_degree(v);
112  }
113 
114 #if 0
115  edge_iterator begin_row(int row) const { untested();
116  auto r1 = boost::out_edges(row, *_matrix);
117  auto r2 = boost::out_edges(row, _extra_fill);
118 
119  return edge_iterator(r1.first, r1.second, r2.first, r2.second);
120  }
121  edge_iterator end_row(int row) const { untested();
122  auto r1 = boost::out_edges(row, *_matrix);
123  auto r2 = boost::out_edges(row, _extra_fill);
124 
125  return edge_iterator(r1.second, r1.second, r2.second, r2.second);
126  }
127 #endif
128  adjacency_iterator begin_row(int row) const {
129  auto r1 = boost::adjacent_vertices(row, *_matrix);
130  auto r2 = boost::adjacent_vertices(row, _extra_fill);
131 
132  return adjacency_iterator(r1.first, r1.second, r2.first, r2.first);
133  }
134  adjacency_iterator end_row(int row) const {
135  auto r1 = boost::adjacent_vertices(row, *_matrix);
136  auto r2 = boost::adjacent_vertices(row, _extra_fill);
137 
138  return adjacency_iterator(r1.second, r2.first, r2.second);
139  }
140 
141 private:
142  T const* _matrix;
144 
145 private:
146  class map_type{
147  public:
148  explicit map_type(T_adj_it const* i, T_adj_it const* e) : _it(i), _end(e){}
149 
150  int operator[](int i) const{
151  assert(_it[i] != _end[i]);
152  return *_it[i];
153  }
154 
155  private:
156  T_adj_it const* _it;
157  T_adj_it const* _end;
158  };
159 }; // UndirectedMatrix
160 
161 // refresh missing fill. This is O(nonzeroes)
162 template<class T>
164 {
165 #ifndef NDEBUG
166  double t = get_clock_s();
167 #endif
168 
169  assert(_matrix);
170  size_t N = _matrix->num_rows();
171  assert(N == _matrix->num_cols());
172  assert(!_matrix->iters()); // for now.
173 
174  _extra_fill = G(N);
175 
176  typedef boost::bucket_sorter<unsigned, unsigned,
177  map_type, boost::identity_property_map > container_type;
178 
179  std::vector<T_adj_it> c(N);
180  std::vector<T_adj_it> e(N);
181  map_type M(&c[0], &e[0]);
182 
183  container_type bs(N, N, M);
184 
185  for(size_t k=0; k<N; ++k){
186  auto rr = boost::adjacent_vertices(k, *_matrix);
187  c[k] = rr.first;
188  e[k] = rr.second;
189 
190  if(c[k] != e[k]){
191  bs.push(k);
192  }else{
193  }
194  }
195 
196 #if 0
197  for(size_t j=0; j<N; ++j){
198  std::cerr << "bs init " << j << "... ";
199  for(auto t : bs[j]){
200  std::cerr << " " << t;
201  }
202  std::cerr << "\n";
203  }
204 #endif
205 
206  for(size_t j=0; j<N; ++j){
207  // std::cerr << "====== " << j << " ====\n";
208  if(c[j] == e[j]){
209  }else if(*c[j]==j){
210  ++c[j];
211 
212  if(c[j] == e[j]){ itested();
213  bs.remove(j);
214  }else{
215  bs.update(j);
216  }
217 
218  }else{
219  assert(*c[j]>j);
220  }
221 
222  // upper triangle, visit nonzeroes.
223  for(; c[j] != e[j];){
224  int k = *c[j];
225  if(c[k] == e[k]){
226  assert(size_t(k)<N);
227  assert(j<N);
228  // std::cerr << "lower fill0 " << k << " " << j << "\n";
229  boost::add_edge(k, j, _extra_fill);
230  }else if(*c[k] > j){
231  assert(size_t(k)<N);
232  assert(j<N);
233  // std::cerr << "lower fill1 " << k << " " << j << "\n";
234  boost::add_edge(k, j, _extra_fill);
235  }else if(*c[k] == j){
236  ++c[k];
237  if(c[k] == e[k]){
238  bs.remove(k);
239  }else{
240  bs.update(k);
241  }
242  }
243  ++c[j];
244 
245  if(c[j] == e[j]){
246  bs.remove(j);
247  }else{
248  bs.update(j);
249  }
250  }
251 
252  // lower triangle, visit subset of nonzeroes.
253  // std::cerr << "====== lower " << j << " ====\n";
254  assert(j<N);
255  auto bj = bs[j];
256 
257  for(auto t=bj.begin(); t!=bj.end(); ){
258  int i = *t;
259  ++t;
260 
261  // std::cerr << "upper fill " << j << " " << i << "\n";
262  boost::add_edge(j, i, _extra_fill);
263 
264  assert(*c[i]==j);
265 
266  ++c[i];
267  if(c[i] == e[i]){
268  bs.remove(i);
269  }else if(int(*c[i]) < i){ itested();
270  // std::cerr << "bs push " << i << " " << j << " " << *c[i] << "\n";
271  assert(*c[i] > j);
272  bs.update(i);
273  }else{ itested();
274  assert(*c[i] > j);
275  // bs.remove(i);
276  }
277 
278  }
279  }
280 
281  c.clear();
282  e.clear();
283  assert(!_matrix->iters());
284 
285 #ifndef NDEBUG
286  UG_LOG("Undirected refresh " << get_clock_s()-t << "\n");
287 #endif
288 }
289 
290 } // ug
291 
292 #endif // guard
Definition: sparsematrix_boost.h:37
Definition: sparsematrix_boost.h:152
Definition: bucket_sorter.hpp:47
Definition: undirected.h:57
edge(int a, int b)
Definition: undirected.h:61
edge(boost::graph_traits< G >::edge_descriptor)
Definition: undirected.h:66
edge()
Definition: undirected.h:59
edge(boost::SM_edge< value_type >)
Definition: undirected.h:63
Definition: undirected.h:146
int operator[](int i) const
Definition: undirected.h:150
T_adj_it const * _end
Definition: undirected.h:157
map_type(T_adj_it const *i, T_adj_it const *e)
Definition: undirected.h:148
T_adj_it const * _it
Definition: undirected.h:156
Definition: undirected.h:50
boost::graph_traits< T >::adjacency_iterator T_adj_it
Definition: undirected.h:55
void refresh()
Definition: undirected.h:163
boost::adjacency_list< boost::vecS, boost::vecS > G
Definition: undirected.h:54
UndirectedMatrix(T const *m=nullptr)
Definition: undirected.h:76
int num_rows() const
Definition: undirected.h:96
G _extra_fill
Definition: undirected.h:143
UndirectedMatrix(UndirectedMatrix &&o)=delete
int degree(int v) const
Definition: undirected.h:110
UndirectedMatrix & operator=(UndirectedMatrix const &o)
Definition: undirected.h:87
T::const_row_iterator const_row_iterator
Definition: undirected.h:51
T::value_type value_type
Definition: undirected.h:53
T const * _matrix
Definition: undirected.h:142
int out_degree(int v) const
Definition: undirected.h:102
UndirectedMatrix(UndirectedMatrix const &o)
Definition: undirected.h:84
boost::graph_traits< G >::adjacency_iterator G_adj_it
Definition: undirected.h:56
boost::geometry::concatenate_iterator< boost::SM_adjacency_iterator< value_type >, G_adj_it, int, int > adjacency_iterator
Definition: undirected.h:73
int num_cols() const
Definition: undirected.h:99
int in_degree(int v) const
Definition: undirected.h:106
adjacency_iterator begin_row(int row) const
Definition: undirected.h:128
adjacency_iterator end_row(int row) const
Definition: undirected.h:134
#define UG_LOG(msg)
Definition: log.h:367
#define untested()
Definition: lua_table_handle.cpp:15
std::pair< typename graph_traits< T >::adjacency_iterator, typename graph_traits< T >::adjacency_iterator > adjacent_vertices(size_t v, ug::BidirectionalMatrix< T > const &M)
Definition: bidirectional_boost.h:108
std::pair< SM_out_edge_iterator< typename T::value_type >, SM_out_edge_iterator< typename T::value_type > > out_edges(size_t v, ug::BidirectionalMatrix< T > const &g)
Definition: bidirectional_boost.h:136
int out_degree(int v, ug::BidirectionalMatrix< T > const &M)
Definition: bidirectional_boost.h:76
Definition: smart_pointer.h:814
the ug namespace
double get_clock_s()
Definition: stopwatch.h:103
T value_type
Definition: sparsematrix_interface.h:2
stopwatch class for quickly taking times
#define incomplete()
Definition: trace.h:10
#define itested()
Definition: trace.h:9