Skip to content

Improvements to VTU output - #631

Merged
ktbolt merged 16 commits into
SimVascular:mainfrom
michelebucelli:feature/vtu-output-timevalue
Sep 2, 2026
Merged

Improvements to VTU output#631
ktbolt merged 16 commits into
SimVascular:mainfrom
michelebucelli:feature/vtu-output-timevalue

Conversation

@michelebucelli

Copy link
Copy Markdown
Collaborator

Fixes #618.

Current situation

  1. VTU output files do not carry any time information, but only their timestep number (inferred from their file name). Therefore, to properly interpret the data in the VTU file, one needs to manually keep track of the time step size used for that simulation. Additionally, Paraview does not use the timestep indices from filenames, but rescales everything to 0, 1, 2, ..., so that also the output frequency is not immediately accessible in the viewer.
  2. The initial condition is never exported. Since Paraview indexes file series starting at 0, this causes a shift between what the simulation computes and what Paraview reports (i.e. the first exported file corresponds to timestep 1, but is shown as 0 in Paraview, and so on).
  3. Only the first exported frame contains the DOMAIN_ID field.

Release Notes

Major

  1. Exported VTU files now contain a TimeValue field attribute containing the time, which viewers such as ParaView use to properly show the physical time in the UI.
  2. If Start_saving_after_time_step == 0, then the initial condition is exported to result_000.vtu. This improves the alignment between timestep indices in the simulation and viewers (on top of allowing to view the initial solution). This can be disabled by setting Start_saving_after_time_step to anything strictly greater than 0.
  3. A new parameter General_simulation_parameters/Save_domain_ID_in_every_file toggles exporting the Domain_ID field to every timestep, instead of just the first. It is disabled by default (meaning that the default is the same as the current state). If enabled, it allows e.g. thresholding the simulation results based on subdomains.

Minor

  1. Increment_in_saving_VTK_files and Increment_in_saving_restart_files defaulted to the invalid value 0, and there was no check that they are >= 1. I changed the default value to 1, and introduced those assertions.
  2. Removed the unused variable ComMod::sepOutput.

Documentation

Newly added or modified variables and functions have been given Doxygen documentation.

Testing

Automatic tests all pass after the changes.

Code of Conduct & Contributing Guidelines

@michelebucelli michelebucelli self-assigned this Aug 29, 2026

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Comment thread Code/Source/solver/VtkData.h

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves VTK/VTU output usability and correctness when visualizing solver results (e.g., in ParaView) by exporting physical time metadata, aligning timestep indexing with viewers by optionally exporting the initial condition, and providing a switch to persist Domain_ID across all saved frames.

Changes:

  • Add VTK TimeValue field-data output for VTU/VTP writers and set it on VTU outputs (and URIS outputs) to expose physical time in viewers.
  • Export the initial condition as *_000.vtu when Start_saving_after_time_step == 0 (non-restart path), and ensure CEP ionic-model initial membrane potential is copied into the initial solution state.
  • Add Save_domain_ID_in_every_file parameter (default off) and thread it through ComMod/MPI distribution to optionally export Domain_ID every timestep; also validate VTK/restart save increments are >= 1 and fix defaults.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated no comments.

