diff --git a/.github/workflows/oneapi.yml b/.github/workflows/oneapi.yml
index c502684c05e..cdaaf040f0e 100644
--- a/.github/workflows/oneapi.yml
+++ b/.github/workflows/oneapi.yml
@@ -56,7 +56,7 @@ jobs:
conda list
- name: Install Basix
- run: pip install --no-build-isolation git+https://github.com/FEniCS/basix.git@${{ needs.fenicsx-refs.outputs.basix_ref }}
+ run: uv pip install --no-build-isolation git+https://github.com/FEniCS/basix.git@${{ needs.fenicsx-refs.outputs.basix_ref }}
- name: Clone FFCx
uses: actions/checkout@v4
@@ -82,8 +82,8 @@ jobs:
- name: Install UFL and FFCx modules
run: |
- pip install --no-build-isolation git+https://github.com/FEniCS/ufl.git@${{ needs.fenicsx-refs.outputs.ufl_ref }}
- pip install --no-build-isolation ffcx/
+ uv pip install --no-build-isolation git+https://github.com/FEniCS/ufl.git@${{ needs.fenicsx-refs.outputs.ufl_ref }}
+ uv pip install --no-build-isolation ffcx/
- name: Build and run DOLFINx C++ unit tests (serial and MPI)
run: |
@@ -102,7 +102,7 @@ jobs:
ctest -R demo -R mpi_2
- name: Build DOLFINx Python interface
- run: pip -v install --check-build-dependencies --no-build-isolation --config-settings=cmake.build-type="Developer" python/
+ run: uv pip -v install --no-build-isolation --config-settings=cmake.build-type="Developer" python/
- name: Run DOLFINx demos (Python, serial)
run: python -m pytest -v -n=2 -m serial --durations=10 python/demo/test.py
- name: Run DOLFINx demos (Python, MPI (np=2))
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 1bdd3d2a9fd..982020e3102 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -104,7 +104,7 @@ jobs:
(Get-Content __init__.py).Replace('# WINDOWSDLL', 'import os; os.add_dll_directory("D:/a/dolfinx/dolfinx-install/bin"); os.add_dll_directory("C:/Program Files (x86)/Intel/oneAPI/mpi/2021.12/opt/mpi/libfabric/bin")') | Set-Content __init__.py
Get-Content __init__.py
- - uses: mpi4py/setup-mpi@v1.2.7
+ - uses: mpi4py/setup-mpi@v1.2.8
with:
mpi: "intelmpi"
diff --git a/ChangeLog.rst b/ChangeLog.rst
index bb16a89693b..7567d1c3e65 100644
--- a/ChangeLog.rst
+++ b/ChangeLog.rst
@@ -28,7 +28,7 @@ solver `_.
- Remove ``Mesh::size``. Use ``Mesh::num_entities`` instead.
- Improved mesh topology computation performance.
- Remove excessive calls to MPI init. It may now be necessary in some
- cases to explicitly intialise MPI.
+ cases to explicitly initialise MPI.
- Improvements to sparsity pattern computation.
- Addition of some interfaces using ``Eigen::Map/ref`` in addition to
``dolfin::Array(View)``. ``dolfin::Array(View)``interfaces will be
@@ -146,7 +146,7 @@ solver `_.
- Require polynomial degree or finite element for Expressions in the
Python interface (fixes Issue #355,
https://bitbucket.org/fenics-project/dolfin/issues/355)
-- Switch to Google Test framwork for C++ unit tests
+- Switch to Google Test framework for C++ unit tests
- Fix bug when reading domain data from mesh file for a ghosted mesh
- Add interface for manipulating mesh geometry using (higher-order) FE
functions: free functions set_coordinates, get_coordinates,
@@ -223,7 +223,7 @@ solver `_.
#443)
- Add quadrature rules for multimesh/cut-cell integration up to order
6
-- Implement MPI reductions and XML ouput of Table class
+- Implement MPI reductions and XML output of Table class
- list_timings() is now collective and returns MPI average across
processes
- Add dump_timings_to_xml()
@@ -324,7 +324,7 @@ solver `_.
module
- Add function Form::set_some_coefficients()
- Remove Boost.MPI dependency
-- Change GenericMatrix::compresss to return a new matrix (7be3a29)
+- Change GenericMatrix::compress to return a new matrix (7be3a29)
- Add function GenericTensor::empty()
- Deprecate resizing of linear algebra via the GenericFoo interfaces
(fixes #213)
@@ -387,7 +387,7 @@ solver `_.
- Fixes bug where child/parent hierarchy in Python were destroyed
- Add utility script dolfin-get-demos
- MeshFunctions in python now support iterable protocol
-- Add timed VTK output for Mesh and MeshFunction in addtion to
+- Add timed VTK output for Mesh and MeshFunction in addition to
Functions
- Expose ufc::dofmap::tabulate_entity_dofs to GenericDofMap interface
- Expose ufc::dofmap::num_entity_dofs to GenericDofMap interface
@@ -477,7 +477,7 @@ solver `_.
- Add sparray method in the Python interface of GenericMatrix,
requires scipy.sparse
- Make methods that return a view of contiguous c-arrays, via a NumPy
- array, keep a reference from the object so it wont get out of scope
+ array, keep a reference from the object so it won't get out of scope
- Add parameter: "use_petsc_signal_handler", which enables/disable
PETSc system signals
- Avoid unnecessary resize of result vector for A*b
@@ -684,7 +684,7 @@ solver `_.
- Thread-safe fixed in Function class
- Make GenericFunction::eval thread-safe (Data class removed)
- Optimize and speedup topology computation (mesh.init())
-- Add function Mesh::clean() for cleaning out auxilliary topology data
+- Add function Mesh::clean() for cleaning out auxiliary topology data
- Improve speed and accuracy of timers
- Fix bug in 3D uniform mesh refinement
- Add built-in meshes UnitTriangle and UnitTetrahedron
@@ -761,7 +761,7 @@ solver `_.
refinement
- Add functionality for smoothing the boundary of a mesh
- Speedup assembly over exterior facets by not using BoundaryMesh
-- Mesh refinement improvements, remove unecessary copying in Python
+- Mesh refinement improvements, remove unnecessary copying in Python
interface
- Clean PETSc and Epetra Krylov solvers
- Add separate preconditioner classes for PETSc and Epetra solvers
@@ -935,7 +935,7 @@ solver `_.
check range
- Add unit tests to the memorycheck
- Add call to clean up libxml2 parser at exit
-- Remove unecessary arguments in DofMap member functions
+- Remove unnecessary arguments in DofMap member functions
- Remove reference constructors from DofMap, FiniteElement and
FunctionSpace
- Use a shared_ptr to store the mesh in DofMap objects
@@ -1215,7 +1215,7 @@ solver `_.
- Disable PETSc by default, use --enable-petsc to enable
- Modify ODE solver interface for u0() and f()
- Add class ConvectionMatrix
-- Readd classes LoadVector, MassMatrix, StiffnessMatrix
+- Read classes LoadVector, MassMatrix, StiffnessMatrix
- Add matrix factory for simple creation of standard finite element
matrices
- Collect static solvers in LU and GMRES
@@ -1500,7 +1500,7 @@ solver `_.
- Update PETSc wrappers NewVector, NewMatrix, and NewGMRES
- Fix initialization of PETSc
- Add mono-adaptive cG(q) and dG(q) solvers (experimental)
-- Implementation of new assebly: NewFEM, using output from FFC
+- Implementation of new assembly: NewFEM, using output from FFC
- Add access to mesh for nodes, cells, faces and edges
- Add Tecplot I/O interface; contributed by Garth N. Wells
@@ -1623,7 +1623,7 @@ solver `_.
- Optimize Lagrange polynomials
- Optimize sparsity: use stl containers
- Optimize choice of discrete residual for multi-adaptive solver
-- Don't save solution in benchmark proble
+- Don't save solution in benchmark problem
- Improve computation of divergence factor for underdamped systems
- Don't check residual on first slab for fixed time step
- Decrease largest (default) time step to 0.1
diff --git a/README.md b/README.md
index b510ec5d06c..da261745acf 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,12 @@ DOLFINx is the computational environment of
Solving Environment in C++ and Python. DOLFINx is a new version of
DOLFIN and is actively developed.
+For questions about using DOLFINx, visit the [FEniCS
+Discourse](https://fenicsproject.discourse.group/) page or use the
+[FEniCS Slack channel](https://fenicsproject.slack.com/) (use
+[this](https://join.slack.com/t/fenicsproject/shared_invite/zt-1lraknsp1-6_3Js5kueDIyWgF192d3nA)
+link to sign up to the Slack channel).
+
## Documentation
Documentation can be viewed at .
@@ -191,19 +197,3 @@ Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with DOLFINx. If not, see
.
-
-## Contact
-
-For questions about using DOLFINx, visit the FEniCS Discourse page:
-
-
-
-or use the FEniCS Slack channel:
-
-
-
-(use to sign up)
-
-For bug reports visit:
-
-
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 20003555877..774c65d0401 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -382,7 +382,7 @@ if(NOT DOLFINX_UFCX_PYTHON)
# Check in CONFIG mode, i.e. look for installed ufcxConfig.cmake
find_package(ufcx 0.10 REQUIRED CONFIG)
else()
- # Check in MODULE mode (using FindUFCX.cmake) using Python intepreter.
+ # Check in MODULE mode (using FindUFCX.cmake) using Python interpreter.
find_package(
Python3
COMPONENTS Interpreter
diff --git a/cpp/doc/Doxyfile b/cpp/doc/Doxyfile
index f94948804e7..e0e2b403289 100644
--- a/cpp/doc/Doxyfile
+++ b/cpp/doc/Doxyfile
@@ -86,7 +86,7 @@ CREATE_SUBDIRS = YES
# level increment doubles the number of directories, resulting in 4096
# directories at level 8 which is the default and also the maximum value. The
# sub-directories are organized in 2 levels, the first level always has a fixed
-# numer of 16 directories.
+# number of 16 directories.
# Minimum value: 0, maximum value: 8, default value: 8.
# This tag requires that the tag CREATE_SUBDIRS is set to YES.
@@ -1007,7 +1007,7 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.
-# EXCLUDE =
+# EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
@@ -2268,7 +2268,7 @@ PERLMOD_MAKEVAR_PREFIX =
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
-ENABLE_PREPROCESSING = NO
+ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
# in the source code. If set to NO, only conditional compilation will be
@@ -2285,7 +2285,7 @@ MACRO_EXPANSION = YES
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-EXPAND_ONLY_PREDEF = YES
+EXPAND_ONLY_PREDEF = NO
# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
diff --git a/cpp/doc/source/jupytext_process.py b/cpp/doc/source/jupytext_process.py
index 44a21de9f91..e31cc7e7f81 100644
--- a/cpp/doc/source/jupytext_process.py
+++ b/cpp/doc/source/jupytext_process.py
@@ -54,7 +54,7 @@ def process():
with open(myst_file, "w") as fw:
fw.write(cpp_myst_text)
- # There is a posibility to use jupyter-notebooks with C++/C kernels
+ # There is a possibility to use jupyter-notebooks with C++/C kernels
# ipynb_file = (demo_doc_dir / fname.name).with_suffix(".ipynb")
# jupytext.write(cpp_demo, ipynb_file, fmt="ipynb")
diff --git a/cpp/dolfinx/common/CMakeLists.txt b/cpp/dolfinx/common/CMakeLists.txt
index 5f46222cee7..3a5c77044e0 100644
--- a/cpp/dolfinx/common/CMakeLists.txt
+++ b/cpp/dolfinx/common/CMakeLists.txt
@@ -12,7 +12,6 @@ set(HEADERS_common
${CMAKE_CURRENT_SOURCE_DIR}/Table.h
${CMAKE_CURRENT_SOURCE_DIR}/Timer.h
${CMAKE_CURRENT_SOURCE_DIR}/TimeLogger.h
- ${CMAKE_CURRENT_SOURCE_DIR}/TimeLogManager.h
${CMAKE_CURRENT_SOURCE_DIR}/timing.h
${CMAKE_CURRENT_SOURCE_DIR}/utils.h
PARENT_SCOPE
@@ -26,6 +25,5 @@ target_sources(
${CMAKE_CURRENT_SOURCE_DIR}/MPI.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Table.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TimeLogger.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TimeLogManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/timing.cpp
)
diff --git a/cpp/dolfinx/common/IndexMap.cpp b/cpp/dolfinx/common/IndexMap.cpp
index 1c4d4e8b174..e4eb98fc53a 100644
--- a/cpp/dolfinx/common/IndexMap.cpp
+++ b/cpp/dolfinx/common/IndexMap.cpp
@@ -416,7 +416,7 @@ compute_submap_indices(const IndexMap& imap,
// If required, preserve the order of the ghost indices
if (order == IndexMapOrder::preserve)
{
- // Build (old postion, new position) list for ghosts and sort
+ // Build (old position, new position) list for ghosts and sort
std::vector> pos;
pos.reserve(submap_ghost.size());
for (std::int32_t idx : submap_ghost)
diff --git a/cpp/dolfinx/common/MPI.h b/cpp/dolfinx/common/MPI.h
index ab04d93cc64..7cfc77e8866 100644
--- a/cpp/dolfinx/common/MPI.h
+++ b/cpp/dolfinx/common/MPI.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2023 Magnus Vikstrøm and Garth N. Wells
+// Copyright (C) 2007-2023 Magnus Vikstrøm, Garth N. Wells and Paul T. Kühner
//
// This file is part of DOLFINx (https://www.fenicsproject.org)
//
@@ -271,39 +271,42 @@ struct dependent_false : std::false_type
};
/// MPI Type
+
+/// @brief Type trait for MPI type conversions.
template
-constexpr MPI_Datatype mpi_type()
-{
- if constexpr (std::is_same_v)
- return MPI_FLOAT;
- else if constexpr (std::is_same_v)
- return MPI_DOUBLE;
- else if constexpr (std::is_same_v>)
- return MPI_C_DOUBLE_COMPLEX;
- else if constexpr (std::is_same_v>)
- return MPI_C_FLOAT_COMPLEX;
- else if constexpr (std::is_same_v)
- return MPI_SHORT;
- else if constexpr (std::is_same_v)
- return MPI_INT;
- else if constexpr (std::is_same_v)
- return MPI_UNSIGNED;
- else if constexpr (std::is_same_v)
- return MPI_LONG;
- else if constexpr (std::is_same_v)
- return MPI_UNSIGNED_LONG;
- else if constexpr (std::is_same_v)
- return MPI_LONG_LONG;
- else if constexpr (std::is_same_v)
- return MPI_UNSIGNED_LONG_LONG;
- else if constexpr (std::is_same_v)
- return MPI_C_BOOL;
- else if constexpr (std::is_same_v)
- return MPI_INT8_T;
- else
- // Issue compile time error
- static_assert(!std::is_same_v);
-}
+struct mpi_type_mapping;
+
+/// @brief Retrieves the MPI data type associated to the provided type.
+/// @tparam T cpp type to map
+template
+MPI_Datatype mpi_t = mpi_type_mapping::type;
+
+/// @brief Registers for cpp_t the corresponding mpi_t which can then be
+/// retrieved with mpi_t from here on.
+#define MAP_TO_MPI_TYPE(cpp_t, mpi_t) \
+ template <> \
+ struct mpi_type_mapping \
+ { \
+ static inline MPI_Datatype type = mpi_t; \
+ };
+
+/// @defgroup MPI type mappings
+/// @{
+/// @cond
+MAP_TO_MPI_TYPE(float, MPI_FLOAT)
+MAP_TO_MPI_TYPE(double, MPI_DOUBLE)
+MAP_TO_MPI_TYPE(std::complex, MPI_C_FLOAT_COMPLEX)
+MAP_TO_MPI_TYPE(std::complex, MPI_C_DOUBLE_COMPLEX)
+MAP_TO_MPI_TYPE(std::int8_t, MPI_INT8_T)
+MAP_TO_MPI_TYPE(std::int16_t, MPI_INT16_T)
+MAP_TO_MPI_TYPE(std::int32_t, MPI_INT32_T)
+MAP_TO_MPI_TYPE(std::int64_t, MPI_INT64_T)
+MAP_TO_MPI_TYPE(std::uint8_t, MPI_UINT8_T)
+MAP_TO_MPI_TYPE(std::uint16_t, MPI_UINT16_T)
+MAP_TO_MPI_TYPE(std::uint32_t, MPI_UINT32_T)
+MAP_TO_MPI_TYPE(std::uint64_t, MPI_UINT64_T)
+/// @endcond
+/// @}
//---------------------------------------------------------------------------
template
@@ -434,7 +437,7 @@ distribute_to_postoffice(MPI_Comm comm, const U& x,
// Send/receive data (x)
MPI_Datatype compound_type;
- MPI_Type_contiguous(shape[1], dolfinx::MPI::mpi_type(), &compound_type);
+ MPI_Type_contiguous(shape[1], dolfinx::MPI::mpi_t, &compound_type);
MPI_Type_commit(&compound_type);
std::vector recv_buffer_data(shape[1] * recv_disp.back());
err = MPI_Neighbor_alltoallv(
@@ -616,7 +619,7 @@ distribute_from_postoffice(MPI_Comm comm, std::span indices,
dolfinx::MPI::check_error(comm, err);
MPI_Datatype compound_type0;
- MPI_Type_contiguous(shape[1], dolfinx::MPI::mpi_type(), &compound_type0);
+ MPI_Type_contiguous(shape[1], dolfinx::MPI::mpi_t, &compound_type0);
MPI_Type_commit(&compound_type0);
std::vector recv_buffer_data(shape[1] * send_disp.back());
@@ -691,8 +694,8 @@ distribute_data(MPI_Comm comm0, std::span indices,
if (comm1 != MPI_COMM_NULL)
{
rank_offset = 0;
- err = MPI_Exscan(&shape0_local, &rank_offset, 1, MPI_INT64_T, MPI_SUM,
- comm1);
+ err = MPI_Exscan(&shape0_local, &rank_offset, 1,
+ dolfinx::MPI::mpi_t, MPI_SUM, comm1);
dolfinx::MPI::check_error(comm1, err);
}
else
diff --git a/cpp/dolfinx/common/Scatterer.h b/cpp/dolfinx/common/Scatterer.h
index b38793dcd2c..72afe81ad11 100644
--- a/cpp/dolfinx/common/Scatterer.h
+++ b/cpp/dolfinx/common/Scatterer.h
@@ -145,8 +145,7 @@ class Scatterer
// Scale sizes and displacements by block size
{
- auto rescale = [](auto& x, int bs)
- {
+ auto rescale = [](auto& x, int bs) {
std::ranges::transform(x, x.begin(), [bs](auto e) { return e *= bs; });
};
rescale(_sizes_local, bs);
@@ -207,11 +206,11 @@ class Scatterer
case type::neighbor:
{
assert(requests.size() == std::size_t(1));
- MPI_Ineighbor_alltoallv(
- send_buffer.data(), _sizes_local.data(), _displs_local.data(),
- dolfinx::MPI::mpi_type(), recv_buffer.data(), _sizes_remote.data(),
- _displs_remote.data(), dolfinx::MPI::mpi_type(), _comm0.comm(),
- requests.data());
+ MPI_Ineighbor_alltoallv(send_buffer.data(), _sizes_local.data(),
+ _displs_local.data(), dolfinx::MPI::mpi_t,
+ recv_buffer.data(), _sizes_remote.data(),
+ _displs_remote.data(), dolfinx::MPI::mpi_t,
+ _comm0.comm(), requests.data());
break;
}
case type::p2p:
@@ -220,14 +219,14 @@ class Scatterer
for (std::size_t i = 0; i < _src.size(); i++)
{
MPI_Irecv(recv_buffer.data() + _displs_remote[i], _sizes_remote[i],
- dolfinx::MPI::mpi_type(), _src[i], MPI_ANY_TAG,
- _comm0.comm(), &requests[i]);
+ dolfinx::MPI::mpi_t, _src[i], MPI_ANY_TAG, _comm0.comm(),
+ &requests[i]);
}
for (std::size_t i = 0; i < _dest.size(); i++)
{
MPI_Isend(send_buffer.data() + _displs_local[i], _sizes_local[i],
- dolfinx::MPI::mpi_type(), _dest[i], 0, _comm0.comm(),
+ dolfinx::MPI::mpi_t, _dest[i], 0, _comm0.comm(),
&requests[i + _src.size()]);
}
break;
@@ -404,11 +403,10 @@ class Scatterer
case type::neighbor:
{
assert(requests.size() == 1);
- MPI_Ineighbor_alltoallv(send_buffer.data(), _sizes_remote.data(),
- _displs_remote.data(), MPI::mpi_type(),
- recv_buffer.data(), _sizes_local.data(),
- _displs_local.data(), MPI::mpi_type(),
- _comm1.comm(), &requests[0]);
+ MPI_Ineighbor_alltoallv(
+ send_buffer.data(), _sizes_remote.data(), _displs_remote.data(),
+ MPI::mpi_t, recv_buffer.data(), _sizes_local.data(),
+ _displs_local.data(), MPI::mpi_t, _comm1.comm(), &requests[0]);
break;
}
case type::p2p:
@@ -418,8 +416,8 @@ class Scatterer
for (std::size_t i = 0; i < _dest.size(); i++)
{
MPI_Irecv(recv_buffer.data() + _displs_local[i], _sizes_local[i],
- dolfinx::MPI::mpi_type(), _dest[i], MPI_ANY_TAG,
- _comm0.comm(), &requests[i]);
+ dolfinx::MPI::mpi_t, _dest[i], MPI_ANY_TAG, _comm0.comm(),
+ &requests[i]);
}
// Start non-blocking receive from neighbor process for which an owned
@@ -427,7 +425,7 @@ class Scatterer
for (std::size_t i = 0; i < _src.size(); i++)
{
MPI_Isend(send_buffer.data() + _displs_remote[i], _sizes_remote[i],
- dolfinx::MPI::mpi_type(), _src[i], 0, _comm0.comm(),
+ dolfinx::MPI::mpi_t, _src[i], 0, _comm0.comm(),
&requests[i + _dest.size()]);
}
break;
diff --git a/cpp/dolfinx/common/Table.cpp b/cpp/dolfinx/common/Table.cpp
index 814cc43d14e..241cebd8532 100644
--- a/cpp/dolfinx/common/Table.cpp
+++ b/cpp/dolfinx/common/Table.cpp
@@ -144,8 +144,9 @@ Table Table::reduce(MPI_Comm comm, Table::Reduction reduction) const
std::partial_sum(pcounts.begin(), pcounts.end(), offsets.begin() + 1);
std::vector values_all(offsets.back());
- err = MPI_Gatherv(values.data(), values.size(), MPI_DOUBLE, values_all.data(),
- pcounts.data(), offsets.data(), MPI_DOUBLE, 0, comm);
+ err = MPI_Gatherv(values.data(), values.size(), dolfinx::MPI::mpi_t,
+ values_all.data(), pcounts.data(), offsets.data(),
+ dolfinx::MPI::mpi_t, 0, comm);
dolfinx::MPI::check_error(comm, err);
// Return empty table on rank > 0
diff --git a/cpp/dolfinx/common/TimeLogManager.cpp b/cpp/dolfinx/common/TimeLogManager.cpp
deleted file mode 100644
index 94474d5d191..00000000000
--- a/cpp/dolfinx/common/TimeLogManager.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (C) 2003-2005 Anders Logg
-//
-// This file is part of DOLFINx (https://www.fenicsproject.org)
-//
-// SPDX-License-Identifier: LGPL-3.0-or-later
-
-#include "TimeLogManager.h"
-#include "TimeLogger.h"
-
-// Initialise static data to avoid "static initialisation order fiasco".
-// See also Meyers' singleton.
-
-dolfinx::common::TimeLogger& dolfinx::common::TimeLogManager::logger()
-{
- // NB static - this only allocates a new Logger on the first call to logger()
- static TimeLogger lg{};
- return lg;
-}
diff --git a/cpp/dolfinx/common/TimeLogManager.h b/cpp/dolfinx/common/TimeLogManager.h
deleted file mode 100644
index 05d048f96fb..00000000000
--- a/cpp/dolfinx/common/TimeLogManager.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (C) 2003-2016 Anders Logg
-//
-// This file is part of DOLFINx (https://www.fenicsproject.org)
-//
-// SPDX-License-Identifier: LGPL-3.0-or-later
-
-#pragma once
-
-#include "TimeLogger.h"
-
-namespace dolfinx::common
-{
-
-class TimeLogger;
-
-/// Logger initialisation
-class TimeLogManager
-{
-public:
- /// Singleton instance of logger
- static TimeLogger& logger();
-};
-} // namespace dolfinx::common
diff --git a/cpp/dolfinx/common/TimeLogger.cpp b/cpp/dolfinx/common/TimeLogger.cpp
index bbe3a43229f..eb356f9b3a1 100644
--- a/cpp/dolfinx/common/TimeLogger.cpp
+++ b/cpp/dolfinx/common/TimeLogger.cpp
@@ -12,6 +12,13 @@
using namespace dolfinx;
using namespace dolfinx::common;
+//-----------------------------------------------------------------------------
+TimeLogger& TimeLogger::instance()
+{
+ static TimeLogger _instance{};
+ return _instance;
+}
+
//-----------------------------------------------------------------------------
void TimeLogger::register_timing(
std::string task, std::chrono::duration> time)
diff --git a/cpp/dolfinx/common/TimeLogger.h b/cpp/dolfinx/common/TimeLogger.h
index e1b852da375..cad8de5f2ad 100644
--- a/cpp/dolfinx/common/TimeLogger.h
+++ b/cpp/dolfinx/common/TimeLogger.h
@@ -16,21 +16,16 @@
namespace dolfinx::common
{
-/// Timer logging
+/// @brief Time logger maintaining data collected by Timer, if registered.
+///
+/// @note This is a monotstate, i.e. the data members are static and thus
+/// timings are aggregated into a single map.
class TimeLogger
{
public:
- /// Constructor
- TimeLogger() = default;
-
- // This class is used as a singleton and thus should not allow copies.
- TimeLogger(const TimeLogger&) = delete;
-
- // This class is used as a singleton and thus should not allow copies.
- TimeLogger& operator=(const TimeLogger&) = delete;
-
- /// Destructor
- ~TimeLogger() = default;
+ /// @brief Singleton access.
+ /// @return Unique time logger object.
+ static TimeLogger& instance();
/// Register timing (for later summary)
void register_timing(std::string task,
@@ -58,6 +53,18 @@ class TimeLogger
timings() const;
private:
+ /// Constructor
+ TimeLogger() = default;
+
+ // This class is used as a singleton and thus should not allow copies.
+ TimeLogger(const TimeLogger&) = delete;
+
+ // This class is used as a singleton and thus should not allow copies.
+ TimeLogger& operator=(const TimeLogger&) = delete;
+
+ /// Destructor
+ ~TimeLogger() = default;
+
// List of timings for tasks, map from string to (num_timings,
// total_wall_time)
std::map
#include
#include
#include
+#include "TimeLogger.h"
+
namespace dolfinx::common
{
/// @brief Timer for measuring and logging elapsed time durations.
@@ -56,7 +57,7 @@ class Timer
if (_start_time.has_value() and _task.has_value())
{
_acc += T::now() - *_start_time;
- TimeLogManager::logger().register_timing(*_task, _acc);
+ TimeLogger::instance().register_timing(*_task, _acc);
}
}
@@ -121,7 +122,7 @@ class Timer
if (_task.has_value())
{
- TimeLogManager::logger().register_timing(*_task, _acc);
+ TimeLogger::instance().register_timing(*_task, _acc);
_task = std::nullopt;
}
}
diff --git a/cpp/dolfinx/common/sort.h b/cpp/dolfinx/common/sort.h
index aefaadb4a23..2801cc744fc 100644
--- a/cpp/dolfinx/common/sort.h
+++ b/cpp/dolfinx/common/sort.h
@@ -20,22 +20,20 @@
namespace dolfinx
{
-
struct __radix_sort
{
-
- /// @brief Sort a range with radix sorting algorithm. The bucket
- /// size is determined by the number of bits to sort at a time (2^BITS).
+ /// @brief Sort a range with radix sorting algorithm. The bucket size
+ /// is determined by the number of bits to sort at a time (2^BITS).
///
- /// This allows usage with standard range containers of integral types, for
- /// example
+ /// This allows usage with standard range containers of integral
+ /// types, for example
/// @code
/// std::array a{2, 3, 1};
/// dolfixn::radix_sort(a); // a = {1, 2, 3}
/// @endcode
- /// Additionally the projection based approach of the STL library is adpated,
- /// which allows for versatile usage, for example the easy realization of an
- /// argsort
+ /// Additionally the projection based approach of the STL library is
+ /// adapted, which allows for versatile usage, for example the easy
+ /// realization of an argsort
/// @code
/// std::array a{2, 3, 1};
/// std::array i{0, 1, 2};
@@ -43,8 +41,8 @@ struct __radix_sort
/// 1} and a[i] = {1, 2, 3};
/// @endcode
/// @tparam R Type of range to be sorted.
- /// @tparam P Projection type to be applied on range elements to produce a
- /// sorting index.
+ /// @tparam P Projection type to be applied on range elements to
+ /// produce a sorting index.
/// @tparam BITS The number of bits to sort at a time.
/// @param[in, out] range The range to sort.
/// @param[in] P Element projection.
@@ -126,9 +124,10 @@ inline constexpr __radix_sort radix_sort{};
/// @brief Compute the permutation array that sorts a 2D array by row.
///
/// @param[in] x The flattened 2D array to compute the permutation array
-/// for.
+/// for (row-major storage).
/// @param[in] shape1 The number of columns of `x`.
-/// @return The permutation array such that `x[perm[i]] <= x[perm[i +1]].
+/// @return The permutation array such that `x[perm[i]] <= x[perm[i
+/// +1]].
/// @pre `x.size()` must be a multiple of `shape1`.
/// @note This function is suitable for small values of `shape1`. Each
/// column of `x` is copied into an array that is then sorted.
@@ -136,6 +135,10 @@ template
std::vector sort_by_perm(std::span x, std::size_t shape1)
{
static_assert(std::is_integral_v, "Integral required.");
+
+ if (x.empty())
+ return std::vector{};
+
assert(shape1 > 0);
assert(x.size() % shape1 == 0);
const std::size_t shape0 = x.size() / shape1;
@@ -147,7 +150,7 @@ std::vector sort_by_perm(std::span x, std::size_t shape1)
std::vector column(shape0);
for (std::size_t i = 0; i < shape1; ++i)
{
- int col = shape1 - 1 - i;
+ std::size_t col = shape1 - 1 - i;
for (std::size_t j = 0; j < shape0; ++j)
column[j] = x[j * shape1 + col];
diff --git a/cpp/dolfinx/common/timing.cpp b/cpp/dolfinx/common/timing.cpp
index cd965e0c342..f48ac44c030 100644
--- a/cpp/dolfinx/common/timing.cpp
+++ b/cpp/dolfinx/common/timing.cpp
@@ -6,31 +6,30 @@
#include "timing.h"
#include "Table.h"
-#include "TimeLogManager.h"
#include "TimeLogger.h"
#include "Timer.h"
//-----------------------------------------------------------------------
dolfinx::Table dolfinx::timing_table()
{
- return dolfinx::common::TimeLogManager::logger().timing_table();
+ return dolfinx::common::TimeLogger::instance().timing_table();
}
//-----------------------------------------------------------------------------
void dolfinx::list_timings(MPI_Comm comm, Table::Reduction reduction)
{
- dolfinx::common::TimeLogManager::logger().list_timings(comm, reduction);
+ dolfinx::common::TimeLogger::instance().list_timings(comm, reduction);
}
//-----------------------------------------------------------------------------
std::pair>>
dolfinx::timing(std::string task)
{
- return dolfinx::common::TimeLogManager::logger().timing(task);
+ return dolfinx::common::TimeLogger::instance().timing(task);
}
//-----------------------------------------------------------------------------
std::map>>>
dolfinx::timings()
{
- return dolfinx::common::TimeLogManager::logger().timings();
+ return dolfinx::common::TimeLogger::instance().timings();
}
//-----------------------------------------------------------------------------
diff --git a/cpp/dolfinx/common/utils.h b/cpp/dolfinx/common/utils.h
index 945e5ad44d7..bbe7ec08e6d 100644
--- a/cpp/dolfinx/common/utils.h
+++ b/cpp/dolfinx/common/utils.h
@@ -88,9 +88,9 @@ std::size_t hash_global(MPI_Comm comm, const T& x)
// Gather hash keys on root process
std::vector all_hashes(dolfinx::MPI::size(comm));
- int err = MPI_Gather(&local_hash, 1, dolfinx::MPI::mpi_type(),
- all_hashes.data(), 1,
- dolfinx::MPI::mpi_type(), 0, comm);
+ int err = MPI_Gather(&local_hash, 1, dolfinx::MPI::mpi_t,
+ all_hashes.data(), 1, dolfinx::MPI::mpi_t,
+ 0, comm);
dolfinx::MPI::check_error(comm, err);
// Hash the received hash keys
@@ -98,8 +98,7 @@ std::size_t hash_global(MPI_Comm comm, const T& x)
std::size_t global_hash = hash(all_hashes);
// Broadcast hash key to all processes
- err = MPI_Bcast(&global_hash, 1, dolfinx::MPI::mpi_type(), 0,
- comm);
+ err = MPI_Bcast(&global_hash, 1, dolfinx::MPI::mpi_t, 0, comm);
dolfinx::MPI::check_error(comm, err);
return global_hash;
diff --git a/cpp/dolfinx/fem/DirichletBC.h b/cpp/dolfinx/fem/DirichletBC.h
index 83e8994a36b..5341dd518cd 100644
--- a/cpp/dolfinx/fem/DirichletBC.h
+++ b/cpp/dolfinx/fem/DirichletBC.h
@@ -338,7 +338,7 @@ class DirichletBC
if (g->shape.size() != V->element()->value_shape().size())
{
throw std::runtime_error(
- "Rank mis-match between Constant and function space in DirichletBC");
+ "Rank mismatch between Constant and function space in DirichletBC");
}
if (g->value.size() != _function_space->dofmap()->bs())
diff --git a/cpp/dolfinx/fem/FiniteElement.h b/cpp/dolfinx/fem/FiniteElement.h
index 41f6938e87e..575275ad615 100644
--- a/cpp/dolfinx/fem/FiniteElement.h
+++ b/cpp/dolfinx/fem/FiniteElement.h
@@ -39,7 +39,7 @@ struct BasixElementData
element; ///< Finite element.
std::optional> value_shape
= std::nullopt; ///< Value shape. Can only be set for scalar `element`.
- bool symmetry = false; ///< Symmetry. Should ony set set for 2nd-order tensor
+ bool symmetry = false; ///< Symmetry. Should only set set for 2nd-order tensor
///< blocked elements.
};
@@ -65,8 +65,8 @@ class FiniteElement
/// for a vector in 3D or `{2, 2}` for a rank-2 tensor in 2D. Can only
/// be set for blocked scalar `element`. For other elements and scalar
/// elements it should be `std::nullopt`.
- /// @param[in] symmetric Is the element a symmetric tensor? Should ony
- /// set for 2nd-order tensor blocked elements.
+ /// @param[in] symmetric Is the element a symmetric tensor? Should
+ /// only set for 2nd-order tensor blocked elements.
FiniteElement(const basix::FiniteElement& element,
std::optional> value_shape
= std::nullopt,
@@ -792,7 +792,7 @@ class FiniteElement
/// consistent physical element degree-of-freedom ordering. The
/// permutation is computed in-place.
///
- /// @param[in,out] doflist Indicies associated with the
+ /// @param[in,out] doflist Indices associated with the
/// degrees-of-freedom. Size=`num_dofs`.
/// @param[in] cell_permutation Permutation data for the cell.
void permute(std::span doflist,
@@ -811,7 +811,7 @@ class FiniteElement
/// element degree-of-freedom ordering. The permutation is computed
/// in-place.
///
- /// @param[in,out] doflist Indicies associated with the
+ /// @param[in,out] doflist Indices associated with the
/// degrees-of-freedom. Size=`num_dofs`.
/// @param[in] cell_permutation Permutation data for the cell.
void permute_inv(std::span doflist,
diff --git a/cpp/dolfinx/fem/Form.h b/cpp/dolfinx/fem/Form.h
index 6b61e4a8490..58f3eef2ebd 100644
--- a/cpp/dolfinx/fem/Form.h
+++ b/cpp/dolfinx/fem/Form.h
@@ -48,8 +48,8 @@ struct integral_data
/// @param[in] id Domain ID.
/// @param[in] kernel Integration kernel.
/// @param[in] entities Indices of entities to integrate over.
- /// @param[in] coeffs Indicies of the coefficients are present
- /// (active) in `kernel`.
+ /// @param[in] coeffs Indices of the coefficients are present (active)
+ /// in `kernel`.
template
requires std::is_convertible_v<
std::remove_cvref_t,
@@ -70,11 +70,11 @@ struct integral_data
/// @param[in] id Domain ID.
/// @param[in] kernel Integration kernel.
/// @param[in] entities Indices of entities to integrate over.
- /// @param[in] coeffs Indicies of the coefficients that are active in
+ /// @param[in] coeffs Indices of the coefficients that are active in
/// the `kernel`.
///
- /// @note This version allows `entities` to be passed as a std::span,
- /// which is then copied.
+ /// @note This version allows `entities` to be passed as a
+ /// `std::span`, which is then copied.
template
requires std::is_convertible_v<
std::remove_cvref_t,
diff --git a/cpp/dolfinx/fem/assemble_matrix_impl.h b/cpp/dolfinx/fem/assemble_matrix_impl.h
index a1a0a042c50..78582892f4f 100644
--- a/cpp/dolfinx/fem/assemble_matrix_impl.h
+++ b/cpp/dolfinx/fem/assemble_matrix_impl.h
@@ -116,8 +116,8 @@ void assemble_cells(
P1T(_Ae, cell_info1, c1, ndim0); // A = B P1_T
// Zero rows/columns for essential bcs
- auto dofs0 = std::span(dmap0.data_handle() + c0 * num_dofs0, num_dofs0);
- auto dofs1 = std::span(dmap1.data_handle() + c1 * num_dofs1, num_dofs1);
+ std::span dofs0(dmap0.data_handle() + c0 * num_dofs0, num_dofs0);
+ std::span dofs1(dmap1.data_handle() + c1 * num_dofs1, num_dofs1);
if (!bc0.empty())
{
@@ -255,8 +255,8 @@ void assemble_exterior_facets(
P1T(_Ae, cell_info1, cell1, ndim0);
// Zero rows/columns for essential bcs
- auto dofs0 = std::span(dmap0.data_handle() + cell0 * num_dofs0, num_dofs0);
- auto dofs1 = std::span(dmap1.data_handle() + cell1 * num_dofs1, num_dofs1);
+ std::span dofs0(dmap0.data_handle() + cell0 * num_dofs0, num_dofs0);
+ std::span dofs1(dmap1.data_handle() + cell1 * num_dofs1, num_dofs1);
if (!bc0.empty())
{
for (int i = 0; i < num_dofs0; ++i)
diff --git a/cpp/dolfinx/fem/assemble_vector_impl.h b/cpp/dolfinx/fem/assemble_vector_impl.h
index 6e7a440fd75..6d9879c39fc 100644
--- a/cpp/dolfinx/fem/assemble_vector_impl.h
+++ b/cpp/dolfinx/fem/assemble_vector_impl.h
@@ -473,20 +473,20 @@ void _lift_bc_interior_facets(
}
// Get dof maps for cells and pack
- auto dmap0_cell0
- = std::span(dmap0.data_handle() + cells0[0] * num_dofs0, num_dofs0);
- auto dmap0_cell1
- = std::span(dmap0.data_handle() + cells0[1] * num_dofs0, num_dofs0);
+ std::span dmap0_cell0(dmap0.data_handle() + cells0[0] * num_dofs0,
+ num_dofs0);
+ std::span dmap0_cell1(dmap0.data_handle() + cells0[1] * num_dofs0,
+ num_dofs0);
dmapjoint0.resize(dmap0_cell0.size() + dmap0_cell1.size());
std::ranges::copy(dmap0_cell0, dmapjoint0.begin());
std::ranges::copy(dmap0_cell1,
std::next(dmapjoint0.begin(), dmap0_cell0.size()));
- auto dmap1_cell0
- = std::span(dmap1.data_handle() + cells1[0] * num_dofs1, num_dofs1);
- auto dmap1_cell1
- = std::span(dmap1.data_handle() + cells1[1] * num_dofs1, num_dofs1);
+ std::span dmap1_cell0(dmap1.data_handle() + cells1[0] * num_dofs1,
+ num_dofs1);
+ std::span dmap1_cell1(dmap1.data_handle() + cells1[1] * num_dofs1,
+ num_dofs1);
dmapjoint1.resize(dmap1_cell0.size() + dmap1_cell1.size());
std::ranges::copy(dmap1_cell0, dmapjoint1.begin());
diff --git a/cpp/dolfinx/fem/dofmapbuilder.cpp b/cpp/dolfinx/fem/dofmapbuilder.cpp
index 676bb48eeba..fd7113a60ef 100644
--- a/cpp/dolfinx/fem/dofmapbuilder.cpp
+++ b/cpp/dolfinx/fem/dofmapbuilder.cpp
@@ -209,7 +209,9 @@ build_basic_dofmaps(
local_entity_offsets.back()
+ num_entity_dofs * (im->size_local() + im->num_ghosts()));
- if (d < D and !topology.connectivity({D, i}, {d, et_index}))
+ if (d < D
+ and !topology.connectivity({int(D), int(i)},
+ {int(d), int(et_index)}))
{
throw std::runtime_error("Missing needed connectivity. Cell type:"
+ std::to_string(i)
@@ -279,10 +281,17 @@ build_basic_dofmaps(
const std::vector>& e_dofs_d = entity_dofs[d];
+ // Skip over undefined topology, e.g. quad facets of tetrahedra
+ if (d < D
+ and !topology.connectivity({int(D), int(i)}, {int(d), int(et)}))
+ continue;
+
// Iterate over each entity of current dimension d and type et
std::span c_to_e
- = d < D ? topology.connectivity({D, i}, {d, et})->links(c)
- : std::span(&c, 1);
+ = d < D
+ ? topology.connectivity({int(D), int(i)}, {int(d), int(et)})
+ ->links(c)
+ : std::span(&c, 1);
int w = 0;
for (std::size_t e = 0; e < e_dofs_d.size(); ++e)
diff --git a/cpp/dolfinx/fem/interpolate.h b/cpp/dolfinx/fem/interpolate.h
index d2a098d8c8c..f1ee49e1e42 100644
--- a/cpp/dolfinx/fem/interpolate.h
+++ b/cpp/dolfinx/fem/interpolate.h
@@ -128,7 +128,7 @@ void interpolate(Function& u, std::span f,
namespace impl
{
-/// @brief Convenience typdef
+/// @brief Convenience typedef
template
using mdspan_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
T, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents>;
@@ -274,9 +274,9 @@ void scatter_values(MPI_Comm comm, std::span src_ranks,
std::vector values(recv_offsets.back());
values.reserve(1);
MPI_Neighbor_alltoallv(send_values.data_handle(), send_sizes.data(),
- send_offsets.data(), dolfinx::MPI::mpi_type(),
+ send_offsets.data(), dolfinx::MPI::mpi_t,
values.data(), recv_sizes.data(), recv_offsets.data(),
- dolfinx::MPI::mpi_type(), reverse_comm);
+ dolfinx::MPI::mpi_t, reverse_comm);
MPI_Comm_free(&reverse_comm);
// Insert values received from neighborhood communicator in output
diff --git a/cpp/dolfinx/geometry/BoundingBoxTree.h b/cpp/dolfinx/geometry/BoundingBoxTree.h
index 64ede45a057..9d25b9bf406 100644
--- a/cpp/dolfinx/geometry/BoundingBoxTree.h
+++ b/cpp/dolfinx/geometry/BoundingBoxTree.h
@@ -13,6 +13,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -37,8 +38,9 @@ std::array compute_bbox_of_entity(const mesh::Mesh& mesh, int dim,
= mesh::entities_to_geometry(mesh, dim, entity, false);
std::array b;
- auto b0 = std::span(b).template subspan<0, 3>();
- auto b1 = std::span(b).template subspan<3, 3>();
+ std::span b0(b.data(), 3);
+ std::span b1(b.data() + 3, 3);
+
std::copy_n(std::next(xg.begin(), 3 * vertex_indices.front()), 3, b0.begin());
std::copy_n(std::next(xg.begin(), 3 * vertex_indices.front()), 3, b1.begin());
@@ -203,6 +205,11 @@ template
class BoundingBoxTree
{
private:
+ /// @brief Return a range of entity indices of the given topological dimension
+ /// (including ghosts).
+ /// @param topology Topology to get entities from.
+ /// @param tdim Dimension of the entities.
+ /// @return Range of local indices, including ghosts.
static std::vector range(mesh::Topology& topology, int tdim)
{
topology.create_entities(tdim);
@@ -220,13 +227,32 @@ class BoundingBoxTree
/// @param[in] tdim Topological dimension of the mesh entities to
/// build the bounding box tree for.
/// @param[in] entities List of entity indices (local to process) to
- /// compute the bounding box for (may be empty, if none).
+ /// compute the bounding box for. If `std::nullopt`, the bounding box tree is
+ /// computed for all local entities (including ghosts) of the given `tdim`.
/// @param[in] padding Value to pad (extend) the the bounding box of
/// each entity by.
BoundingBoxTree(const mesh::Mesh& mesh, int tdim,
- std::span entities, double padding = 0)
+ std::optional> entities
+ = std::nullopt,
+ double padding = 0)
: _tdim(tdim)
{
+ // Initialize entities of given dimension if they don't exist
+ mesh.topology_mutable()->create_entities(tdim);
+
+ // Get input entities. If not provided, get all local entities of the given
+ // dimension (including ghosts)
+ std::span entities_span;
+ std::optional> local_range(std::nullopt);
+ if (entities)
+ entities_span = entities.value();
+ else
+ {
+ local_range.emplace(range(*mesh.topology_mutable(), tdim));
+ entities_span = std::span(local_range->data(),
+ local_range->size());
+ }
+
if (tdim < 0 or tdim > mesh.topology()->dim())
{
throw std::runtime_error(
@@ -234,14 +260,12 @@ class BoundingBoxTree
"equal to the topological dimension of the mesh");
}
- // Initialize entities of given dimension if they don't exist
- mesh.topology_mutable()->create_entities(tdim);
mesh.topology_mutable()->create_connectivity(tdim, mesh.topology()->dim());
// Create bounding boxes for all mesh entities (leaves)
std::vector, std::int32_t>> leaf_bboxes;
- leaf_bboxes.reserve(entities.size());
- for (std::int32_t e : entities)
+ leaf_bboxes.reserve(entities_span.size());
+ for (std::int32_t e : entities_span)
{
std::array b = impl_bb::compute_bbox_of_entity(mesh, tdim, e);
std::transform(b.cbegin(), std::next(b.cbegin(), 3), b.begin(),
@@ -257,20 +281,7 @@ class BoundingBoxTree
= impl_bb::build_from_leaf(leaf_bboxes);
spdlog::info("Computed bounding box tree with {} nodes for {} entities",
- num_bboxes(), entities.size());
- }
-
- /// Constructor
- /// @param[in] mesh The mesh for building the bounding box tree
- /// @param[in] tdim The topological dimension of the mesh entities to
- /// build the bounding box tree for
- /// @param[in] padding Value to pad (extend) the the bounding box of
- /// each entity by.
- BoundingBoxTree(const mesh::Mesh& mesh, int tdim, T padding = 0)
- : BoundingBoxTree::BoundingBoxTree(
- mesh, tdim, range(mesh.topology_mutable(), tdim), padding)
- {
- // Do nothing
+ num_bboxes(), entities_span.size());
}
/// Constructor @param[in] points Cloud of points, with associated
@@ -335,8 +346,8 @@ class BoundingBoxTree
if (num_bboxes() > 0)
std::copy_n(std::prev(_bbox_coordinates.end(), 6), 6, send_bbox.begin());
std::vector recv_bbox(mpi_size * 6);
- MPI_Allgather(send_bbox.data(), 6, dolfinx::MPI::mpi_type(),
- recv_bbox.data(), 6, dolfinx::MPI::mpi_type(), comm);
+ MPI_Allgather(send_bbox.data(), 6, dolfinx::MPI::mpi_t, recv_bbox.data(),
+ 6, dolfinx::MPI::mpi_t, comm);
std::vector, std::int32_t>> _recv_bbox(mpi_size);
for (std::size_t i = 0; i < _recv_bbox.size(); ++i)
diff --git a/cpp/dolfinx/geometry/utils.h b/cpp/dolfinx/geometry/utils.h
index 0f643e62643..4e287fcb4cb 100644
--- a/cpp/dolfinx/geometry/utils.h
+++ b/cpp/dolfinx/geometry/utils.h
@@ -771,8 +771,8 @@ PointOwnershipData determine_point_ownership(const mesh::Mesh& mesh,
std::vector received_points((std::size_t)recv_offsets.back());
MPI_Neighbor_alltoallv(
send_data.data(), send_sizes.data(), send_offsets.data(),
- dolfinx::MPI::mpi_type(), received_points.data(), recv_sizes.data(),
- recv_offsets.data(), dolfinx::MPI::mpi_type(), forward_comm);
+ dolfinx::MPI::mpi_t, received_points.data(), recv_sizes.data(),
+ recv_offsets.data(), dolfinx::MPI::mpi_t, forward_comm);
// Get mesh geometry for closest entity
const mesh::Geometry& geometry = mesh.geometry();
@@ -905,8 +905,8 @@ PointOwnershipData determine_point_ownership(const mesh::Mesh& mesh,
std::vector recv_distances(recv_offsets.back());
MPI_Neighbor_alltoallv(
squared_distances.data(), send_sizes.data(), send_offsets.data(),
- dolfinx::MPI::mpi_type(), recv_distances.data(), recv_sizes.data(),
- recv_offsets.data(), dolfinx::MPI::mpi_type(), reverse_comm);
+ dolfinx::MPI::mpi_t, recv_distances.data(), recv_sizes.data(),
+ recv_offsets.data(), dolfinx::MPI::mpi_t, reverse_comm);
// Update point ownership with extrapolation information
std::vector closest_distance(point_owners.size(),
diff --git a/cpp/dolfinx/graph/partitioners.cpp b/cpp/dolfinx/graph/partitioners.cpp
index 68bc0a57847..fade5e160cf 100644
--- a/cpp/dolfinx/graph/partitioners.cpp
+++ b/cpp/dolfinx/graph/partitioners.cpp
@@ -94,7 +94,7 @@ graph::AdjacencyList compute_destination_ranks(
while (it != node_to_dest.end())
{
// Current destination rank
- dest.push_back((*it)[0]);
+ dest.push_back(it->front());
// Find iterator to next destination rank and pack send data
auto it1
@@ -103,8 +103,8 @@ graph::AdjacencyList compute_destination_ranks(
send_sizes.push_back(2 * std::distance(it, it1));
for (auto itx = it; itx != it1; ++itx)
{
- send_buffer.push_back((*itx)[1]);
- send_buffer.push_back((*itx)[2]);
+ send_buffer.push_back(itx->at(1));
+ send_buffer.push_back(itx->at(2));
}
it = it1;
@@ -444,7 +444,7 @@ graph::partition_fn graph::scotch::partitioner(graph::scotch::strategy strategy,
// Exchange halo with node_partition data for ghosts
common::Timer timer3("SCOTCH: call SCOTCH_dgraphHalo");
err = SCOTCH_dgraphHalo(&dgrafdat, node_partition.data(),
- dolfinx::MPI::mpi_type());
+ dolfinx::MPI::mpi_t);
if (err != 0)
throw std::runtime_error("Error during SCOTCH halo exchange");
timer3.stop();
@@ -554,9 +554,8 @@ graph::partition_fn graph::parmetis::partitioner(double imbalance,
const int psize = dolfinx::MPI::size(pcomm);
const idx_t num_local_nodes = graph.num_nodes();
node_disp = std::vector(psize + 1, 0);
- MPI_Allgather(&num_local_nodes, 1, dolfinx::MPI::mpi_type(),
- node_disp.data() + 1, 1, dolfinx::MPI::mpi_type(),
- pcomm);
+ MPI_Allgather(&num_local_nodes, 1, dolfinx::MPI::mpi_t,
+ node_disp.data() + 1, 1, dolfinx::MPI::mpi_t, pcomm);
std::partial_sum(node_disp.begin(), node_disp.end(), node_disp.begin());
std::vector array(graph.array().begin(), graph.array().end());
std::vector offsets(graph.offsets().begin(),
@@ -631,8 +630,13 @@ graph::partition_fn graph::kahip::partitioner(int mode, int seed,
common::Timer timer1("KaHIP: build adjacency data");
std::vector node_disp(dolfinx::MPI::size(comm) + 1, 0);
const T num_local_nodes = graph.num_nodes();
- MPI_Allgather(&num_local_nodes, 1, dolfinx::MPI::mpi_type(),
- node_disp.data() + 1, 1, dolfinx::MPI::mpi_type(), comm);
+
+ // KaHIP internally relies on an unsigned long long int type, which is not
+ // easily convertible to a general mpi type due to platform specific
+ // differences. So we can not rely on the general mpi_t<> mapping and do it
+ // by hand in this sole occurrence.
+ MPI_Allgather(&num_local_nodes, 1, MPI_UNSIGNED_LONG_LONG,
+ node_disp.data() + 1, 1, MPI_UNSIGNED_LONG_LONG, comm);
std::partial_sum(node_disp.begin(), node_disp.end(), node_disp.begin());
std::vector array(graph.array().begin(), graph.array().end());
std::vector offsets(graph.offsets().begin(), graph.offsets().end());
diff --git a/cpp/dolfinx/io/CMakeLists.txt b/cpp/dolfinx/io/CMakeLists.txt
index a3060dd6852..81d770ba501 100644
--- a/cpp/dolfinx/io/CMakeLists.txt
+++ b/cpp/dolfinx/io/CMakeLists.txt
@@ -1,26 +1,27 @@
set(HEADERS_io
- ${CMAKE_CURRENT_SOURCE_DIR}/dolfinx_io.h
- ${CMAKE_CURRENT_SOURCE_DIR}/ADIOS2Writers.h
- ${CMAKE_CURRENT_SOURCE_DIR}/cells.h
- ${CMAKE_CURRENT_SOURCE_DIR}/HDF5Interface.h
- ${CMAKE_CURRENT_SOURCE_DIR}/vtk_utils.h
- ${CMAKE_CURRENT_SOURCE_DIR}/VTKFile.h
- ${CMAKE_CURRENT_SOURCE_DIR}/XDMFFile.h
- ${CMAKE_CURRENT_SOURCE_DIR}/xdmf_function.h
- ${CMAKE_CURRENT_SOURCE_DIR}/xdmf_mesh.h
- ${CMAKE_CURRENT_SOURCE_DIR}/xdmf_utils.h
- PARENT_SCOPE
+ ${CMAKE_CURRENT_SOURCE_DIR}/dolfinx_io.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/ADIOS2Writers.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/cells.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/HDF5Interface.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/vtk_utils.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/VTKFile.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/VTKHDF.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/XDMFFile.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/xdmf_function.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/xdmf_mesh.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/xdmf_utils.h
+ PARENT_SCOPE
)
target_sources(
dolfinx
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/ADIOS2Writers.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/cells.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/HDF5Interface.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/VTKFile.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/vtk_utils.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/XDMFFile.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/xdmf_function.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/xdmf_mesh.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/xdmf_utils.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/cells.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/HDF5Interface.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/VTKFile.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/vtk_utils.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/XDMFFile.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/xdmf_function.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/xdmf_mesh.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/xdmf_utils.cpp
)
diff --git a/cpp/dolfinx/io/HDF5Interface.h b/cpp/dolfinx/io/HDF5Interface.h
index 2d559a77677..ccf148c56eb 100644
--- a/cpp/dolfinx/io/HDF5Interface.h
+++ b/cpp/dolfinx/io/HDF5Interface.h
@@ -37,6 +37,8 @@ hid_t hdf5_type()
return H5T_NATIVE_INT64;
else if constexpr (std::is_same_v)
return H5T_NATIVE_UINT64;
+ else if constexpr (std::is_same_v)
+ return H5T_NATIVE_UINT8;
else if constexpr (std::is_same_v)
{
throw std::runtime_error(
diff --git a/cpp/dolfinx/io/VTKHDF.h b/cpp/dolfinx/io/VTKHDF.h
new file mode 100644
index 00000000000..197a3ce98fc
--- /dev/null
+++ b/cpp/dolfinx/io/VTKHDF.h
@@ -0,0 +1,301 @@
+// Copyright (C) 2024 Chris Richardson
+//
+// This file is part of DOLFINx (https://www.fenicsproject.org)
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+
+#include "HDF5Interface.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include