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 : 4994 : node_connectivity_t() { } // default cons 35 : : 36 : : //! Non-const-ref accessor to state 37 : : //! \return All node pairs 38 : 15664 : node_list_t& data() { return nodes; } 39 : 15664 : 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 : 2468 : { 48 [ + + ]: 267599 : 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 : 265131 : node_list_value_t value = nodes.size() + empty_node_count; 156 : 265131 : empty_node_count++; 157 : 0 : return value; 158 : : } 159 : : else { 160 : : assert(A != B); 161 : : } 162 : : 163 [ + + ]: 134293 : 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 : 21866 : 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