Skip to content

Add time-dependent function input for boundary conditions#223

Open
Copilot wants to merge 14 commits intomasterfrom
copilot/cleanup-draft-pr-186
Open

Add time-dependent function input for boundary conditions#223
Copilot wants to merge 14 commits intomasterfrom
copilot/cleanup-draft-pr-186

Conversation

Copy link
Copy Markdown

Copilot AI commented Apr 13, 2026

Summary

Adds support for specifying boundary conditions using arbitrary time-dependent mathematical expressions (functions of t), as an alternative to the existing tabular time-value arrays. This allows users to write closed-form formulas like 2*pi*cos(2*pi*t) directly in the JSON input file instead of supplying discrete t and Q/P arrays.

Feature: fn field for flow and pressure boundary conditions

FlowReferenceBC and PressureReferenceBC now accept an optional fn field containing a mathematical expression string. When fn is provided, the solver evaluates the expression at each time step to obtain the boundary condition value, bypassing the t/Q or t/P arrays (which become optional when fn is present).

Example input:

{
  "bc_type": "FLOW",
  "bc_values": {
    "fn": "2.0 * (4*ATAN(1.)) * COS(2.0 * (4*ATAN(1.)) * t)"
  }
}

Expression evaluation is powered by the exprtk library (vendored at src/ThirdParty/exprtk.hpp, version 20250101). The library supports standard math operators, functions (sin, cos, exp, log, …), and built-in constants. Any compilation errors in the expression string are reported at model load time with detailed diagnostics before throwing.

Implementation details

  • Parameter (src/model/Parameter.h/.cpp): Added a new constructor and update() overload that accept an expression string. Expression state is held in a PIMPL struct (ExprtkImpl) so that exprtk types stay out of the header, keeping compile times manageable. Parameter::get(double time) evaluates the compiled expression when is_function == true. Explicit destructor, move constructor, and move assignment are defined in the .cpp to support the unique_ptr<ExprtkImpl> member.
  • InputParameter (src/model/Parameter.h): Added an is_function flag so that the parameter-dispatch logic in SimulationParameters.cpp knows to read a string rather than a numeric array.
  • Model (src/model/Model.h/.cpp): Added add_parameter(const std::string expression_string) overload. Also added a fallback that sets cardiac_cycle_period = 1.0 when no cardiac cycle period can be inferred (needed for models that use only function-based BCs with no periodic arrays).
  • SimulationParameters.cpp: Extended generate_block() to handle is_function parameters by reading a string field and calling the new Model::add_parameter overload. The t and value arrays are now treated as optional when a function is also declared.
  • FlowReferenceBC / PressureReferenceBC: The t and Q/P parameters are now marked optional (is_optional = true); a new optional fn parameter with is_function = true is added to each block's parameter list.
  • exprtk.hpp: Vendored at src/ThirdParty/exprtk.hpp. Included only in Parameter.cpp (never in headers) and wrapped in #pragma diagnostic push/pop to suppress -Wshadow warnings from the third-party code. MSVC requires /bigobj for Parameter.cpp due to exprtk's template expansion, added via set_source_files_properties in src/model/CMakeLists.txt.

Tests

  • tests/cases/timeDep_Flow.json and timeDep_Pressure.json: Two new minimal test models (RC vessel, one inlet and one outlet) that drive the boundary condition with fn = "2*pi*cos(2*pi*t)".
  • tests/test_io.py::test_time_dependent_block: Verifies that the computed flow and pressure at the inlet match the analytical expression to within 0.3% relative tolerance after the initial transient settles.

Adds support for time-dependent boundary conditions specified as
mathematical function expressions (e.g. "2.0 * pi * COS(2.0 * pi * t)")
using the exprtk header-only library. This enables FLOW and PRESSURE
boundary conditions to accept an "fn" parameter as an alternative to
providing Q/P and t arrays.

Changes:
- Add src/ThirdParty/exprtk.hpp expression parsing library
- Extend Parameter class with function expression support
- Add Model::add_parameter(string) for function-based parameters
- Update SimulationParameters to parse "fn" string parameters
- Make Q/P and t arrays optional in Flow/Pressure BCs when fn is used
- Add test cases and reference results for time-dependent BCs
- Add directed graph results for new test cases

Agent-Logs-Url: https://github.com/SimVascular/svZeroDSolver/sessions/bf516764-19f7-45f0-b5af-9a031d3e9fc7

