Skip to content

Split openTEPES_OutputResults into new modules#128

Merged
arght merged 10 commits into
masterfrom
refactor/output-results-split
Jun 4, 2026
Merged

Split openTEPES_OutputResults into new modules#128
arght merged 10 commits into
masterfrom
refactor/output-results-split

Conversation

@erikfilias

Copy link
Copy Markdown
Contributor

Reason

The output code was one large file. Grouping it by topic makes it easier to read and maintain, and lines it up with the rest of the layered restructure.

Changes

Splits the ~2800-line openTEPES_OutputResults.py into new modules at the package root — the output-side counterpart of the earlier openTEPES_Input* and openTEPES_ProblemSolving* splits.

New modules: ...Investment, ...Generation, ...Storage, ...SectorCoupling (hydrogen + heat networks), ...Network (electricity network + map), ...Economic (marginal / cost / economic), ...Summary (summary / flexibility / reliability), and ...RawDump (the raw parameter/variable/constraint DuckDB dump). Shared pieces live in ...Common (output-directory helper + the three Altair plot builders) and ...MapCommon (the flow-series and snapshot helpers the three network maps had each copied).

The old openTEPES_OutputResults.py is removed: __init__.py and openTEPES.py import the result functions from the concern modules directly, the same way the Input and ProblemSolving splits are wired. Dispatch order is still controlled by OUTPUT_REGISTRY in openTEPES.py and is unchanged. Cross-module imports use the same try/except ImportError relative-import guard as the other split modules, so "Run Python File" works.

Additional changes not planned

  • Two small cleanups: removed 34 no-op "".join([f"..."]) wrappers (each is just the f-string), and stopped ESSOperationResults writing its inventory-utilisation scaling back into mTEPES.pMaxStorage (computed locally instead).
  • Bug fix: two operating-reserve guards loop over storage units es but checked pIndOperReserve*[nr]nr was a leftover from an earlier loop. They now use es, matching the two sibling guards that were already correct (a third read Gen ... or ... Gen where siblings read Gen ... or ... Con; the second is now Con). Unchanged on 9n; corrected for cases where the leftover unit's reserve flags differ from the storage units'.

  The output-writing code lived in one 2827-line file. This splits it into
  eight files grouped by topic (investment, generation, storage, sector
  coupling, network, economic, summary, and a raw parameter dump), with the
  shared plot helpers in a Common module. The old file becomes a thin facade
  that re-exports every public name, so existing imports keep working.

  Function bodies are unchanged. Run order still comes from OUTPUT_REGISTRY
  in openTEPES.py and is untouched. Verified on case 9n with PYTHONHASHSEED=0:
  all 87 result tables are bit-identical to the previous code; total cost
  164.382043867 MEUR.
  The three network maps each built a flow series and each picked the same
  snapshot period and scenario with identical code. Those two helpers move to a
  new openTEPES_OutputResultsMapCommon module and are called from one place. The
  per-sector map-frame builder stays in each module because its body genuinely
  differs (the electric map scales by 1e3 and adds a voltage-to-width and an
  overload colour step the others do not have).

  Output is unchanged. Verified on case 9n with PYTHONHASHSEED=0: all 87 result
  tables stay bit-identical to the previous code; total cost 164.382043867 MEUR.
  Removes openTEPES_OutputResults.py. The package __init__ now imports each
  openTEPES_OutputResults<Concern> module directly, and openTEPES.py imports the
  result functions from those modules — matching how the Input and
  ProblemSolving splits are already wired, so there is no leftover re-export
  shim.

  Output is unchanged. Verified on case 9n with PYTHONHASHSEED=0: all 87 result
  tables stay bit-identical; total cost 164.382043867 MEUR.
  - Wrap each module's cross-module import in the same try/except ImportError
    guard the Input modules use, so they also resolve when a script is run
    directly (e.g. VS Code) with no parent package.
  - Bump the header date to June 03, 2026 to match the rest of the package.
  - Remove no-op "".join([f"..."]) wrappers (34 of them); each is just the
    f-string and only added a list allocation per element in hot loops.
  - Stop mutating mTEPES.pMaxStorage inside ESSOperationResults; compute the
    inventory-utilization denominator inline instead, so the scaled value no
    longer leaks to later reads of the parameter.

  No behaviour change. Verified on case 9n with PYTHONHASHSEED=0: all 87 result
  tables stay bit-identical; total cost 164.382043867 MEUR.
  Two operating-reserve guards in the marginal and economic results looped over
  storage units (es) but checked pIndOperReserve*[nr] — nr only existed as a
  leftover from an earlier for-loop. Use es, matching the correct sibling
  guards. On case 9n the result is unchanged; on cases where the leftover unit's
  reserve flags differ from the storage units' this corrects which
  operating-reserve-revenue tables are written.
@erikfilias erikfilias requested a review from arght June 3, 2026 19:17
@erikfilias erikfilias self-assigned this Jun 3, 2026
@erikfilias erikfilias added the enhancement New feature or request label Jun 3, 2026
  Per Andres' review on PR #128: openTEPES_OutputResultsSectorCoupling.py
  bundled two unrelated carriers. Move each writer into its own module --
  openTEPES_OutputResultsHydrogen.py (NetworkH2OperationResults) and
  openTEPES_OutputResultsHeat.py (NetworkHeatOperationResults). Pure move:
  both function bodies are unchanged. Import sites in openTEPES.py and
  __init__.py and the CHANGELOG are updated; OUTPUT_REGISTRY dispatch is
  unchanged.

  Verified bit-identical output (PYTHONHASHSEED=0) on 9n, 9n_heat, and a
  new 9n_H2 case, before vs after the split.
  Parametrise the single-stage solve test with the new 9n_H2 case so CI
  exercises the hydrogen result writer on the minimal 9-node system, the
  counterpart of 9n_heat. Expected cost 259.547153 under the 7-day HiGHS
  fixture; confirmed deterministic across repeated solves.
  Add a CHANGELOG entry for the 9n_H2 case and its CI coverage. Redraw the
  Layer 6 (Results) block of the architecture diagram to show the real
  implemented concern modules (including the new Hydrogen and Heat modules)
  in green, and re-render the PNG.
@arght arght merged commit 8fbb3dc into master Jun 4, 2026
13 checks passed
@erikfilias erikfilias deleted the refactor/output-results-split branch June 4, 2026 11:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants