ClusterTree.hpp
Go to the documentation of this file.
1/*
2 * STRUMPACK -- STRUctured Matrices PACKage, Copyright (c) 2014, The
3 * Regents of the University of California, through Lawrence Berkeley
4 * National Laboratory (subject to receipt of any required approvals
5 * from the U.S. Dept. of Energy). All rights reserved.
6 *
7 * If you have questions about your rights to use or distribute this
8 * software, please contact Berkeley Lab's Technology Transfer
9 * Department at TTD@lbl.gov.
10 *
11 * NOTICE. This software is owned by the U.S. Department of Energy. As
12 * such, the U.S. Government has been granted for itself and others
13 * acting on its behalf a paid-up, nonexclusive, irrevocable,
14 * worldwide license in the Software to reproduce, prepare derivative
15 * works, and perform publicly and display publicly. Beginning five
16 * (5) years after the date permission to assert copyright is obtained
17 * from the U.S. Department of Energy, and subject to any subsequent
18 * five (5) year renewals, the U.S. Government is granted for itself
19 * and others acting on its behalf a paid-up, nonexclusive,
20 * irrevocable, worldwide license in the Software to reproduce,
21 * prepare derivative works, distribute copies to the public, perform
22 * publicly and display publicly, and to permit others to do so.
23 *
24 * Developers: Pieter Ghysels, Francois-Henry Rouet, Xiaoye S. Li.
25 * (Lawrence Berkeley National Lab, Computational Research
26 * Division).
27 *
28 */
33#ifndef CLUSTER_TREE_HPP
34#define CLUSTER_TREE_HPP
35
36#include <vector>
37#include <unordered_map>
38#include <cassert>
39#include <iostream>
40
41#include "StrumpackConfig.hpp"
42#if defined(STRUMPACK_USE_MPI)
43#include "misc/MPIWrapper.hpp"
44#endif
45
46namespace strumpack {
47 namespace structured {
48
68 public:
73 int size;
74
80 std::vector<ClusterTree> c;
81
85 ClusterTree() : size(0) {}
86
94 ClusterTree(int n) : size(n) {}
95
104 const ClusterTree& refine(int leaf_size) {
105 assert(c.empty());
106 if (size >= 2*leaf_size) {
107 c.resize(2);
108 c[0].size = size/2;
109 c[0].refine(leaf_size);
110 c[1].size = size - size/2;
111 c[1].refine(leaf_size);
112 }
113 return *this;
114 }
115
119 void print() const {
120 for (auto& ch : c) ch.print();
121 std::cout << size << " ";
122 }
123
130 int nodes() const {
131 int nr_nodes = 1;
132 for (auto& ch : c)
133 nr_nodes += ch.nodes();
134 return nr_nodes;
135 }
136
142 int levels() const {
143 int lvls = 0;
144 for (auto& ch : c)
145 lvls = std::max(lvls, ch.levels());
146 return lvls + 1;
147 }
148
158 truncate_complete_rec(1, min_levels());
159 }
160
176 void expand_complete(bool allow_zero_nodes) {
177 expand_complete_rec(1, levels(), allow_zero_nodes);
178 }
179
187 void expand_complete_levels(int lvls) {
188 expand_complete_levels_rec(1, lvls);
189 }
190
200 template<typename integer_t> static ClusterTree
201 deserialize(const std::vector<integer_t>& buf) {
202 return deserialize(buf.data());
203 }
204
214 template<typename integer_t> static ClusterTree
215 deserialize(const integer_t* buf) {
216 ClusterTree t;
217 int n = buf[0];
218 int pid = n-1;
219 t.de_serialize_rec(buf+1, buf+n+1, buf+2*n+1, pid);
220 return t;
221 }
222
233 std::vector<int> serialize() const {
234 int n = nodes(), pid = 0;
235 std::vector<int> buf(3*n+1);
236 buf[0] = n;
237 serialize_rec(buf.data()+1, buf.data()+n+1, buf.data()+2*n+1, pid);
238 return buf;
239 }
240
241#if defined(STRUMPACK_USE_MPI)
242 void broadcast(const MPIComm& comm) {
243 if (comm.is_root()) {
244 auto v = serialize();
245 auto vsize = v.size();
246 comm.broadcast(vsize);
247 comm.broadcast(v);
248 } else {
249 std::size_t vsize = 0;
250 comm.broadcast(vsize);
251 std::vector<int> v(vsize);
252 comm.broadcast(v);
253 *this = deserialize(v);
254 }
255 }
256#endif
257
264 bool is_complete() const {
265 if (c.empty()) return true;
266 else return c[0].levels() == c[1].levels();
267 }
268
274 template<typename integer_t>
275 std::vector<integer_t> leaf_sizes() const {
276 std::vector<integer_t> lf;
277 leaf_sizes_rec(lf);
278 return lf;
279 }
280
288 std::pair<std::vector<int>,std::vector<int>>
290 int n = (1 << lvls) - 1;
291 std::vector<int> map0(n, -1), map1(n, -1);
292 int leaf = 0;
293 complete_to_orig_rec(1, map0, map1, leaf);
294 for (int i=0; i<n; i++) {
295 if (map0[i] == -1) map0[i] = map0[(i+1)/2-1];
296 if (map1[i] == -1) map1[i] = map1[(i+1)/2-1];
297 }
298 // std::cout << "nodes=" << nodes() << " levels()=" << levels()
299 // << " lvls=" << lvls << " map0/map1 = [";
300 // for (int i=0; i<n; i++)
301 // std::cout << map0[i] << "/" << map1[i] << " ";
302 // std::cout << std::endl;
303 return {map0, map1};
304 }
305
306 private:
307 int min_levels() const {
308 int lvls = levels();
309 for (auto& ch : c)
310 lvls = std::min(lvls, 1 + ch.min_levels());
311 return lvls;
312 }
313 void truncate_complete_rec(int lvl, int lvls) {
314 if (lvl == lvls) c.clear();
315 else
316 for (auto& ch : c)
317 ch.truncate_complete_rec(lvl+1, lvls);
318 }
319 void expand_complete_rec(int lvl, int lvls, bool allow_zero_nodes) {
320 if (c.empty()) {
321 if (lvl != lvls) {
322 c.resize(2);
323 if (allow_zero_nodes) {
324 c[0].size = size;
325 c[1].size = 0;
326 } else {
327 int l1 = 1 << (lvls - lvl - 1);
328 c[0].size = size - l1;
329 c[1].size = l1;
330 }
331 c[0].expand_complete_rec(lvl+1, lvls, allow_zero_nodes);
332 c[1].expand_complete_rec(lvl+1, lvls, allow_zero_nodes);
333 }
334 } else
335 for (auto& ch : c)
336 ch.expand_complete_rec(lvl+1, lvls, allow_zero_nodes);
337 }
338
339 void complete_to_orig_rec
340 (int id, std::vector<int>& map0, std::vector<int>& map1,
341 int& leaf) const {
342 if (c.empty()) map0[id-1] = map1[id-1] = leaf++;
343 else {
344 c[0].complete_to_orig_rec(id*2, map0, map1, leaf);
345 c[1].complete_to_orig_rec(id*2+1, map0, map1, leaf);
346 map0[id-1] = map0[id*2-1];
347 map1[id-1] = map1[id*2];
348 }
349 }
350
351 void expand_complete_levels_rec(int lvl, int lvls) {
352 if (c.empty()) {
353 if (lvl != lvls) {
354 c.resize(2);
355 c[0].size = size / 2;
356 c[1].size = size - size / 2;
357 c[0].expand_complete_levels_rec(lvl+1, lvls);
358 c[1].expand_complete_levels_rec(lvl+1, lvls);
359 }
360 } else
361 for (auto& ch : c)
362 ch.expand_complete_levels_rec(lvl+1, lvls);
363 }
364 template<typename integer_t>
365 void leaf_sizes_rec(std::vector<integer_t>& lf) const {
366 for (auto& ch : c)
367 ch.leaf_sizes_rec(lf);
368 if (c.empty())
369 lf.push_back(size);
370 }
371 void serialize_rec(int* sizes, int* lchild, int* rchild, int& pid) const {
372 if (!c.empty()) {
373 c[0].serialize_rec(sizes, lchild, rchild, pid);
374 auto lroot = pid;
375 c[1].serialize_rec(sizes, lchild, rchild, pid);
376 lchild[pid] = lroot-1;
377 rchild[pid] = pid-1;
378 } else lchild[pid] = rchild[pid] = -1;
379 sizes[pid++] = size;
380 }
381
382 template<typename integer_t> void de_serialize_rec
383 (const integer_t* sizes, const integer_t* lchild,
384 const integer_t* rchild, int& pid) {
385 size = sizes[pid--];
386 if (rchild[pid+1] != -1) {
387 c.resize(2);
388 c[1].de_serialize_rec(sizes, lchild, rchild, pid);
389 c[0].de_serialize_rec(sizes, lchild, rchild, pid);
390 }
391 }
392 };
393
394 } // end namespace structured
395} // end namespace strumpack
396
397#endif
Contains some simple C++ MPI wrapper utilities.
Wrapper class around an MPI_Comm object.
Definition: MPIWrapper.hpp:194
bool is_root() const
Definition: MPIWrapper.hpp:293
The cluster tree, or partition tree that represents the partitioning of the rows or columns of a hier...
Definition: ClusterTree.hpp:67
bool is_complete() const
Definition: ClusterTree.hpp:264
const ClusterTree & refine(int leaf_size)
Definition: ClusterTree.hpp:104
void expand_complete(bool allow_zero_nodes)
Definition: ClusterTree.hpp:176
std::pair< std::vector< int >, std::vector< int > > map_from_complete_to_leafs(int lvls) const
Definition: ClusterTree.hpp:289
void print() const
Definition: ClusterTree.hpp:119
void truncate_complete()
Definition: ClusterTree.hpp:157
static ClusterTree deserialize(const integer_t *buf)
Definition: ClusterTree.hpp:215
std::vector< integer_t > leaf_sizes() const
Definition: ClusterTree.hpp:275
std::vector< int > serialize() const
Definition: ClusterTree.hpp:233
int levels() const
Definition: ClusterTree.hpp:142
ClusterTree()
Definition: ClusterTree.hpp:85
static ClusterTree deserialize(const std::vector< integer_t > &buf)
Definition: ClusterTree.hpp:201
int size
Definition: ClusterTree.hpp:73
ClusterTree(int n)
Definition: ClusterTree.hpp:94
int nodes() const
Definition: ClusterTree.hpp:130
std::vector< ClusterTree > c
Definition: ClusterTree.hpp:80
void expand_complete_levels(int lvls)
Definition: ClusterTree.hpp:187
Definition: StrumpackOptions.hpp:43