Skip to content

AgentiGrid: keep "};" on MATPOWER cell arrays so ExaGO reads genfuel - #149

Open
ahajdar wants to merge 5 commits into
developfrom
amir/fix-genfuel-terminators
Open

ahajdar wants to merge 5 commits into
developfrom
amir/fix-genfuel-terminators

Conversation

@ahajdar

@ahajdar ahajdar commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Replaces #137 (fork PR, closed so CI can run).

Merge request type

  • New feature
  • Resolves bug
  • Documentation
  • Other

Relates to

  • OPFLOW
  • SOPFLOW
  • SCOPFLOW
  • TCOPFLOW
  • CMake build system
  • Spack configuration
  • Manual
  • Web docs
  • Other (AgentiGrid)

This MR updates

  • Header files
  • Source code
  • CMake build system
  • Spack configuration
  • Web docs
  • Manual
  • Other (AgentiGrid tests and test fixture)

Summary

AgentiGrid's MATPOWER writer dropped the ; after cell arrays (mpc.genfuel = { ... } instead of ... };). ExaGO's reader (src/ps/psreaddata.cpp) ends mpc.genfuel at the first line containing };, so for every case AgentiGrid rewrote, ExaGO ignored the fuel types:

  • every unit took the default fuel;
  • ramp rates were 0, so SCOPFLOW could not redispatch in contingencies and reported local infeasibility on ACTIVSg200 at base load (the original file converges);
  • wind and solar units stayed at Pmin = Pmax.

The repository's own test data shows the bug: agentigrid/tests/fixtures/sample_opflow_output.txt (OPFLOW on AgentiGrid-rewritten ACTIVSg200) listed all 49 generators as COAL, while case_ACTIVSg200.m has 25 coal, 17 ng, 6 wind and 1 nuclear (bus 189), and the wind units had Pmin = Pmax. test_gen_189 asserted COAL.

Commit 1 — the fix:

  • agentigrid/parsers/matpower_parser.py keeps }; / ]; on cell-array sections; matpower_writer.py writes };, including for networks parsed before the fix.
  • New tests/grid_files/test_matpower_cell_terminators.py (3 tests) mimics ExaGO's genfuel detection on a round-tripped ACTIVSg200; all 3 fail without the fix.

Commit 2 — tests:

  • Regenerated tests/fixtures/sample_opflow_output.txt with the fixed writer (Ipopt 3.14.14); updated expected values in tests/results/test_opflow_parser.py (bus 189 NUCLEAR, 21 iterations, 0.021 s) and added test_fuel_mix_matches_case_file.
  • TestExecutorLive::test_opflow_run overwrote this tracked fixture on every run with an opflow binary, so the parser tests depended on the machine and test order (test_solve_time already failed against the committed fixture). It now writes the fixture only with AGENTIGRID_REGENERATE_FIXTURES=1, and the class skips without the binary, like TestMPIGuard. tests/README.md documents regeneration.
  • Entry in agentigrid/claude_code_changes.md.

Testing: python -m pytest -m "not slow" from agentigrid/ — 1083 passed, 13 skipped without ExaGO binaries (2 failures before this change). The file-naming check (buildsystem/tools/file_naming_conventions.pl) returns 0.

AI assistance: prepared with Claude (Anthropic); commits carry Co-Authored-By: Claude, and the change is logged in claude_code_changes.md.

Linked Issue(s)

None filed.

ahajdar and others added 4 commits October 20, 2026 06:08
The MATPOWER parser stored mpc.gentype / mpc.genfuel / mpc.bus_name without
the trailing ";", and the writer wrote them back as a bare "}". ExaGO's reader
(src/ps/psreaddata.cpp) ends mpc.genfuel at the first line containing "};", so
for every case AgentiGrid rewrote, ExaGO ignored the fuel types: all units fell
back to the default fuel, ramp rates stayed 0 (SCOPFLOW cannot redispatch in
contingencies and reports local infeasibility on ACTIVSg200 at base load, where
the original file converges) and wind/solar units stayed at Pmin = Pmax.

The parser now keeps "};" / "];"; the writer also terminates raw sections from
networks parsed before this fix. tests/grid_files/test_matpower_cell_terminators.py
mimics ExaGO's genfuel detection on a round-tripped ACTIVSg200 (3 tests; all
fail without the fix).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…s without opflow

tests/fixtures/sample_opflow_output.txt is OPFLOW output for case_ACTIVSg200.m
as rewritten by AgentiGrid. It was produced by the writer fixed in the previous
commit and therefore listed all 49 generators as COAL; test_gen_189 asserted
COAL although the case file says nuclear for bus 189. Regenerated with the
fixed writer (25 coal, 17 ng, 6 wind, 1 nuclear) and updated the expected
values in tests/results/test_opflow_parser.py; test_fuel_mix_matches_case_file
guards against regenerating it with a broken writer again.

TestExecutorLive now skips without the opflow binary, like TestMPIGuard.
(Develop already stopped the live test from overwriting the fixture in #147.)
tests/README.md describes the fixture; claude_code_changes.md has the entry
for both commits.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…nd trips

Five defects found while specifying the parser and writer:

1. Rows with a non-numeric value were skipped with only a log warning, so a
   bus, generator or branch could silently disappear; too-short rows crashed
   with IndexError. Known sections (bus, gen, branch, gencost) now raise
   ValueError naming the section and row for non-numeric values, column
   counts outside the section's limits, and non-integral values in integer
   columns.
2. Valid MATLAB syntax was misread: two rows on one line became one garbage
   row and comma-separated rows were all dropped. These, '...' continuations,
   unterminated blocks and a missing mpc.bus now raise ValueError.
3. The writer crashed on Inf/NaN, which the reader accepts. They are written
   as Inf/-Inf/NaN; bus solution columns no longer lose precision to .4f.
4. Every read/write round trip added another "MATPOWER Case Format" header
   line. Writing is now idempotent.
5. Case version '1' was accepted although ExaGO reads version 2; it now
   raises. A missing version still means '2'.

CRLF input is normalised on read and output is always LF. The function line
always carries network.casename. All 29 case files in datafiles/ still parse
and round-trip to equivalent networks. New
tests/grid_files/test_matpower_hardening.py (29 tests, 22 fail without the fix).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…rounding, baseMVA literals

Three defects found by property-based round-trip testing:

1. A finite value near the float maximum was written with 10 significant
   digits that round past it and read back as Inf. The writer now falls back
   to the exact representation when rounding overflows.
2. A value that rounds to an integer (e.g. 9999999999.5) was written as
   "1e+10" the first time and "10000000000" after re-reading, so writing was
   not idempotent. The integer form is now decided on the rounded value.
3. mpc.baseMVA was read with a digits-and-dots pattern: "1e2" (and "1e+15",
   which the writer itself emits for large values) was silently read as 1,
   and a negative value was reported as missing. Any numeric literal (sign,
   exponent, Inf/NaN) on an mpc.baseMVA line is now accepted, text in
   comments is ignored, and a non-numeric value raises ValueError.

18 more tests in tests/grid_files/test_matpower_hardening.py (12 fail
without the fix). All 29 case files in datafiles/ still round-trip.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@ahajdar ahajdar changed the title Replaces #137 (fork PR, closed so CI can run). AgentiGrid: keep "};" on MATPOWER cell arrays so ExaGO reads genfuel Oct 20, 2026
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