Repository: pyvista/pyvista

Issue:
Allow passing through cell data in `to_tetrahedra` method in RectilinearGrid
### Describe the feature you would like to be added.

No cell data is passed through when converting to a tetrahedra.  The user can currently request to pass through the original cell id, but it requires one more step to regenerate the cell data on the tetrahedralized mesh.

### Links to VTK Documentation, Examples, or Class Definitions.

_No response_

### Pseudocode or Screenshots

Currently we have to do

```python
mesh # Rectilinear or UniformGrid, which has cell data "cell_data"
tetra_mesh = mesh.to_tetrahedra(pass_cell_ids=True)
tetra_mesh["cell_data"] = mesh["cell_data"][tetra_mesh.cell_data.active_scalars]
```

It would be better to do something like

```python
mesh # Rectilinear or UniformGrid, which has cell data "cell_data"
tetra_mesh = mesh.to_tetrahedra(pass_cell_data=True)  # the prior code would occur inside the method
```


Discussion:

Patch:
diff --git a/pyvista/core/datasetattributes.py b/pyvista/core/datasetattributes.py
--- a/pyvista/core/datasetattributes.py
+++ b/pyvista/core/datasetattributes.py
@@ -1072,7 +1072,12 @@ def active_scalars_name(self) -> Optional[str]:
 
         """
         if self.GetScalars() is not None:
-            return str(self.GetScalars().GetName())
+            name = self.GetScalars().GetName()
+            if name is None:
+                # Getting the keys has the side effect of naming "unnamed" arrays
+                self.keys()
+                name = self.GetScalars().GetName()
+            return str(name)
         return None
 
     @active_scalars_name.setter
diff --git a/pyvista/core/filters/rectilinear_grid.py b/pyvista/core/filters/rectilinear_grid.py
--- a/pyvista/core/filters/rectilinear_grid.py
+++ b/pyvista/core/filters/rectilinear_grid.py
@@ -17,7 +17,8 @@ def to_tetrahedra(
         self,
         tetra_per_cell: int = 5,
         mixed: Union[Sequence[int], bool] = False,
-        pass_cell_ids: bool = False,
+        pass_cell_ids: bool = True,
+        pass_cell_data: bool = True,
         progress_bar: bool = False,
     ):
         """Create a tetrahedral mesh structured grid.
@@ -39,10 +40,17 @@ def to_tetrahedra(
             string uses a cell array rather than the active array to determine
             the number of tetrahedra to generate per cell.
 
-        pass_cell_ids : bool, default: False
+        pass_cell_ids : bool, default: True
             Set to ``True`` to make the tetrahedra have scalar data indicating
             which cell they came from in the original
-            :class:`pyvista.RectilinearGrid`.
+            :class:`pyvista.RectilinearGrid`. The name of this array is
+            ``'vtkOriginalCellIds'`` within the ``cell_data``.
+
+        pass_cell_data : bool, default: True
+            Set to ``True`` to make the tetradera mesh have the cell data from
+            the original :class:`pyvista.RectilinearGrid`.  This uses
+            ``pass_cell_ids=True`` internally. If ``True``, ``pass_cell_ids``
+            will also be set to ``True``.
 
         progress_bar : bool, default: False
             Display a progress bar to indicate progress.
@@ -80,7 +88,7 @@ def to_tetrahedra(
 
         """
         alg = _vtk.vtkRectilinearGridToTetrahedra()
-        alg.SetRememberVoxelId(pass_cell_ids)
+        alg.SetRememberVoxelId(pass_cell_ids or pass_cell_data)
         if mixed is not False:
             if isinstance(mixed, str):
                 self.cell_data.active_scalars_name = mixed
@@ -107,4 +115,17 @@ def to_tetrahedra(
 
         alg.SetInputData(self)
         _update_alg(alg, progress_bar, 'Converting to tetrahedra')
-        return _get_output(alg)
+        out = _get_output(alg)
+        if pass_cell_data:
+            # algorithm stores original cell ids in active scalars
+            for name in self.cell_data:  # type: ignore
+                if name != out.cell_data.active_scalars_name:
+                    out[name] = self.cell_data[name][out.cell_data.active_scalars]  # type: ignore
+
+        if alg.GetRememberVoxelId():
+            # original cell_ids are not named and are the active scalars
+            out.cell_data.set_array(
+                out.cell_data.pop(out.cell_data.active_scalars_name), 'vtkOriginalCellIds'
+            )
+
+        return out


Test patch:
diff --git a/tests/filters/test_rectilinear_grid.py b/tests/filters/test_rectilinear_grid.py
--- a/tests/filters/test_rectilinear_grid.py
+++ b/tests/filters/test_rectilinear_grid.py
@@ -45,3 +45,25 @@ def test_to_tetrahedral_mixed(tiny_rectilinear):
 def test_to_tetrahedral_edge_case():
     with pytest.raises(RuntimeError, match='is 1'):
         pv.UniformGrid(dimensions=(1, 2, 2)).to_tetrahedra(tetra_per_cell=12)
+
+
+def test_to_tetrahedral_pass_cell_ids(tiny_rectilinear):
+    tet_grid = tiny_rectilinear.to_tetrahedra(pass_cell_ids=False, pass_cell_data=False)
+    assert not tet_grid.cell_data
+    tet_grid = tiny_rectilinear.to_tetrahedra(pass_cell_ids=True, pass_cell_data=False)
+    assert 'vtkOriginalCellIds' in tet_grid.cell_data
+    assert np.issubdtype(tet_grid.cell_data['vtkOriginalCellIds'].dtype, np.integer)
+
+
+def test_to_tetrahedral_pass_cell_data(tiny_rectilinear):
+    tiny_rectilinear["cell_data"] = np.ones(tiny_rectilinear.n_cells)
+
+    tet_grid = tiny_rectilinear.to_tetrahedra(pass_cell_ids=False, pass_cell_data=False)
+    assert not tet_grid.cell_data
+
+    tet_grid = tiny_rectilinear.to_tetrahedra(pass_cell_ids=False, pass_cell_data=True)
+    assert tet_grid.cell_data
+    assert "cell_data" in tet_grid.cell_data
+
+    # automatically added
+    assert 'vtkOriginalCellIds' in tet_grid.cell_data