Show a summary per file
File Description
Code/Source/solver/VtkData.h Adds set_time_value() API to VTK writer abstraction.
Code/Source/solver/VtkData.cpp Implements writing TimeValue field data for VTP/VTU outputs.
Code/Source/solver/vtk_xml.cpp Sets TimeValue on VTU output (non-averaged) and extends Domain_ID emission conditions.
Code/Source/solver/uris.cpp Sets TimeValue on URIS VTU outputs.
Code/Source/solver/Simulation.cpp Wires new Save_domain_ID_in_every_file parameter into ComMod.
Code/Source/solver/Parameters.h Adds save_domain_id_in_every_file to general simulation parameters.
Code/Source/solver/Parameters.cpp Sets valid default save increments (1) and enforces >= 1; registers new domain ID toggle parameter.
Code/Source/solver/main.cpp Writes initial-condition VTU before entering the time loop when configured.
Code/Source/solver/initialize.cpp Updates CEP initialization call to provide solution state for initialization consistency.
Code/Source/solver/distribute.cpp Broadcasts alwaysSaveDomainID across MPI ranks.
Code/Source/solver/ComMod.h Adds alwaysSaveDomainID flag; removes unused sepOutput.
Code/Source/solver/ComMod.cpp Initializes new alwaysSaveDomainID member; removes sepOutput init.
Code/Source/solver/cep_ion.h Updates cep_init() signature and documents behavior.
Code/Source/solver/cep_ion.cpp Copies initialized action potential into the initial solution velocity so initial exports reflect ionic model state.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@codecov

codecov Bot commented Aug 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.14967% with 133 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.11%. Comparing base (effd85e) to head (7d67876).

Files with missing lines Patch % Lines
Code/Source/solver/VtkData.cpp 68.03% 132 Missing ⚠️
Code/Source/solver/vtk_xml.cpp 83.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #631      +/-   ##
==========================================
+ Coverage   72.86%   73.11%   +0.25%     
==========================================
  Files         258      259       +1     
  Lines       39486    39445      -41     
  Branches     6724     6672      -52     
==========================================
+ Hits        28771    28841      +70     
+ Misses      10472    10361     -111     
  Partials      243      243              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mrp089 mrp089 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, @michelebucelli! Looks good. Only idea I would have is add TimeValue to some of the integration tests as a check.

@michelebucelli

Copy link
Copy Markdown
Collaborator Author

@mrp089 That's a good idea! I have updated the integration tests (in this commit) so that they all check the computed TimeValue against an expected one. The expected one is not read from the reference solution, but rather determined based on time step size and number of timesteps from the simulation.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The VtkData refactor introduces concrete correctness issues in VTP writing (cell insertion/array selection and tuple-count validation) that can crash or break existing output paths.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (2)

Code/Source/solver/VtkData.cpp:635

  • VtkVtpData::insert_cell() always inserts into vtkPolyData::Polys and never initializes the underlying vtkCellArray. This can crash (GetPolys() may be null) and also produces incorrect output for 1D faces where cell_type() returns VTK_LINE (those should be stored in Lines, not Polys).
void VtkVtpData::insert_cell(int vtk_cell_type,
                             vtkSmartPointer<vtkIdList> elem_nodes) {
  // A vtkPolyData derives the type of a polygon from its number of points, so
  // vtk_cell_type is not needed here.
  vtk_polydata->GetPolys()->InsertNextCell(elem_nodes);
}

Code/Source/solver/VtkData.cpp:63

  • get_connectivity() allocates the output array using num_points_per_elem_ (from the first cell), but then iterates up to each cell's actual number of points without validation. If a file contains mixed cell types (or corrupt data), this will write past the allocated row count. Validate that all cells have the expected number of points (and use a smart pointer to avoid leaking vtkGenericCell).
Array<int> VtkData::get_connectivity() const {
  Array<int> connectivity(num_points_per_elem_, num_elems_);

  auto cell = vtkGenericCell::New();
  for (int i = 0; i < num_elems_; i++) {
    vtk_data->GetCell(i, cell);

    const int num_cell_pts = cell->GetNumberOfPoints();

    for (int j = 0; j < num_cell_pts; ++j) {
      connectivity(j, i) = cell->PointIds->GetId(j);
    }
  • Files reviewed: 18/18 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread Code/Source/solver/VtkData.cpp
Comment thread Code/Source/solver/VtkData.cpp
Comment thread tests/conftest.py Outdated

@ktbolt ktbolt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good !

@ktbolt
ktbolt merged commit 5e5a450 into SimVascular:main Sep 2, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improvements to VTU output

4 participants