Skip to content

PR 4/7: Pyomo multi-period DAE model#9

Merged
bernalde merged 5 commits into
pr/pyomo-utils-singlestepfrom
pr/pyomo-model
May 30, 2026
Merged

PR 4/7: Pyomo multi-period DAE model#9
bernalde merged 5 commits into
pr/pyomo-utils-singlestepfrom
pr/pyomo-model

Conversation

@bernalde

@bernalde bernalde commented Mar 3, 2026

Copy link
Copy Markdown
Member

Summary

Full trajectory optimization model. Discretizes the drying process into multiple time periods, encoding the physics (vapor pressure, product resistance, energy balance, mass transfer) as Pyomo constraints. Supports both finite-difference and collocation discretization. Log-transform for vapor pressure to avoid numerical issues with exponentials.

PR 4 of 7 in the Pyomo integration series.

Changes

  • lyopronto/pyomo_models/model.py — Full multi-period DAE model
  • tests/test_pyomo_models/test_model_multi_period.py — Multi-period tests (741 lines)
  • tests/test_pyomo_models/test_model_advanced.py — Advanced model tests
  • tests/test_pyomo_models/test_model_validation.py — Validation against scipy
  • tests/test_pyomo_models/test_physics_equations.py — Physics equation tests

Key Physics Encoded as Constraints

Psub = 2.698e10 * exp(-6144.96 / (Tsub + 273.15))     # Vapor pressure (log-transformed)
Rp = R0 + A1 * Lck / (1 + A2 * Lck)                   # Product resistance
dmdt = Ap / Rp * (Psub - Pch)                          # Sublimation rate
Kv * Av * (Tsh - Tbot) = dmdt * dHs                    # Energy balance

PR Chain

