DOLFINx 0.12.0.0
DOLFINx C++
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 <algorithm>
11#include <basix/mdspan.hpp>
12#include <cassert>
13#include <concepts>
14#include <cstdint>
15#include <dolfinx/common/IndexMap.h>
16#include <dolfinx/common/MPI.h>
17#include <dolfinx/fem/CoordinateElement.h>
18#include <dolfinx/fem/ElementDofLayout.h>
19#include <dolfinx/fem/dofmapbuilder.h>
20#include <dolfinx/graph/AdjacencyList.h>
21#include <dolfinx/graph/partition.h>
22#include <functional>
23#include <iterator>
24#include <memory>
25#include <numeric>
26#include <span>
27#include <spdlog/spdlog.h>
28#include <stdexcept>
29#include <type_traits>
30#include <utility>
31#include <vector>
32
33namespace dolfinx::mesh
34{
35
37template <std::floating_point T>
39{
40public:
42 using value_type = T;
43
67 template <typename U, typename V, typename W>
68 requires std::is_convertible_v<std::remove_cvref_t<U>,
69 std::vector<std::vector<std::int32_t>>>
70 and std::is_convertible_v<std::remove_cvref_t<V>,
71 std::vector<T>>
72 and std::is_convertible_v<std::remove_cvref_t<W>,
73 std::vector<std::int64_t>>
75 std::shared_ptr<const common::IndexMap> index_map, U&& dofmaps,
76 const std::vector<fem::CoordinateElement<
77 typename std::remove_reference_t<typename V::value_type>>>& elements,
78 V&& x, int dim, W&& input_global_indices)
79 : _dim(dim), _dofmaps(std::forward<U>(dofmaps)),
80 _index_map(std::move(index_map)), _cmaps(elements),
81 _x(std::forward<V>(x)),
82 _input_global_indices(std::forward<W>(input_global_indices))
83 {
84 if (_x.size() % 3 != 0)
85 throw std::invalid_argument("x size must be a multiple of 3.");
86 if (_x.size() / 3 != _input_global_indices.size())
87 throw std::invalid_argument("Geometry size mismatch.");
88
89 if (_dofmaps.size() != _cmaps.size())
90 {
91 throw std::invalid_argument("Geometry number of dofmaps not equal to the "
92 "number of coordinate elements.");
93 }
94
95 // TODO: check that elements dim == number of dofmap columns
96 }
97
99 Geometry(const Geometry&) = default;
100
102 Geometry(Geometry&&) = default;
103
105 ~Geometry() = default;
106
107 // Copy assignment (deleted)
108 Geometry& operator=(const Geometry&) = delete;
109
112
114 int dim() const { return _dim; }
115
119 [[deprecated("Use dofmaps().front() instead.")]]
120 md::mdspan<const std::int32_t, md::dextents<std::size_t, 2>> dofmap() const
121 {
122 if (_dofmaps.size() != 1)
123 throw std::runtime_error("Multiple dofmaps");
124 std::size_t ndofs = _cmaps.front().dim();
125 return md::mdspan<const std::int32_t, md::dextents<std::size_t, 2>>(
126 _dofmaps.front().data(), _dofmaps.front().size() / ndofs, ndofs);
127 }
128
133 std::vector<md::mdspan<const std::int32_t, md::dextents<std::size_t, 2>>>
134 dofmaps() const
135 {
136 std::vector<md::mdspan<const std::int32_t, md::dextents<std::size_t, 2>>>
137 dms(_dofmaps.size());
138 for (std::size_t i = 0; i < _dofmaps.size(); ++i)
139 {
140 std::size_t ndofs = _cmaps.at(i).dim();
141 dms[i] = md::mdspan<const std::int32_t, md::dextents<std::size_t, 2>>(
142 _dofmaps.at(i).data(), _dofmaps.at(i).size() / ndofs, ndofs);
143 }
144 return dms;
145 }
146
149 std::shared_ptr<const common::IndexMap> index_map() const
150 {
151 return _index_map;
152 }
153
158 std::span<const value_type> x() const { return _x; }
159
165 std::span<value_type> x() { return _x; }
166
169 const std::vector<fem::CoordinateElement<value_type>>& cmaps() const
170 {
171 return _cmaps;
172 }
173
175 const std::vector<std::int64_t>& input_global_indices() const
176 {
177 return _input_global_indices;
178 }
179
180private:
181 // Geometric dimension
182 int _dim;
183
184 // Map per cell for extracting coordinate data for each cmap
185 std::vector<std::vector<std::int32_t>> _dofmaps;
186
187 // IndexMap for geometry 'dofmap'
188 std::shared_ptr<const common::IndexMap> _index_map;
189
190 // The coordinate elements
191 std::vector<fem::CoordinateElement<value_type>> _cmaps;
192
193 // Coordinates for all points stored as a contiguous array (row-major,
194 // column size = 3)
195 std::vector<value_type> _x;
196
197 // Global indices as provided on Geometry creation
198 std::vector<std::int64_t> _input_global_indices;
199};
200
203template <typename U, typename V, typename W>
204Geometry(std::shared_ptr<const common::IndexMap>, U&&,
205 const std::vector<fem::CoordinateElement<
206 typename std::remove_reference_t<typename V::value_type>>>&,
207 V&&, int, W&&)
208 -> Geometry<typename std::remove_cvref_t<typename V::value_type>>;
210
240template <typename U>
241Geometry<typename std::remove_reference_t<typename U::value_type>>
242create_geometry(const Topology& topology,
243 const std::vector<fem::CoordinateElement<
244 std::remove_reference_t<typename U::value_type>>>& elements,
245 std::span<const std::int64_t> nodes,
246 std::span<const std::int64_t> xdofs, const U& x, int dim,
247 const std::function<std::vector<int>(
248 const graph::AdjacencyList<std::int32_t>&)>& reorder_fn
249 = nullptr)
250{
251 spdlog::info("Create Geometry (multiple)");
252
253 if (dim < 1 or dim > 3)
254 throw std::invalid_argument("dim must be 1, 2 or 3.");
255
256 assert(std::ranges::is_sorted(nodes));
257 using T = typename std::remove_reference_t<typename U::value_type>;
258
259 // Check elements match cell types in topology
260 const int tdim = topology.dim();
261 const std::size_t num_cell_types = topology.entity_types(tdim).size();
262 if (elements.size() != num_cell_types)
263 throw std::invalid_argument("Mismatch between topology and geometry.");
264
265 std::vector<fem::ElementDofLayout> dof_layouts;
266 dof_layouts.reserve(elements.size());
267 for (auto& el : elements)
268 dof_layouts.push_back(el.create_dof_layout());
269
270 // Build 'geometry' dofmap on the topology
271 auto [_dof_index_map, bs, dofmaps]
272 = fem::build_dofmap_data(topology.index_maps(topology.dim())[0]->comm(),
273 topology, dof_layouts, reorder_fn);
274 auto dof_index_map
275 = std::make_shared<common::IndexMap>(std::move(_dof_index_map));
276
277 // If the mesh has higher order geometry, permute the dofmap
278 if (elements.front().needs_dof_permutations())
279 {
280 const std::int32_t num_cells
281 = topology.connectivity(topology.dim(), 0)->num_nodes();
282 const std::vector<std::uint32_t>& cell_info
283 = topology.get_cell_permutation_info();
284 int d = elements.front().dim();
285 for (std::int32_t cell = 0; cell < num_cells; ++cell)
286 {
287 std::span dofs(dofmaps.front().data() + cell * d, d);
288 elements.front().permute_inv(dofs, cell_info[cell]);
289 }
290 }
291
292 // Compute local-to-global map from local indices in dofmap to the
293 // corresponding global indices in cells, and pass to function to
294 // compute local (dof) to local (position in coords) map from (i)
295 // local-to-global for dofs and (ii) local-to-global for entries in
296 // coords
297
298 std::vector<std::int32_t> all_dofmaps;
299 all_dofmaps.reserve(std::accumulate(
300 dofmaps.begin(), dofmaps.end(), std::size_t(0),
301 [](std::size_t n, const auto& q) { return n + q.size(); }));
302 for (const std::vector<std::int32_t>& q : dofmaps)
303 all_dofmaps.insert(all_dofmaps.end(), q.begin(), q.end());
304
305 const std::vector<std::int32_t> l2l = graph::build::compute_local_to_local(
306 graph::build::compute_local_to_global(xdofs, all_dofmaps), nodes);
307
308 // Cross-validate the three independently-derived quantities that the
309 // rest of this function assumes are equal: the number of coordinate
310 // rows in `x`, `nodes.size()`, and the geometry-dof count implied by
311 // `xdofs`/`dofmaps` (l2l.size()).
312 if (x.size() % dim != 0)
313 throw std::invalid_argument("x size must be a multiple of dim.");
314 if (x.size() / dim != nodes.size())
315 throw std::invalid_argument("x row count must equal nodes.size().");
316 if (l2l.size() != nodes.size())
317 {
318 throw std::invalid_argument(
319 "Mismatch between xdofs/dofmaps and nodes: derived geometry dof "
320 "count does not equal nodes.size().");
321 }
322
323 // Allocate space for input global indices and copy data
324 std::vector<std::int64_t> igi(nodes.size());
325 std::ranges::transform(l2l, igi.begin(),
326 [&nodes](auto index) { return nodes[index]; });
327
328 // Build coordinate dof array, copying coordinates to correct position
329 const std::size_t shape0 = x.size() / dim;
330 const std::size_t shape1 = dim;
331 std::vector<T> xg(3 * shape0, 0);
332 for (std::size_t i = 0; i < shape0; ++i)
333 {
334 std::copy_n(std::next(x.begin(), shape1 * l2l[i]), shape1,
335 std::next(xg.begin(), 3 * i));
336 }
337
338 return Geometry(dof_index_map, std::move(dofmaps), elements, std::move(xg),
339 dim, std::move(igi));
340}
341
342} // namespace dolfinx::mesh
Definition CoordinateElement.h:39
This class provides a static adjacency list data structure.
Definition AdjacencyList.h:41
Geometry stores the geometry imposed on a mesh.
Definition Geometry.h:39
~Geometry()=default
Destructor.
std::span< value_type > x()
Access geometry degrees-of-freedom data (non-const version).
Definition Geometry.h:165
Geometry(std::shared_ptr< const common::IndexMap > index_map, U &&dofmaps, 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:74
std::shared_ptr< const common::IndexMap > index_map() const
Index map for the geometry 'degrees-of-freedom'.
Definition Geometry.h:149
Geometry(Geometry &&)=default
Move constructor.
Geometry(const Geometry &)=default
Copy constructor.
std::vector< md::mdspan< const std::int32_t, md::dextents< std::size_t, 2 > > > dofmaps() const
Degree-of-freedom map associated with each coordinate map element in the geometry.
Definition Geometry.h:134
int dim() const
Return dimension of the Euclidean coordinate system.
Definition Geometry.h:114
Geometry & operator=(Geometry &&)=default
Move assignment.
md::mdspan< const std::int32_t, md::dextents< std::size_t, 2 > > dofmap() const
DofMap for the geometry.
Definition Geometry.h:120
const std::vector< std::int64_t > & input_global_indices() const
Global user indices.
Definition Geometry.h:175
std::span< const value_type > x() const
Access geometry degrees-of-freedom data (const version).
Definition Geometry.h:158
const std::vector< fem::CoordinateElement< value_type > > & cmaps() const
The elements that describes the geometry map.
Definition Geometry.h:169
T value_type
Value type.
Definition Geometry.h:42
Topology stores the topology of a mesh, consisting of mesh entities and connectivity (incidence relat...
Definition Topology.h:49
const std::vector< std::uint32_t > & get_cell_permutation_info() const
Get the cell permutation information.
Definition Topology.cpp:959
std::shared_ptr< const graph::AdjacencyList< std::int32_t > > connectivity(std::array< int, 2 > d0, std::array< int, 2 > d1) const
Get the connectivity from entities of topological dimension d0 to dimension d1.
Definition Topology.cpp:939
const std::vector< CellType > & entity_types(int dim) const
Entity types in the topology for a given dimension.
Definition Topology.cpp:883
int dim() const noexcept
Topological dimension of the mesh.
Definition Topology.cpp:878
std::vector< std::shared_ptr< const common::IndexMap > > index_maps(int dim) const
Get the index maps that describe the parallel distribution of the mesh entities of a given topologica...
Definition Topology.cpp:906
std::tuple< common::IndexMap, int, std::vector< 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)
Definition dofmapbuilder.cpp:661
std::vector< std::int64_t > compute_local_to_global(std::span< const std::int64_t > global, std::span< const std::int32_t > local)
Definition partition.cpp:576
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:598
Mesh data structures and algorithms on meshes.
Definition DofMap.h:32
Geometry< typename std::remove_reference_t< typename U::value_type > > create_geometry(const Topology &topology, const std::vector< fem::CoordinateElement< std::remove_reference_t< typename U::value_type > > > &elements, std::span< const std::int64_t > nodes, std::span< const std::int64_t > xdofs, const U &x, int dim, const std::function< std::vector< int >(const graph::AdjacencyList< std::int32_t > &)> &reorder_fn=nullptr)
Build Geometry from input data.
Definition Geometry.h:242