DOLFINx 0.12.0.0
DOLFINx C++
Loading...
Searching...
No Matches
refine.h
1// Copyright (C) 2010-2024 Garth N. Wells and Paul T. Kühner
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 "dolfinx/common/MPI.h"
10#include "dolfinx/graph/AdjacencyList.h"
11#include "dolfinx/graph/partitioners.h"
12#include "dolfinx/mesh/Mesh.h"
13#include "dolfinx/mesh/Topology.h"
14#include "dolfinx/mesh/cell_types.h"
15#include "dolfinx/mesh/utils.h"
16#include "interval.h"
17#include "plaza.h"
18#include <algorithm>
19#include <concepts>
20#include <mpi.h>
21#include <optional>
22#include <spdlog/spdlog.h>
23#include <stdexcept>
24#include <utility>
25#include <variant>
26
27namespace dolfinx::refinement
28{
29
41template <std::floating_point T>
44 std::span<std::int32_t> parent_cell)
45{
46 // TODO: optimize for non ghosted mesh?
47
48 return [&parent_mesh, parent_cell](
49 MPI_Comm comm, int /*nparts*/,
50 const graph::AdjacencyList<std::int64_t>& dual_graph,
51 std::optional<std::span<const std::int32_t>> /* cell_weights */,
52 std::optional<std::span<const std::int32_t>> /* edge_weights */,
53 bool /* ghosting */) -> graph::AdjacencyList<std::int32_t>
54 {
55 auto parent_cell_im
56 = parent_mesh.topology()->index_map(parent_mesh.topology()->dim());
57 std::int32_t parent_num_cells = parent_cell_im->size_local();
58 std::span parent_cell_owners = parent_cell_im->owners();
59
60 std::int32_t num_cells = dual_graph.num_nodes();
61 std::vector<std::int32_t> destinations(num_cells);
62
63 int rank = dolfinx::MPI::rank(comm);
64 for (std::size_t i = 0; i < destinations.size(); i++)
65 {
66 bool parent_is_ghost_cell = parent_cell[i] > parent_num_cells;
67 if (parent_is_ghost_cell)
68 destinations[i] = parent_cell_owners[parent_cell[i] - parent_num_cells];
69 else
70 destinations[i] = rank;
71 }
72
73 if (comm == MPI_COMM_NULL)
74 return graph::regular_adjacency_list(std::move(destinations), 1);
75
76 std::vector<std::int32_t> node_disp(MPI::size(comm) + 1, 0);
77 std::int32_t local_size = dual_graph.num_nodes();
78 MPI_Allgather(&local_size, 1, dolfinx::MPI::mpi_t<std::int32_t>,
79 node_disp.data() + 1, 1, dolfinx::MPI::mpi_t<std::int32_t>,
80 comm);
81 std::partial_sum(node_disp.begin(), node_disp.end(), node_disp.begin());
82 return compute_destination_ranks(comm, dual_graph, node_disp, destinations);
83 };
84}
85
90
121template <std::floating_point T>
122std::tuple<mesh::Mesh<T>, std::optional<std::vector<std::int32_t>>,
123 std::optional<std::vector<std::int8_t>>>
125 std::optional<std::span<const std::int32_t>> edges,
126 std::variant<IdentityPartitionerPlaceholder, graph::partition_fn>
127 partitioner = IdentityPartitionerPlaceholder(),
129 mesh::GhostMode ghost_mode = mesh::GhostMode::none)
130{
131 auto topology = mesh.topology();
132 assert(topology);
133 if (!mesh::is_simplex(topology->cell_type()))
134 throw std::runtime_error("Refinement only defined for simplices");
135
136 auto [cell_adj, new_vertex_coords, xshape, parent_cell, parent_facet]
137 = (topology->cell_type() == mesh::CellType::interval)
138 ? interval::compute_refinement_data(mesh, edges, option)
139 : plaza::compute_refinement_data(mesh, edges, option);
140
141 if (std::holds_alternative<IdentityPartitionerPlaceholder>(partitioner))
142 {
143 if (!parent_cell)
144 {
145 throw std::runtime_error(
146 "Identity partitioner relies on parent cell computation");
147 }
148 assert(parent_cell);
149 partitioner = create_identity_partitioner(mesh, parent_cell.value());
150 }
151
152 assert(std::holds_alternative<graph::partition_fn>(partitioner));
153
155 mesh.comm(), mesh.comm(), cell_adj.array(),
156 mesh.geometry().cmaps().front(), mesh.comm(), new_vertex_coords, xshape,
157 graph::Partitioner{.fn = std::get<graph::partition_fn>(partitioner)},
158 ghost_mode, 2, 1);
159
160 // Report the number of refined cells
161 const int D = topology->dim();
162 const std::int64_t n0 = topology->index_map(D)->size_global();
163 const std::int64_t n1 = mesh1.topology()->index_map(D)->size_global();
164 spdlog::info(
165 "Number of cells increased from {} to {} ({}% increase).", n0, n1,
166 100.0 * (static_cast<double>(n1) / static_cast<double>(n0) - 1.0));
167
168 return {std::move(mesh1), std::move(parent_cell), std::move(parent_facet)};
169}
170
171} // namespace dolfinx::refinement
This class provides a static adjacency list data structure.
Definition AdjacencyList.h:41
A Mesh consists of a set of connected and numbered mesh topological entities, and geometry data.
Definition Mesh.h:23
std::shared_ptr< Topology > topology()
Get mesh topology.
Definition Mesh.h:69
Functions supporting mesh operations.
MPI_Datatype mpi_t
Retrieves the MPI data type associated to the provided type.
Definition MPI.h:320
int size(MPI_Comm comm)
Definition MPI.cpp:81
int rank(MPI_Comm comm)
Return process rank for the communicator.
Definition MPI.cpp:73
AdjacencyList< typename std::decay_t< U >::value_type, V > regular_adjacency_list(U &&data, int degree)
Construct a constant degree (valency) adjacency list.
Definition AdjacencyList.h:262
std::function< graph::AdjacencyList< std::int32_t >( MPI_Comm, int, const AdjacencyList< std::int64_t > &, std::optional< std::span< const std::int32_t > >, std::optional< std::span< const std::int32_t > >, bool)> partition_fn
Signature of functions for computing the parallel partitioning of a distributed graph,...
Definition partition.h:38
Mesh data structures and algorithms on meshes.
Definition DofMap.h:32
bool is_simplex(CellType type)
Check if cell is a simplex.
Definition cell_types.cpp:98
Mesh< typename std::remove_reference_t< typename U::value_type > > create_mesh(MPI_Comm comm, MPI_Comm commt, std::vector< std::span< const std::int64_t > > cells, const std::vector< fem::CoordinateElement< typename std::remove_reference_t< typename U::value_type > > > &elements, MPI_Comm commg, const U &x, std::array< std::size_t, 2 > xshape, const graph::Partitioner &partitioner, GhostMode ghost_mode, std::optional< std::int32_t > max_facet_to_cell_links, int num_threads, const CellReorderFunction &reorder_fn=graph::reorder_rcm)
Create a distributed mesh::Mesh from mesh data and using the provided graph partitioning function for...
Definition utils.h:1246
GhostMode
Enum for different partitioning ghost modes.
Definition types.h:19
std::tuple< graph::AdjacencyList< std::int64_t >, std::vector< T >, std::array< std::size_t, 2 >, std::optional< std::vector< std::int32_t > >, std::optional< std::vector< std::int8_t > > > compute_refinement_data(const mesh::Mesh< T > &mesh, std::optional< std::span< const std::int32_t > > edges, Option option)
Definition plaza.h:466
Mesh refinement algorithms.
Definition dolfinx_refinement.h:8
Option
Options for data to compute during mesh refinement.
Definition option.h:16
@ parent_cell
Definition option.h:20
@ parent_facet
Definition option.h:18
std::tuple< mesh::Mesh< T >, std::optional< std::vector< std::int32_t > >, std::optional< std::vector< std::int8_t > > > refine(const mesh::Mesh< T > &mesh, std::optional< std::span< const std::int32_t > > edges, std::variant< IdentityPartitionerPlaceholder, graph::partition_fn > partitioner=IdentityPartitionerPlaceholder(), Option option=Option::parent_cell, mesh::GhostMode ghost_mode=mesh::GhostMode::none)
Refine a mesh with markers.
Definition refine.h:124
graph::partition_fn create_identity_partitioner(const mesh::Mesh< T > &parent_mesh, std::span< std::int32_t > parent_cell)
Create a cell partitioner which maintains the partition of a coarse mesh.
Definition refine.h:43
An AnyPartitionFunction together with the node weights it should be called with, if any.
Definition partition.h:156
Placeholder for the creation of an identity partitioner in refine.
Definition refine.h:88