Skip to content

Use PETSc's options parser instead of our own (#642) - #652

Open
lmoresi wants to merge 2 commits into
developmentfrom
bugfix/negative-cli-values
Open

Use PETSc's options parser instead of our own (#642)#652
lmoresi wants to merge 2 commits into
developmentfrom
bugfix/negative-cli-values

Conversation

@lmoresi

@lmoresi lmoresi commented Aug 26, 2026

Copy link
Copy Markdown
Member

Fixes the silent half of #642. Two commits: the first patches our parser, the second deletes it in favour of PETSc's. The second is the one that matters — read the diff, not just the first commit.

Root cause — ours, not PETSc's

parse_cmd_line_options decided what was an option name with

item[0] == "-" and item[1] != "-"

which accepts -2. So in -uw_sense -2 the parser read -2 as the next key, stored uw_sense with no value, and registered a stray option 2. The negative never arrived, Params fell back to its default, and nothing was said. It once ran half of a 26-run parameter ladder at the default sign while reporting it under the requested label.

PETSc does not have this problem. PetscOptionsValidKey requires a hyphen followed by a letter, which is exactly what separates -uw_sense from -2.

Why the second commit

The first commit copied PETSc's rule into our parser. That repaired the one instance and left the duplication — and the duplication was the actual defect. UW parameters are namespaced -uw_* precisely so they can sit in the PETSc options database alongside PETSc's own, and uw.options is already a PETSc.Options("uw_") view onto it. Parsing was the single part being re-done by hand, and the only part that was wrong.

So the body is now a hand-off to PetscOptionsInsertString (petsc4py's Options.insertString), which applies the same rules PETSc applies to its own arguments.

The function still exists and is still called per Params construction, because petsc4py does not populate the database from sys.argv on every platform (#111, Gadi). Arguments carrying whitespace are re-quoted, since insertString takes one string and PETSc reads double quotes.

Measured

argv before after
-uw_sense 2 '2' '2'
-uw_sense -2 '' '-2'
-uw_sense 2.5 '2.5' '2.5'
-uw_sense -2.5 '' '-2.5'
-uw_sense -1e-5 '' '-1e-5'

End to end, -uw_sense -2 now yields -2.0 from source cli. A value containing a space survives intact, and a positional argument alongside the options does not disturb them.

Tests

Negative integer, negative float, and negative exponent — the last because its inner hyphen is the case a naive fix would miss. The test fails on the old predicate (verified by reverting the installed copy) and passes now. A positive-value test sits beside it as the negative control, since this narrows what counts as an option name.

level_1 and tier_a: 1074 passed, 0 failed.

Deliberately not fixed here

getInt raises on a float-valued option, and the legacy branch of _get_petsc_option swallows it with a bare except: return default — so uw.Params(uw_steps=3) with -uw_steps 2.5 still falls back to 3 silently. Same failure class, different route. Documented on #642; #642 should stay open for it.

Underworld development team with AI support from Claude Code

`parse_cmd_line_options` decided what was an option NAME with

    item[0] == "-" and item[1] != "-"

which accepts `-2`. So in `-uw_sense -2` the parser read `-2` as the next key,
stored `uw_sense` with no value, and registered a stray option `2`. The
negative never arrived, `Params` fell back to its default, and said nothing.
It once ran half of a 26-run parameter ladder at the default sign while
reporting it under the requested label; it was caught only because the
partition numbers came out identical to the +1 runs.

PETSc does not have this problem. `PetscOptionsValidKey` requires a hyphen
followed by a LETTER, which is precisely what separates `-uw_sense` from `-2`.
This adopts the same rule. `--long` stays excluded exactly as before, and a
leading underscore is allowed for symmetry with the names PETSc accepts.

Measured at the options database, before -> after:

    -uw_sense 2        '2'      -> '2'
    -uw_sense -2       ''       -> '-2'
    -uw_sense 2.5      '2.5'    -> '2.5'
    -uw_sense -2.5     ''       -> '-2.5'
    -uw_sense -1e-5    ''       -> '-1e-5'

and end to end through Params, `-uw_sense -2` now gives -2.0 from source 'cli'
where it gave the default.

The regression covers a negative integer, a negative float and a negative
exponent (whose inner hyphen is the case a naive fix would miss). It FAILS on
the old predicate and passes on the new one, and a positive-value test sits
beside it as the negative control, since this change narrows what counts as an
option name and the ordinary path has to be shown still working.

Not fixed here, and left on #642: `getInt` RAISES on a float-valued option, and
the legacy branch of `_get_petsc_option` swallows it with a bare `except:
return default` -- so an int parameter given a float on the command line still
falls back silently. Same failure class, different route, and it needs its own
decision about whether to raise.

Underworld development team with AI support from Claude Code
Copilot AI lite review requested due to automatic review settings August 26, 2026 08:48

Copilot AI left a comment

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 was unable to review this pull request because the user who requested the review has reached their quota limit.

The previous commit fixed our hand-rolled argv parser by copying PETSc's
valid-key rule into it. That was the wrong shape of fix: UW parameters are
namespaced `-uw_*` precisely so they can live in the PETSc options database
next to PETSc's own, and `uw.options` is already a `PETSc.Options("uw_")` view
onto it. The parsing was the one part being re-implemented, and it was the one
part that was wrong.

`PetscOptionsInsertString` -- petsc4py's `Options.insertString` -- applies the
same rules PETSc applies to its own arguments, negative numbers included. So
the body becomes a hand-off, and the whole class of divergence-from-PETSc goes
with it rather than the single instance we happened to hit.

Kept: the function still exists and is still called on every `Params`
construction, because petsc4py does not populate the database from `sys.argv`
on every platform (#111, Gadi). It is still idempotent. Arguments carrying
whitespace are re-quoted, since `insertString` takes one string and PETSc reads
double quotes.

Verified after the change:

    -uw_sense 2       -> '2'       -uw_sense -2      -> '-2'
    -uw_sense 2.5     -> '2.5'     -uw_sense -2.5    -> '-2.5'
                                   -uw_sense -1e-5   -> '-1e-5'

end to end through Params (-2.0 from source 'cli'), a value containing a space
survives intact, and a positional argument sitting alongside the options does
not disturb them.

Underworld development team with AI support from Claude Code
@lmoresi lmoresi changed the title Let a negative number be a value, not an option name (#642) Use PETSc's options parser instead of our own (#642) Aug 27, 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.

2 participants