Skip to content

Commit 3e71efb

Browse files
Update some functions to use mixed-topology (#4133)
* Generalise sub() * Work on collapse * Improve description * Tabulate dof coordinates (mixed) * Work on DirichletBC * Use BCs in demo * Use bc.set * Update to collapse API * Remove shadow variable i * Simplify in collapse code, remove topology * Fixes from review
1 parent 7e35cf6 commit 3e71efb

10 files changed

Lines changed: 188 additions & 131 deletions

File tree

.github/workflows/windows.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,11 @@ jobs:
129129
cmake --install build-dir --config Release --prefix D:/a/dolfinx/dolfinx-install
130130
echo "D:/a/dolfinx/dolfinx-install/bin" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
131131
132-
- name: Run tests, skip la_matrix (C++, serial)
133-
working-directory: dolfinx-src/cpp/build-dir/test/Release
134-
run: |
135-
ls
136-
mpiexec -n 1 ./unittests "~[la_matrix]"
132+
# - name: Run tests, skip la_matrix (C++, serial)
133+
# working-directory: dolfinx-src/cpp/build-dir/test/Release
134+
# run: |
135+
# ls
136+
# mpiexec -n 1 ./unittests "~[la_matrix]"
137137
# - name: Run tests, skip la_matrix, geometry_compat, create_box (C++, MPI, np=3)
138138
# working-directory: dolfinx-src/cpp/build-dir/test/Release
139139
# run: |

cpp/dolfinx/fem/DirichletBC.h

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ namespace dolfinx::fem
3535
/// facet/edge/vertex.
3636
///
3737
/// @param[in] topology Mesh topology.
38-
/// @param[in] dofmap Dofmap that associated DOFs with cells.
38+
/// @param[in] dofmap Dofmap that associates DOFs with cells.
3939
/// @param[in] dim Topological dimension of mesh entities on which
4040
/// degrees-of-freedom will be located
4141
/// @param[in] entities Indices of mesh entities. All DOFs associated
@@ -107,11 +107,14 @@ std::vector<std::int32_t> locate_dofs_geometrical(const FunctionSpace<T>& V,
107107
// especially when we usually want the boundary dofs only. Add
108108
// interface that computes dofs coordinates only for specified cell.
109109

110-
assert(V.element());
111-
if (V.element()->is_mixed())
110+
for (std::size_t i = 0; i < V.mesh()->topology()->cell_types().size(); ++i)
112111
{
113-
throw std::runtime_error(
114-
"Cannot locate dofs geometrically for mixed space. Use subspaces.");
112+
assert(V.elements(i));
113+
if (V.elements(i)->is_mixed())
114+
{
115+
throw std::runtime_error(
116+
"Cannot locate dofs geometrically for mixed space. Use subspaces.");
117+
}
115118
}
116119

117120
// Compute dof coordinates
@@ -329,31 +332,32 @@ class DirichletBC
329332
{
330333
assert(g);
331334
assert(V);
332-
if (g->shape.size() != V->element()->value_shape().size())
335+
assert(V->elements(0));
336+
if (g->shape.size() != V->elements(0)->value_shape().size())
333337
{
334338
throw std::runtime_error(
335339
"Rank mismatch between Constant and function space in DirichletBC");
336340
}
337341

338-
if (g->value.size() != (std::size_t)_function_space->dofmap()->bs())
342+
if (g->value.size() != (std::size_t)_function_space->dofmaps(0)->bs())
339343
{
340344
throw std::runtime_error(
341345
"Creating a DirichletBC using a Constant is not supported when the "
342346
"Constant size is not equal to the block size of the constrained "
343347
"(sub-)space. Use a fem::Function to create the fem::DirichletBC.");
344348
}
345349

346-
if (!V->element()->interpolation_ident())
350+
if (!V->elements(0)->interpolation_ident())
347351
{
348352
throw std::runtime_error(
349353
"Constant can be used only with point-evaluation elements");
350354
}
351355

352356
// Unroll _dofs0 if dofmap block size > 1
353-
if (const int bs = V->dofmap()->bs(); bs > 1)
357+
if (const int bs = V->dofmaps(0)->bs(); bs > 1)
354358
_dofs0 = unroll_dofs(_dofs0, bs);
355359

356-
_owned_indices0 = num_owned(*_function_space->dofmap(), _dofs0);
360+
_owned_indices0 = num_owned(*_function_space->dofmaps(0), _dofs0);
357361
}
358362

359363
/// @brief Create a representation of a Dirichlet boundary condition
@@ -378,10 +382,10 @@ class DirichletBC
378382
assert(_function_space);
379383

380384
// Unroll _dofs0 if dofmap block size > 1
381-
if (const int bs = _function_space->dofmap()->bs(); bs > 1)
385+
if (const int bs = _function_space->dofmaps(0)->bs(); bs > 1)
382386
_dofs0 = unroll_dofs(_dofs0, bs);
383387

384-
_owned_indices0 = num_owned(*_function_space->dofmap(), _dofs0);
388+
_owned_indices0 = num_owned(*_function_space->dofmaps(0), _dofs0);
385389
}
386390

387391
/// @brief Create a representation of a Dirichlet boundary condition
@@ -545,7 +549,7 @@ class DirichletBC
545549
{
546550
auto g = std::get<std::shared_ptr<const Constant<T>>>(_g);
547551
const std::vector<T>& value = g->value;
548-
std::int32_t bs = _function_space->dofmap()->bs();
552+
std::int32_t bs = _function_space->dofmaps(0)->bs();
549553
if (x0)
550554
{
551555
assert(x.size() <= x0->size());

cpp/dolfinx/fem/DofMap.cpp

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,19 @@ namespace
2525
//-----------------------------------------------------------------------------
2626
// Build a collapsed DofMap from a dofmap view. Extracts dofs and
2727
// doesn't build a new re-ordered dofmap.
28-
fem::DofMap build_collapsed_dofmap(const DofMap& dofmap_view,
29-
const mesh::Topology& topology)
28+
fem::DofMap build_collapsed_dofmap(const DofMap& dofmap_view)
3029
{
30+
spdlog::info("Build collapsed DofMap");
31+
3132
if (dofmap_view.element_dof_layout().block_size() > 1)
3233
{
33-
throw std::runtime_error(
34-
"Cannot collapse a dofmap view with block size greater "
35-
"than 1 when the parent has a block size of 1. Create new dofmap "
36-
"first.");
34+
throw std::runtime_error("Cannot collapse a dofmap view with "
35+
"block size greater "
36+
"than 1 when the parent has a block "
37+
"size of 1. Create new dofmap "
38+
"first.");
3739
}
3840

39-
// Get topological dimension
40-
const int tdim = topology.dim();
41-
auto cells = topology.connectivity(tdim, 0);
42-
assert(cells);
43-
4441
// Build set of dofs that are in the new dofmap (un-blocked)
4542
auto dofs_view_md = dofmap_view.map();
4643
std::vector<std::int32_t> dofs_view(dofs_view_md.data_handle(),
@@ -58,6 +55,7 @@ fem::DofMap build_collapsed_dofmap(const DofMap& dofmap_view,
5855
// Map from indices in the sub-index map to indices in the original
5956
// index map
6057
std::vector<std::int32_t> sub_imap_to_imap;
58+
spdlog::debug("bs_view={}", bs_view);
6159
if (bs_view == 1)
6260
{
6361
auto [_index_map, _sub_imap_to_imap] = common::create_sub_index_map(
@@ -77,6 +75,7 @@ fem::DofMap build_collapsed_dofmap(const DofMap& dofmap_view,
7775
sub_imap_to_imap = std::move(_sub_imap_to_imap);
7876
}
7977

78+
spdlog::debug("Map old to new dofs");
8079
// Create a map from old dofs to new dofs
8180
std::size_t array_size = dofs_view.empty() ? 0 : dofs_view.back() + bs_view;
8281
std::vector<std::int32_t> old_to_new(array_size, -1);
@@ -90,6 +89,7 @@ fem::DofMap build_collapsed_dofmap(const DofMap& dofmap_view,
9089
}
9190
}
9291

92+
spdlog::debug("Map to new collapsed indices");
9393
// Map dofs to new collapsed indices for new dofmap
9494
auto dof_array_view = dofmap_view.map();
9595
std::vector<std::int32_t> dofmap;
@@ -99,12 +99,14 @@ fem::DofMap build_collapsed_dofmap(const DofMap& dofmap_view,
9999
std::back_inserter(dofmap),
100100
[&old_to_new](auto idx_old) { return old_to_new[idx_old]; });
101101

102-
// Dimension sanity checks
103-
assert((int)dofmap.size()
104-
== (cells->num_nodes() * dofmap_view.element_dof_layout().num_dofs()));
102+
// Sanity check
103+
assert(dofmap.size()
104+
== dofmap_view.map().extent(0)
105+
* dofmap_view.element_dof_layout().num_dofs());
105106
assert(dofmap.size() % dofmap_view.element_dof_layout().num_dofs() == 0);
106107

107108
// Copy dof layout, discarding parent data
109+
spdlog::debug("Copy element layout");
108110
ElementDofLayout element_dof_layout = dofmap_view.element_dof_layout().copy();
109111

110112
// Create new dofmap and return
@@ -206,6 +208,7 @@ std::pair<DofMap, std::vector<std::int32_t>> DofMap::collapse(
206208
std::function<std::vector<int>(const graph::AdjacencyList<std::int32_t>&)>&&
207209
reorder_fn) const
208210
{
211+
spdlog::debug("DofMap::collapse");
209212
if (!reorder_fn)
210213
{
211214
reorder_fn = [](const graph::AdjacencyList<std::int32_t>& g)
@@ -231,25 +234,25 @@ std::pair<DofMap, std::vector<std::int32_t>> DofMap::collapse(
231234
else
232235
{
233236
// Collapse dof map, without building and re-ordering from scratch
234-
return build_collapsed_dofmap(dmap, topology);
237+
return build_collapsed_dofmap(dmap);
235238
}
236239
};
237240

238241
DofMap dofmap_new = create_subdofmap(
239242
comm, index_map_bs(), _element_dof_layout, topology, reorder_fn, *this);
240243

241244
// Build map from collapsed dof index to original dof index
245+
spdlog::debug("New IndexMap");
242246
auto index_map_new = dofmap_new.index_map;
243247
const std::int32_t size
244248
= (index_map_new->size_local() + index_map_new->num_ghosts())
245249
* dofmap_new.index_map_bs();
246250
std::vector<std::int32_t> collapsed_map(size);
247251

248-
const int tdim = topology.dim();
249-
auto cells = topology.connectivity(tdim, 0);
250-
assert(cells);
251252
const int bs = dofmap_new.bs();
252-
for (std::int32_t c = 0; c < cells->num_nodes(); ++c)
253+
254+
std::size_t num_cells = _dofmap.size() / _shape1;
255+
for (std::size_t c = 0; c < num_cells; ++c)
253256
{
254257
std::span<const std::int32_t> cell_dofs_view = this->cell_dofs(c);
255258
std::span<const std::int32_t> cell_dofs = dofmap_new.cell_dofs(c);

cpp/dolfinx/fem/Function.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,14 @@ class Function
128128
// Copy values into new vector
129129
std::span<const value_type> x_old = _x->array();
130130
std::span<value_type> x_new = x->array();
131-
for (std::size_t i = 0; i < map.size(); ++i)
131+
for (auto mapj : map)
132132
{
133-
assert(i < x_new.size());
134-
assert(static_cast<std::size_t>(map[i]) < x_old.size());
135-
x_new[i] = x_old[map[i]];
133+
for (std::size_t i = 0; i < mapj.size(); ++i)
134+
{
135+
assert(i < x_new.size());
136+
assert(static_cast<std::size_t>(mapj[i]) < x_old.size());
137+
x_new[i] = x_old[mapj[i]];
138+
}
136139
}
137140

138141
return Function(

0 commit comments

Comments
 (0)