From a1d0027bdc72ba33af7a0f9cce325ec09ad1cc7b Mon Sep 17 00:00:00 2001 From: schnellerhase <56360279+schnellerhase@users.noreply.github.com> Date: Wed, 24 Jul 2024 13:37:59 +0200 Subject: [PATCH] Unify refine interface --- cpp/dolfinx/refinement/CMakeLists.txt | 1 + cpp/dolfinx/refinement/interval.h | 104 +++----- cpp/dolfinx/refinement/option.h | 50 ++++ cpp/dolfinx/refinement/plaza.h | 252 ++++-------------- cpp/dolfinx/refinement/refine.h | 117 ++++---- cpp/test/CMakeLists.txt | 1 + cpp/test/refinement/interval.cpp | 40 +-- cpp/test/refinement/option.cpp | 51 ++++ python/dolfinx/mesh.py | 74 +---- python/dolfinx/wrappers/refinement.cpp | 114 +++----- python/test/unit/refinement/test_interval.py | 29 +- .../{mesh => refinement}/test_refinement.py | 69 ++--- 12 files changed, 369 insertions(+), 533 deletions(-) create mode 100644 cpp/dolfinx/refinement/option.h create mode 100644 cpp/test/refinement/option.cpp rename python/test/unit/{mesh => refinement}/test_refinement.py (76%) diff --git a/cpp/dolfinx/refinement/CMakeLists.txt b/cpp/dolfinx/refinement/CMakeLists.txt index 5254b1dd066..9560e45c823 100644 --- a/cpp/dolfinx/refinement/CMakeLists.txt +++ b/cpp/dolfinx/refinement/CMakeLists.txt @@ -4,6 +4,7 @@ set(HEADERS_refinement ${CMAKE_CURRENT_SOURCE_DIR}/plaza.h ${CMAKE_CURRENT_SOURCE_DIR}/refine.h ${CMAKE_CURRENT_SOURCE_DIR}/utils.h + ${CMAKE_CURRENT_SOURCE_DIR}/option.h PARENT_SCOPE ) diff --git a/cpp/dolfinx/refinement/interval.h b/cpp/dolfinx/refinement/interval.h index 00a8b098d23..05b49e836ea 100644 --- a/cpp/dolfinx/refinement/interval.h +++ b/cpp/dolfinx/refinement/interval.h @@ -7,39 +7,44 @@ #pragma once #include -#include -#include - #include +#include #include #include #include #include -#include "dolfinx/mesh/Mesh.h" -#include "dolfinx/mesh/cell_types.h" -#include "dolfinx/mesh/utils.h" -#include "dolfinx/refinement/plaza.h" +#include -namespace dolfinx::refinement -{ +#include "dolfinx/mesh/Mesh.h" +#include "dolfinx/refinement/option.h" +#include "dolfinx/refinement/utils.h" -namespace impl +namespace dolfinx::refinement::interval { /// Refine with markers returning new mesh data. /// /// @param[in] mesh Input mesh to be refined /// @param[in] cells Indices of the cells that are marked for refinement -/// +/// @param[in] option Refinement option indicating if parent cells and/or facets +/// are to be computed /// @return New mesh data: cell topology, vertex coordinates and parent /// cell indices. template std::tuple, std::vector, - std::array, std::vector> -compute_interval_refinement(const mesh::Mesh& mesh, - std::optional> cells) + std::array, std::optional>, + std::optional>> +compute_refinement_data(const mesh::Mesh& mesh, + std::optional> cells, + Option option) { + bool compute_parent_facet = option_parent_facet(option); + bool compute_parent_cell = option_parent_cell(option); + + if (compute_parent_facet) + throw std::runtime_error("Parent facet computation not yet supported!"); + auto topology = mesh.topology(); assert(topology); assert(topology->dim() == 1); @@ -127,8 +132,12 @@ compute_interval_refinement(const mesh::Mesh& mesh, std::vector cell_topology; cell_topology.reserve(refined_cell_count * 2); - std::vector parent_cell; - parent_cell.reserve(refined_cell_count); + std::optional> parent_cell(std::nullopt); + if (compute_parent_cell) + { + parent_cell.emplace(); + parent_cell->reserve(refined_cell_count); + } for (std::int32_t cell = 0; cell < map_c->size_local(); ++cell) { @@ -150,18 +159,22 @@ compute_interval_refinement(const mesh::Mesh& mesh, // Add new cells/edges to refined topology cell_topology.insert(cell_topology.end(), {a, c, c, b}); - parent_cell.insert(parent_cell.end(), {cell, cell}); + + if (compute_parent_cell) + parent_cell->insert(parent_cell->end(), {cell, cell}); } else { // Copy the previous cell cell_topology.insert(cell_topology.end(), {a, b}); - parent_cell.push_back(cell); + + if (compute_parent_cell) + parent_cell->push_back(cell); } } assert(cell_topology.size() == refined_cell_count * 2); - assert(parent_cell.size() == refined_cell_count); + assert(parent_cell->size() == (compute_parent_cell ? refined_cell_count : 0)); std::vector offsets(refined_cell_count + 1); std::ranges::generate(offsets, [i = 0]() mutable { return 2 * i++; }); @@ -169,56 +182,7 @@ compute_interval_refinement(const mesh::Mesh& mesh, graph::AdjacencyList cell_adj(std::move(cell_topology), std::move(offsets)); return {std::move(cell_adj), std::move(new_vertex_coords), xshape, - std::move(parent_cell)}; -} - -} // namespace impl - -/// Refines a (topologically) one dimensional mesh by splitting cells, i.e. -/// edges. -/// -/// @param[in] mesh Mesh to be refined -/// @param[in] cells Optional indices of the cells that should be refined by -/// this refinement. If not provided, all cells are considered marked for -/// refinement, i.e. a uniform refinement is performed. -/// @param[in] redistribute Option to enable redistribution of the refined mesh -/// across processes. -/// @param[in] ghost_mode Ghost mode of the refined mesh, default is ghost mode -/// none -/// -/// @return Refined mesh, and list of parent cells and an array mapping the -/// child cell index of the refined mesh to its parent cell index in the -/// unrefined mesh. -template -std::tuple, std::vector> -refine_interval(const mesh::Mesh& mesh, - std::optional> cells, - bool redistribute, - mesh::GhostMode ghost_mode = mesh::GhostMode::shared_facet) -{ - - if (mesh.topology()->cell_type() != mesh::CellType::interval) - throw std::runtime_error("Cell type not supported"); - - assert(mesh.topology()->dim() == 1); - assert(mesh.topology()->index_map(1)); - - auto [cell_adj, new_coords, xshape, parent_cell] - = impl::compute_interval_refinement(mesh, cells); - - if (dolfinx::MPI::size(mesh.comm()) == 1) - { - return {mesh::create_mesh(mesh.comm(), cell_adj.array(), - mesh.geometry().cmap(), new_coords, xshape, - mesh::GhostMode::none), - std::move(parent_cell)}; - } - else - { - return {partition(mesh, cell_adj, std::span(new_coords), xshape, - redistribute, ghost_mode), - std::move(parent_cell)}; - } + std::move(parent_cell), std::nullopt}; } -} // namespace dolfinx::refinement +} // namespace dolfinx::refinement::interval diff --git a/cpp/dolfinx/refinement/option.h b/cpp/dolfinx/refinement/option.h new file mode 100644 index 00000000000..86ed5a30ccf --- /dev/null +++ b/cpp/dolfinx/refinement/option.h @@ -0,0 +1,50 @@ +// Copyright (C) 2024 Paul Kühner +// +// This file is part of DOLFINX (https://www.fenicsproject.org) +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include +#include + +namespace dolfinx::refinement +{ + +/// @brief Options for data to compute during mesh refinement. +enum class Option : std::uint8_t +{ + none = 0b00, + parent_facet = 0b01, + parent_cell = 0b10, + parent_cell_and_facet = 0b11 +}; + +/// @brief Combine two refinement options into one, both flags will be set for +/// the resulting option. +inline constexpr Option operator|(Option a, Option b) { + using bitmask_t = std::underlying_type_t