1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144 | #ifndef AMR_id_generator_h
#define AMR_id_generator_h
#include <limits><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <cassert><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
// TODO: make this have a base class to support multiple generator schemes
// using the policy design pattern
namespace AMR {
class id_generator_t {
public:
size_t start_id;
// Used to track which tet_id to give the next parent
// The range between this and get_child_id(this) determinate how
// many tets can be on the first level
size_t next_tet_id;
// Constructor
explicit id_generator_t(size_t start_tet_id = 0) :
start_id(start_tet_id),
next_tet_id(start_id)
{
}
/**
* @brief Helper function to generate tet ids
*
* @return Id of the next tet
*/
size_t get_next_tet_id()
{
return next_tet_id++;
}
/**
* Helper function to get all the child ids for a given parent
*
* WARNING: If you don't use all the children you ask for, you may have a bad time...
*
* @param parent_id The id of the parent
* @param count Number of children
*
* @return The list of children ids
*/
child_id_list_t generate_child_ids(size_t parent_id, size_t count = MAX_CHILDREN)<--- Parent function 'id_generator_t::generate_child_ids'
{
child_id_list_t c;
c.resize(count);
c[0] = parent_id; // FIXME: Remove this hack which suppresses warning
for (auto& i : c)
{
// cppcheck-suppress useStlAlgorithm
i = get_next_tet_id();
}
return c;
}
};
class morton_id_generator_t : public id_generator_t
{
public:
// This can be calculated as something like floor( num_bits - log_2(START_TET_ID) ) / log_2(MAX_CHILDREN)
// So for a simulation which supports an initial grid of ~1,048,576 elements in 3D:
// (64 - 20) / 3 = 14
// This basically says the number of tets which can be in an initial grid
// A sensible value is 2^20 (1,048,576) for big simulations, and anything
// smaller for toy problems
#define START_TET_ID 1024
// Constructor to reset START_TET_ID on the new value
morton_id_generator_t() : id_generator_t(START_TET_ID) {
// Empty
}
/**
* @brief Helper function to convert from parent id to (base) child
* id
*
* @param parent_id Id of parent
*
* @return Id of child
*/
static size_t get_child_id(size_t parent_id)
{
return parent_id << ID_SHIFT;
}
/**
* @brief Helper function to get the all the child ids for a given
* parent
*
* @param parent_id The id of the parent
* @param count Number of children
*
* @return The list of children ids
*/
static child_id_list_t generate_child_ids(size_t parent_id, size_t count = MAX_CHILDREN)<--- Derived function 'morton_id_generator_t::generate_child_ids'
{
child_id_list_t c;
c.resize(count);
for (size_t i = 0; i < count; i++)
{
c[i] = get_child_id(parent_id, i);
}
return c;
}
/**
* @brief Helper function to get the child id of a specific child
* of a parent
*
* @param parent_id id of the parent
* @param offset offset into the parent list (i.e number of child)
*
* @return the id of the given child
*/
static size_t get_child_id(size_t parent_id, size_t offset)
{
// Try detect overflow
assert( parent_id <= get_parent_id(std::numeric_limits<size_t>::max()));
return get_child_id(parent_id) + offset;
}
/**
* @brief Helper function to get the parent id of a child
*
* @param child_id Child for whom we should find the parent
*
* @return The parent id
*/
static size_t get_parent_id(size_t child_id)
{
return (child_id >> ID_SHIFT);
}
};
}
#endif // guard
|