Branch data Line data Source code
1 : : #ifndef AMR_edge_store_h
2 : : #define AMR_edge_store_h
3 : :
4 : : #include <cassert>
5 : :
6 : : #include "Loggers.hpp"
7 : : #include "AMR/AMR_types.hpp"
8 : :
9 : : namespace AMR {
10 : :
11 : : class edge_store_t {
12 : : public:
13 : : // TODO: convert this to an unordered map with a custom hash (can lift from Quinoa)
14 : : edges_t edges;
15 : :
16 : : // Node connectivity does this any way, but in a slightly less efficient way
17 : : // Maps the edge to the child node which splits it
18 : : // This was added retrospectivley to support the operation "for
19 : : // edge formed of initial nodes {A,B}, what node(s) were added
20 : : // between them"
21 : : // NOTE: At some point, this could probably be deleted..
22 : : // NOTE: This is only mainted by split.
23 : : //std::map<edge_t, size_t> children;
24 : :
25 : : size_t size()
26 : : {
27 : : return edges.size();
28 : : }
29 : :
30 : : /**
31 : : * @brief Function to create new edge between two nodes with an
32 : : * intermediate. Given nodes A, B, and AB makes edge A->AB and AB->B
33 : : *
34 : : * @param A First end node
35 : : * @param B Second end node
36 : : * @param AB Intermediate node
37 : : * @param lc Lock case for the new edges
38 : : */
39 : : void split(size_t A, size_t B, size_t AB, Edge_Lock_Case lc)
40 : : {
41 : : trace_out << "Splitting with lock case " << lc << std::endl;
42 : 262386 : generate(A, AB, lc);
43 : 262386 : generate(B, AB, lc);
44 : :
45 : : //children.insert( std::pair<edge_t, size_t>(edge_t(A,B), AB));
46 : : // Generate pertinent keys
47 : : //edge_t keyAB = nodes_to_key(A, B);
48 : :
49 : : // NOTE: This isn't explicitly needed in the paper, and may be
50 : : // implicitly dealt with somewhere?
51 : : //mark_edge_for_refinement(keyAB);
52 : : }
53 : :
54 : : /**
55 : : * @brief Given nodes A and B, generate an edge between them
56 : : *
57 : : * @param A First node
58 : : * @param B Second node
59 : : * @param lc Lock case for new edge
60 : : */
61 [ + + ]: 1136292 : void generate(size_t A, size_t B, Edge_Lock_Case lc)
62 : : {
63 : : if ((A != 0) && (B != 0)) {
64 : : trace_out << "A " << A << " B " << B << std::endl;
65 : : assert(A != B);
66 : : }
67 : :
68 : : // Generate key
69 : : edge_t keyAB = nodes_to_key(A, B);
70 : : //Create refined edge
71 : : Edge_Refinement edgeAB = Edge_Refinement(A, B, false, false, lc);
72 : : // Add edge to store
73 : : add(keyAB, edgeAB);
74 : 1136292 : }
75 : :
76 : : bool exists(edge_t key)
77 : : {
78 [ - - ]: 0 : if (edges.find(key) != edges.end())
79 : : {
80 : : return true;
81 : : }
82 : : return false;
83 : : }
84 : :
85 : : /**
86 : : * @brief Function to retrieve an edge from the edge store
87 : : *
88 : : * @param key Key of the edge to get
89 : : *
90 : : * @return A reference to the fetched edge
91 : : */
92 : 25971595 : Edge_Refinement& get(edge_t key)
93 : : {
94 : : //trace_out << "get edge " << key << std::endl;
95 : : // cppcheck-suppress assertWithSideEffect
96 : 25971595 : if (!exists(key)) trace_out << "key not found " << key.first()
97 : : << " - " << key.second() << std::endl;
98 : : assert( exists(key) );
99 : 25971595 : return edges[key];
100 : : }
101 : :
102 : : Edge_Lock_Case lock_case(const edge_t& key)
103 : : {
104 [ - - ][ + + ]: 597 : return get(key).lock_case;
105 : : }
106 : :
107 : : void erase(edge_t key)
108 : : {
109 : : trace_out << "Deref removing edge: " << key.first() << " - "
110 : : << key.second() << std::endl;
111 : : edges.erase(key);
112 : : }
113 : :
114 : : /**
115 : : * @brief Function to add edge to edge store
116 : : *
117 : : * @param key The key for the given edge
118 : : * @param e The edge data
119 : : *
120 : : * Note: This tolerate the addition of duplicate edges
121 : : */
122 : : void add(edge_t key, Edge_Refinement e)
123 : : {
124 : : // Add edge if it doesn't exist (default behavior of insert)
125 : 2986986 : edges.insert( std::pair<edge_t, Edge_Refinement>(key, e));
126 : :
127 : : // TODO: It may be worth adding a check here to ensure if we're
128 : : // trying to add a new edge that exists it should contain the
129 : : // same data
130 : : }
131 : :
132 : : static edge_t nodes_to_key(size_t A, size_t B)
133 : : {
134 : 4121640 : return edge_t(A,B);
135 : : }
136 : :
137 : : /**
138 : : * @brief Function to build a string key from two node ids
139 : : * NOTE: Regardless of order of arguments, the same key will be generated
140 : : */
141 : : //static std::string nodes_to_key(size_t A, size_t B)
142 : : //{
143 : : //return std::to_string(std::min(A,B)) + KEY_DELIM + std::to_string(std::max(A,B));
144 : : //}
145 : :
146 : : /**
147 : : * @brief function to take the nodes representing a face
148 : : * and to build the possible edges based on that
149 : : *
150 : : * For a given face {ABC}, generate the edge pairs {AB, AC, BC}
151 : : *
152 : : * @param face_ids The ids of the face to generate this for
153 : : *
154 : : * @return A (partially filled) list of all edges present on the
155 : : * face
156 : : */
157 : : // FIXME: Is it OK that it leaves some of the array blank?
158 : 22652 : static edge_list_t generate_keys_from_face_ids(face_ids_t face_ids)
159 : : {
160 : : edge_list_t key_list;
161 : 22652 : size_t A = face_ids[0];
162 : 22652 : size_t B = face_ids[1];
163 [ + + ]: 22652 : size_t C = face_ids[2];
164 : :
165 : : edge_t key = nodes_to_key(A,B);
166 [ + + ]: 22652 : key_list[0] = key; // TODO: Is it OK to use copy assignment here?
167 : :
168 : : key = nodes_to_key(A,C);
169 [ + + ]: 22652 : key_list[1] = key;
170 : :
171 : : key = nodes_to_key(B,C);
172 : 22652 : key_list[2] = key;
173 : :
174 : 22652 : return key_list;
175 : : }
176 : :
177 : : /**
178 : : * @brief function to take a list of edge and mark them all
179 : : * as needing to be refined
180 : : *
181 : : * @param ids List of ids to mark for refinement
182 : : */
183 : : void mark_edges_for_refinement(std::vector<node_pair_t> ids) {
184 : : for (const auto& id : ids)
185 : : {
186 : : edge_t key = nodes_to_key(id[0], id[1]);
187 : :
188 : : mark_for_refinement(key);
189 : : trace_out << get(key).needs_refining << std::endl;
190 : : }
191 : : }
192 : :
193 : :
194 : : /**
195 : : * @brief function to mark a single edge as needing
196 : : * refinement (provides a nice abstraction from messing with the
197 : : * struct directly).
198 : : *
199 : : * @param key The edge key to mark as refinement
200 : : */
201 : : void mark_for_refinement(const edge_t& key)
202 : : {
203 : : // cppcheck-suppress assertWithSideEffect
204 : : assert( exists(key) );
205 [ + - ]: 683668 : get(key).needs_refining = 1;
206 : 1381 : }
207 : :
208 : : /**
209 : : * @brief function to take a list of edge and mark them all
210 : : * as needing to be refined as a part of the 8:4 derefinement
211 : : *
212 : : * @param ids List of ids to mark for deref-refinement
213 : : */
214 : 0 : void mark_edges_for_deref_ref(std::vector<node_pair_t> ids)
215 : : {
216 [ - - ]: 0 : for (const auto& id : ids)
217 : : {
218 [ - - ]: 0 : edge_t key = nodes_to_key(id[0], id[1]);
219 : :
220 : : // cppcheck-suppress assertWithSideEffect
221 : : assert( exists(key) );
222 : : // value of 2 for needs_refining indicates part of derefine
223 : 0 : get(key).needs_refining = 2;
224 : :
225 : : trace_out << "edge: " << key.get_data()[0] << "-"
226 : : << key.get_data()[1] << " deref-ref: "
227 : : << get(key).needs_refining << std::endl;
228 : : }
229 : 0 : }
230 : :
231 : : /**
232 : : * @brief Function to unmark and edge as needing refinement
233 : : *
234 : : * @param key The key representing the edge to unmark
235 : : */
236 : : void unmark_for_refinement(const edge_t& key)
237 : : {
238 : : // cppcheck-suppress assertWithSideEffect
239 : : assert( exists(key) );
240 [ + - ]: 30847 : get(key).needs_refining = 0;
241 : 20461 : }
242 : :
243 : : /**
244 : : * @brief For a given list of node pairs, mark the edge as needing
245 : : * to be de-refined
246 : : *
247 : : * @param ids a vector of pairs to mark for derefinement
248 : : */
249 : : void mark_edges_for_derefinement(std::vector<node_pair_t> ids) {
250 : : for (const auto& id : ids)
251 : : {
252 : : edge_t key = nodes_to_key(id[0], id[1]);
253 : :
254 : : mark_edge_for_derefinement(key);
255 : : }
256 : : }
257 : : void mark_edge_for_derefinement(const edge_t& key) {
258 : : get(key).needs_derefining = true;
259 : : }
260 : :
261 : :
262 : : /**
263 : : * @brief Function to generate a list of edge keys from a tet
264 : : *
265 : : * @param tet The tet to generate edge pairs for
266 : : *
267 : : * @return A list (array) of edge keys which can be separated out to
268 : : * name the two composing node ids
269 : : */
270 : 4335491 : edge_list_t generate_keys(tet_t tet)
271 : : {
272 : : // FIXME : Generate these with a (2d) loop and not hard code them?
273 : : edge_list_t key_list;
274 : :
275 : 4335491 : size_t A = tet[0];
276 : 4335491 : size_t B = tet[1];
277 : 4335491 : size_t C = tet[2];
278 [ + + ]: 4335491 : size_t D = tet[3];
279 : :
280 : : edge_t key;
281 : :
282 : : key = nodes_to_key(A,B);
283 [ + + ]: 4335491 : key_list[0] = key;
284 : :
285 : : key = nodes_to_key(A,C);
286 [ + + ]: 4335491 : key_list[1] = key;
287 : :
288 : : key = nodes_to_key(A,D);
289 [ + + ]: 4335491 : key_list[2] = key;
290 : :
291 : : key = nodes_to_key(B,C);
292 [ + + ]: 4335491 : key_list[3] = key;
293 : :
294 : : key = nodes_to_key(B,D);
295 [ + + ]: 4335491 : key_list[4] = key;
296 : :
297 : : key = nodes_to_key(C,D);
298 : 4335491 : key_list[5] = key;
299 : :
300 : 4335491 : return key_list;
301 : : }
302 : :
303 : : /**
304 : : * @brief Helper debug function to print edge information
305 : : */
306 : : void print() {
307 : : for (const auto& kv : edges)
308 : : {
309 : : trace_out << "edge " << kv.first << " between " <<
310 : : kv.second.A << " and " << kv.second.B <<
311 : : std::endl;
312 : : }
313 : : }
314 : : };
315 : : }
316 : :
317 : : #endif // AMR_edge_store
|