Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multiple dofmaps and elements to Geometry #3071

Merged
merged 124 commits into from
Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
6526435
Add b ack some mixed topology
chrisrichardson Jan 5, 2024
c803c90
merge
chrisrichardson Jan 5, 2024
b487445
Start working on mixed topology again
chrisrichardson Jan 5, 2024
d81d7e0
Merge branch 'main' into chris/topology-nightmare
chrisrichardson Jan 8, 2024
54fcc69
Create _entity_types instead of _cell_type
chrisrichardson Jan 9, 2024
a4d5225
Merge branch 'main' into chris/topology-nightmare
chrisrichardson Jan 9, 2024
0828d81
Fixes in Python for testing
chrisrichardson Jan 9, 2024
9accbe4
A bit of debug and a test
chrisrichardson Jan 9, 2024
46d6049
Add access to IndexMaps
chrisrichardson Jan 9, 2024
7202acc
Add more accessors and tests
chrisrichardson Jan 9, 2024
94312f4
Use general version of create_topology
chrisrichardson Jan 10, 2024
9c7ee0d
Clarify for mypy
chrisrichardson Jan 10, 2024
8b7a0c9
merge
chrisrichardson Jan 10, 2024
34d3fd3
Add more accessors and test
chrisrichardson Jan 10, 2024
e08d614
Use nb::overload_cast
chrisrichardson Jan 10, 2024
4e249b0
Remove commented code
chrisrichardson Jan 10, 2024
d33c5b1
Add test file
chrisrichardson Jan 10, 2024
4655a7a
more tests
chrisrichardson Jan 10, 2024
eefaa42
Merge branch 'main' into chris/topology-nightmare
chrisrichardson Jan 11, 2024
f2a8c27
Merge branch 'chris/topology-nightmare' of ssh://github.com/fenics/do…
chrisrichardson Jan 11, 2024
bc419c0
Improve docs
chrisrichardson Jan 11, 2024
cc43a38
Merge branch 'main' into chris/topology-nightmare
chrisrichardson Jan 11, 2024
96f4c99
Const fix
chrisrichardson Jan 11, 2024
6e1c53d
const fix
chrisrichardson Jan 11, 2024
589d2a6
Doc fix
chrisrichardson Jan 11, 2024
ddc318e
Rewrite topology computation slightly
chrisrichardson Jan 12, 2024
300fc33
Use int8_t
chrisrichardson Jan 12, 2024
464f500
more int8
chrisrichardson Jan 12, 2024
fc52ba8
Merge branch 'chris/topology-nightmare' into chris/topology-computation
chrisrichardson Jan 12, 2024
0c1bc84
Adjustments to compute_entities
chrisrichardson Jan 13, 2024
e90ba90
Something not working
chrisrichardson Jan 14, 2024
c234594
Merge branch 'main' into chris/topology-nightmare
chrisrichardson Jan 15, 2024
d48e9dd
Merge branch 'main' into chris/topology-computation
chrisrichardson Jan 15, 2024
180a36c
Fix up
chrisrichardson Jan 15, 2024
e4395fe
Pass more back up
chrisrichardson Jan 15, 2024
9d142a7
Make all entities of dim
chrisrichardson Jan 15, 2024
4e87645
flake8
chrisrichardson Jan 15, 2024
b0cf2da
More suggestions
chrisrichardson Jan 15, 2024
e939247
Fixes for suggestions
chrisrichardson Jan 15, 2024
5e1d508
flake8
chrisrichardson Jan 15, 2024
9239b0c
Update test
chrisrichardson Jan 15, 2024
b1bdde4
merge
chrisrichardson Jan 15, 2024
dee2a49
update test
chrisrichardson Jan 15, 2024
2ef5a07
Merge branch 'main' into chris/topology-nightmare
chrisrichardson Jan 16, 2024
19daac2
Apply suggestions from code review
chrisrichardson Jan 16, 2024
0d3e92f
Add a few suggestions
chrisrichardson Jan 15, 2024
6127fbe
Update cpp/dolfinx/mesh/Topology.cpp
chrisrichardson Jan 16, 2024
c8356ff
Merge branch 'chris/topology-nightmare' of ssh://github.com/FEniCS/do…
chrisrichardson Jan 15, 2024
0313310
Fixes for multiple cell types
chrisrichardson Jan 17, 2024
d4747e6
merge
chrisrichardson Jan 17, 2024
0cbd01f
Compute connectivity (edges)
chrisrichardson Jan 17, 2024
ce65f81
Fix create_connectivity and test
chrisrichardson Jan 17, 2024
7cb58de
Print some topology
chrisrichardson Jan 17, 2024
fe212a4
merge
chrisrichardson Jan 17, 2024
c4d4745
Fix typo
chrisrichardson Jan 17, 2024
650d343
Make interprocess_facets available
chrisrichardson Jan 17, 2024
d7b835e
Merge branch 'main' into chris/topology-computation
chrisrichardson Jan 19, 2024
6106f53
Clean up test a bit
chrisrichardson Jan 19, 2024
e02800e
Merge branch 'main' into chris/geometry-mix-dofmap
chrisrichardson Jan 19, 2024
bd8103a
Merge branch 'chris/topology-computation' into chris/geometry-mix-dofmap
chrisrichardson Jan 19, 2024
23d22bf
Start work on Geometry
chrisrichardson Jan 19, 2024
98ddd19
work in progress
chrisrichardson Jan 20, 2024
075c427
merge
chrisrichardson Jan 23, 2024
015320f
More work to do...
chrisrichardson Jan 23, 2024
1e533aa
doc fix
chrisrichardson Jan 24, 2024
98e7527
Python fixes
chrisrichardson Jan 24, 2024
f3c01dd
Add python wrapper
chrisrichardson Jan 24, 2024
802dae6
Pass IndexMaps, not topology
chrisrichardson Jan 25, 2024
b2d5b08
More work in progress [skip ci]
chrisrichardson Jan 26, 2024
6ab48f9
Fix [skip ci]
chrisrichardson Jan 26, 2024
6b9c2ea
Add a (failing) test
chrisrichardson Jan 26, 2024
58552b5
Debug and test
chrisrichardson Jan 26, 2024
78dc684
isort
chrisrichardson Jan 26, 2024
77e25fb
int type
chrisrichardson Jan 26, 2024
354c7ee
Get a parallel test working
chrisrichardson Jan 26, 2024
09d356b
merge
chrisrichardson Jan 26, 2024
4bf838b
isort
chrisrichardson Jan 26, 2024
29ef2e4
Create an actual mesh
chrisrichardson Jan 26, 2024
5d5fcbb
Create a dofmap
chrisrichardson Jan 29, 2024
0ecaedd
docs
chrisrichardson Jan 29, 2024
fe35625
More changes
chrisrichardson Jan 30, 2024
964c5af
Merge branch 'main' into chris/geometry-mix-more
chrisrichardson Jan 31, 2024
4d3fbfc
More work on build_basic_dofmap
chrisrichardson Jan 31, 2024
9650f42
More tidying up
chrisrichardson Jan 31, 2024
5ca197e
Fix global offset loop level
chrisrichardson Feb 1, 2024
b5fcc40
Remove a few unneeded checks
chrisrichardson Feb 1, 2024
a6275f6
Compute global start correctly
chrisrichardson Feb 1, 2024
85a917f
clean up
chrisrichardson Feb 1, 2024
66442fa
Remove unused
chrisrichardson Feb 1, 2024
d7c3ba3
merge
chrisrichardson Feb 2, 2024
153aa0e
format
chrisrichardson Feb 2, 2024
6a3360b
Merge branch 'main' into chris/geometry-mix-more
chrisrichardson Feb 3, 2024
f6ea4a9
doc
chrisrichardson Feb 4, 2024
fdf209e
Merge branch 'main' into chris/geometry-mix-more
chrisrichardson Feb 5, 2024
f3b67cc
merge
chrisrichardson Feb 14, 2024
6617754
Fix typo
chrisrichardson Feb 14, 2024
f4fa1af
Update ufl syntax
chrisrichardson Feb 14, 2024
40a037f
Merge branch 'chris/geometry-mix-more' of ssh://github.com/fenics/dol…
chrisrichardson Feb 19, 2024
46e4a4a
Merge branch 'main' into chris/geometry-mix-more
chrisrichardson Feb 19, 2024
455a592
Some tidy up
chrisrichardson Feb 19, 2024
8d16135
Update test
chrisrichardson Feb 19, 2024
3fbfadc
Update test
chrisrichardson Feb 20, 2024
2a2f1d1
Merge branch 'main' into chris/geometry-mix-more
chrisrichardson Feb 20, 2024
3311ec9
Merge branch 'main' into chris/geometry-mix-more
chrisrichardson Feb 26, 2024
e1981ae
Revert Geometry.h to main
chrisrichardson Feb 26, 2024
a2679c1
Improvements to utils.cpp
chrisrichardson Feb 26, 2024
45e5266
Adjust python interface
chrisrichardson Feb 26, 2024
0969547
Fix for name resolution in pybind
chrisrichardson Feb 26, 2024
f824751
Clean up debug
chrisrichardson Feb 26, 2024
d222ffc
More test updates
chrisrichardson Feb 26, 2024
1a07ddb
Merge branch 'main' into chris/geometry-mix-more
chrisrichardson Feb 26, 2024
fbefc2e
Specify dtype more precisely
chrisrichardson Feb 26, 2024
9e74dc7
More dtype
chrisrichardson Feb 26, 2024
b6caa63
Merge branch 'main' into chris/geometry-mix-more
chrisrichardson Feb 27, 2024
020e1ef
Update to types in utils.cpp
chrisrichardson Feb 27, 2024
0427dc3
Update to python interface
chrisrichardson Feb 27, 2024
8545e1e
test names
chrisrichardson Feb 27, 2024
51ba2ec
Merge branch 'main' into chris/geometry-mix-more
chrisrichardson Feb 27, 2024
0d4642b
Apply suggestions from code review
chrisrichardson Feb 29, 2024
589cd9f
Changes from review so far
chrisrichardson Feb 29, 2024
be56203
Fix memory allocation
chrisrichardson Feb 29, 2024
e85f8c9
Merge branch 'main' into chris/geometry-mix-more
chrisrichardson Feb 29, 2024
18610ed
Merge branch 'main' into chris/geometry-mix-more
chrisrichardson Mar 2, 2024
44b65e7
Suggested changes
chrisrichardson Mar 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
390 changes: 228 additions & 162 deletions cpp/dolfinx/fem/dofmapbuilder.cpp

