-
Notifications
You must be signed in to change notification settings - Fork 15
Description
Bug description
The decimate_mesh function in the external aerodynamics example pipeline does not apply any effective mesh decimation. Although the function calls PyVista’s decimation methods, the final output in data.surface_polydata remains identical to the input mesh. As a consequence, all downstream surface arrays (surface_mesh_centers, surface_areas, surface_normals, surface_fields) also remain unchanged, and the exported files have exactly the same size before and after decimation.
Affected code:
physicsnemo-curator/examples/external_aerodynamics/external_aero_surface_data_processors.py
Lines 339 to 384 in bd9944d
| def decimate_mesh( | |
| data: ExternalAerodynamicsExtractedDataInMemory, | |
| algo: str = None, | |
| reduction: float = 0.0, | |
| **kwargs, | |
| ) -> ExternalAerodynamicsExtractedDataInMemory: | |
| """Decimate mesh using pyvista.""" | |
| if reduction < 0: | |
| logger.error(f"Reduction must be >= 0: {reduction}") | |
| return data | |
| if not algo or reduction == 0: | |
| return data | |
| mesh = data.surface_polydata | |
| # Need point_data to interpolate target mesh node values. | |
| mesh = mesh.cell_data_to_point_data() | |
| # Decimation algos require tri-mesh. | |
| mesh = mesh.triangulate() | |
| match algo: | |
| case "decimate_pro": | |
| mesh = mesh.decimate_pro(reduction, **kwargs) | |
| case "decimate": | |
| if mesh.n_points > 400_000: | |
| warnings.warn("decimate algo may hang on meshes of size more than 400K") | |
| mesh = mesh.decimate( | |
| reduction, | |
| attribute_error=True, | |
| scalars=True, | |
| vectors=True, | |
| **kwargs, | |
| ) | |
| case _: | |
| logger.error(f"Unsupported decimation algo {algo}") | |
| return data | |
| # Compute cell data. | |
| data.surface_polydata = mesh.point_data_to_cell_data() | |
| # Update metadata | |
| data.metadata.decimation_algo = algo | |
| data.metadata.decimation_reduction = reduction | |
| return data |
Root cause
After decimating the mesh, the function assigns:
data.surface_polydata = mesh.point_data_to_cell_data()but does not recompute any of the dependent surface arrays stored inside ExternalAerodynamicsExtractedDataInMemory. These arrays are still based on the pre-decimation mesh. Because the writer exports these arrays instead of re-deriving them from the modified mesh, the resulting output files remain unchanged.
How to reproduce
- Run any external aerodynamics ETL config with:
preprocessing:
decimation_algo: decimate_pro
decimation_reduction: 0.8- Compare the size of the generated surface .vtp or downstream data.
- The file size and number of cells remain exactly the same before and after decimation.
Suggested fix
After decimation, recompute all surface‑related arrays from the actual decimated mesh, not from the original mesh.
The key missing logic is roughly:
# After mesh decimation
mesh = mesh.point_data_to_cell_data()
data.surface_polydata = mesh
# Recompute derived arrays
data.surface_mesh_centers = mesh.cell_centers().points.astype(np.float32)
data.surface_areas = np.asarray(mesh.compute_cell_sizes().cell_data["Area"], dtype=np.float32)
data.surface_normals = np.asarray(mesh.compute_normals(cell_normals=True).cell_data["Normals"], dtype=np.float32)
# Reconstruct surface_fields based on metadata and available cell_data
...I can open a PR with the fix if desired.