Skip to content

Encapsulate Newton iteration in Integrator class (#442)#450

Merged
mrp089 merged 54 commits intoSimVascular:mainfrom
Eleven7825:feature/issue-442-integrator-class
Apr 13, 2026
Merged

Encapsulate Newton iteration in Integrator class (#442)#450
mrp089 merged 54 commits intoSimVascular:mainfrom
Eleven7825:feature/issue-442-integrator-class

Conversation

@Eleven7825
Copy link
Copy Markdown
Collaborator

@Eleven7825 Eleven7825 commented Oct 13, 2025

Current situation

This PR addresses #442 - Encapsulate the Newton iteration in main.cpp.

As discussed in the issue, this is the first step toward implementing a partitioned Fluid-Structure
Interaction (FSI) by creating an Integrator class to handle the Newton iteration loop. This
refactoring prepares the codebase for future work where separate integrators will be used for fluid
and structure domains.

Release Notes

  • Refactoring: Encapsulated Newton iteration logic into a new Integrator class
  • Architecture: New Integrator class manages solution variables (Ag, Yg, Dg) and handles
    complete Newton iteration workflow
  • Backward Compatibility: No changes to physics or numerics - pure refactoring with identical
    behavior
  • Build System: Added integrator.h and integrator.cpp to CMakeLists.txt

Documentation

  • Added comprehensive class documentation in integrator.h header file
  • Documented all public and private methods with parameter descriptions
  • Added inline comments explaining the Newton iteration workflow
  • Maintained existing code comments from original main.cpp implementation
  • Updated file headers with proper copyright notices

Testing

  • Build: Compiles successfully without errors or warnings
  • Manual Testing: Validated with fluid/pipe_RCR_3d test case
    • 2 timesteps completed successfully
    • Newton iterations converge correctly (residuals: ~10^-13)
    • Output matches expected convergence behavior
  • Integration: All existing functionality preserved

Code Coverage: The new Integrator class executes the same code paths as the original
implementation, maintaining existing test coverage. The refactoring does not introduce new physics
or algorithms requiring additional test cases.

Code of Conduct & Contributing Guidelines

- Add CMake-generated files (CMakeCache.txt, CMakeFiles/, Makefile, etc.)
- Add build directories (*-build/, *-prefix/)
- Add compiled outputs (Code/bin/, Code/lib/)
- Add generated headers
- Add vim swap files (*.swp, *.swo, *~)

Related to SimVascular#442
- Create integrator.h and integrator.cpp with Integrator class
- Encapsulates solution variables (Ag, Yg, Dg)
- Handles Newton iteration loop
- Manages linear system assembly and solve
- Applies boundary conditions
- Update CMakeLists.txt to include new source files

This is the first step toward implementing partitioned FSI as described in SimVascular#442
- Replace Newton iteration loop with Integrator::step() call
- Remove local Ag, Yg, Dg arrays (now managed by Integrator)
- Simplify iterate_solution() function
- Add integrator.h include

Addresses SimVascular#442: Encapsulate Newton iteration in main.cpp
The iEqOld variable is needed for output::output_result() calls
after the Newton iteration completes. This variable tracks which
equation was solved in the last iteration.
@codecov
Copy link
Copy Markdown

codecov Bot commented Oct 13, 2025

Codecov Report

❌ Patch coverage is 82.35294% with 120 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.02%. Comparing base (6801130) to head (21ade6b).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
Code/Source/solver/ris.cpp 26.31% 28 Missing ⚠️
Code/Source/solver/initialize.cpp 61.66% 23 Missing ⚠️
Code/Source/solver/post.cpp 52.94% 16 Missing ⚠️
Code/Source/solver/read_msh.cpp 0.00% 13 Missing ⚠️
Code/Source/solver/Integrator.cpp 94.73% 11 Missing ⚠️
Code/Source/solver/set_bc.cpp 91.30% 8 Missing ⚠️
Code/Source/solver/main.cpp 81.25% 6 Missing ⚠️
Code/Source/solver/txt.cpp 71.42% 6 Missing ⚠️
Code/Source/solver/output.cpp 44.44% 5 Missing ⚠️
Code/Source/solver/Simulation.cpp 83.33% 1 Missing ⚠️
... and 3 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #450      +/-   ##
==========================================
+ Coverage   67.89%   68.02%   +0.12%     
==========================================
  Files         168      170       +2     
  Lines       32898    33093     +195     
  Branches     5782     5780       -2     
==========================================
+ Hits        22336    22510     +174     
- Misses      10425    10446      +21     
  Partials      137      137              

☔ View full report in Codecov by Sentry.
📢 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.

Copy link
Copy Markdown
Member

@mrp089 mrp089 left a comment

Choose a reason for hiding this comment

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

Thanks for taking a crack at this, @Eleven7825! I've added some comments.

Comment thread .gitignore
Comment thread Code/Source/solver/Integrator.cpp
Comment thread Code/Source/solver/Integrator.cpp Outdated
Comment thread Code/Source/solver/integrator.cpp Outdated
Comment thread Code/Source/solver/Integrator.cpp
Comment thread Code/Source/solver/Integrator.cpp Outdated
Comment thread Code/Source/solver/main.cpp Outdated
Comment thread Code/Source/solver/integrator.cpp Outdated
@ktbolt
Copy link
Copy Markdown
Collaborator

ktbolt commented Oct 15, 2025

@Eleven7825 This is a big change and needs to be discussed with the solver team.

@mrp089
Copy link
Copy Markdown
Member

mrp089 commented Oct 15, 2025

Sounds good! Who do we talk to and when?

@Eleven7825
Copy link
Copy Markdown
Collaborator Author

Maybe we could bring this up this Friday during the refactory meeting?

@ktbolt
Copy link
Copy Markdown
Collaborator

ktbolt commented Oct 15, 2025

@mrp089 The initial refactoring effort will be the design and implementation of some sort of solver class to encapsulate solver data and support G&R. We can start this discussion in the first svMultiPhysics c++ OO refactor planning meeting.

@ktbolt ktbolt self-requested a review October 18, 2025 02:02
Comment thread Code/Source/solver/CMakeLists.txt Outdated
@mrp089
Copy link
Copy Markdown
Member

mrp089 commented Oct 20, 2025

@dcodoni suggested removing com_mod from all function calls in Integrator (which will require changes in other functions/classes, too). This will require following the function calls with that have com_mod as an argument all the way down and figuring out which parts of com_mod are actually needed. It might be necessary to create a few structs in Integrator that encapsulate a few items to avoid having functions with a ton of arguments.

- Rename integrator.h to Integrator.h
- Rename integrator.cpp to Integrator.cpp
- Update all #include statements in main.cpp and Integrator.cpp
- Update CMakeLists.txt reference

Addresses PR SimVascular#450 review feedback on file naming convention.
- Use JavaDoc-style /** */ comments throughout Integrator.h
- Add @brief, @param, and @return tags following svZeroDSolver conventions
- Document all public methods and private members
- Improve descriptions for solution variables (Ag, Yg, Dg) and helper methods

Addresses PR SimVascular#450 review feedback on Doxygen documentation format.
- Add istr_ as private member variable in Integrator class
- Update step() method to set istr_ instead of using local variable
- Replace all istr references with istr_ throughout the code
- Simplify debug write statements in apply_boundary_conditions()

This change enables individual helper functions to access istr_ for
their own debug outputs, preparing for the next step of moving write
statements into individual functions.

Addresses PR SimVascular#450 review feedback on variable management.
- Move all .write() debug statements from step() to their respective helper functions
- initiator_step() now handles its own debug output (Ag, Yg, Dg, Yn)
- allocate_linear_system() now handles Val output
- set_body_forces() now handles Val output
- assemble_equations() now handles R and Val output
- apply_boundary_conditions() now handles Val, R, Yg, Dg output
- solve_linear_system() now handles Val and R output
- corrector_and_check_convergence() now handles Yn output

This makes step() cleaner and more focused on orchestration, while
each helper function manages its own debug logging. All functions
now use the istr_ class member variable for consistent debug naming.

Addresses PR SimVascular#450 review feedback on code organization.
…oop'

- Rename inner_count_ to newton_count_ throughout Integrator class
- Update comments to use 'Newton iteration' instead of 'inner loop'
- Update debug messages to show 'Newton Iteration' instead of 'Inner Loop'

This makes the terminology more precise and consistent with standard
computational mechanics nomenclature, clarifying that we're referring
to the Newton iteration within each time step (as opposed to the outer
time loop).

Addresses PR SimVascular#450 review feedback on terminology consistency.
@Eleven7825 Eleven7825 marked this pull request as ready for review October 23, 2025 18:58
- Move debug print statements from step() into individual helper functions
- Each function now handles its own debug output:
  * initiator_step()
  * allocate_linear_system()
  * set_body_forces()
  * assemble_equations()
  * apply_boundary_conditions()
  * update_residual_arrays()
  * solve_linear_system()
  * corrector_and_check_convergence()
- Makes step() method cleaner and more focused on orchestration
- Each helper function is now self-contained with its own debug logging

This addresses PR SimVascular#450 review feedback on code organization.
@Eleven7825
Copy link
Copy Markdown
Collaborator Author

Hi Martin, I have moved the debug messages into respective functions, and the code is ready for review. As for your last comment, I think we should address it in another issue and PR.

Moved all pic namespace functions (picp, pici, picc, pic_eth) into the
Integrator class as member functions:
- picp -> predictor() (public method, called from main.cpp)
- pici -> pici() (private method)
- picc -> picc() (private method)
- pic_eth -> pic_eth() (private method)

Updated all call sites to use the new member functions.
Removed pic.h and pic.cpp files and updated CMakeLists.txt.

Related to GitHub issue SimVascular#459.
Move time integration variables An (acceleration), Dn (displacement), and
Yn (velocity) from the global ComMod structure into the Integrator class.
These variables are now passed as function parameters throughout the
codebase instead of accessing them through ComMod.

Changes include:
- Add An_, Dn_, Yn_ members to Integrator with public getters
- Initialize from Ao, Do, Yo in Integrator::initialize_arrays()
- Update 19 files to pass these variables as Array<double>& parameters
- Remove An, Dn, Yn declarations from ComMod.h
This commit completes the extraction of time-level variables from the global
ComMod structure to the Integrator class. Ao, Do, Yo (old acceleration,
displacement, velocity at time level n) join An, Dn, Yn as Integrator members.

Key changes:
- ComMod.h: Removed Ao, Do, Yo member variables
- Integrator.h/cpp: Added Ao_, Do_, Yo_ members with move constructor and getters
- Simulation.h/cpp: Added initialize_integrator() to transfer ownership
- initialize.cpp: Made Ao, Do, Yo local variables, moved to Integrator
- Updated 25+ files with function signatures to pass Ao/Do/Yo parameters
- Fixed default parameter placement (declarations only, not definitions)

All time integration state is now encapsulated in the Integrator class,
improving modularity and preparing for future multi-physics enhancements.
Copy link
Copy Markdown
Member

@mrp089 mrp089 left a comment

Choose a reason for hiding this comment

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

Great job, @shiyi! I definitely appreciate the missing lines in ComMod.h!

I had mostly minor comments. Two major things I noticed:

  1. Does the remeshing still work as intended? I'm not sure if this is covered by a test.
  2. It seems in initialize.cpp there are a few things that are not adapted yet to the n's, potentially set_bc::set_bc_dir and txt_ns::txt.
    We should look at the coverage report carefully for this one and make sure all the changed lines are covered by a test.

Comment thread Code/Source/solver/nn.cpp Outdated
Comment thread Code/Source/solver/ComMod.h Outdated
Comment thread Code/Source/solver/Integrator.cpp Outdated
Comment thread Code/Source/solver/Integrator.cpp Outdated
Comment thread Code/Source/solver/Integrator.cpp Outdated
Comment thread Code/Source/solver/ris.cpp Outdated
Comment thread Code/Source/solver/ris.cpp Outdated
Comment thread Code/Source/solver/ris.cpp Outdated
Comment thread Code/Source/solver/uris.cpp Outdated
Comment thread Code/Source/solver/uris.cpp Outdated
…nd integration functions

Following the extraction of Ao/Do/Yo from ComMod to Integrator class, this commit
completes the parameter threading work by updating all functions that perform face
integration or boundary condition operations to accept and pass Do/Dn parameters.

Changes include:

Boundary Condition Functions:
- bc_ini(): Add Do parameter, update 3 integ() calls for parabolic profiles and flux normalization
- set_bc_cmm(), set_bc_cmm_l(): Add Do parameter for CMM boundary conditions
- set_bc_neu(), set_bc_neu_l(): Add Do parameter for Neumann boundary conditions
- set_bc_dir_w(), set_bc_dir_wl(): Add Do parameter for Dirichlet wall conditions
- set_bc_trac_l(): Add Do parameter for traction boundary conditions
- set_bc_rbnl(): Add Do parameter for Robin boundary conditions
- set_bc_cpl(): Update to pass Do to bc_ini() for coupled BC area recalculation

FSI and Mesh Functions:
- fsi_ls_upd(): Add both Dn and Do parameters for level set updates
- fsi_ls_ini(): Add Do parameter for FSI initialization
- b_assem_neu_bc(), b_neu_folw_p(): Add Do parameter for Neumann BC assembly

RIS (Reduced Immersed Surface) Functions:
- ris_meanq(): Add Do parameter, update 2 integ() calls for pressure/flow computation
- ris0d_status(): Add Do parameter, update 3 integ() calls for 0D coupling
- ris_resbc(), setbc_ris(), ris0d_bc(): Add Do parameter for RIS boundary conditions

CMM (Coupled Momentum Method):
- cmm_b(): Add Do parameter, update nn::gnnb() call with full parameters

Integration Functions:
- All face-based integ() calls updated to pass Do parameter via pointer
- Updated calls to use proper signatures with pFlag, cfg, Dn, and Do parameters
- Enhanced error reporting in nn::gnnb() to include face name, mesh name, and element

Main Integration Loop:
- Integrator::iterate(): Updated all set_bc calls to pass Do_ parameter
- main.cpp: Updated ris_meanq() and ris0d_status() calls to pass Do
This commit fixes systematic issues with displacement parameter passing throughout the solver:

1. Corrected parameter confusion in set_bc.cpp where An/Ao were incorrectly used instead of Dn/Do
2. Replaced nullptr with proper Dn/Do parameters in 14 integ() calls across ris.cpp, txt.cpp, baf_ini.cpp, and set_bc.cpp
3. Fixed critical bug in txt.cpp:520 where missing pFlag parameter caused &Do to be misinterpreted as boolean
4. Enhanced error messages in all_fun.cpp to identify exact failure locations

These fixes resolve 12 test failures in moving mesh simulations (genBC and RIS tests).
@mrp089 mrp089 dismissed their stale review April 1, 2026 22:19

I participated in the refactoring, so my review should be replaced by someone else's

@mrp089 mrp089 requested review from aabrown100-git and ktbolt April 1, 2026 22:20
@mrp089
Copy link
Copy Markdown
Member

mrp089 commented Apr 1, 2026

This is ready from our side. @ktbolt, @aabrown100-git, please give it a review. Thank you!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors the solver time-stepping workflow to encapsulate the Newton iteration loop into a new Integrator class and to centralize solution variable handling via SolutionStates, as groundwork for future partitioned FSI (separate integrators per domain).

Changes:

  • Introduced SolutionStates to carry old/current solution arrays and threaded it through BC, post-processing, IO, and mesh utilities.
  • Added Integrator class to own the Newton loop and generalized-alpha working arrays (Ag/Yg/Dg), and updated main.cpp to delegate predictor + Newton step.
  • Removed Ao/An/Yo/Yn/Do/Dn from ComMod and updated build + related call sites accordingly.

Reviewed changes

Copilot reviewed 43 out of 44 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
Code/Source/solver/vtk_xml.h Updates VTU writer API to accept SolutionStates.
Code/Source/solver/vtk_xml.cpp Uses SolutionStates for VTU output and routes post-processing calls accordingly.
Code/Source/solver/Vector.h Adds <cstring> include (likely for mem ops used in Vector implementation).
Code/Source/solver/uris.h Updates URIS APIs to accept SolutionStates.
Code/Source/solver/uris.cpp Switches URIS computations to read state from SolutionStates and passes it into integrations.
Code/Source/solver/txt.h Updates TXT output APIs to accept SolutionStates.
Code/Source/solver/txt.cpp Switches TXT output and integral writers to use SolutionStates.
Code/Source/solver/SolutionStates.h Adds new Solution / SolutionStates containers for old/current solution arrays.
Code/Source/solver/Simulation.h Adds integrator ownership/accessors and initialize_integrator().
Code/Source/solver/Simulation.cpp Implements integrator initialization and guarded accessor.
Code/Source/solver/set_bc.h Threads SolutionStates through BC APIs; changes set_bc_dir signature.
Code/Source/solver/set_bc.cpp Updates BC implementations to use SolutionStates and updated integration/normal APIs.
Code/Source/solver/ris.h Updates RIS APIs to accept SolutionStates.
Code/Source/solver/ris.cpp Switches RIS logic to use SolutionStates (including updater/status paths).
Code/Source/solver/remesh.cpp Removes clearing of ComMod solution arrays now managed elsewhere.
Code/Source/solver/read_msh.h Threads SolutionStates into mesh quality checks (mvMsh displacement access).
Code/Source/solver/read_msh.cpp Uses SolutionStates displacement when computing mesh properties.
Code/Source/solver/post.h Updates post-processing APIs to accept SolutionStates.
Code/Source/solver/post.cpp Switches post-processing to read from SolutionStates; updates bin2vtk path to use temp states.
Code/Source/solver/pic.h Removes legacy PIC header (predictor/initiator/corrector moved into Integrator).
Code/Source/solver/output.h Threads SolutionStates into restart/results writing.
Code/Source/solver/output.cpp Uses SolutionStates arrays for restart/results output.
Code/Source/solver/nn.h Updates gnnb() signature to accept SolutionStates for configuration-based geometry.
Code/Source/solver/nn.cpp Uses SolutionStates displacement in gnnb() (mvMsh and timestep configs).
Code/Source/solver/mesh.h Threads SolutionStates into mesh construction.
Code/Source/solver/mesh.cpp Uses SolutionStates displacement instead of ComMod.Do.
Code/Source/solver/main.cpp Replaces inline Newton loop with Integrator calls; routes outputs/BC/RIS/URIS via SolutionStates.
Code/Source/solver/Integrator.h Adds new Integrator interface encapsulating Newton iteration + generalized-alpha state.
Code/Source/solver/Integrator.cpp Implements predictor/initiator/corrector and Newton loop formerly in main.cpp/PIC routines.
Code/Source/solver/initialize.h Updates init APIs to fill SolutionStates rather than ComMod solution arrays.
Code/Source/solver/initialize.cpp Builds initial SolutionStates, applies BCs, initializes integrator, updates restart/init paths.
Code/Source/solver/eq_assem.h Threads SolutionStates into assembly helpers and global assembly.
Code/Source/solver/eq_assem.cpp Passes SolutionStates into mesh construction and BC-related normal computations.
Code/Source/solver/ComMod.h Removes Ao/An/Yo/Yn/Do/Dn members from ComMod.
Code/Source/solver/cmm.h Threads SolutionStates into CMM boundary routine signature.
Code/Source/solver/cmm.cpp Passes SolutionStates into nn::gnnb() for consistent geometry configuration.
Code/Source/solver/CMakeLists.txt Adds Integrator.* and removes pic.* from build.
Code/Source/solver/cep_ion.h Updates CEP integration API to accept SolutionStates.
Code/Source/solver/cep_ion.cpp Uses SolutionStates (and updated post API) for CEP state integration.
Code/Source/solver/baf_ini.h Threads SolutionStates into face/bc initialization and FSILS init APIs.
Code/Source/solver/baf_ini.cpp Updates BAF init to pass SolutionStates into face/bc init and coupling init calls.
Code/Source/solver/all_fun.h Threads SolutionStates through integration overloads (mvMsh displacement access).
Code/Source/solver/all_fun.cpp Uses SolutionStates displacement in volume/face integrals and normal computations.
.gitignore Expands ignored build artifacts and generated outputs/headers.
Comments suppressed due to low confidence (2)

Code/Source/solver/Integrator.cpp:365

  • res_ is a persistent member but is never reset in update_residual_arrays(). Only entries touched by lsPtr are overwritten, so stale values from previous equations/iterations can leak into ls_solve() for indices not set this call. Clear res_ (or at least the active indices) at the start of this function, alongside incL_ = 0.
    Code/Source/solver/Integrator.cpp:464
  • Inside the #ifdef debug_picp block, coef is logged before it is declared/initialized (dmsg << "coef: " << coef; comes before double coef = ...). If debug_picp is enabled this won’t compile (or may print an indeterminate value if an outer coef exists). Move the debug print after the coef definition or log eq.gam only.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Code/Source/solver/baf_ini.cpp Outdated
Comment thread Code/Source/solver/SolutionStates.h Outdated
Comment thread Code/Source/solver/baf_ini.cpp
Comment thread Code/Source/solver/ComMod.h
Comment thread Code/Source/solver/eq_assem.cpp Outdated
Comment thread Code/Source/solver/eq_assem.cpp
Comment thread Code/Source/solver/initialize.cpp
Comment thread Code/Source/solver/Integrator.cpp
Comment thread Code/Source/solver/main.cpp
Comment thread Code/Source/solver/set_bc.cpp
Comment thread Code/Source/solver/SolutionStates.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@Eleven7825 Eleven7825 requested a review from zasexton April 9, 2026 03:38
Comment thread Code/Source/solver/Integrator.cpp
Comment thread Code/Source/solver/Integrator.h Outdated
Copy link
Copy Markdown
Collaborator Author

@Eleven7825 Eleven7825 left a comment

Choose a reason for hiding this comment

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

Reply to @zasexton and @aabrown100-git review

Comment thread Code/Source/solver/baf_ini.cpp
Comment thread Code/Source/solver/Integrator.cpp
@mrp089 mrp089 requested a review from aabrown100-git April 10, 2026 21:22
Comment thread Code/Source/solver/baf_ini.cpp
Copy link
Copy Markdown
Collaborator

@zasexton zasexton left a comment

Choose a reason for hiding this comment

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

I have completed review of the PR for the integrator encapsulation. I believe it should be fine to pull in. If we believe it is necessary we can add additional issues for cleanup of ownership and dataflow but there is nothing precluding this code. It removes some members from com_mod so it is definitely in the right direction.

Copy link
Copy Markdown
Collaborator

@aabrown100-git aabrown100-git left a comment

Choose a reason for hiding this comment

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

Looks good, I approve!

@zasexton
Copy link
Copy Markdown
Collaborator

@ktbolt we believe this PR is in a sufficient position for now to merge.

@mrp089 mrp089 merged commit 97ef512 into SimVascular:main Apr 13, 2026
8 checks passed
@ktbolt
Copy link
Copy Markdown
Collaborator

ktbolt commented Apr 13, 2026

@zasexton Looks good to me too.

@Eleven7825 Thank you for all of your hard work on this !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

duplicate This issue or pull request already exists

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants