Note: this is documentation for an old release. View the latest documentation at docs.fenicsproject.org/dolfinx/v0.9.0/cpp/doxygen/d3/d8b/Geometry_8h_source.html
DOLFINx 0.7.3
DOLFINx C++ interface
Loading...
Searching...
No Matches
Geometry.h
1// Copyright (C) 2006-2022 Anders Logg and Garth N. Wells
2//
3// This file is part of DOLFINx (https://www.fenicsproject.org)
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6
7#pragma once
8
9#include "Topology.h"
10#include <basix/mdspan.hpp>
11#include <concepts>
12#include <cstdint>
13#include <dolfinx/common/IndexMap.h>
14#include <dolfinx/common/MPI.h>
15#include <dolfinx/common/sort.h>
16#include <dolfinx/fem/CoordinateElement.h>
17#include <dolfinx/fem/ElementDofLayout.h>
18#include <dolfinx/fem/dofmapbuilder.h>
19#include <dolfinx/graph/AdjacencyList.h>
20#include <dolfinx/graph/partition.h>
21#include <functional>
22#include <memory>
23#include <span>
24#include <utility>
25#include <vector>
26
27namespace dolfinx::mesh
28{
29
31template <std::floating_point T>
33{
34public:
36 using value_type = T;
37
50 template <typename U, typename V, typename W>
51 requires std::is_convertible_v<std::remove_cvref_t<U>,
52 std::vector<std::int32_t>>
53 and std::is_convertible_v<std::remove_cvref_t<V>,
54 std::vector<T>>
55 and std::is_convertible_v<std::remove_cvref_t<W>,
56 std::vector<std::int64_t>>
57 Geometry(std::shared_ptr<const common::IndexMap> index_map, U&& dofmap,
58 const std::vector<fem::CoordinateElement<
59 typename
60
61 std::remove_reference_t<typename V::value_type>>>& elements,
62 V&& x, int dim, W&& input_global_indices)
63 : _dim(dim), _dofmap(std::forward<U>(dofmap)), _index_map(index_map),
64 _cmaps(elements), _x(std::forward<V>(x)),
65 _input_global_indices(std::forward<W>(input_global_indices))
66 {
67 assert(_x.size() % 3 == 0);
68 if (_x.size() / 3 != _input_global_indices.size())
69 throw std::runtime_error("Geometry size mis-match");
70 }
71
73 Geometry(const Geometry&) = default;
74
76 Geometry(Geometry&&) = default;
77
79 ~Geometry() = default;
80
82 Geometry& operator=(const Geometry&) = delete;
83
86
88 int dim() const { return _dim; }
89
91 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
92 const std::int32_t,
93 MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>
94 dofmap() const
95 {
96 int ndofs = _cmaps[0].dim();
97 return MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
98 const std::int32_t,
99 MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>(
100 _dofmap.data(), _dofmap.size() / ndofs, ndofs);
101 }
102
104 std::shared_ptr<const common::IndexMap> index_map() const
105 {
106 return _index_map;
107 }
108
113 std::span<const value_type> x() const { return _x; }
114
120 std::span<value_type> x() { return _x; }
121
125 const std::vector<fem::CoordinateElement<value_type>>& cmaps() const
126 {
127 return _cmaps;
128 }
129
131 const std::vector<std::int64_t>& input_global_indices() const
132 {
133 return _input_global_indices;
134 }
135
136private:
137 // Geometric dimension
138 int _dim;
139
140 // Map per cell for extracting coordinate data
141 std::vector<std::int32_t> _dofmap;
142
143 // IndexMap for geometry 'dofmap'
144 std::shared_ptr<const common::IndexMap> _index_map;
145
146 // The coordinate elements
147 std::vector<fem::CoordinateElement<value_type>> _cmaps;
148
149 // Coordinates for all points stored as a contiguous array (row-major,
150 // column size = 3)
151 std::vector<value_type> _x;
152
153 // Global indices as provided on Geometry creation
154 std::vector<std::int64_t> _input_global_indices;
155};
156
177template <typename U>
180 MPI_Comm comm, const Topology& topology,
181 const std::vector<fem::CoordinateElement<
182 std::remove_reference_t<typename U::value_type>>>& elements,
183 const graph::AdjacencyList<std::int64_t>& cell_nodes, const U& x, int dim,
184 std::function<std::vector<int>(const graph::AdjacencyList<std::int32_t>&)>
185 reorder_fn
186 = nullptr)
187{
188 // TODO: make sure required entities are initialised, or extend
189 // fem::build_dofmap_data
190
191 std::vector<fem::ElementDofLayout> dof_layouts;
192 for (auto e : elements)
193 dof_layouts.push_back(e.create_dof_layout());
194
195 // Build 'geometry' dofmap on the topology
196 auto [_dof_index_map, bs, dofmap]
197 = fem::build_dofmap_data(comm, topology, dof_layouts, reorder_fn);
198 auto dof_index_map
199 = std::make_shared<common::IndexMap>(std::move(_dof_index_map));
200
201 // If the mesh has higher order geometry, permute the dofmap
202 if (elements[0].needs_dof_permutations())
203 {
204 if (elements.size() > 1)
205 throw std::runtime_error("Unsupported for Mixed Topology");
206 const int D = topology.dim();
207 const int num_cells = topology.connectivity(D, 0)->num_nodes();
208 const std::vector<std::uint32_t>& cell_info
209 = topology.get_cell_permutation_info();
210
211 int dim = elements[0].dim();
212 for (std::int32_t cell = 0; cell < num_cells; ++cell)
213 {
214 std::span<std::int32_t> dofs(dofmap.data() + cell * dim, dim);
215 elements[0].unpermute_dofs(dofs, cell_info[cell]);
216 }
217 }
218
219 auto remap_data
220 = [](auto comm, auto& cell_nodes, auto& x, int dim, auto& dofmap)
221 {
222 // Build list of unique (global) node indices from adjacency list
223 // (geometry nodes)
224 std::vector<std::int64_t> indices = cell_nodes.array();
225 dolfinx::radix_sort(std::span(indices));
226 indices.erase(std::unique(indices.begin(), indices.end()), indices.end());
227
228 // Distribute node coordinates by global index from other ranks.
229 // Order of coords matches order of the indices in 'indices'.
230 std::vector coords = dolfinx::MPI::distribute_data(comm, indices, x, dim);
231
232 // Compute local-to-global map from local indices in dofmap to the
233 // corresponding global indices in cell_nodes
234 std::vector l2g
235 = graph::build::compute_local_to_global(cell_nodes.array(), dofmap);
236
237 // Compute local (dof) to local (position in coords) map from (i)
238 // local-to-global for dofs and (ii) local-to-global for entries in
239 // coords
240 std::vector l2l = graph::build::compute_local_to_local(l2g, indices);
241
242 // Allocate space for input global indices and copy data
243 std::vector<std::int64_t> igi(indices.size());
244 std::transform(l2l.cbegin(), l2l.cend(), igi.begin(),
245 [&indices](auto index) { return indices[index]; });
246
247 return std::tuple(std::move(coords), std::move(l2l), std::move(igi));
248 };
249
250 auto [coords, l2l, igi] = remap_data(comm, cell_nodes, x, dim, dofmap);
251
252 // Build coordinate dof array, copying coordinates to correct
253 // position
254 assert(coords.size() % dim == 0);
255 const std::size_t shape0 = coords.size() / dim;
256 const std::size_t shape1 = dim;
257 std::vector<typename std::remove_reference_t<typename U::value_type>> xg(
258 3 * shape0, 0);
259 for (std::size_t i = 0; i < shape0; ++i)
260 {
261 std::copy_n(std::next(coords.cbegin(), shape1 * l2l[i]), shape1,
262 std::next(xg.begin(), 3 * i));
263 }
264
266 dof_index_map, std::move(dofmap), elements, std::move(xg), dim,
267 std::move(igi));
268}
269
278template <std::floating_point T>
279std::pair<mesh::Geometry<T>, std::vector<int32_t>>
280create_subgeometry(const Topology& topology, const Geometry<T>& geometry,
281 int dim, std::span<const std::int32_t> subentity_to_entity)
282{
283 if (geometry.cmaps().size() > 1)
284 throw std::runtime_error("Mixed topology not supported");
285
286 // Get the geometry dofs in the sub-geometry based on the entities in
287 // sub-geometry
288 const fem::ElementDofLayout layout = geometry.cmaps()[0].create_dof_layout();
289 // NOTE: Unclear what this return for prisms
290 const std::size_t num_entity_dofs = layout.num_entity_closure_dofs(dim);
291
292 std::vector<std::int32_t> x_indices;
293 x_indices.reserve(num_entity_dofs * subentity_to_entity.size());
294 {
295 auto xdofs = geometry.dofmap();
296 const int tdim = topology.dim();
297
298 // Fetch connectivities required to get entity dofs
299 const std::vector<std::vector<std::vector<int>>>& closure_dofs
300 = layout.entity_closure_dofs_all();
301 auto e_to_c = topology.connectivity(dim, tdim);
302 assert(e_to_c);
303 auto c_to_e = topology.connectivity(tdim, dim);
304 assert(c_to_e);
305 for (std::size_t i = 0; i < subentity_to_entity.size(); ++i)
306 {
307 const std::int32_t idx = subentity_to_entity[i];
308 assert(!e_to_c->links(idx).empty());
309 // Always pick the last cell to be consistent with the e_to_v connectivity
310 const std::int32_t cell = e_to_c->links(idx).back();
311 auto cell_entities = c_to_e->links(cell);
312 auto it = std::find(cell_entities.begin(), cell_entities.end(), idx);
313 assert(it != cell_entities.end());
314 std::size_t local_entity = std::distance(cell_entities.begin(), it);
315
316 auto xc = MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE::
317 submdspan(xdofs, cell, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
318 for (std::int32_t entity_dof : closure_dofs[dim][local_entity])
319 x_indices.push_back(xc[entity_dof]);
320 }
321 }
322
323 std::vector<std::int32_t> sub_x_dofs = x_indices;
324 std::sort(sub_x_dofs.begin(), sub_x_dofs.end());
325 sub_x_dofs.erase(std::unique(sub_x_dofs.begin(), sub_x_dofs.end()),
326 sub_x_dofs.end());
327
328 // Get the sub-geometry dofs owned by this process
329 auto x_index_map = geometry.index_map();
330 assert(x_index_map);
331 auto subx_to_x_dofmap
332 = common::compute_owned_indices(sub_x_dofs, *x_index_map);
333 std::shared_ptr<common::IndexMap> sub_x_dof_index_map;
334 {
335 std::pair<common::IndexMap, std::vector<int32_t>> map_data
336 = x_index_map->create_submap(subx_to_x_dofmap);
337 sub_x_dof_index_map
338 = std::make_shared<common::IndexMap>(std::move(map_data.first));
339
340 // Create a map from the dofs in the sub-geometry to the geometry
341 subx_to_x_dofmap.reserve(sub_x_dof_index_map->size_local()
342 + sub_x_dof_index_map->num_ghosts());
343 std::transform(map_data.second.begin(), map_data.second.end(),
344 std::back_inserter(subx_to_x_dofmap),
345 [offset = x_index_map->size_local()](auto x_dof_index)
346 { return offset + x_dof_index; });
347 }
348
349 // Create sub-geometry coordinates
350 std::span<const T> x = geometry.x();
351 std::int32_t sub_num_x_dofs = subx_to_x_dofmap.size();
352 std::vector<T> sub_x(3 * sub_num_x_dofs);
353 for (int i = 0; i < sub_num_x_dofs; ++i)
354 {
355 std::copy_n(std::next(x.begin(), 3 * subx_to_x_dofmap[i]), 3,
356 std::next(sub_x.begin(), 3 * i));
357 }
358
359 // Create geometry to sub-geometry map
360 std::vector<std::int32_t> x_to_subx_dof_map(
361 x_index_map->size_local() + x_index_map->num_ghosts(), -1);
362 for (std::size_t i = 0; i < subx_to_x_dofmap.size(); ++i)
363 x_to_subx_dof_map[subx_to_x_dofmap[i]] = i;
364
365 // Create sub-geometry dofmap
366 std::vector<std::int32_t> sub_x_dofmap;
367 sub_x_dofmap.reserve(x_indices.size());
368 std::transform(x_indices.cbegin(), x_indices.cend(),
369 std::back_inserter(sub_x_dofmap),
370 [&x_to_subx_dof_map](auto x_dof)
371 {
372 assert(x_to_subx_dof_map[x_dof] != -1);
373 return x_to_subx_dof_map[x_dof];
374 });
375
376 // Create sub-geometry coordinate element
377 CellType sub_coord_cell
378 = cell_entity_type(geometry.cmaps()[0].cell_shape(), dim, 0);
379 fem::CoordinateElement<T> sub_coord_ele(sub_coord_cell,
380 geometry.cmaps()[0].degree(),
381 geometry.cmaps()[0].variant());
382
383 // Sub-geometry input_global_indices
384 // TODO: Check this
385 const std::vector<std::int64_t>& igi = geometry.input_global_indices();
386 std::vector<std::int64_t> sub_igi;
387 sub_igi.reserve(subx_to_x_dofmap.size());
388 std::transform(subx_to_x_dofmap.begin(), subx_to_x_dofmap.end(),
389 std::back_inserter(sub_igi),
390 [&igi](std::int32_t sub_x_dof) { return igi[sub_x_dof]; });
391
392 // Create geometry
393 return {Geometry<T>(sub_x_dof_index_map, std::move(sub_x_dofmap),
394 {sub_coord_ele}, std::move(sub_x), geometry.dim(),
395 std::move(sub_igi)),
396 std::move(subx_to_x_dofmap)};
397}
398
399} // namespace dolfinx::mesh
A CoordinateElement manages coordinate mappings for isoparametric cells.
Definition CoordinateElement.h:39
The class represents the degree-of-freedom (dofs) for an element. Dofs are associated with a mesh ent...
Definition ElementDofLayout.h:31
const std::vector< std::vector< std::vector< int > > > & entity_closure_dofs_all() const
Direct access to all entity closure dofs (dof = _entity_dofs[dim][entity][i])
Definition ElementDofLayout.cpp:92
int num_entity_closure_dofs(int dim) const
Return the number of closure dofs for a given entity dimension.
Definition ElementDofLayout.cpp:68
This class provides a static adjacency list data structure. It is commonly used to store directed gra...
Definition AdjacencyList.h:28
Geometry stores the geometry imposed on a mesh.
Definition Geometry.h:33
~Geometry()=default
Destructor.
and std::is_convertible_v< std::remove_cvref_t< V >, std::vector< T > > and std::is_convertible_v< std::remove_cvref_t< W >, std::vector< std::int64_t > > Geometry(std::shared_ptr< const common::IndexMap > index_map, U &&dofmap, const std::vector< fem::CoordinateElement< typename std::remove_reference_t< typename V::value_type > > > &elements, V &&x, int dim, W &&input_global_indices)
Constructor of object that holds mesh geometry data.
Definition Geometry.h:57
std::span< value_type > x()
Access geometry degrees-of-freedom data (non-const version).
Definition Geometry.h:120
std::shared_ptr< const common::IndexMap > index_map() const
Index map.
Definition Geometry.h:104
Geometry(Geometry &&)=default
Move constructor.
Geometry(const Geometry &)=default
Copy constructor.
int dim() const
Return Euclidean dimension of coordinate system.
Definition Geometry.h:88
Geometry & operator=(Geometry &&)=default
Move Assignment.
MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan< const std::int32_t, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents< std::size_t, 2 > > dofmap() const
DOF map.
Definition Geometry.h:94
const std::vector< std::int64_t > & input_global_indices() const
Global user indices.
Definition Geometry.h:131
std::span< const value_type > x() const
Access geometry degrees-of-freedom data (const version).
Definition Geometry.h:113
Geometry & operator=(const Geometry &)=delete
Copy Assignment.
const std::vector< fem::CoordinateElement< value_type > > & cmaps() const
The elements that describes the geometry maps.
Definition Geometry.h:125
T value_type
Value type.
Definition Geometry.h:36
Topology stores the topology of a mesh, consisting of mesh entities and connectivity (incidence relat...
Definition Topology.h:44
std::shared_ptr< const graph::AdjacencyList< std::int32_t > > connectivity(int d0, int d1) const
Return connectivity from entities of dimension d0 to entities of dimension d1.
Definition Topology.cpp:836
const std::vector< std::uint32_t > & get_cell_permutation_info() const
Returns the permutation information.
Definition Topology.cpp:851
int dim() const noexcept
Return the topological dimension of the mesh.
Definition Topology.cpp:728
std::vector< typename std::remove_reference_t< typename U::value_type > > distribute_data(MPI_Comm comm, std::span< const std::int64_t > indices, const U &x, int shape1)
Distribute rows of a rectangular data array to ranks where they are required (scalable version).
Definition MPI.h:676
std::vector< int32_t > compute_owned_indices(std::span< const std::int32_t > indices, const IndexMap &map)
Given a vector of indices (local numbering, owned or ghost) and an index map, this function returns t...
Definition IndexMap.cpp:39
std::tuple< common::IndexMap, int, std::vector< std::int32_t > > build_dofmap_data(MPI_Comm comm, const mesh::Topology &topology, const std::vector< ElementDofLayout > &element_dof_layouts, const std::function< std::vector< int >(const graph::AdjacencyList< std::int32_t > &)> &reorder_fn)
Build dofmap data for an element on a mesh topology.
Definition dofmapbuilder.cpp:651
std::vector< std::int64_t > compute_local_to_global(std::span< const std::int64_t > global, std::span< const std::int32_t > local)
Given an adjacency list with global, possibly non-contiguous, link indices and a local adjacency list...
Definition partition.cpp:378
std::vector< std::int32_t > compute_local_to_local(std::span< const std::int64_t > local0_to_global, std::span< const std::int64_t > local1_to_global)
Compute a local0-to-local1 map from two local-to-global maps with common global indices.
Definition partition.cpp:401
Mesh data structures and algorithms on meshes.
Definition DofMap.h:32
mesh::Geometry< typename std::remove_reference_t< typename U::value_type > > create_geometry(MPI_Comm comm, const Topology &topology, const std::vector< fem::CoordinateElement< std::remove_reference_t< typename U::value_type > > > &elements, const graph::AdjacencyList< std::int64_t > &cell_nodes, const U &x, int dim, std::function< std::vector< int >(const graph::AdjacencyList< std::int32_t > &)> reorder_fn=nullptr)
Build Geometry from input data.
Definition Geometry.h:179
std::pair< mesh::Geometry< T >, std::vector< int32_t > > create_subgeometry(const Topology &topology, const Geometry< T > &geometry, int dim, std::span< const std::int32_t > subentity_to_entity)
Create a sub-geometry for a subset of entities.
Definition Geometry.h:280
CellType cell_entity_type(CellType type, int d, int index)
Return type of cell for entity of dimension d at given entity index.
Definition cell_types.cpp:64
CellType
Cell type identifier.
Definition cell_types.h:22
void radix_sort(std::span< T > array)
Sort a vector of integers with radix sorting algorithm. The bucket size is determined by the number o...
Definition sort.h:27