From 35a65b43b26809d9474a231fef71e0be6e937182 Mon Sep 17 00:00:00 2001 From: Massimiliano Leoni Date: Mon, 14 Oct 2024 14:51:55 +0200 Subject: [PATCH 01/11] Safe default value for unbound variables in dolfinx.conf --- cpp/cmake/templates/dolfinx.conf.in | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/cmake/templates/dolfinx.conf.in b/cpp/cmake/templates/dolfinx.conf.in index 02bd8e4f826..36fcae00f7c 100644 --- a/cpp/cmake/templates/dolfinx.conf.in +++ b/cpp/cmake/templates/dolfinx.conf.in @@ -1,10 +1,10 @@ # Helper file for setting non-default DOLFINx environment variables # Common Unix variables -export @OS_LIBRARY_PATH_NAME@=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@:$@OS_LIBRARY_PATH_NAME@ -export PATH=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@:$PATH -export PKG_CONFIG_PATH=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/pkgconfig:$PKG_CONFIG_PATH -export CMAKE_PREFIX_PATH=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/cmake:$CMAKE_PREFIX_PATH +export @OS_LIBRARY_PATH_NAME@=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@:${@OS_LIBRARY_PATH_NAME@:-} +export PATH=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@:${PATH:-} +export PKG_CONFIG_PATH=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/pkgconfig:${PKG_CONFIG_PATH:-} +export CMAKE_PREFIX_PATH=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/cmake:${CMAKE_PREFIX_PATH:-} # Special macOS variables -export DYLD_FRAMEWORK_PATH=/opt/local/Library/Frameworks:$DYLD_FRAMEWORK_PATH +export DYLD_FRAMEWORK_PATH=/opt/local/Library/Frameworks:${DYLD_FRAMEWORK_PATH:-} From 2700ed759abf43385fa8e54589f0d0c2f15ec840 Mon Sep 17 00:00:00 2001 From: Massimiliano Leoni Date: Mon, 25 Nov 2024 09:35:04 +0100 Subject: [PATCH 02/11] Make read_meshtags a template function --- cpp/dolfinx/io/XDMFFile.cpp | 23 +++++++++++++++++------ cpp/dolfinx/io/XDMFFile.h | 9 +++++---- python/dolfinx/wrappers/io.cpp | 2 +- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/cpp/dolfinx/io/XDMFFile.cpp b/cpp/dolfinx/io/XDMFFile.cpp index aee81c258a0..72c53abc53c 100644 --- a/cpp/dolfinx/io/XDMFFile.cpp +++ b/cpp/dolfinx/io/XDMFFile.cpp @@ -333,7 +333,8 @@ template void XDMFFile::write_meshtags(const mesh::MeshTags&, std::string, std::string); /// @endcond //----------------------------------------------------------------------------- -mesh::MeshTags +template +mesh::MeshTags XDMFFile::read_meshtags(const mesh::Mesh& mesh, std::string name, std::optional attribute_name, std::string xpath) @@ -365,8 +366,8 @@ XDMFFile::read_meshtags(const mesh::Mesh& mesh, std::string name, else values_data_node = attribute_node.child("DataItem"); } - const std::vector values = xdmf_utils::get_dataset( - _comm.comm(), values_data_node, _h5_id); + const std::vector values + = xdmf_utils::get_dataset(_comm.comm(), values_data_node, _h5_id); const std::pair cell_type_str = xdmf_utils::get_cell_type(grid_node.child("Topology")); @@ -380,8 +381,8 @@ XDMFFile::read_meshtags(const mesh::Mesh& mesh, std::string name, const std::int64_t, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents> entities_span(entities1.data(), eshape); - std::pair, std::vector> - entities_values = xdmf_utils::distribute_entity_data( + std::pair, std::vector> entities_values + = xdmf_utils::distribute_entity_data( *mesh.topology(), mesh.geometry().input_global_indices(), mesh.geometry().index_map()->size_global(), mesh.geometry().cmap().create_dof_layout(), mesh.geometry().dofmap(), @@ -397,12 +398,22 @@ XDMFFile::read_meshtags(const mesh::Mesh& mesh, std::string name, num_vertices_per_entity); mesh::MeshTags meshtags = mesh::create_meshtags( mesh.topology(), mesh::cell_dim(cell_type), entities_adj, - std::span(entities_values.second)); + std::span(entities_values.second)); meshtags.name = name; return meshtags; } //----------------------------------------------------------------------------- +// Instantiation for different types +/// @cond +template mesh::MeshTags +XDMFFile::read_meshtags(const mesh::Mesh& mesh, std::string name, + std::string attribute_name, std::string xpath); +template mesh::MeshTags +XDMFFile::read_meshtags(const mesh::Mesh& mesh, std::string name, + std::string attribute_name, std::string xpath); +/// @endcond +//----------------------------------------------------------------------------- std::pair XDMFFile::read_cell_type(std::string grid_name, std::string xpath) { diff --git a/cpp/dolfinx/io/XDMFFile.h b/cpp/dolfinx/io/XDMFFile.h index 18d510867bd..7832a6dc022 100644 --- a/cpp/dolfinx/io/XDMFFile.h +++ b/cpp/dolfinx/io/XDMFFile.h @@ -170,10 +170,11 @@ class XDMFFile /// GridType="Uniform" /// @param[in] attribute_name Name of the attribute to read /// @param[in] xpath XPath where MeshTags Grid is stored in file - mesh::MeshTags - read_meshtags(const mesh::Mesh& mesh, std::string name, - std::optional attribute_name, - std::string xpath = "/Xdmf/Domain"); + template + mesh::MeshTags read_meshtags(const mesh::Mesh& mesh, + std::string name, + std::optional attribute_name, + std::string xpath = "/Xdmf/Domain"); /// Write Information /// @param[in] name diff --git a/python/dolfinx/wrappers/io.cpp b/python/dolfinx/wrappers/io.cpp index 35ab47e2378..7cc3655ec74 100644 --- a/python/dolfinx/wrappers/io.cpp +++ b/python/dolfinx/wrappers/io.cpp @@ -271,7 +271,7 @@ void io(nb::module_& m) nb::arg("name") = "mesh", nb::arg("xpath") = "/Xdmf/Domain") .def("read_cell_type", &dolfinx::io::XDMFFile::read_cell_type, nb::arg("name") = "mesh", nb::arg("xpath") = "/Xdmf/Domain") - .def("read_meshtags", &dolfinx::io::XDMFFile::read_meshtags, + .def("read_meshtags", &dolfinx::io::XDMFFile::read_meshtags, nb::arg("mesh"), nb::arg("name"), nb::arg("attribute_name").none(), nb::arg("xpath")) .def("write_information", &dolfinx::io::XDMFFile::write_information, From c53d5d3089697da677a0bcb35206c00ea240a2a1 Mon Sep 17 00:00:00 2001 From: Massimiliano Leoni Date: Mon, 25 Nov 2024 09:39:47 +0100 Subject: [PATCH 03/11] Add XDMFFile::read_function to read P1 functions --- cpp/dolfinx/io/XDMFFile.cpp | 130 ++++++++++++++++++++++++++++++++++++ cpp/dolfinx/io/XDMFFile.h | 8 +++ 2 files changed, 138 insertions(+) diff --git a/cpp/dolfinx/io/XDMFFile.cpp b/cpp/dolfinx/io/XDMFFile.cpp index 72c53abc53c..45ae294397e 100644 --- a/cpp/dolfinx/io/XDMFFile.cpp +++ b/cpp/dolfinx/io/XDMFFile.cpp @@ -297,6 +297,136 @@ XDMFFile::write_function(const fem::Function, double>&, double, std::string); /// @endcond //----------------------------------------------------------------------------- +void XDMFFile::read_function(const mesh::Mesh& mesh, std::string name, + fem::Function& u, + std::string xpath) +{ + /* + * This is the main function that I implemented so far. As the name says, + * it is supposed to read a function from file. This function closely + * follows `XDMFFile::read_meshtags` below. + * + * For reference, I am reading an xdmf file whose header is + * + * + * + * + * + * power.h5:/data0 + * + * power.h5:/data1 + * + * power.h5:/data2 + * + * + * + * + * + * and that I generated saving a vtu file from Paraview and converting it to + * xdmf with meshio. + * + * The goal for now is to read a P1 function, so the degrees of freedom are + * the vertexes of the mesh. This is different from the meshtags I am used to + * in that meshtags are cell data, not point data. + */ + spdlog::info("XDMF read function ({})", name); + pugi::xml_node node = _xml_doc->select_node(xpath.c_str()).node(); + if (!node) + throw std::runtime_error("XML node '" + xpath + "' not found."); + pugi::xml_node grid_node + = node.select_node(("Grid[@Name='" + name + "']").c_str()).node(); + if (!grid_node) + throw std::runtime_error(" with name '" + name + "' not found."); + + pugi::xml_node values_data_node + = grid_node.child("Attribute").child("DataItem"); + const std::vector values + = xdmf_utils::get_dataset(_comm.comm(), values_data_node, _h5_id); + + /* + * Similarly, reading the cell type would read "hexahedron", so I set this + * manually to "point" instead. + */ + mesh::CellType cell_type = mesh::CellType::point; + + /* + * The `entities1` vector contains the global indexes of the entities + * [aka points] that this process owns. I used the local_range to choose + * the correct values, which however might not be correct after all. + */ + std::int64_t num_xnodes = mesh.geometry().index_map()->size_global(); + auto range + = dolfinx::MPI::local_range(dolfinx::MPI::rank(mesh.comm()), num_xnodes, + dolfinx::MPI::size(mesh.comm())); + std::vector entities1(range[1] - range[0]); + std::iota(entities1.begin(), entities1.end(), range[0]); + + std::array shape + = {static_cast(range[1] - range[0]), 1}; + + MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan< + const std::int64_t, + MDSPAN_IMPL_STANDARD_NAMESPACE::dextents> + entities_span(entities1.data(), shape); + /* + * This call is analogous to the one in `read_meshtags` except that I + * had to make the function `distribute_entity_data` a template because + * it read only integers but I want to read doubles instead. + */ + std::pair, std::vector> entities_values + = xdmf_utils::distribute_entity_data( + *mesh.topology(), mesh.geometry().input_global_indices(), + mesh.geometry().index_map()->size_global(), + mesh.geometry().cmap().create_dof_layout(), mesh.geometry().dofmap(), + mesh::cell_dim(cell_type), entities_span, values); + + auto num_vertices_per_cell + = dolfinx::mesh::num_cell_vertices(mesh.topology()->cell_type()); + std::vector local_vertex_map(num_vertices_per_cell); + + for (int i = 0; i < num_vertices_per_cell; ++i) + { + const auto v_to_d + = u.function_space()->dofmap()->element_dof_layout().entity_dofs(0, i); + assert(v_to_d.size() == 1); + local_vertex_map[i] = v_to_d.front(); + } + + const auto tdim = mesh.topology()->dim(); + const auto c_to_v = mesh.topology()->connectivity(tdim, 0); + std::vector vertex_to_dofmap( + mesh.topology()->index_map(0)->size_local() + + mesh.topology()->index_map(0)->num_ghosts()); + + for (int i = 0; i < mesh.topology()->index_map(tdim)->size_local(); ++i) + { + const auto local_vertices = c_to_v->links(i); + const auto local_dofs = u.function_space()->dofmap()->cell_dofs(i); + for (int j = 0; j < num_vertices_per_cell; ++j) + { + vertex_to_dofmap[local_vertices[j]] = local_dofs[local_vertex_map[j]]; + } + } + + /* + * After the data is read and distributed, I just need to place the + * retrieved values in the correct position in the function's array, + * reading values and positions from `entities_values`. + */ + for (int i = 0; i < entities_values.first.size(); ++i) + { + u.x()->mutable_array()[vertex_to_dofmap[entities_values.first[i]]] + = entities_values.second[i]; + } + + u.x()->scatter_fwd(); +} +//----------------------------------------------------------------------------- template void XDMFFile::write_meshtags(const mesh::MeshTags& meshtags, const mesh::Geometry& x, diff --git a/cpp/dolfinx/io/XDMFFile.h b/cpp/dolfinx/io/XDMFFile.h index 7832a6dc022..e496c6078ad 100644 --- a/cpp/dolfinx/io/XDMFFile.h +++ b/cpp/dolfinx/io/XDMFFile.h @@ -152,6 +152,14 @@ class XDMFFile std::string mesh_xpath = "/Xdmf/Domain/Grid[@GridType='Uniform'][1]"); + /// Read Function + /// @param[in] mesh The Mesh that the data is defined on + /// @param[in] name + /// @param[in] xpath XPath where MeshFunction Grid is stored in file + void read_function(const mesh::Mesh& mesh, std::string name, + fem::Function& u, + std::string xpath = "/Xdmf/Domain"); + /// Write MeshTags /// @param[in] meshtags /// @param[in] x Mesh geometry From 8d7c60c297911c4c89df2e796c666221ac6ab003 Mon Sep 17 00:00:00 2001 From: Massimiliano Leoni Date: Mon, 25 Nov 2024 10:35:43 +0100 Subject: [PATCH 04/11] Fix signature of explicit template instantiation --- cpp/dolfinx/io/XDMFFile.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cpp/dolfinx/io/XDMFFile.cpp b/cpp/dolfinx/io/XDMFFile.cpp index 72c53abc53c..d65fef61296 100644 --- a/cpp/dolfinx/io/XDMFFile.cpp +++ b/cpp/dolfinx/io/XDMFFile.cpp @@ -408,10 +408,12 @@ XDMFFile::read_meshtags(const mesh::Mesh& mesh, std::string name, /// @cond template mesh::MeshTags XDMFFile::read_meshtags(const mesh::Mesh& mesh, std::string name, - std::string attribute_name, std::string xpath); + std::optional attribute_name, + std::string xpath); template mesh::MeshTags XDMFFile::read_meshtags(const mesh::Mesh& mesh, std::string name, - std::string attribute_name, std::string xpath); + std::optional attribute_name, + std::string xpath); /// @endcond //----------------------------------------------------------------------------- std::pair XDMFFile::read_cell_type(std::string grid_name, From 85daf1fa68a69c1d0507c4ae98d5bd54c804285b Mon Sep 17 00:00:00 2001 From: Massimiliano Leoni Date: Mon, 25 Nov 2024 09:39:47 +0100 Subject: [PATCH 05/11] Add XDMFFile::read_function to read P1 functions --- cpp/dolfinx/io/XDMFFile.cpp | 130 ++++++++++++++++++++++++++++++++++++ cpp/dolfinx/io/XDMFFile.h | 8 +++ 2 files changed, 138 insertions(+) diff --git a/cpp/dolfinx/io/XDMFFile.cpp b/cpp/dolfinx/io/XDMFFile.cpp index d65fef61296..b4fee122e9c 100644 --- a/cpp/dolfinx/io/XDMFFile.cpp +++ b/cpp/dolfinx/io/XDMFFile.cpp @@ -297,6 +297,136 @@ XDMFFile::write_function(const fem::Function, double>&, double, std::string); /// @endcond //----------------------------------------------------------------------------- +void XDMFFile::read_function(const mesh::Mesh& mesh, std::string name, + fem::Function& u, + std::string xpath) +{ + /* + * This is the main function that I implemented so far. As the name says, + * it is supposed to read a function from file. This function closely + * follows `XDMFFile::read_meshtags` below. + * + * For reference, I am reading an xdmf file whose header is + * + * + * + * + * + * power.h5:/data0 + * + * power.h5:/data1 + * + * power.h5:/data2 + * + * + * + * + * + * and that I generated saving a vtu file from Paraview and converting it to + * xdmf with meshio. + * + * The goal for now is to read a P1 function, so the degrees of freedom are + * the vertexes of the mesh. This is different from the meshtags I am used to + * in that meshtags are cell data, not point data. + */ + spdlog::info("XDMF read function ({})", name); + pugi::xml_node node = _xml_doc->select_node(xpath.c_str()).node(); + if (!node) + throw std::runtime_error("XML node '" + xpath + "' not found."); + pugi::xml_node grid_node + = node.select_node(("Grid[@Name='" + name + "']").c_str()).node(); + if (!grid_node) + throw std::runtime_error(" with name '" + name + "' not found."); + + pugi::xml_node values_data_node + = grid_node.child("Attribute").child("DataItem"); + const std::vector values + = xdmf_utils::get_dataset(_comm.comm(), values_data_node, _h5_id); + + /* + * Similarly, reading the cell type would read "hexahedron", so I set this + * manually to "point" instead. + */ + mesh::CellType cell_type = mesh::CellType::point; + + /* + * The `entities1` vector contains the global indexes of the entities + * [aka points] that this process owns. I used the local_range to choose + * the correct values, which however might not be correct after all. + */ + std::int64_t num_xnodes = mesh.geometry().index_map()->size_global(); + auto range + = dolfinx::MPI::local_range(dolfinx::MPI::rank(mesh.comm()), num_xnodes, + dolfinx::MPI::size(mesh.comm())); + std::vector entities1(range[1] - range[0]); + std::iota(entities1.begin(), entities1.end(), range[0]); + + std::array shape + = {static_cast(range[1] - range[0]), 1}; + + MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan< + const std::int64_t, + MDSPAN_IMPL_STANDARD_NAMESPACE::dextents> + entities_span(entities1.data(), shape); + /* + * This call is analogous to the one in `read_meshtags` except that I + * had to make the function `distribute_entity_data` a template because + * it read only integers but I want to read doubles instead. + */ + std::pair, std::vector> entities_values + = xdmf_utils::distribute_entity_data( + *mesh.topology(), mesh.geometry().input_global_indices(), + mesh.geometry().index_map()->size_global(), + mesh.geometry().cmap().create_dof_layout(), mesh.geometry().dofmap(), + mesh::cell_dim(cell_type), entities_span, values); + + auto num_vertices_per_cell + = dolfinx::mesh::num_cell_vertices(mesh.topology()->cell_type()); + std::vector local_vertex_map(num_vertices_per_cell); + + for (int i = 0; i < num_vertices_per_cell; ++i) + { + const auto v_to_d + = u.function_space()->dofmap()->element_dof_layout().entity_dofs(0, i); + assert(v_to_d.size() == 1); + local_vertex_map[i] = v_to_d.front(); + } + + const auto tdim = mesh.topology()->dim(); + const auto c_to_v = mesh.topology()->connectivity(tdim, 0); + std::vector vertex_to_dofmap( + mesh.topology()->index_map(0)->size_local() + + mesh.topology()->index_map(0)->num_ghosts()); + + for (int i = 0; i < mesh.topology()->index_map(tdim)->size_local(); ++i) + { + const auto local_vertices = c_to_v->links(i); + const auto local_dofs = u.function_space()->dofmap()->cell_dofs(i); + for (int j = 0; j < num_vertices_per_cell; ++j) + { + vertex_to_dofmap[local_vertices[j]] = local_dofs[local_vertex_map[j]]; + } + } + + /* + * After the data is read and distributed, I just need to place the + * retrieved values in the correct position in the function's array, + * reading values and positions from `entities_values`. + */ + for (int i = 0; i < entities_values.first.size(); ++i) + { + u.x()->mutable_array()[vertex_to_dofmap[entities_values.first[i]]] + = entities_values.second[i]; + } + + u.x()->scatter_fwd(); +} +//----------------------------------------------------------------------------- template void XDMFFile::write_meshtags(const mesh::MeshTags& meshtags, const mesh::Geometry& x, diff --git a/cpp/dolfinx/io/XDMFFile.h b/cpp/dolfinx/io/XDMFFile.h index 7832a6dc022..e496c6078ad 100644 --- a/cpp/dolfinx/io/XDMFFile.h +++ b/cpp/dolfinx/io/XDMFFile.h @@ -152,6 +152,14 @@ class XDMFFile std::string mesh_xpath = "/Xdmf/Domain/Grid[@GridType='Uniform'][1]"); + /// Read Function + /// @param[in] mesh The Mesh that the data is defined on + /// @param[in] name + /// @param[in] xpath XPath where MeshFunction Grid is stored in file + void read_function(const mesh::Mesh& mesh, std::string name, + fem::Function& u, + std::string xpath = "/Xdmf/Domain"); + /// Write MeshTags /// @param[in] meshtags /// @param[in] x Mesh geometry From 38c82f70c9c7f1bc18daf5b6669163f799cc5912 Mon Sep 17 00:00:00 2001 From: Massimiliano Leoni Date: Mon, 25 Nov 2024 13:46:10 +0100 Subject: [PATCH 06/11] Improve comments --- cpp/dolfinx/io/XDMFFile.cpp | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/cpp/dolfinx/io/XDMFFile.cpp b/cpp/dolfinx/io/XDMFFile.cpp index b4fee122e9c..5c47b860e7e 100644 --- a/cpp/dolfinx/io/XDMFFile.cpp +++ b/cpp/dolfinx/io/XDMFFile.cpp @@ -302,11 +302,10 @@ void XDMFFile::read_function(const mesh::Mesh& mesh, std::string name, std::string xpath) { /* - * This is the main function that I implemented so far. As the name says, - * it is supposed to read a function from file. This function closely + * This routine reads a function from file. The implementation closely * follows `XDMFFile::read_meshtags` below. * - * For reference, I am reading an xdmf file whose header is + * For reference, we are reading an xdmf file whose header is akin to * * * @@ -327,12 +326,11 @@ void XDMFFile::read_function(const mesh::Mesh& mesh, std::string name, * * * - * and that I generated saving a vtu file from Paraview and converting it to - * xdmf with meshio. + * and that was generated saving a vtu file from Paraview and converting it + * to xdmf with meshio. * * The goal for now is to read a P1 function, so the degrees of freedom are - * the vertexes of the mesh. This is different from the meshtags I am used to - * in that meshtags are cell data, not point data. + * the vertexes of the mesh. */ spdlog::info("XDMF read function ({})", name); pugi::xml_node node = _xml_doc->select_node(xpath.c_str()).node(); @@ -349,15 +347,14 @@ void XDMFFile::read_function(const mesh::Mesh& mesh, std::string name, = xdmf_utils::get_dataset(_comm.comm(), values_data_node, _h5_id); /* - * Similarly, reading the cell type would read "hexahedron", so I set this + * Reading the cell type would read "hexahedron", so we set this * manually to "point" instead. */ mesh::CellType cell_type = mesh::CellType::point; /* * The `entities1` vector contains the global indexes of the entities - * [aka points] that this process owns. I used the local_range to choose - * the correct values, which however might not be correct after all. + * [aka points] that this process owns. */ std::int64_t num_xnodes = mesh.geometry().index_map()->size_global(); auto range @@ -373,11 +370,7 @@ void XDMFFile::read_function(const mesh::Mesh& mesh, std::string name, const std::int64_t, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents> entities_span(entities1.data(), shape); - /* - * This call is analogous to the one in `read_meshtags` except that I - * had to make the function `distribute_entity_data` a template because - * it read only integers but I want to read doubles instead. - */ + std::pair, std::vector> entities_values = xdmf_utils::distribute_entity_data( *mesh.topology(), mesh.geometry().input_global_indices(), @@ -414,7 +407,7 @@ void XDMFFile::read_function(const mesh::Mesh& mesh, std::string name, } /* - * After the data is read and distributed, I just need to place the + * After the data is read and distributed, we need to place the * retrieved values in the correct position in the function's array, * reading values and positions from `entities_values`. */ From c453138fc8c2bfe15d18ecbdcc6dd27410377c89 Mon Sep 17 00:00:00 2001 From: Massimiliano Leoni Date: Mon, 25 Nov 2024 13:48:06 +0100 Subject: [PATCH 07/11] Fix loop variable type --- cpp/dolfinx/io/XDMFFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/dolfinx/io/XDMFFile.cpp b/cpp/dolfinx/io/XDMFFile.cpp index 5c47b860e7e..f568e2ad16b 100644 --- a/cpp/dolfinx/io/XDMFFile.cpp +++ b/cpp/dolfinx/io/XDMFFile.cpp @@ -411,7 +411,7 @@ void XDMFFile::read_function(const mesh::Mesh& mesh, std::string name, * retrieved values in the correct position in the function's array, * reading values and positions from `entities_values`. */ - for (int i = 0; i < entities_values.first.size(); ++i) + for (size_t i = 0; i < entities_values.first.size(); ++i) { u.x()->mutable_array()[vertex_to_dofmap[entities_values.first[i]]] = entities_values.second[i]; From 147ae0384610f120cb2405458ae6d4b519222338 Mon Sep 17 00:00:00 2001 From: Massimiliano Leoni Date: Mon, 25 Nov 2024 15:27:03 +0100 Subject: [PATCH 08/11] Fix docstring --- cpp/dolfinx/io/XDMFFile.h | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/dolfinx/io/XDMFFile.h b/cpp/dolfinx/io/XDMFFile.h index e496c6078ad..ad0ae9cad28 100644 --- a/cpp/dolfinx/io/XDMFFile.h +++ b/cpp/dolfinx/io/XDMFFile.h @@ -155,6 +155,7 @@ class XDMFFile /// Read Function /// @param[in] mesh The Mesh that the data is defined on /// @param[in] name + /// @param[in/out] u The function into which to read data /// @param[in] xpath XPath where MeshFunction Grid is stored in file void read_function(const mesh::Mesh& mesh, std::string name, fem::Function& u, From 08e3332227e41705e90cc402ba6eeceb68d6ba81 Mon Sep 17 00:00:00 2001 From: Massimiliano Leoni Date: Mon, 25 Nov 2024 15:47:47 +0100 Subject: [PATCH 09/11] Fix docstring --- cpp/dolfinx/io/XDMFFile.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/dolfinx/io/XDMFFile.h b/cpp/dolfinx/io/XDMFFile.h index ad0ae9cad28..afc4d17322a 100644 --- a/cpp/dolfinx/io/XDMFFile.h +++ b/cpp/dolfinx/io/XDMFFile.h @@ -155,7 +155,7 @@ class XDMFFile /// Read Function /// @param[in] mesh The Mesh that the data is defined on /// @param[in] name - /// @param[in/out] u The function into which to read data + /// @param[out] u The function into which to read data /// @param[in] xpath XPath where MeshFunction Grid is stored in file void read_function(const mesh::Mesh& mesh, std::string name, fem::Function& u, From c300e3e685726d2f4c5a1dfa54c420cbfa5b1981 Mon Sep 17 00:00:00 2001 From: Massimiliano Leoni Date: Tue, 26 Nov 2024 11:10:45 +0100 Subject: [PATCH 10/11] Fix random typo --- cpp/dolfinx/fem/assembler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/dolfinx/fem/assembler.h b/cpp/dolfinx/fem/assembler.h index ab41da82792..03c3a938cc1 100644 --- a/cpp/dolfinx/fem/assembler.h +++ b/cpp/dolfinx/fem/assembler.h @@ -309,7 +309,7 @@ void assemble_matrix( /// @param[in] mat_add The function for adding values into the matrix /// @param[in] a The bilinear from to assemble /// @param[in] bcs Boundary conditions to apply. For boundary condition -/// dofs the row and column are zeroed. The diagonal entry is not set. +/// dofs the row and column are zeroed. The diagonal entry is not set. template void assemble_matrix( auto mat_add, const Form& a, From 32849057e1f8605ea80f438bf4fd4ed17dc164c9 Mon Sep 17 00:00:00 2001 From: Massimiliano Leoni Date: Tue, 26 Nov 2024 11:10:56 +0100 Subject: [PATCH 11/11] Add optional function name to read --- cpp/dolfinx/io/XDMFFile.cpp | 15 +++++++++++++++ cpp/dolfinx/io/XDMFFile.h | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/cpp/dolfinx/io/XDMFFile.cpp b/cpp/dolfinx/io/XDMFFile.cpp index f568e2ad16b..54855072472 100644 --- a/cpp/dolfinx/io/XDMFFile.cpp +++ b/cpp/dolfinx/io/XDMFFile.cpp @@ -299,6 +299,7 @@ XDMFFile::write_function(const fem::Function, double>&, //----------------------------------------------------------------------------- void XDMFFile::read_function(const mesh::Mesh& mesh, std::string name, fem::Function& u, + std::optional function_name, std::string xpath) { /* @@ -343,6 +344,20 @@ void XDMFFile::read_function(const mesh::Mesh& mesh, std::string name, pugi::xml_node values_data_node = grid_node.child("Attribute").child("DataItem"); + if (function_name) + { + // Search for a child that contains an attribute with the requested name + pugi::xml_node function_node = grid_node.find_child( + [fun_name = *function_name](auto n) + { return n.attribute("Name").value() == fun_name; }); + if (!function_node) + { + throw std::runtime_error("Function with name '" + *function_name + + "' not found."); + } + else + values_data_node = function_node.child("DataItem"); + } const std::vector values = xdmf_utils::get_dataset(_comm.comm(), values_data_node, _h5_id); diff --git a/cpp/dolfinx/io/XDMFFile.h b/cpp/dolfinx/io/XDMFFile.h index afc4d17322a..9b4708ea995 100644 --- a/cpp/dolfinx/io/XDMFFile.h +++ b/cpp/dolfinx/io/XDMFFile.h @@ -156,9 +156,10 @@ class XDMFFile /// @param[in] mesh The Mesh that the data is defined on /// @param[in] name /// @param[out] u The function into which to read data + /// @param[in] function_name The (optinal) name of the function to read from file /// @param[in] xpath XPath where MeshFunction Grid is stored in file void read_function(const mesh::Mesh& mesh, std::string name, - fem::Function& u, + fem::Function& u, std::optional function_name, std::string xpath = "/Xdmf/Domain"); /// Write MeshTags