# PR Status
0 Sync upstream (#5) Merged
1 CI/CD for Pyomo (#6) Open
2 Pyomo dependencies (#7) Open
3 Utils & single-step (#8) Open
4 Multi-period model (this PR)
5 Optimizer functions Pending
6 Benchmarks Pending
7 Docs & examples Pending

Testing

~2075 lines of new tests covering model construction, discretization, physics constraints, and validation against scipy baseline.

@bernalde bernalde force-pushed the pr/pyomo-utils-singlestep branch from fa26a34 to 65fc2c3 Compare March 3, 2026 00:51
@bernalde bernalde force-pushed the pr/pyomo-utils-singlestep branch 2 times, most recently from b8a82c3 to 53ad6d9 Compare March 3, 2026 01:29
@bernalde bernalde force-pushed the pr/pyomo-utils-singlestep branch from 53ad6d9 to 389c49e Compare March 3, 2026 18:07
@bernalde bernalde force-pushed the pr/pyomo-utils-singlestep branch from 389c49e to 518df8b Compare April 1, 2026 20:56
@bernalde bernalde force-pushed the pr/pyomo-model branch 2 times, most recently from 3c852b8 to 07c52ee Compare April 1, 2026 21:36
@bernalde bernalde force-pushed the pr/pyomo-utils-singlestep branch from 518df8b to c4356ba Compare April 1, 2026 21:36
@bernalde bernalde force-pushed the pr/pyomo-utils-singlestep branch from c4356ba to 15eb233 Compare April 2, 2026 22:19
@bernalde bernalde force-pushed the pr/pyomo-utils-singlestep branch from 15eb233 to 38607c8 Compare May 7, 2026 21:39
@bernalde bernalde force-pushed the pr/pyomo-model branch 2 times, most recently from 4347637 to bbda9c5 Compare May 7, 2026 22:27

@bernalde bernalde left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I found several blocking issues in the core model formulation and in the new test coverage. The main concerns are that the product-temperature constraint is applied to the wrong variable/direction, scaled solves return scaled rather than physical units, warmstart initializes dmdt 10x too high, the cake-length ODE does not match the existing scipy drying-rate update, and one new Pyomo test fails when networkx is not installed.

Comment thread lyopronto/pyomo_models/model.py Outdated
Comment thread lyopronto/pyomo_models/model.py Outdated
Comment thread lyopronto/pyomo_models/model.py Outdated
Comment thread lyopronto/pyomo_models/model.py Outdated
Comment thread tests/test_pyomo_models/test_model_multi_period.py
Comment thread lyopronto/pyomo_models/model.py Outdated
Comment thread lyopronto/pyomo_models/model.py Outdated

@bernalde bernalde left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Review summary:

  1. Blocking issues: the default scaled create_multi_period_model() result does not expose the documented unscaled model attributes and cannot be passed to warmstart_from_scipy_trajectory; dmdt[0] is unconstrained but is returned as part of the solution trajectory.
  2. Nonblocking issues: none.
  3. Questions: none.
  4. Tests run and outcomes: PYTHONPATH=/tmp/LyoPRONTO_pr9 pytest tests/test_pyomo_models -m "pyomo and not slow" -n 0 --tb=short --maxfail=10 passed with 67 passed, 9 skipped, 14 deselected; RUN_SLOW_TESTS=1 PYTHONPATH=/tmp/LyoPRONTO_pr9 pytest tests/test_pyomo_models/test_model_multi_period.py::TestModelOptimization::test_optimization_runs tests/test_pyomo_models/test_model_validation.py::TestOptimizationComparison::test_optimization_improves_over_scipy tests/test_pyomo_models/test_model_validation.py::TestOptimizationComparison::test_optimized_solution_satisfies_constraints -n 0 --tb=short --maxfail=3 passed with 3 passed; ruff check lyopronto/pyomo_models/model.py tests/test_pyomo_models/test_model_advanced.py tests/test_pyomo_models/test_model_multi_period.py tests/test_pyomo_models/test_model_validation.py tests/test_pyomo_models/test_physics_equations.py passed; git diff --check origin/pr/pyomo-utils-singlestep...HEAD passed.
  5. Merge as-is: no. I would not merge this until the blocking issues above are addressed.

Comment thread lyopronto/pyomo_models/model.py Outdated
Comment thread lyopronto/pyomo_models/model.py Outdated

@bernalde bernalde left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Propagating review feedback from the lower Pyomo PRs where the same issue still applies.

Comment thread lyopronto/pyomo_models/model.py
Comment thread tests/test_pyomo_models/test_model_multi_period.py Outdated
bernalde added 4 commits May 8, 2026 00:07
This PR adds the core multi-period Pyomo model:

lyopronto/pyomo_models/model.py (640 lines):
- Multi-period differential-algebraic equation (DAE) formulation
- Orthogonal collocation discretization for time integration
- Physics constraints: vapor pressure, sublimation rate, heat transfer
- Equipment capability constraints
- Product temperature limits
- Variable scaling for numerical stability
- Support for both Tsh and Pch optimization

Key features:
- Uses Pyomo DAE transformations from IDAES
- Implements same physics as scipy-based calculators
- Warmstart from scipy solution for faster convergence
- Configurable time discretization (number of periods)

Tests (4 files):
- test_model_multi_period.py: Multi-period model construction
- test_model_advanced.py: Advanced model features
- test_model_validation.py: Input validation
- test_physics_equations.py: Physics equation verification

This is the core model used by the optimizer functions (PR 5).

@bernalde bernalde left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Review summary:

  1. Blocking issues: final_dryness stops the optimizer at 95% dried while optimize_multi_period() reports t_final as total drying time.
  2. Nonblocking issues: none.
  3. Questions: none.
  4. Tests run and outcomes: targeted non-slow Pyomo suite passed; targeted slow multi-period IPOPT tests passed; CI-style Pyomo marker suite passed; ruff passed; git diff --check passed. The broader non-Pyomo CI command was interrupted after reaching 99% with one xdist worker still running for several minutes and no failures observed before interruption.
  5. Merge as-is: no. I would not merge this until the blocking issues above are addressed.

GitHub rejected REQUEST_CHANGES because the authenticated account owns this PR, so this review is submitted as COMMENT.

Comment thread lyopronto/pyomo_models/model.py Outdated

def final_dryness_rule(m):
"""Ensure drying is complete at final time."""
return m.Lck[1] >= 0.95 * Lpr0 # 95% dried

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Blocking: This terminal constraint lets the optimizer report t_final when the cake is only 95% dry. Since the objective minimizes t_final, the optimum stops at this threshold; with the standard warmstart I get Lck[-1] / Lpr0 = 0.94999999. That underestimates primary drying time compared with the existing calc_knownRp.dry completion event, which targets Lpr0 - L == 0 when the schedule permits. Please either enforce full completion, or add an explicit documented target_dry_fraction parameter that defaults to complete drying, and add a regression that checks the returned final Lck/percent dried reaches that target.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Addressed in fe5fc82. target_dry_fraction now defaults to 1.0, final_dryness enforces that target, and the optimized-solution validation now checks complete drying by default. Added tests for default, custom, and invalid terminal targets.

@bernalde

Copy link
Copy Markdown
Member Author

Commits pushed:

  • fe5fc82 Require complete drying in multi-period model

Main changes made:

  • Added target_dry_fraction to create_multi_period_model() and optimize_multi_period(), defaulting to 1.0 for complete drying.
  • Changed final_dryness to enforce target_dry_fraction * Lpr0 instead of a hardcoded 95% threshold.
  • Added regression coverage for the default complete-drying target, custom target values, invalid target values, and updated optimized-solution validation.

Tests run and results:

  • PYTHONPATH=/tmp/lyopronto_pr9_review MPLCONFIGDIR=/tmp/mplconfig pytest tests/test_pyomo_models/test_model_multi_period.py::TestModelStructure::test_final_dryness_defaults_to_complete_drying tests/test_pyomo_models/test_model_multi_period.py::TestModelStructure::test_final_dryness_target_can_be_configured tests/test_pyomo_models/test_model_multi_period.py::TestModelStructure::test_final_dryness_target_validates_fraction -n 0 --tb=short: 5 passed.
  • RUN_SLOW_TESTS=1 PYTHONPATH=/tmp/lyopronto_pr9_review MPLCONFIGDIR=/tmp/mplconfig pytest tests/test_pyomo_models/test_model_validation.py::TestOptimizationComparison::test_optimized_solution_satisfies_constraints -n 0 --tb=short --maxfail=1: 1 passed.
  • PYTHONPATH=/tmp/lyopronto_pr9_review MPLCONFIGDIR=/tmp/mplconfig pytest tests/test_pyomo_models -m "pyomo and not slow" -n 0 --tb=short --maxfail=10: 82 passed, 1 skipped, 14 deselected, 1 xfailed.
  • RUN_SLOW_TESTS=1 PYTHONPATH=/tmp/lyopronto_pr9_review MPLCONFIGDIR=/tmp/mplconfig pytest tests/test_pyomo_models/test_model_multi_period.py::TestModelOptimization::test_optimization_runs tests/test_pyomo_models/test_model_validation.py::TestOptimizationComparison::test_optimization_improves_over_scipy tests/test_pyomo_models/test_model_validation.py::TestOptimizationComparison::test_optimized_solution_satisfies_constraints -n 0 --tb=short --maxfail=3: 3 passed.
  • python -m ruff check lyopronto/pyomo_models/model.py tests/test_pyomo_models/test_model_multi_period.py tests/test_pyomo_models/test_model_validation.py: passed.
  • git diff --check: passed.

Comments intentionally not addressed:

  • Previously resolved or outdated review threads were left unchanged; the current code already contains their fixes.
  • No top-level discussion comments required separate code changes.

Remaining risks or follow-up items:

  • The broader non-Pyomo CI command was not rerun after this isolated Pyomo change. During review it reached 99% and then one xdist worker remained running for several minutes, so I kept validation focused on the modified Pyomo model and tests.

@bernalde bernalde merged commit 87efe1d into pr/pyomo-utils-singlestep May 30, 2026
2 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.

1 participant