Branch data Line data Source code
1 : : #ifndef AMR_node_connectivity_h
2 : : #define AMR_node_connectivity_h
3 : :
4 : : #include <unordered_map>
5 : : #include <UnsMesh.hpp>
6 : :
7 : : namespace AMR {
8 : :
9 : : /**
10 : : * @brief This class stores the connectivity of the node. Simply what this
11 : : * means is that it just a mapping of node ids to a unique index. The
12 : : * value of the map is the index, and the key is the two nodes the new node
13 : : * joins
14 : : */
15 : 0 : class node_connectivity_t {
16 : :
17 : : private:
18 : : //using Hash = tk::UnsMesh::Hash;
19 : : //using Eq = tk::UnsMesh::Eq;
20 : :
21 : : using node_list_key_t = node_pair_t;
22 : : using node_list_value_t = size_t;
23 : : using node_list_t = std::unordered_map<node_list_key_t, node_list_value_t, tk::UnsMesh::Hash<2>, tk::UnsMesh::Eq<2>>;
24 : : using inv_node_list_t = std::unordered_map<node_list_value_t, node_list_key_t>;
25 : :
26 : : node_list_t nodes;
27 : : inv_node_list_t inv_nodes;
28 : :
29 : : public:
30 : :
31 : : size_t empty_node_count = 0;
32 : :
33 : :
34 : 4495 : node_connectivity_t() { } // default cons
35 : :
36 : : //! Non-const-ref accessor to state
37 : : //! \return All node pairs
38 : 14279 : node_list_t& data() { return nodes; }
39 : 14279 : inv_node_list_t& inv_data() { return inv_nodes; }
40 : :
41 : : /**
42 : : * @brief Method to add initial nodes to the store
43 : : *
44 : : * @param initial_size Size of the list to fill to
45 : : */
46 : : explicit node_connectivity_t(size_t initial_size)
47 : 2585 : {
48 [ + + ]: 307551 : for (size_t i = 0; i < initial_size; i++)
49 : : {
50 : : // These can initially be 0 as initial nodes don't join any
51 : : // two others.. this could be updated to track
52 : : // intermediates, but this currently tracks "added" nodes
53 : : // nicely
54 : : add(0,0);
55 : : }
56 : : }
57 : :
58 : : /**
59 : : * @brief Return size of node container -- the number of nodes
60 : : *
61 : : * @return Number of nodes
62 : : */
63 : : size_t size()
64 : : {
65 : : return nodes.size();
66 : : }
67 : :
68 : : /**
69 : : * @brief Getter into node storage *VALUE*
70 : : *
71 : : * @param id VALUE of the node to get
72 : : *
73 : : * @return The node_pair at the given id
74 : : */
75 : : node_pair_t get(size_t id)
76 : : {
77 : : //trace_out << "PROBLEM FINDING ID " << id << std::endl;
78 : :
79 : : // Ban getting of a node whos parents are {0,0}
80 : : //assert(id > empty_node_count-1); //[0..empty_node_counts)
81 : :
82 : : auto iter = inv_nodes.find(id);
83 : :
84 : : /* old linear search code
85 : : auto it = nodes.begin();
86 : : for (; it != nodes.end(); ++it) {
87 : : if (it->second == id) break;
88 : : }
89 : : */
90 : :
91 : : //assert(iter != inv_nodes.end());
92 : : //return iter->second;
93 [ + + ][ + - ]: 2574826 : return (iter != inv_nodes.end() ? iter->second : node_pair_t{{id,id}});
[ - - ]
94 : : }
95 : :
96 : : /**
97 : : * @brief function to calculate which node is opposite a
98 : : * tet face
99 : : *
100 : : * @param face_list A list of faces on the tet
101 : : * @param opposite_index The index for the face you want to know
102 : : * the opposite node for
103 : : *
104 : : * @return An index (0-3) to tell you if A, B, C, or D
105 : : * (respectively) is opposite the given face_list_t
106 : : *
107 : : * This function is tightly coupled (too coupled) to generate_face_lists
108 : : *
109 : : * generate_face_lists generates the faces {ABC, ABD, ACD, BCD} in
110 : : * a fixed order. Opposite_index says the face from a face list we
111 : : * care about. This function returns a number in the range {0,3} to
112 : : * tell you which node is missing from that face.
113 : : *
114 : : * I.e If opposite_index is 1, Node C is missing => 2.
115 : : */
116 : : static size_t face_list_opposite(face_list_t face_list, size_t opposite_index)
117 : : {
118 : : // FIXME: make this actually inspect the face_list and be much
119 : : // more robust...
120 : : size_t result = face_list[0][0];
121 : : switch(opposite_index)
122 : : {
123 : : case 0: // ABC
124 : : result = 3;
125 : : break;
126 : : case 1: // ABD
127 : : result = 2;
128 : : break;
129 : : case 2: // ACD
130 : : result = 1;
131 : : break;
132 : : case 3: // BCD
133 : : result = 0;
134 : : break;
135 : : default: // something went horribly wrong..
136 : : assert(0);
137 : : break;
138 : : }
139 : : return result;
140 : : }
141 : :
142 : : /**
143 : : * @brief Add connectivity, unless it already exists
144 : : *
145 : : * @param A First node
146 : : * @param B Second node
147 : : *
148 : : * @return Id/unique identifier of the node
149 : : */
150 : 83956 : node_list_value_t add(size_t A, size_t B)
151 : : {
152 [ + + ][ - + ]: 83956 : if ((A == 0) && (B == 0))
153 : : {
154 : : trace_out << "empty nodes = " << empty_node_count << std::endl;
155 : 304966 : node_list_value_t value = nodes.size() + empty_node_count;
156 : 304966 : empty_node_count++;
157 : 0 : return value;
158 : : }
159 : : else {
160 : : assert(A != B);
161 : : }
162 : :
163 : 83956 : node_list_key_t key = {{std::min(A,B), std::max(A,B)}};
164 : : auto iter = nodes.find(key);
165 : :
166 : : trace_out << "A " << A << " B " << B << std::endl;
167 : :
168 : : // return the corresponding value if we find the key in the map
169 [ + + ]: 83956 : if(iter != nodes.end()) {
170 : : trace_out << "Reuse " << iter->second << std::endl;
171 : 62090 : return iter->second;
172 : : }
173 : : else {
174 : : // if not in map
175 [ + - ]: 21866 : node_list_value_t value = nodes.size() + empty_node_count;
176 [ + - ]: 21866 : nodes[key] = value;
177 : 21866 : inv_nodes[value] = key;
178 : : trace_out << "Made new node " << value << std::endl;
179 : : return value;
180 : : }
181 : : }
182 : :
183 : : /**
184 : : * @brief Print connectivity a id: a-b
185 : : */
186 : : void print()
187 : : {
188 : : // std::cout << "Connectivity" << std::endl;
189 : : // for (size_t i = 0; i < size(); i ++)
190 : : // {
191 : : // std::cout << i << ": A " << get(i)[0] << " B " << get(i)[1] << std::endl;
192 : : // }
193 : : }
194 : :
195 : : };
196 : : }
197 : :
198 : : #endif // guard
|