<!– This file is generated from CHANGELOG.md by docs/scripts/update_changelog.jl. –>
Changelog
All notable changes to MacroEnergy.jl will be documented in this file.
The format is based on Keep a Changelog, and this project follows Julia package versioning through Project.toml releases.
[Unreleased]
Added
- Added
@add_to_balancefor appending raw terms to an existing named balance. - Added
@add_to_storage_balanceas the preferred helper for extending storage law-of-motion balances. - Added
@inspect_stoichiometric_balanceto inspect the pairwise equations generated by@add_stoichiometric_balance. - Added focused single-asset solve tests under
test/asset_teststo validate migrated asset balances against manual algebraic rewrites where appropriate. - Added scaling functionality for input data. New
ParameterScaling(defaultfalse) andParameterScalingFactor(default1e3) parameters have been added to case settings. - Added capacity_summary.csv for multi-period cases, combining per-period capacity outputs into a single long- or wide-format file.
- Added optional StartYear input in case_settings.json to label periods by calendar year.
- Added
capex.csvoutput file to report per-component asset capital costs. - Added repository-local benchmarking tools to compare case loading, case generation, and model generation between
upstream/mainand the current worktree using reproducible example inputs. - Added system-wide and per-location capacity constraints for selected groups of assets:
MaxCapacityConstraintandMinCapacityConstraintbound total capacity, andMaxNewCapacityConstraintbounds newly built capacity. Limits are configured via aconstraintsblock insystem_data.json(whole system) or per location inlocations.json, using asset-type and tag selectors. The limit values are scaled withParameterScalinglike other capacity inputs. - For
VRE, the optionaltechnologyinput is normalized into an asset tag (for example,technology: "Solar"adds:solar) without changing the asset's Julia type. - Added
ConstrainedFossilLiquidFuels, a refinery asset with fixed jet-fuel and diesel output ratios and configurable fuel-specific emissions. - Added optional auxiliary-fuel inputs to
BECCSHydrogenand captured-CO₂ return flows toSyntheticLiquidFuels. - Added unit-commitment support for
Electrolyzerhydrogen output, including startup electricity consumption, minimum up/down times, and ramping limits. - Added time-domain reduction (TDR) to replace full input time series with weighted representative periods. The new
preprocess_inputsandtime_domain_reductionworkflows generate a separate reduced case that loads and runs through the ordinary MacroEnergy APIs. - Added JSON-configured TDR with independent per-System settings, k-means, k-medoids and autoencoder clustering, feature selection and weights, scaling, and forced extreme-period selection.
- Added TDR input discovery for JSON and model-input CSV references across arbitrary directories, including inline time-series vectors. Per-System copies retain only required files and time-series columns, preserve model-input CSV format, and consolidate identical shared inputs.
- Added optional model-output clustering features from isolated candidate-period solves, with distributed execution, selective policy-constraint exclusion, retained inputs/results, and fingerprint-validated feature caches under the source case’s
TDR/directory. - Added support for reclustering into shorter representative periods while preserving source-period boundaries and occurrence weights. TDR reports trimmed timesteps, rejects longer requested periods, updates time settings, and validates source/destination separation before overwriting.
- Added TDR period maps, provenance and feature-use logs, including records of inputs reduced without being used for clustering. Preprocessing logs are saved under
preprocessing_logs/in the reduced case.
Changed
- Cached repeated reads of shared CSV inputs within each case or system load, avoiding repeated full-file parsing when assets select different columns from the same file.
@add_balanceis now the recommended API for ordinary algebraic balance equations and inequalities, and follows standard algebraic sign conventions forflow(...)terms.@add_balancenow validates balance expressions more strictly and rejects unsupported non-flow(...)variable terms.@add_stoichiometric_balancenow expands recipe-style balances using a consistent proportional rule around the selectedbase_term.- Asset balance definitions have been migrated away from legacy raw
balance_data = Dict(...)patterns toward@add_balance,@add_to_storage_balance, and@add_stoichiometric_balance. - Updated MacroEnergyScaling.jl compatibility to 0.4. Constraint scaling now updates constraints in place, so existing JuMP
ConstraintRefs remain valid instead of being invalidated by constraint replacement. This version also allows for objective scaling in the future. - Hoisted repeated time-data lookups during model construction and simplified ramping and minimum up/down-time constraints to avoid temporary expression and index containers.
- Weight policy slack to ensure CO2 slack penalty has economic interpretation.
- A constraint entry in a
constraintsblock may now be an inline configuration object (carrying its settings) instead of only the booleantrue/falsetoggle, enabling data-driven constraint parameterization. - Location entries in
locations.jsonmay now be objects carrying aconstraintsblock (bare id strings still work), allowing location-specific constraints to be loaded from input data. - Reduced model-generation allocations in edge balance updates by inserting flow variables directly into vertex balance expressions instead of constructing temporary effective-flow expressions.
run_casenow scopes logging to the run, restores the caller’s logger, and closes its own file log stream on success or failure.- Storage Charge/Discharge limit constraints now can be applied to
LongDurationStorage.
Removed
- Removed
ReviseandTestfrom the package dependencies.MacroEnergy.jlno longer loadsReviseat package load time, so developers who relied on that must now load it themselves;Testremains available to the test suite through[extras]/[targets].
Fixed
- Myopic runs with
MyopicSettings.ReturnModels = falsenow actually free each period's model. Each period's references are now released once its results have been written, and the model is emptied. Results are unchanged; scalar capacities remain readable on the returnedCaseasFloat64. - Fixed asset component traversal and Benders planning updates for assets whose optional edges are absent.
StorageChargeLimitConstraintis now attached to aBattery's charge edge. Before, it was declared as a top-level key in the charge edge's default data instead of inside itsconstraintsdictionary, so it was silently dropped.- Dual exports now handle unavailable solver duals safely, recording
NaNinstead of failing while preservingFloat64output arrays. - CSV input reading now releases file handles deterministically to allow immediate rewriting and deletion on Windows. JSON reads/writes and CSV header reads also close streams after exceptions.
Documentation
- Expanded the balance documentation with guidance on choosing between balance macros, stoichiometric coefficient bases, pairwise expansion limits, multi-term algebraic balances, common mistakes, and numerical sensitivity.
- Updated modeler documentation to include balance APIs in the asset-construction workflow and to recommend a small single-asset regression test for each new asset.
- Updated debugging guidance around
balance_data,get_balance, and@inspect_stoichiometric_balance. - Updated asset-specific documentation examples to use the balance macros instead of legacy raw balance dictionaries.
- Added preprocessing and TDR manuals covering configuration, input discovery, candidate construction, clustering, output-feature caching, generated files, and function workflow trees.
Migration guide
- When updating an asset, prefer
@add_balancefor ordinary algebraic equalities and inequalities, prefer@add_to_storage_balancefor storage law-of-motion terms, and use@add_stoichiometric_balanceonly when the relationship is naturally a recipe-style proportional conversion. - Legacy raw balance dictionaries should usually be replaced with explicit balance macros. For example:
transform.balance_data = Dict(
:energy => Dict(
output_edge.id => coeff,
input_edge.id => 1.0,
),
)can become:
@add_balance(transform, :energy, flow(output_edge) == coeff * flow(input_edge))or, when the relationship is best represented as a recipe:
@add_stoichiometric_balance(
transform,
:production,
coeff * flow(input_edge) --> flow(output_edge),
flow(output_edge),
)- Use
@add_balancewhen the relationship is easiest to write as an explicit equation, includes three or more independently varying terms, or is not just a set of pairwise proportional relations. - Use
@add_stoichiometric_balancewhen onebase_termshould anchor several proportional relationships and all coefficients can be written on a common recipe basis. - In one
@add_stoichiometric_balanceexpression, all coefficients must share a common basis. For example, if the base term is product output, coefficients should usually be expressed per unit output; if the base term is fuel input, coefficients should usually be expressed per unit fuel. - When extending the
:storagebalance of a storage component, use@add_to_storage_balance(storage, coeff * flow(edge)). In normal usage, write positive magnitudes for both inflows and outflows and let MacroEnergy apply the effective sign through edge direction. - During migration, inspect generated pairwise equations with
@inspect_stoichiometric_balance(...), inspect stored coefficients withbalance_data(component, balance_id), inspect compiled expressions withget_balance(component, balance_id), and validate the asset with a small single-asset solve test. - Small differences in large-system results do not automatically indicate a balance bug. Algebraically equivalent formulations can change row scaling and solver tie-breaking in large, near-degenerate systems, so localized single-asset regression tests are the primary evidence that migrated balances remain correct.
- Results change: no public API changed, but any case using a
Batteryasset could now produce different results. The charge limit (charge_flow[t] <= capacity - storage_level[t-1], scaled by the charge efficiency) was previously not included by default and is now enforced. To keep the old behavior, disable it explicitly on the charge edge:"charge_edge": {"constraints": {"StorageChargeLimitConstraint": false}}. - If you set
StorageChargeLimitConstraintas a top-level key on a charge edge, rather than inside that edge'sconstraintsdictionary, it was and still is ignored. Move it insideconstraintsfor it to take effect. StorageChargeLimitConstraintonly applies to an edge whose end vertex is the storage, i.e. the charge edge. Setting it on the discharge edge (or viadischarge_constraintsin the simple input format) has no effect.
[0.2.4] - 2026-09-10
Changed
- Skip Julia CI tests when changes are confined to
CHANGELOG.md,README.md, ordocs/, while retaining documentation builds and a consistentCI resultcheck that reports successful tests or an intentional skip.
Fixed
- Removed
[skip ci]from automated changelog commit messages so release tags pointing to those commits can trigger documentation deployment.
[0.2.3] - 2026-08-31
Documentation
- Switched documentation math rendering to MathJax3 and pinned Mermaid to 11.16.1 to avoid Mermaid 11.17's RequireJS compatibility regression.
[0.2.2] - 2026-08-05
Fixed
- Duplicate asset IDs within a system are now rejected during system generation, preventing ambiguous myopic capacity carry-over and late wide-output failures.
[0.2.1] - 2026-07-15
Changed
- Updated MacroEnergySolvers.jl version to 0.2.2
Fixed
- Fix wacc default preventing fallback to DiscountRate. Omitted
waccwas silently treated as0.0instead of falling back to the case-levelDiscountRate.
Migration guide
- Results change: no public API changed, but any case that omits an asset's
waccwill now produce different results. Previously the missingwaccdefaulted to0.0; it now falls back to the case'sDiscountRate. Cases relying on the old default will see different annualized investment costs after upgrading. To keep the old behavior, setwaccexplicitly to0.0for the affected asset(s).
[0.2.0] - 2026-05-22
Added
- Outputs can now be written to a JSON file using the
write_to_jsonmethod. This method writes to a compressed.json.gzbut also supports regular.jsonoutputs. It is not currently built into any of the run tools. - Improved JSON serialization coverage of commodities, storage, constraints, dual values, time data, solution algorithms, named tuples, JuMP containers, and special numeric values like Inf, -Inf, and NaN
Changed
- CSV asset input files can now have their
TypeandIdcolumns in any position in the file, instead of needing to be in the first two columns. TheTypeandIdcolumns are still required. run_casenow returns(case, solution)as opposed to(systems, solution). Thecaseobject contains thesystemsas well ascase-level settings.
Migration guide
- If you are using the
run_casefunction, update your code to handle the new return signature of(case, solution)instead of(systems, solution).
For example, if you previously had:
(system, solution) = run_case(@__DIR__;
optimizer=HiGHS.Optimizer,
optimizer_attributes=("solver" => "ipm", "run_crossover" => "off", "ipm_optimality_tolerance" => 1e-3)
);You should now use:
(case, solution) = run_case(@__DIR__;
optimizer=HiGHS.Optimizer,
optimizer_attributes=("solver" => "ipm", "run_crossover" => "off", "ipm_optimality_tolerance" => 1e-3)
);If you need to access the systems, you can retrieve them from the case object.
systems = case.systems[0.1.0] - 2026-04-14
Added
- Expanded result writing and postprocessing for non-served demand, storage level, curtailment, time weights, discounted and undiscounted cost outputs, and detailed cost breakdowns.
- Added full time-series reconstruction across Monolithic, Myopic, and Benders workflows through
WriteFullTimeseries. - Added
SyntheticAmmonia,SyntheticMethanol,ThermalAmmonia,ThermalAmmoniaCCS,ThermalMethanol,ThermalMethanolCCS, andOneWayTransmissionLinkassets. - Added
StorageChargeLimitConstraint, long-duration storage feasibility constraints for Benders, and additional storage safety checks. - Added Myopic restart support,
StopAfterPeriod, optional JuMP direct-model generation, optional string names, updated default HiGHS settings, and economic utilities for present-value and cash-flow calculations.
Changed
- Redesigned node supply inputs around named supply dictionaries with per-segment
price,min, andmaxvalues. - Split edge types into explicit unidirectional and bidirectional forms.
- Changed
TransmissionLinkto model bidirectional transfer; useOneWayTransmissionLinkfor one-way transfer. - Cleaned up user extension loading through the
user_additions/layout. - Renamed emissions-tracking assets to
UpstreamEmissionsandDownstreamEmissions, with compatibility aliases for older names. - Expanded documentation and tests for TimeData, timeseries outputs, retrofitting, run workflows, outputs, constraints, assets, transmission links, supply parsing, and user additions.
Removed
- Removed legacy unified output code in favor of the expanded
write_*output suite.
Fixed
- Improved Benders output parity and cost handling by performing a final operational solve for the selected planning solution.
- Fixed and improved transmission, storage, dual, cost, and documentation behavior across the release.
Migration guide
- Update node supply inputs to the named
supplydictionary format. Each supply segment should defineprice,min, andmaxvalues. Legacyprice_supplyandmax_supplyinputs are still handled, andupdate_node_supply_inputs(...)can help convert existing cases. - Review any cases using automatically generated supply segment names. Segment names now use
segment1,segment2, and so on. - Review transmission assets.
TransmissionLinkis now bidirectional by default; useOneWayTransmissionLinkwhen directionality matters. - Update any direct use of edge types to the explicit unidirectional and bidirectional edge forms.
- Update output-processing scripts that relied on the legacy unified output code. Use the expanded
write_*output functions instead. - Review models that assumed nodes did not include balance constraints by default. Nodes now have
BalanceConstraintenabled by default. - Prefer the renamed emissions assets
UpstreamEmissionsandDownstreamEmissions. Compatibility aliases remain for older names, includingFossilFuelsUpstreamandFuelsEndUse.
[0.0.3] - 2025-11-21
Added
- Added iron and steel sector assets and documentation.
- Added heat and steam sector commodities, assets, examples, and documentation.
- Added aluminum sector default real-world parameters.
- Added output support for dual values from
BalanceConstraintandCO2CapConstraint. - Added minimum retired capacity tracking and extended retrofit features to multi-stage models.
- Added Windows coverage to CI.
Changed
- Updated installation instructions, citation metadata, asset library docs, modeler debugging docs, and timeseries documentation.
Fixed
- Fixed several Windows-related path and user-additions issues.
- Fixed retrofit integer decisions, hydropower reservoir efficiency handling, documentation cross references, and Benders dual scaling behavior.
[0.0.2] - 2025-09-25
Added
- Added logging options.
- Added settings output in results.
- Added automatic Mermaid diagrams for assets.
- Added asset retrofits for single-stage cases.
- Added options to free model memory and write myopic outputs during iterations.
Changed
- Refactored output-writing utilities.
Fixed
- Fixed subcommodity loading.
[0.0.1] - 2025-08-20
Added
- Initial registered release of MacroEnergy.jl.
[Unreleased]: https://github.com/macroenergy/MacroEnergy.jl/compare/v0.2.0...HEAD [0.2.0]: https://github.com/macroenergy/MacroEnergy.jl/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/macroenergy/MacroEnergy.jl/compare/v0.0.3...v0.1.0 [0.0.3]: https://github.com/macroenergy/MacroEnergy.jl/compare/v0.0.2...v0.0.3 [0.0.2]: https://github.com/macroenergy/MacroEnergy.jl/compare/v0.0.1...v0.0.2 [0.0.1]: https://github.com/macroenergy/MacroEnergy.jl/releases/tag/v0.0.1