DOLFINx 0.9.0
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 <algorithm>
11#include <basix/mdspan.hpp>
12#include <concepts>
13#include <cstdint>
14#include <dolfinx/common/IndexMap.h>
15#include <dolfinx/common/MPI.h>
16#include <dolfinx/common/sort.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 <memory>
24#include <span>
25#include <utility>
26#include <vector>
27
28namespace dolfinx::mesh
29{
30
32template <std::floating_point T>
34{
35public:
37 using value_type = T;
38
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>>
58 std::shared_ptr<const common::IndexMap> index_map, U&& dofmap,
60 typename std::remove_reference_t<typename V::value_type>>& element,
61 V&& x, int dim, W&& input_global_indices)
62 : _dim(dim), _dofmaps({dofmap}), _index_map(index_map), _cmaps({element}),
63 _x(std::forward<V>(x)),
64 _input_global_indices(std::forward<W>(input_global_indices))
65 {
66 assert(_x.size() % 3 == 0);
67 if (_x.size() / 3 != _input_global_indices.size())
68 throw std::runtime_error("Geometry size mis-match");
69 }
70
82 template <typename V, typename W>
83 requires std::is_convertible_v<std::remove_cvref_t<V>, std::vector<T>>
84 and std::is_convertible_v<std::remove_cvref_t<W>,
85 std::vector<std::int64_t>>
87 std::shared_ptr<const common::IndexMap> index_map,
88 const std::vector<std::vector<std::int32_t>>& dofmaps,
89 const std::vector<fem::CoordinateElement<
90 typename std::remove_reference_t<typename V::value_type>>>& elements,
91 V&& x, int dim, W&& input_global_indices)
92 : _dim(dim), _dofmaps(dofmaps), _index_map(index_map), _cmaps(elements),
93 _x(std::forward<V>(x)),
94 _input_global_indices(std::forward<W>(input_global_indices))
95 {
96 assert(_x.size() % 3 == 0);
97 if (_x.size() / 3 != _input_global_indices.size())
98 throw std::runtime_error("Geometry size mis-match");
99 }
100
102 Geometry(const Geometry&) = default;
103
105 Geometry(Geometry&&) = default;
106
108 ~Geometry() = default;
109
111 Geometry& operator=(const Geometry&) = delete;
112
115
117 int dim() const { return _dim; }
118
121 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
122 const std::int32_t,
123 MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>
124 dofmap() const
125 {
126 if (_dofmaps.size() != 1)
127 throw std::runtime_error("Multiple dofmaps");
128
129 int ndofs = _cmaps.front().dim();
130 return MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
131 const std::int32_t,
132 MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>(
133 _dofmaps.front().data(), _dofmaps.front().size() / ndofs, ndofs);
134 }
135
140 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
141 const std::int32_t,
142 MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>
143 dofmap(std::int32_t i) const
144 {
145 if (i < 0 or i >= (int)_dofmaps.size())
146 {
147 throw std::out_of_range("Cannot get dofmap:" + std::to_string(i)
148 + " out of range");
149 }
150 int ndofs = _cmaps[i].dim();
151
152 return MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
153 const std::int32_t,
154 MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>(
155 _dofmaps[i].data(), _dofmaps[i].size() / ndofs, ndofs);
156 }
157
160 std::shared_ptr<const common::IndexMap> index_map() const
161 {
162 return _index_map;
163 }
164
169 std::span<const value_type> x() const { return _x; }
170
176 std::span<value_type> x() { return _x; }
177
182 {
183 if (_cmaps.size() != 1)
184 throw std::runtime_error("Multiple cmaps.");
185 return _cmaps.front();
186 }
187
191 const fem::CoordinateElement<value_type>& cmap(std::int32_t i) const
192 {
193 if (i < 0 or i >= (int)_cmaps.size())
194 {
195 throw std::out_of_range("Cannot get cmap:" + std::to_string(i)
196 + " out of range");
197 }
198 return _cmaps[i];
199 }
200
202 const std::vector<std::int64_t>& input_global_indices() const
203 {
204 return _input_global_indices;
205 }
206
207private:
208 // Geometric dimension
209 int _dim;
210
211 // Map per cell for extracting coordinate data for each cmap
212 std::vector<std::vector<std::int32_t>> _dofmaps;
213
214 // IndexMap for geometry 'dofmap'
215 std::shared_ptr<const common::IndexMap> _index_map;
216
217 // The coordinate elements
218 std::vector<fem::CoordinateElement<value_type>> _cmaps;
219
220 // Coordinates for all points stored as a contiguous array (row-major,
221 // column size = 3)
222 std::vector<value_type> _x;
223
224 // Global indices as provided on Geometry creation
225 std::vector<std::int64_t> _input_global_indices;
226};
227
230template <typename U, typename V, typename W>
231Geometry(std::shared_ptr<const common::IndexMap>, U,
232 const std::vector<fem::CoordinateElement<
233 typename std::remove_reference_t<typename V::value_type>>>&,
234 V, int,
235 W) -> Geometry<typename std::remove_cvref_t<typename V::value_type>>;
237
262template <typename U>
263Geometry<typename std::remove_reference_t<typename U::value_type>>
265 const Topology& topology,
266 const std::vector<fem::CoordinateElement<
267 std::remove_reference_t<typename U::value_type>>>& elements,
268 std::span<const std::int64_t> nodes, std::span<const std::int64_t> xdofs,
269 const U& x, int dim,
270 std::function<std::vector<int>(const graph::AdjacencyList<std::int32_t>&)>
271 reorder_fn
272 = nullptr)
273{
274 spdlog::info("Create Geometry (multiple)");
275
276 assert(std::ranges::is_sorted(nodes));
277 using T = typename std::remove_reference_t<typename U::value_type>;
278
279 // Check elements match cell types in topology
280 const int tdim = topology.dim();
281 const std::size_t num_cell_types = topology.entity_types(tdim).size();
282 if (elements.size() != num_cell_types)
283 throw std::runtime_error("Mismatch between topology and geometry.");
284
285 std::vector<fem::ElementDofLayout> dof_layouts;
286 for (const auto& el : elements)
287 dof_layouts.push_back(el.create_dof_layout());
288
289 spdlog::info("Got {} dof layouts", dof_layouts.size());
290
291 // Build 'geometry' dofmap on the topology
292 auto [_dof_index_map, bs, dofmaps]
293 = fem::build_dofmap_data(topology.index_map(topology.dim())->comm(),
294 topology, dof_layouts, reorder_fn);
295 auto dof_index_map
296 = std::make_shared<common::IndexMap>(std::move(_dof_index_map));
297
298 // If the mesh has higher order geometry, permute the dofmap
299 if (elements.front().needs_dof_permutations())
300 {
301 const std::int32_t num_cells
302 = topology.connectivity(topology.dim(), 0)->num_nodes();
303 const std::vector<std::uint32_t>& cell_info
304 = topology.get_cell_permutation_info();
305 int d = elements.front().dim();
306 for (std::int32_t cell = 0; cell < num_cells; ++cell)
307 {
308 std::span dofs(dofmaps.front().data() + cell * d, d);
309 elements.front().permute_inv(dofs, cell_info[cell]);
310 }
311 }
312
313 spdlog::info("Calling compute_local_to_global");
314 // Compute local-to-global map from local indices in dofmap to the
315 // corresponding global indices in cells, and pass to function to
316 // compute local (dof) to local (position in coords) map from (i)
317 // local-to-global for dofs and (ii) local-to-global for entries in
318 // coords
319
320 spdlog::info("xdofs.size = {}", xdofs.size());
321 std::vector<std::int32_t> all_dofmaps;
322 std::stringstream s;
323 for (auto q : dofmaps)
324 {
325 s << q.size() << " ";
326 all_dofmaps.insert(all_dofmaps.end(), q.begin(), q.end());
327 }
328 spdlog::info("dofmap sizes = {}", s.str());
329 spdlog::info("all_dofmaps.size = {}", all_dofmaps.size());
330 spdlog::info("nodes.size = {}", nodes.size());
331
332 const std::vector<std::int32_t> l2l = graph::build::compute_local_to_local(
333 graph::build::compute_local_to_global(xdofs, all_dofmaps), nodes);
334
335 // Allocate space for input global indices and copy data
336 std::vector<std::int64_t> igi(nodes.size());
337 std::ranges::transform(l2l, igi.begin(),
338 [&nodes](auto index) { return nodes[index]; });
339
340 // Build coordinate dof array, copying coordinates to correct position
341 assert(x.size() % dim == 0);
342 const std::size_t shape0 = x.size() / dim;
343 const std::size_t shape1 = dim;
344 std::vector<T> xg(3 * shape0, 0);
345 for (std::size_t i = 0; i < shape0; ++i)
346 {
347 std::copy_n(std::next(x.begin(), shape1 * l2l[i]), shape1,
348 std::next(xg.begin(), 3 * i));
349 }
350
351 spdlog::info("Creating geometry with {} dofmaps", dof_layouts.size());
352
353 return Geometry(dof_index_map, std::move(dofmaps), elements, std::move(xg),
354 dim, std::move(igi));
355}
356
380template <typename U>
381Geometry<typename std::remove_reference_t<typename U::value_type>>
383 const Topology& topology,
385 std::remove_reference_t<typename U::value_type>>& element,
386 std::span<const std::int64_t> nodes, std::span<const std::int64_t> xdofs,
387 const U& x, int dim,
388 std::function<std::vector<int>(const graph::AdjacencyList<std::int32_t>&)>
389 reorder_fn
390 = nullptr)
391{
392 assert(std::ranges::is_sorted(nodes));
393 using T = typename std::remove_reference_t<typename U::value_type>;
394
395 fem::ElementDofLayout dof_layout = element.create_dof_layout();
396
397 // Build 'geometry' dofmap on the topology
398 auto [_dof_index_map, bs, dofmaps]
399 = fem::build_dofmap_data(topology.index_map(topology.dim())->comm(),
400 topology, {dof_layout}, reorder_fn);
401 auto dof_index_map
402 = std::make_shared<common::IndexMap>(std::move(_dof_index_map));
403
404 // If the mesh has higher order geometry, permute the dofmap
405 if (element.needs_dof_permutations())
406 {
407 const std::int32_t num_cells
408 = topology.connectivity(topology.dim(), 0)->num_nodes();
409 const std::vector<std::uint32_t>& cell_info
410 = topology.get_cell_permutation_info();
411 int d = element.dim();
412 for (std::int32_t cell = 0; cell < num_cells; ++cell)
413 {
414 std::span dofs(dofmaps.front().data() + cell * d, d);
415 element.permute_inv(dofs, cell_info[cell]);
416 }
417 }
418
419 // Compute local-to-global map from local indices in dofmap to the
420 // corresponding global indices in cells, and pass to function to
421 // compute local (dof) to local (position in coords) map from (i)
422 // local-to-global for dofs and (ii) local-to-global for entries in
423 // coords
424 const std::vector<std::int32_t> l2l = graph::build::compute_local_to_local(
425 graph::build::compute_local_to_global(xdofs, dofmaps.front()), nodes);
426
427 // Allocate space for input global indices and copy data
428 std::vector<std::int64_t> igi(nodes.size());
429 std::ranges::transform(l2l, igi.begin(),
430 [&nodes](auto index) { return nodes[index]; });
431
432 // Build coordinate dof array, copying coordinates to correct position
433 assert(x.size() % dim == 0);
434 const std::size_t shape0 = x.size() / dim;
435 const std::size_t shape1 = dim;
436 std::vector<T> xg(3 * shape0, 0);
437 for (std::size_t i = 0; i < shape0; ++i)
438 {
439 std::copy_n(std::next(x.cbegin(), shape1 * l2l[i]), shape1,
440 std::next(xg.begin(), 3 * i));
441 }
442
443 return Geometry(dof_index_map, std::move(dofmaps.front()), {element},
444 std::move(xg), dim, std::move(igi));
445}
446
447} // namespace dolfinx::mesh
Definition XDMFFile.h:27
Definition ElementDofLayout.h:30
Definition topologycomputation.h:24
Geometry stores the geometry imposed on a mesh.
Definition Geometry.h:34
~Geometry()=default
Destructor.
std::span< value_type > x()
Access geometry degrees-of-freedom data (non-const version).
Definition Geometry.h:176
Geometry(std::shared_ptr< const common::IndexMap > index_map, const std::vector< std::vector< std::int32_t > > &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:86
Geometry(std::shared_ptr< const common::IndexMap > index_map, U &&dofmap, const fem::CoordinateElement< typename std::remove_reference_t< typename V::value_type > > &element, V &&x, int dim, W &&input_global_indices)
Constructor of object that holds mesh geometry data.
Definition Geometry.h:57
MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan< const std::int32_t, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents< std::size_t, 2 > > dofmap(std::int32_t i) const
The dofmap associated with the ith coordinate map in the geometry.
Definition Geometry.h:143
std::shared_ptr< const common::IndexMap > index_map() const
Index map.
Definition Geometry.h:160
Geometry(Geometry &&)=default
Move constructor.
Geometry(const Geometry &)=default
Copy constructor.
const fem::CoordinateElement< value_type > & cmap() const
The element that describes the geometry map.
Definition Geometry.h:181
int dim() const
Return dimension of the Euclidean coordinate system.
Definition Geometry.h:117
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
DofMap for the geometry.
Definition Geometry.h:124
const fem::CoordinateElement< value_type > & cmap(std::int32_t i) const
The element that describe the ith geometry map.
Definition Geometry.h:191
const std::vector< std::int64_t > & input_global_indices() const
Global user indices.
Definition Geometry.h:202
std::span< const value_type > x() const
Access geometry degrees-of-freedom data (const version).
Definition Geometry.h:169
Geometry & operator=(const Geometry &)=delete
Copy Assignment.
T value_type
Value type.
Definition Geometry.h:37
Topology stores the topology of a mesh, consisting of mesh entities and connectivity (incidence relat...
Definition Topology.h:44
std::shared_ptr< const common::IndexMap > index_map(int dim) const
Get the IndexMap that described the parallel distribution of the mesh entities.
Definition Topology.cpp:815
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. Assumes only one entit...
Definition Topology.cpp:931
const std::vector< std::uint32_t > & get_cell_permutation_info() const
Returns the permutation information.
Definition Topology.cpp:981
std::vector< CellType > entity_types(std::int8_t dim) const
Get the entity types in the topology for a given dimension.
Definition Topology.cpp:1023
int dim() const noexcept
Return the topological dimension of the mesh.
Definition Topology.cpp:794
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:617
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:534
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:556
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, std::function< std::vector< int >(const graph::AdjacencyList< std::int32_t > &)> reorder_fn=nullptr)
Build Geometry from input data.
Definition Geometry.h:264