Add figure of merit enum#4272
Conversation
…ptions for clarity
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4272 +/- ##
==========================================
+ Coverage 50.13% 50.17% +0.04%
==========================================
Files 151 151
Lines 29349 29378 +29
==========================================
+ Hits 14714 14741 +27
- Misses 14635 14637 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…larity and maintainability
There was a problem hiding this comment.
Pull request overview
This PR refactors PROCESS’s “figure of merit” (FoM) handling by introducing a centralized FiguresOfMerit IntEnum in process/data_structure/numerics.py, replacing the legacy lablmm list and the OBJECTIVE_NAMES mapping, and updating call sites in the solver, scan/output, plotting, and documentation.
Changes:
- Adds
FiguresOfMeritenum (ID + description) and removeslablmminitialization/usage. - Refactors objective evaluation and various outputs/plots to derive FoM labels from the enum.
- Updates documentation to refer to
FiguresOfMeritrather thanlablmm.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| process/data_structure/numerics.py | Introduces FiguresOfMerit enum and removes legacy lablmm list. |
| process/core/solver/objectives.py | Replaces OBJECTIVE_NAMES and switches FoM selection logic to enum-based dispatch. |
| process/core/scan.py | Uses enum descriptions for objective function naming in post-optimise output. |
| process/core/io/plot/summary.py | Replaces objective-name mapping with enum usage in plot headers/cover page text. |
| process/core/io/plot/solutions.py | Uses enum descriptions when falling back to minmax for older MFiles. |
| process/core/init.py | Uses enum descriptions when printing the run summary header. |
| documentation/source/io/input-guide.md | Updates minmax help text to reference FiguresOfMerit. |
| documentation/source/development/add-vars.md | Updates “add FoM” instructions to point to numerics.py + enum. |
Comments suppressed due to low confidence (1)
process/core/solver/objectives.py:55
objective_functioncompares against enum members that don't exist inFiguresOfMerit(e.g.TF_PF_COIL_POWER,FUSION_GAIN,INJECTED_POWER,PLANT_AVAILABILITY, etc.). This will raiseAttributeErrorat runtime. Update these comparisons to use the actual enum member names defined inprocess/data_structure/numerics.py(or rename the enum members to match the names used here) so the mapping for cases 4/5/11/15/16/18/19 is consistent.
if figure_of_merit == FiguresOfMerit.MAJOR_RADIUS:
objective_metric = 0.2 * physics_variables.rmajor
elif figure_of_merit == FiguresOfMerit.NEUTRON_WALL_LOAD:
objective_metric = physics_variables.pflux_fw_neutron_mw
elif figure_of_merit == FiguresOfMerit.TF_PF_COIL_POWER:
objective_metric = (tfcoil_variables.tfcmw + 1e-3 * data.pf_power.srcktpm) / 10.0
elif figure_of_merit == FiguresOfMerit.FUSION_GAIN:
objective_metric = data.current_drive.big_q_plasma
elif figure_of_merit == FiguresOfMerit.COST_OF_ELECTRICITY:
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ) | ||
|
|
||
| objf_name = f'"{numerics.lablmm[abs(numerics.minmax) - 1]}"' | ||
| objf_name = f'"{FiguresOfMerit(abs(numerics.minmax)).description}"' |
| fom_string = data_structure.numerics.lablmm[ | ||
| abs(data_structure.numerics.minmax) - 1 | ||
| ] | ||
| fom_string = FiguresOfMerit(abs(data_structure.numerics.minmax)).description |
| numerics.init_numerics() | ||
| objf_list = { | ||
| numerics.lablmm[int(abs(minmax)) - 1] for minmax in diffs_df["minmax"] | ||
| FiguresOfMerit(abs(minmax)).description for minmax in diffs_df["minmax"] | ||
| } |
| else ( | ||
| f"!{OBJECTIVE_NAMES[abs(int(mfile.get('minmax', scan=-1)))]}", | ||
| f"!{FiguresOfMerit(abs(int(mfile.get('minmax', scan=-1)))).name}", | ||
| "Optimising:", |
| figure_of_merit = FiguresOfMerit(abs(minmax)) | ||
|
|
…escription usage in plot functions
| elif figure_of_merit == FiguresOfMerit.FUSION_GAIN_BURN_TIME: | ||
| objective_metric = -0.5 * (data.current_drive.big_q_plasma / 20.0) - 0.5 * ( | ||
| data.times.t_plant_pulse_burn / 7200.0 | ||
| ) |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…FiguresOfMerit enum
This pull request refactors how figures of merit (FoM) are represented and used throughout the PROCESS codebase. The main improvement is the introduction of a new
FiguresOfMeritenumeration innumerics.py, replacing the previous use of thelablmmlist and scattered constants. This makes the code more maintainable, type-safe, and easier to extend. All references to figures of merit in both code and documentation have been updated to use this new enum, and related descriptions and logic have been centralized.Core Refactoring:
FiguresOfMeritenum inprocess/data_structure/numerics.pyto represent all available figures of merit, each with an associated integer value and description.lablmmlist and theOBJECTIVE_NAMESdictionary, updating all code to use the new enum for descriptions and names.Code Updates:
FiguresOfMerit, including ininit.py,scan.py, and plotting modules, ensuring consistent and clear usage.big_q_plasmadirectly, aligning with the new enum's semantics.Documentation Updates:
FiguresOfMeritinstead oflablmm, and clarified instructions for adding new figures of merit.These changes modernize and centralize how figures of merit are handled, making future extensions and maintenance significantly easier.## Description
Checklist
I confirm that I have completed the following checks: