FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
dynamic_graph.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8// includes, FEAT
9#include <kernel/adjacency/base.hpp>
10#include <kernel/adjacency/adjactor.hpp>
11
12// includes, system
13#include <algorithm>
14#include <vector>
15#include <set>
16
17namespace FEAT
18{
19 namespace Adjacency
20 {
29 {
30 protected:
32 typedef std::set<Index> IdxSet;
33 typedef std::vector<IdxSet> IdxSetVec;
35
36 public:
38 typedef IdxSet::const_iterator ImageIterator;
39
40 protected:
46 IdxSetVec _indices;
47
48 public:
53 {
54 }
55
67 explicit DynamicGraph(
68 Index num_nodes_domain,
69 Index num_nodes_image)
70 :
71 _num_nodes_domain(num_nodes_domain),
72 _num_nodes_image(num_nodes_image),
73 _indices(num_nodes_domain)
74 {
75 }
76
88 template<typename Adjactor_>
89 explicit DynamicGraph(
90 RenderType render_type,
91 const Adjactor_& adjactor)
92 :
95 _indices()
96 {
97 switch(render_type)
98 {
103 _render_as_is(adjactor);
104 break;
105
110 _render_transpose(adjactor);
111 break;
112 }
113 }
114
129 template<
130 typename Adjactor1_,
131 typename Adjactor2_>
132 explicit DynamicGraph(
133 RenderType render_type,
134 const Adjactor1_& adjactor1,
135 const Adjactor2_& adjactor2)
136 :
139 _indices()
140 {
141 switch(render_type)
142 {
147 _render_as_is(adjactor1, adjactor2);
148 break;
149
154 _render_transpose(adjactor1, adjactor2);
155 break;
156 }
157 }
158
163 _indices(std::move(other._indices))
164 {
165 }
166
169 {
170 // avoid self-move
171 if(this == &other)
172 return *this;
173
174 _num_nodes_domain = other._num_nodes_domain;
175 _num_nodes_image = other._num_nodes_image;
176 _indices = std::move(other._indices);
177
178 other._num_nodes_domain = other._num_nodes_image = Index(0);
179
180 return *this;
181 }
182
185 {
186 }
187
194 {
196 graph._indices = _indices;
197 return graph;
198 }
199
212 Index degree(Index domain_node) const
213 {
214 ASSERTM(domain_node < _num_nodes_domain, "Domain node index out of range");
215 return Index(_indices[domain_node].size());
216 }
217
229 Index degree() const
230 {
231 Index deg(0);
232 for(Index i(0); i < _num_nodes_domain; ++i)
233 {
234 deg = std::max(deg, Index(_indices[i].size()));
235 }
236 return deg;
237 }
238
248 {
249 Index nidx(0);
250 for(Index i(0); i < _num_nodes_domain; ++i)
251 {
252 nidx += Index(_indices[i].size());
253 }
254 return nidx;
255 }
256
262 void clear()
263 {
264 for(Index i(0); i < _num_nodes_domain; ++i)
265 {
266 _indices[i].clear();
267 }
268 }
269
282 bool exists(Index domain_node, Index image_node) const
283 {
284 ASSERTM(domain_node < _num_nodes_domain, "Domain node index out of range");
285 ASSERTM(image_node < _num_nodes_image, "Image node index out of range");
286 return _indices[domain_node].find(image_node) != _indices[domain_node].end();
287 }
288
301 bool insert(Index domain_node, Index image_node)
302 {
303 ASSERTM(domain_node < _num_nodes_domain, "Domain node index out of range");
304 ASSERTM(image_node < _num_nodes_image, "Image node index out of range");
305 return _indices[domain_node].insert(image_node).second;
306 }
307
320 bool erase(Index domain_node, Index image_node)
321 {
322 ASSERTM(domain_node < _num_nodes_domain, "Domain node index out of range");
323 ASSERTM(image_node < _num_nodes_image, "Image node index out of range");
324 // note: std::set.erase() returns the number of deleted elements
325 return _indices[domain_node].erase(image_node) > 0;
326 }
327
334 template<typename Adjactor_>
335 void compose(const Adjactor_& adjactor)
336 {
337 XASSERTM(_num_nodes_image == adjactor.get_num_nodes_domain(), "Adjactor dimension mismatch!");
338
339 typedef typename Adjactor_::ImageIterator AImIt;
340
341 // image index buffer vector
342 std::vector<Index> img_idx;
343
344 // loop over all domain nodes
345 for(Index i(0); i < _num_nodes_domain; ++i)
346 {
347 // clear image index buffer
348 img_idx.clear();
349
350 // loop over all image indices of this adjactor and make a backup of them
351 {
352 ImageIterator it(_indices[i].begin());
353 ImageIterator jt(_indices[i].end());
354 for(; it != jt; ++it)
355 {
356 img_idx.push_back(*it);
357 }
358 }
359
360 // clear the current domain node
361 _indices[i].clear();
362
363 // loop over all entries of the index buffer vector
364 for(Index j(0); j < img_idx.size(); ++j)
365 {
366 // iterator over all adjacent nodes
367 AImIt it(adjactor.image_begin(img_idx[j]));
368 AImIt jt(adjactor.image_end(img_idx[j]));
369 for(; it != jt; ++it)
370 {
371 _indices[i].insert(*it);
372 }
373 }
374 }
375
376 // store new image node count
377 _num_nodes_image = adjactor.get_num_nodes_image();
378 }
379
380 /* *************************************************** */
381 /* R E N D E R F U N C T I O N T E M P L A T E S */
382 /* *************************************************** */
383 private:
385 // renders adjactor
386 template<typename Adjactor_>
387 void _render_as_is(const Adjactor_& adj)
388 {
389 typedef typename Adjactor_::ImageIterator AImIt;
390
391 // set counts
392 _num_nodes_domain = adj.get_num_nodes_domain();
393 _num_nodes_image = adj.get_num_nodes_image();
395
396 // loop over all domain nodes
397 for(Index i(0); i < _num_nodes_domain; ++i)
398 {
399 AImIt cur(adj.image_begin(i));
400 AImIt end(adj.image_end(i));
401 for(; cur != end; ++cur)
402 {
403 insert(i, *cur);
404 }
405 }
406 }
407
408 // renders transposed adjactor
409 template<typename Adjactor_>
410 void _render_transpose(const Adjactor_& adj)
411 {
412 typedef typename Adjactor_::ImageIterator AImIt;
413
414 // set counts
415 _num_nodes_domain = adj.get_num_nodes_image();
416 _num_nodes_image = adj.get_num_nodes_domain();
418
419 // loop over all image nodes
420 for(Index i(0); i < _num_nodes_image; ++i)
421 {
422 AImIt cur(adj.image_begin(i));
423 AImIt end(adj.image_end(i));
424 for(; cur != end; ++cur)
425 {
426 insert(*cur, i);
427 }
428 }
429 }
430
431 // renders adjactor composition
432 template<
433 typename Adjactor1_,
434 typename Adjactor2_>
435 void _render_as_is(
436 const Adjactor1_& adj1,
437 const Adjactor2_& adj2)
438 {
439 // validate adjactor dimensions
440 XASSERTM(adj1.get_num_nodes_image() == adj2.get_num_nodes_domain(), "Adjactor dimension mismatch!");
441
442 typedef typename Adjactor1_::ImageIterator AImIt1;
443 typedef typename Adjactor2_::ImageIterator AImIt2;
444
445 // set counts
446 _num_nodes_domain = adj1.get_num_nodes_domain();
447 _num_nodes_image = adj2.get_num_nodes_image();
449
450 // loop over all domain nodes
451 for(Index i(0); i < _num_nodes_domain; ++i)
452 {
453 AImIt1 cur1(adj1.image_begin(i));
454 AImIt1 end1(adj1.image_end(i));
455 for(; cur1 != end1; ++cur1)
456 {
457 AImIt2 cur2(adj2.image_begin(*cur1));
458 AImIt2 end2(adj2.image_end(*cur1));
459 for(; cur2 != end2; ++cur2)
460 {
461 insert(i, *cur2);
462 }
463 }
464 }
465 }
466
467 template<
468 typename Adjactor1_,
469 typename Adjactor2_>
470 void _render_transpose(
471 const Adjactor1_& adj1,
472 const Adjactor2_& adj2)
473 {
474 // validate adjactor dimensions
475 XASSERTM(adj1.get_num_nodes_image() == adj2.get_num_nodes_domain(), "Adjactor dimension mismatch!");
476
477 typedef typename Adjactor1_::ImageIterator AImIt1;
478 typedef typename Adjactor2_::ImageIterator AImIt2;
479
480 // set counts
481 _num_nodes_domain = adj2.get_num_nodes_image();
482 _num_nodes_image = adj1.get_num_nodes_domain();
484
485 // loop over all domain nodes
486 for(Index i(0); i < _num_nodes_image; ++i)
487 {
488 AImIt1 cur1(adj1.image_begin(i));
489 AImIt1 end1(adj1.image_end(i));
490 for(; cur1 != end1; ++cur1)
491 {
492 AImIt2 cur2(adj2.image_begin(*cur1));
493 AImIt2 end2(adj2.image_end(*cur1));
494 for(; cur2 != end2; ++cur2)
495 {
496 insert(*cur2, i);
497 }
498 }
499 }
500 }
502
503 /* ******************************************************************* */
504 /* A D J A C T O R I N T E R F A C E I M P L E M E N T A T I O N */
505 /* ******************************************************************* */
506 public:
509 {
510 return _num_nodes_domain;
511 }
512
515 {
516 return _num_nodes_image;
517 }
518
520 inline ImageIterator image_begin(Index domain_node) const
521 {
522 ASSERTM(domain_node < _num_nodes_domain, "Domain node index out of range");
523 return _indices[domain_node].begin();
524 }
525
527 inline ImageIterator image_end(Index domain_node) const
528 {
529 ASSERTM(domain_node < _num_nodes_domain, "Domain node index out of range");
530 return _indices[domain_node].end();
531 }
532 }; // class DynamicGraph
533 } // namespace Adjacency
534} // namespace FEAT
#define ASSERTM(expr, msg)
Debug-Assertion macro definition with custom message.
Definition: assertion.hpp:230
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Dynamic Adjacency Graph implementation.
Index degree(Index domain_node) const
Returns the degree of a domain node.
DynamicGraph(Index num_nodes_domain, Index num_nodes_image)
Constructor.
DynamicGraph(RenderType render_type, const Adjactor1_ &adjactor1, const Adjactor2_ &adjactor2)
Composite-Render constructor.
Index _num_nodes_image
total number of image nodes
DynamicGraph()
default constructor
void clear()
Clears the graph.
bool insert(Index domain_node, Index image_node)
Inserts a new adjacency entry to the graph.
bool exists(Index domain_node, Index image_node) const
Checks whether an adjacency entry exists.
bool erase(Index domain_node, Index image_node)
Erases an adjacency entry from the graph.
Index get_num_nodes_image() const
Returns the number of image nodes.
Index get_num_indices() const
Returns the total number of indices.
Index _num_nodes_domain
total number of domain nodes
ImageIterator image_begin(Index domain_node) const
Returns an iterator for the first adjacent image node.
virtual ~DynamicGraph()
virtual destructor
DynamicGraph(DynamicGraph &&other)
move ctor
void compose(const Adjactor_ &adjactor)
Composes this dynamic graph with another adjactor in-situ.
IdxSet::const_iterator ImageIterator
ImageIterator for Adjactor interface implementation.
DynamicGraph clone() const
Clones this dynamic graph.
DynamicGraph(RenderType render_type, const Adjactor_ &adjactor)
Render constructor.
DynamicGraph & operator=(DynamicGraph &&other)
move-assign operator
IdxSetVec _indices
index-set-vector
Index get_num_nodes_domain() const
Returns the number of domain nodes.
ImageIterator image_end(Index domain_node) const
Returns an iterator for the first position past the last adjacent image node.
Index degree() const
Returns the degree of the graph.
RenderType
Render type enumeration.
Definition: base.hpp:26
@ injectify_sorted
Render-Injectified mode, sort image indices.
@ transpose
Render-Transpose mode.
@ injectify_transpose
Render-Injectified-Transpose mode.
@ injectify_transpose_sorted
Render-Injectified-Transpose mode, sort image indices.
@ injectify
Render-Injectified mode.
@ transpose_sorted
Render-Transpose mode, sort image indices.
@ as_is
Render-As-Is mode.
@ as_is_sorted
Render-As-Is mode, sort image indices.
FEAT namespace.
Definition: adjactor.hpp:12
std::uint64_t Index
Index data type.