Bug Description
In myopic mode, loan_cost() cuts every tech's amortized investment cost at the end of the myopic view window, not the study horizon boundary. Technologies built more than view_depth periods from final period only pays a fraction of its investment costs.
CAUSE: temoa/components/costs.py::loan_cost() caps the recognized loan repayment at min(lifetime_process, p_e - vintage) (undiscounted branch; the discounted branch applies the same cap inside annuity_to_pv(GDR, min(lifetime_process, p_e - vintage))):
res = (
annuity
* lifetime_loan_process / lifetime_process
* min(lifetime_process, p_e - vintage) # truncation
but p_e is defined as
p_e = model.time_future.last()
# End point of modeled horizon
Steps to Reproduce
We subset CONUS 26z OEO database so we can run this on a small personal laptop:
We subset four regions in the Southeast. We look at the four most representative weeks for all periods, looking at Sunday, Monday, Tuesday. To recreate this minimal dataset, run python build_subset.py in the same directory as the OEO 26 zone CONUS database .sqlite from https://datadocs.openenergyoutlook.org/en/latest/datasets.html.
- build local subset
- remove distributed technologies to avoid infeasibility
- run temoa on the subset with myopic mode (<2 min)
- run truncation verification. note limited years of loan payments
Code or Configuration Example
We start in a folder with config_myopic.toml (added as a .txt file to please the github gods), strip_dg1.sql, verify_truncation.py, and subset_26zone_conus.py.
strip_dg1.sql
config_myopic.txt
subset_26zone_conus.py
verify_truncation.py
source ../temoa_env/bin/activate
# CHANGE PATH BELOW TO OEO CONUS database .sqlite file
python subset_26zone_conus.py --source /path/to/v1-26z_conus_servers.sqlite --out subset_myopic.sqlite --regions SRCA SRCE SRSE SRSG --periods 2027 2030 2035 2040 --horizon-boundary 2045 --seasons p4 p19 p30 p48 --hours 1-48 --fuel-census-division east_south_central south_atlantic mountain --overwrite
python -c "import sqlite3; d=sqlite3.connect('subset_myopic.sqlite'); d.executescript(open('strip_dg1.sql').read()); d.commit(); print('FK check:', d.execute('PRAGMA foreign_key_check').fetchall())"
temoa run config_myopic.toml --silent
python verify_truncation.py subset_myopic.sqlite --view-depth 1 --csv truncation.csv
Expected Behavior
Technologies should make loan payments for said technologies until the end of their planning horizon.
Actual Behavior
Technologies built in period p only make loan payments during that period, automatically making myopic technologies cheaper by about a half or a third of the price.
Environment
Please provide details about your environment. This helps us reproduce the issue.
- Operating System: macOS 26.2, Apple Silicon (arm64), Darwin kernel 25.2.0
- Python Version: 3.13.5
- Project Version: 4.0.0a2
- Relevant Dependencies:
Pyomo 6.9.5
highspy 1.14.0 (HiGHS appsi_highs solver)
numpy 2.4.4
pandas 3.0.2
scipy 1.17.1
openpyxl 3.1.5
temoa_env built from latest project version.
Checklist
- [ x] I have searched existing issues to ensure this bug hasn't already been reported.
- [x ] I have provided clear steps to reproduce the bug.
- [ x] I have provided a minimal, reproducible code example (if applicable).
- [ x] I have included any relevant error messages or stack traces.
- [ x] I have described the expected and actual behavior.
Bug Description
In myopic mode,
loan_cost()cuts every tech's amortized investment cost at the end of the myopic view window, not the study horizon boundary. Technologies built more thanview_depthperiods from final period only pays a fraction of its investment costs.CAUSE:
temoa/components/costs.py::loan_cost()caps the recognized loan repayment atmin(lifetime_process, p_e - vintage)(undiscounted branch; the discounted branch applies the same cap insideannuity_to_pv(GDR, min(lifetime_process, p_e - vintage))):but
p_eis defined asSteps to Reproduce
We subset CONUS 26z OEO database so we can run this on a small personal laptop:
We subset four regions in the Southeast. We look at the four most representative weeks for all periods, looking at Sunday, Monday, Tuesday. To recreate this minimal dataset, run
python build_subset.pyin the same directory as the OEO 26 zone CONUS database .sqlite from https://datadocs.openenergyoutlook.org/en/latest/datasets.html.Code or Configuration Example
We start in a folder with
config_myopic.toml(added as a .txt file to please the github gods),strip_dg1.sql,verify_truncation.py, andsubset_26zone_conus.py.strip_dg1.sql
config_myopic.txt
subset_26zone_conus.py
verify_truncation.py
Expected Behavior
Technologies should make loan payments for said technologies until the end of their planning horizon.
Actual Behavior
Technologies built in period
ponly make loan payments during that period, automatically making myopic technologies cheaper by about a half or a third of the price.Environment
Please provide details about your environment. This helps us reproduce the issue.
Pyomo 6.9.5
highspy 1.14.0 (HiGHS appsi_highs solver)
numpy 2.4.4
pandas 3.0.2
scipy 1.17.1
openpyxl 3.1.5
temoa_env built from latest project version.
Checklist