Add the cell center coordinates to the cell data

Hi everyone,

The solver I use being cell centered, I try more and more to work on the cell data to avoid having the use the cell data to point data filter. The only reason I have to interpolate to the points is to re-calculate moments because I do not have access to the cell centers in a cell data array.Using the cell centers filter does calculate this, but it outputs points … which because unhandy to use the integrate variables filter later on.

So, does anyone knows a trick to get append the cell centers to the cell data, but also keeping my unstructured grid ?

Thanks in advance.

It’s a bit wonky, but it is possible to append the coordinates of the cell centers to the mesh. The following steps should work.

  1. Add the Cell Centers filter. Turn on the Vertex Cells property. Apply.
  2. Add the calculator filter. Set the Result Array Name to “Center” and the expression to compute to “coords”. Apply.
  3. Add the Point Data to Cell Data filter. Apply.
  4. In the pipeline browser, select both your original data set and the Point Data to Cell Data filter you just created. Add the Append Attributes filter. Apply.

That should do it.

For a bit more details, here is what each step is doing.

Step 1 is create a vertex cell (cell containing only one point) at the center of each cell in your original data set.

Step 2 is moving the point coordinates of each point to field data. Because of limitations of the calculator, it gets attached to points instead of cells.

Step 3 moves the field from points to cells. Because each cell only has one point, the values do not change.

Step 4 copies this cell field back to your original dataset.

6 Likes

Thanks for the hint. It’s doing the trick!

You could also accomplish this with a custom filter plugin! I had a similar problem and made a filter you could load into PV 5.6.0+. Check it out:

"""
A snippet for add cell center coordinates to the CellData of an input dataset.

Created by Bane Sullivan <banesullivan@gmail.com> for the PVGeo project <http://pvgeo.org>
"""
from paraview.util.vtkAlgorithm import *
from vtk.util.vtkAlgorithm import VTKPythonAlgorithmBase
import numpy as np
import vtk
from vtk.util import numpy_support as nps
from vtk.numpy_interface import dataset_adapter as dsa

MENU_CAT = 'Custom Filters'

# Extract Cell Centers
@smproxy.filter(name='AppendCellCenters', label='Append Cell Centers')
@smhint.xml('''<ShowInMenu category="%s"/>
    <RepresentationType view="RenderView" type="Surface" />''' % MENU_CAT)
@smproperty.input(name="Input", port_index=0)
@smdomain.datatype(dataTypes=["vtkDataSet"], composite_data_supported=True)
class AppendCellCenters(VTKPythonAlgorithmBase):
    """A filter to extract the cell centers of a data object and append those
    coordinates as a 3-component double array on the Cell Data.

    Created by Bane Sullivan <banesullivan@gmail.com> for the PVGeo project <http://pvgeo.org>
    """
    def __init__(self, **kwargs):
        VTKPythonAlgorithmBase.__init__(self, nInputPorts=1, nOutputPorts=1, inputType='vtkDataSet')

    # THIS IS CRUCIAL to preserve data type through filter
    def RequestDataObject(self, request, inInfo, outInfo):
        """This method lets the pipeline know that the algorithm will dynamically decide
        the output data type based in the input data type.
        """
        self.OutputType = self.GetInputData(inInfo, 0, 0).GetClassName()
        self.FillOutputPortInformation(0, outInfo.GetInformationObject(0))
        return 1

    def RequestData(self, request, inInfoVec, outInfoVec):
        pdi = self.GetInputData(inInfoVec, 0, 0)
        pdo = self.GetOutputData(outInfoVec, 0)
        # Find cell centers
        filt = vtk.vtkCellCenters()
        filt.SetInputDataObject(pdi)
        filt.Update()
        # I use the dataset adapter/numpy interface because its easy
        centers = dsa.WrapDataObject(filt.GetOutput()).Points
        centers = nps.numpy_to_vtk(centers)
        centers.SetName('Cell Centers')
        # Copy input data and add cell centers as tuple array
        pdo.DeepCopy(pdi)
        pdo.GetCellData().AddArray(centers)
        return 1

@banesullivan this should work in the latest releases as well? 5.9+?

It may be useful to add an additional step 3a with a Pass Arrays filter that excludes all data arrays except the newly created Centers. This will avoid duplication of data in the output from Append Attributes filter.

I ended up revisiting this topic while answering a different question. I found my original solution is behaving a little wonky. @banesullivan’s plugin script works great, but fails on multiblock data sets. I found a slightly simpler solution.

  1. Add the Calculator filter. Set the Attribute Type to Point Data. Set the Result Array name to Cell Center. Set the expression to coords. Apply.
  2. Add the Point Data to Cell Data filter. Uncheck Process All Arrays. Uncheck all point arrays except Cell Center. Check Pass Point Data. Apply.

The result should be one more cell field with the cell centers. This should work with any data set whether multi-block or single data set. To make this even easier, here is a custom filter that just adds the Cell Center array as a single filter.

AppendCellCenters.cpd (5.2 KB)

To load this, go to ToolsManage Custom Filters.... Then click the Import button to load this file.

1 Like

I think there is a much easier solution to that problem now: use the “Append Location Attributes” filter since it gives access to the cell centers directly and avoid all weird solution.

I used to be affected by some bug however: https://gitlab.kitware.com/paraview/paraview/-/issues/20890

2 Likes

Awesome. I missed that filter. That is much better.

1 Like