----------------------------------------------------------------------------- Build a simple dofmap from ElementDofmap based on mesh entity indices (local and global) @param [in] mesh The mesh to build the dofmap on @param [in] topology The mesh topology @param [in] element_dof_layout The layout of dofs on each cell type @return Returns: * dofmaps for each cell type (local to the process) local-t
| 150 | /// @note Entities in the local-to-entity map are represented by the pair: |
| 151 | /// [index_map number, mesh entity index]. |
| 152 | std::tuple<std::vector<dofmap_t>, std::vector<std::int64_t>, |
| 153 | std::vector<std::pair<std::int8_t, std::int32_t>>, |
| 154 | std::vector<std::shared_ptr<const common::IndexMap>>, std::int64_t> |
| 155 | build_basic_dofmaps( |
| 156 | const mesh::Topology& topology, |
| 157 | const std::vector<fem::ElementDofLayout>& element_dof_layouts) |
| 158 | { |
| 159 | // Start timer for dofmap initialization |
| 160 | common::Timer t0("Dofmap builder: init dofmap from element dofmap"); |
| 161 | |
| 162 | // Topological dimension |
| 163 | const std::size_t D = topology.dim(); |
| 164 | const std::size_t num_cell_types = topology.entity_types(D).size(); |
| 165 | |
| 166 | spdlog::info("Checking required entities per dimension"); |
| 167 | |
| 168 | // Find which dimensions (d) and entity types (et) are required |
| 169 | // and the number of dofs which are required for each (d, et) combination. |
| 170 | // Also store the IndexMaps and local offsets for each. |
| 171 | std::vector<std::pair<std::int8_t, std::int8_t>> required_dim_et; |
| 172 | std::vector<std::int32_t> num_entity_dofs_et; |
| 173 | std::vector<std::shared_ptr<const common::IndexMap>> topo_index_maps; |
| 174 | std::vector<std::int32_t> local_entity_offsets{0}; |
| 175 | |
| 176 | std::vector<std::vector<mesh::CellType>> entity_types(D + 1); |
| 177 | for (std::size_t d = 0; d <= D; ++d) |
| 178 | entity_types[d] = topology.entity_types(d); |
| 179 | |
| 180 | for (std::size_t i = 0; i < num_cell_types; ++i) |
| 181 | { |
| 182 | mesh::CellType cell_type = entity_types[D][i]; |
| 183 | const std::vector<std::vector<std::vector<int>>>& entity_dofs |
| 184 | = element_dof_layouts[i].entity_dofs_all(); |
| 185 | |
| 186 | for (std::size_t d = 0; d <= D; ++d) |
| 187 | { |
| 188 | const std::vector<std::vector<int>>& entity_dofs_d = entity_dofs[d]; |
| 189 | for (std::size_t e = 0; e < entity_dofs_d.size(); ++e) |
| 190 | { |
| 191 | if (!entity_dofs_d[e].empty()) |
| 192 | { |
| 193 | // There is a dof on this entity... find entity type index |
| 194 | auto et_it = std::find(entity_types[d].begin(), entity_types[d].end(), |
| 195 | mesh::cell_entity_type(cell_type, d, e)); |
| 196 | assert(et_it != entity_types[d].end()); |
| 197 | int et_index = std::distance(entity_types[d].begin(), et_it); |
| 198 | |
| 199 | auto required_entity_it |
| 200 | = std::find(required_dim_et.begin(), required_dim_et.end(), |
| 201 | std::pair<std::int8_t, std::int8_t>{d, et_index}); |
| 202 | if (required_entity_it == required_dim_et.end()) |
| 203 | { |
| 204 | // Save information for this (d, et) combination |
| 205 | required_dim_et.push_back({d, et_index}); |
| 206 | const std::int32_t num_entity_dofs = entity_dofs_d[e].size(); |
| 207 | num_entity_dofs_et.push_back(num_entity_dofs); |
| 208 | auto im = topology.index_maps(d)[et_index]; |
| 209 | topo_index_maps.push_back(im); |
no test coverage detected