Co-authored-by: ncdorn <126125269+ncdorn@users.noreply.github.com>
@ncdorn
Copy link
Copy Markdown
Contributor

ncdorn commented Apr 13, 2026

@mrp089 figured I would have copilot take a shot at cleaning this up as it has been sitting as a draft PR for a while. let me know what you think.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 13, 2026

Codecov Report

❌ Patch coverage is 72.36842% with 21 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.67%. Comparing base (c7b0ca0) to head (6a5b59c).

Files with missing lines Patch % Lines
src/model/Parameter.cpp 63.88% 13 Missing ⚠️
src/solve/SimulationParameters.cpp 66.66% 8 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #223      +/-   ##
==========================================
+ Coverage   78.63%   78.67%   +0.03%     
==========================================
  Files          70       70              
  Lines        2790     2851      +61     
  Branches      318      330      +12     
==========================================
+ Hits         2194     2243      +49     
- Misses        596      608      +12     

☔ 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Two issues were causing CI failures:

1. BUILD FAILURE (macOS/Windows): Parameter.h included exprtk.hpp directly,
   which caused -Wshadow warnings-as-errors for every compilation unit that
   included Parameter.h (via Model.h). Fixed by using the PIMPL pattern:
   - Moved #include "../ThirdParty/exprtk.hpp" from Parameter.h to Parameter.cpp
   - Wrapped the include with #pragma diagnostic push/pop to suppress -Wshadow
   - Added ExprtkImpl forward declaration and std::unique_ptr<ExprtkImpl> in
     Parameter class (private section)
   - Declared ~Parameter(), Parameter(Parameter&&), operator=(Parameter&&)
     in header, defined as = default in Parameter.cpp after ExprtkImpl is complete

2. CODECHECK FAILURE (Prettier): timeDep_Flow.json and timeDep_Pressure.json
   used 4-space indentation but Prettier requires 2-space. Also removed the
   unused reference result files (result_timeDep_Flow.json,
   result_timeDep_Pressure.json) which were not referenced by any test.

Agent-Logs-Url: https://github.com/SimVascular/svZeroDSolver/sessions/6f309553-a450-492b-ac6e-9ae45ea0b244

Co-authored-by: ncdorn <126125269+ncdorn@users.noreply.github.com>
Replace the bundled ThirdParty/exprtk.hpp (20240101) with the latest
upstream release from ArashPartow/exprtk (20250101). The newer version
includes bug fixes including: proper fallthrough annotations, to_str
refactoring, hex_to_bin fix, and other improvements.

The -Wshadow warnings emitted by exprtk.hpp's enum declarations are
already suppressed in Parameter.cpp via #pragma diagnostic push/pop
guards (added in the previous commit), so no additional changes are
needed to handle compilation on macOS/Windows with strict warning flags.

Agent-Logs-Url: https://github.com/SimVascular/svZeroDSolver/sessions/6fd01362-fe19-40aa-ad6c-d31deeb83c57

Co-authored-by: ncdorn <126125269+ncdorn@users.noreply.github.com>
- Add /bigobj flag for Parameter.cpp on MSVC to fix C1128 (too many
  COFF sections from exprtk.hpp template expansion)
- Add doxygen comments to ExprtkImpl members to fix WARN_AS_ERROR
  failures from WARN_NO_PARAMDOC = YES in the Doxyfile
- Add @return doc to Parameter::operator= (also triggered by
  WARN_NO_PARAMDOC)

Agent-Logs-Url: https://github.com/SimVascular/svZeroDSolver/sessions/ccba344d-dc40-4f1f-b274-8b0e1f1b2977

Co-authored-by: ncdorn <126125269+ncdorn@users.noreply.github.com>
Comment thread src/model/Model.cpp
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.

this is useful as it allows future handling of string parameters which previously did not exist

Copy link
Copy Markdown
Contributor

@ncdorn ncdorn left a comment

Choose a reason for hiding this comment

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

this looks good to me. I think the changes are significant but it allows for future implementation of string parameters in blocks.

Comment thread CMakeLists.txt
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.

@copilot this breaks the buid, please revert this change

Comment thread tests/test_io.py
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.

@copilot instead of creating a dict in this code file, just load the appropriate json from the tests/cases directory and make the desired edit to the config key or value. this keeps the code much cleaner and more concise

@ncdorn ncdorn marked this pull request as ready for review April 30, 2026 01:27
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.

2 participants