Large diffs are not rendered by default.

50 changes: 49 additions & 1 deletion cpp/dolfinx/fem/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ fem::DofMap fem::create_dofmap(
// DOF numbering on each cell
if (unpermute_dofs)
{
const int D = topology.dim();
const int num_cells = topology.connectivity(D, 0)->num_nodes();
topology.create_entity_permutations();
const std::vector<std::uint32_t>& cell_info
Expand All @@ -133,6 +132,55 @@ fem::DofMap fem::create_dofmap(
return DofMap(layout, index_map, bs, std::move(dofmaps.front()), bs);
}
//-----------------------------------------------------------------------------
std::vector<fem::DofMap> fem::create_dofmaps(
MPI_Comm comm, const std::vector<ElementDofLayout>& layouts,
mesh::Topology& topology,
std::function<void(std::span<std::int32_t>, std::uint32_t)> unpermute_dofs,
std::function<std::vector<int>(const graph::AdjacencyList<std::int32_t>&)>
reorder_fn)
{
std::int32_t D = topology.dim();
assert(layouts.size() == topology.entity_types(D).size());

// Create required mesh entities
for (std::int32_t d = 0; d < D; ++d)
{
if (layouts.front().num_entity_dofs(d) > 0)
topology.create_entities(d);
}

auto [_index_map, bs, dofmaps]
= build_dofmap_data(comm, topology, layouts, reorder_fn);
auto index_map = std::make_shared<common::IndexMap>(std::move(_index_map));

// If the element's DOF transformations are permutations, permute the
// DOF numbering on each cell
if (unpermute_dofs)
{
if (layouts.size() != 1)
{
throw std::runtime_error(
"DOF transformations not yet supported in mixed topology.");
}
std::int32_t num_cells = topology.connectivity(D, 0)->num_nodes();
topology.create_entity_permutations();
const std::vector<std::uint32_t>& cell_info
= topology.get_cell_permutation_info();
std::int32_t dim = layouts.front().num_dofs();
for (std::int32_t cell = 0; cell < num_cells; ++cell)
{
std::span<std::int32_t> dofs(dofmaps.front().data() + cell * dim, dim);
unpermute_dofs(dofs, cell_info[cell]);
}
}

std::vector<DofMap> dms;
chrisrichardson marked this conversation as resolved.
Show resolved Hide resolved
for (std::size_t i = 0; i < dofmaps.size(); ++i)
dms.emplace_back(layouts[i], index_map, bs, std::move(dofmaps[i]), bs);

return dms;
}
//-----------------------------------------------------------------------------
std::vector<std::string> fem::get_coefficient_names(const ufcx_form& ufcx_form)
{
return std::vector<std::string>(ufcx_form.coefficient_name_map,
Expand Down
17 changes: 17 additions & 0 deletions cpp/dolfinx/fem/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,23 @@ DofMap create_dofmap(
std::function<std::vector<int>(const graph::AdjacencyList<std::int32_t>&)>
reorder_fn);

/// @brief Create a set of dofmaps on a given topology
/// @param[in] comm MPI communicator
/// @param[in] layouts Dof layout on each element type
/// @param[in] topology Mesh topology
/// @param[in] unpermute_dofs Function to un-permute dofs. `nullptr`
/// when transformation is not required.
/// @param[in] reorder_fn Graph reordering function called on the dofmaps
/// @return The list of new dof maps
/// @note The number of layouts must match the number of cell types in the
/// topology
std::vector<DofMap> create_dofmaps(
MPI_Comm comm, const std::vector<ElementDofLayout>& layouts,
mesh::Topology& topology,
std::function<void(std::span<std::int32_t>, std::uint32_t)> unpermute_dofs,
std::function<std::vector<int>(const graph::AdjacencyList<std::int32_t>&)>
reorder_fn);

/// Get the name of each coefficient in a UFC form
/// @param[in] ufcx_form The UFC form
/// @return The name of each coefficient
Expand Down
2 changes: 1 addition & 1 deletion cpp/dolfinx/mesh/Geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ create_geometry(
std::vector<T> xg(3 * shape0, 0);
for (std::size_t i = 0; i < shape0; ++i)
{
std::copy_n(std::next(x.cbegin(), shape1 * l2l[i]), shape1,
std::copy_n(std::next(x.begin(), shape1 * l2l[i]), shape1,
std::next(xg.begin(), 3 * i));
}

Expand Down
24 changes: 24 additions & 0 deletions python/dolfinx/wrappers/fem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,30 @@ void declare_real_functions(nb::module_& m)
nb::arg("element"),
"Create DofMap object from a pointer to ufcx_dofmap.");

m.def(
"create_dofmaps",
[](const dolfinx_wrappers::MPICommWrapper comm,
std::vector<std::uintptr_t> ufcx_dofmaps,
dolfinx::mesh::Topology& topology)
{
std::vector<dolfinx::fem::ElementDofLayout> layouts;
int D = topology.dim();
assert(ufcx_dofmaps.size() == topology.entity_types(D).size());
for (std::size_t i = 0; i < ufcx_dofmaps.size(); ++i)
{
ufcx_dofmap* p = reinterpret_cast<ufcx_dofmap*>(ufcx_dofmaps[i]);
assert(p);
layouts.push_back(dolfinx::fem::create_element_dof_layout(
*p, topology.entity_types(D)[i]));
}

return dolfinx::fem::create_dofmaps(comm.get(), layouts, topology,
nullptr, nullptr);
},
nb::arg("comm"), nb::arg("dofmap"), nb::arg("topology"),
"Create DofMap objects on a mixed topology mesh from pointers to "
"ufcx_dofmaps.");

m.def(
"locate_dofs_topological",
[](const std::vector<
Expand Down
25 changes: 25 additions & 0 deletions python/dolfinx/wrappers/mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,17 @@ void declare_mesh(nb::module_& m, std::string type)
dofs.data_handle(), {dofs.extent(0), dofs.extent(1)});
},
nb::rv_policy::reference_internal)
.def(
"dofmaps",
[](dolfinx::mesh::Geometry<T>& self, int i)
{
auto dofs = self.dofmap(i);
return nb::ndarray<const std::int32_t, nb::numpy>(
dofs.data_handle(), {dofs.extent(0), dofs.extent(1)});
},
nb::rv_policy::reference_internal, nb::arg("i"),
"Get the geometry dofmap associated with coordinate element i (mixed "
"topology)")
.def("index_map", &dolfinx::mesh::Geometry<T>::index_map)
.def_prop_ro(
"x",
Expand Down Expand Up @@ -384,6 +395,20 @@ void declare_mesh(nb::module_& m, std::string type)
return as_nbarray(std::move(idx), {entities.size(), num_vertices});
},
nb::arg("mesh"), nb::arg("dim"), nb::arg("entities"), nb::arg("orient"));

m.def("create_geometry",
[](const dolfinx::mesh::Topology& topology,
const std::vector<dolfinx::fem::CoordinateElement<T>>& elements,
nb::ndarray<const std::int64_t, nb::ndim<1>, nb::c_contig> nodes,
nb::ndarray<const std::int64_t, nb::ndim<1>, nb::c_contig> xdofs,
nb::ndarray<const T, nb::ndim<1>, nb::c_contig> x, int dim)
{
return dolfinx::mesh::create_geometry(
topology, elements,
std::span<const std::int64_t>(nodes.data(), nodes.size()),
std::span<const std::int64_t>(xdofs.data(), xdofs.size()),
std::span<const T>(x.data(), x.size()), dim);
});
}

void mesh(nb::module_& m)
Expand Down
145 changes: 145 additions & 0 deletions python/test/unit/fem/test_mixed_mesh_dofmap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
from mpi4py import MPI

import numpy as np

import basix
import dolfinx.cpp as _cpp
from dolfinx import jit
from dolfinx.cpp.mesh import Mesh_float64, create_geometry, create_topology
from dolfinx.fem import coordinate_element
from dolfinx.fem.dofmap import DofMap
from dolfinx.log import LogLevel, set_log_level
from dolfinx.mesh import CellType


def create_element_dofmap(mesh, cell_types, degree):
cpp_elements = []
dofmaps = []
for cell_type in cell_types:
ufl_e = basix.ufl.element("P", cell_type, degree)
form_compiler_options = {"scalar_type": np.float64}
(ufcx_element, ufcx_dofmap), module, code = jit.ffcx_jit(
mesh.comm, ufl_e, form_compiler_options=form_compiler_options
)
ffi = module.ffi
cpp_elements += [
_cpp.fem.FiniteElement_float64(ffi.cast("uintptr_t", ffi.addressof(ufcx_element)))
]
dofmaps += [ufcx_dofmap]

cpp_dofmaps = _cpp.fem.create_dofmaps(
mesh.comm, [ffi.cast("uintptr_t", ffi.addressof(dm)) for dm in dofmaps], mesh.topology
)

return (cpp_elements, cpp_dofmaps)


def test_dofmap_mixed_topology():
rank = MPI.COMM_WORLD.Get_rank()

# Two triangles and one quadrilateral
tri = [0, 1, 4, 0, 3, 4]
quad = [1, 4, 2, 5]
# cells with global indexing
cells = [[t + 3 * rank for t in tri], [q + 3 * rank for q in quad]]
orig_index = [[3 * rank, 1 + 3 * rank], [2 + 3 * rank]]
# No ghosting
ghost_owners = [[], []]
# All vertices are on boundary
boundary_vertices = [3 * rank + i for i in range(6)]

topology = create_topology(
MPI.COMM_WORLD,
[CellType.triangle, CellType.quadrilateral],
cells,
orig_index,
ghost_owners,
boundary_vertices,
)
# Create dofmaps for Geometry
tri = coordinate_element(CellType.triangle, 1)
quad = coordinate_element(CellType.quadrilateral, 1)
nodes = np.arange(6, dtype=np.int64) + 3 * rank
xdofs = np.array([0, 1, 4, 0, 3, 4, 1, 4, 2, 5], dtype=np.int64) + 3 * rank
x = np.array(
[[0.0, 0.0], [1.0, 0.0], [2.0, 0.0], [0.0, 1.0], [1.0, 1.0], [2.0, 1.0]], dtype=np.float64
)
x[:, 1] += 1.0 * rank

set_log_level(LogLevel.INFO)
geom = create_geometry(
topology, [tri._cpp_object, quad._cpp_object], nodes, xdofs, x.flatten(), 2
)
mesh = Mesh_float64(MPI.COMM_WORLD, topology, geom)

assert mesh.geometry.x.shape == (6, 3)

# Second order dofmap on mixed mesh
elements, dofmaps = create_element_dofmap(
mesh, [basix.CellType.triangle, basix.CellType.quadrilateral], 2
)

assert len(elements) == 2
assert elements[0].basix_element.cell_type.name == "triangle"
assert elements[1].basix_element.cell_type.name == "quadrilateral"

assert len(dofmaps) == 2
q0 = DofMap(dofmaps[0])
q1 = DofMap(dofmaps[1])
assert q0.index_map.size_local == q1.index_map.size_local
# Triangles
print(q0.list)
assert q0.list.shape == (2, 6)
assert len(q0.dof_layout.entity_dofs(2, 0)) == 0
# Quadrilaterals
print(q1.list)
assert q1.list.shape == (1, 9)
assert len(q1.dof_layout.entity_dofs(2, 0)) == 1


def test_dofmap_prism_mesh():
# Prism mesh
cells = [[0, 1, 2, 3, 4, 5]]
# cells with global indexing
orig_index = [[0, 1, 2, 3, 4, 5]]
# No ghosting
ghost_owners = [[]]
# All vertices are on boundary
boundary_vertices = [0, 1, 2, 3, 4, 5]

topology = create_topology(
MPI.COMM_SELF, [CellType.prism], cells, orig_index, ghost_owners, boundary_vertices
)
topology.create_entities(2)

# Create dofmaps for Geometry
prism = coordinate_element(CellType.prism, 1)
nodes = np.array([0, 1, 2, 3, 4, 5], dtype=np.int64)
xdofs = np.array([0, 1, 2, 3, 4, 5], dtype=np.int64)
x = np.array(
[
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 1.0],
[1.0, 0.0, 1.0],
[0.0, 1.0, 1.0],
],
dtype=np.float64,
)

set_log_level(LogLevel.INFO)
geom = create_geometry(topology, [prism._cpp_object], nodes, xdofs, x.flatten(), 3)
mesh = Mesh_float64(MPI.COMM_WORLD, topology, geom)

elements, dofmaps = create_element_dofmap(mesh, [basix.CellType.prism], 2)
print()
assert len(elements) == 1
assert len(dofmaps) == 1
q = DofMap(dofmaps[0])
assert q.index_map.size_local == 18
print(q.list)
facet_dofs = []
for j in range(5):
facet_dofs += q.dof_layout.entity_dofs(2, j)
assert len(facet_dofs) == 3
Loading
Loading