FEniCS / FEniCS/dolfinx

[BUG]: dof_transformation_right_fn mis-slices data for mixed elements with block_size > 1

Open
#4,294 0 comments 0 reactions 1 assignee Claimed by @mscroggs View on GitHub
Dominant language
C++
Stars
1.2k
Forks
261
Avg merge
1d 15h
Merged PRs (30d)
65

Description

### Summarize the issue

This is a bug found by Claude AI - which may or may not be accurate. I don't know if this is correct or not, but just pasting here as an issue, in case anyone can look into it.

File: `cpp/dolfinx/fem/FiniteElement.h`
Function: `FiniteElement::dof_transformation_right_fn` (mixed-element branch)

### Summary

In the mixed-element branch of dof_transformation_right_fn, each sub-element's DOF-transformation function is called with a data span that is not correctly restricted to that sub-element's own columns when block_size > 1. This silently produces incorrect data for any mixed (heterogeneous) element where a sub-element needs a DOF transformation and the transformation is applied from the right with more than one row of data — the situation that arises during bilinear-form matrix assembly.

### Current code

```
cpp// cpp/dolfinx/fem/FiniteElement.h
else if (!_sub_elements.empty())
{
if (!_reference_value_shape) // Mixed element
{
std::vector, std::span, std::int32_t, int)>>
sub_element_fns;
for (std::size_t i = 0; i < _sub_elements.size(); ++i)
{
sub_element_fns.push_back(
_sub_elements[i]->template dof_transformation_right_fn(ttype));
}

return [this, sub_element_fns](std::span data,
std::span cell_info,
std::int32_t cell, int block_size)
{
std::size_t offset = 0;
for (std::size_t e = 0; e < sub_element_fns.size(); ++e)
{
sub_element_fns[e](data.subspan(offset, data.size() - offset),
cell_info, cell, block_size);
offset += _sub_elements[e]->space_dimension();
}
};
}
...
```

### Root cause

block_size here is a row count, not a component count. This is confirmed by the call site in assemble_matrix_impl.h:

```
cpp// cpp/dolfinx/fem/assemble_matrix_impl.h
P0(Ae, cell_info0, cell0, ndim1); // left-apply, ndim1 rows
P1T(Ae, cell_info1, cell1, ndim0); // right-apply, ndim0 rows
```

data is therefore a row-major buffer of shape (block_size rows) x (total dofs). For sub-element e, occupying dof-columns [offset, offset + dim_e), the correct data for that sub-element is a strided slice — the same column range repeated in every row — not a single contiguous run.

### How to reproduce the bug

N/A

### Minimal Example (Python)

```Python

```

### Output (Python)

```bash

```

### Version

main branch

### DOLFINx git commit

_No response_

### Installation

_No response_

### Additional information

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.