Skip to content

[Bug]: Myopic window truncates capex loan payments, underreports cost #364

Description

@DavidLikesLearning

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.

  1. build local subset
  2. remove distributed technologies to avoid infeasibility
  3. run temoa on the subset with myopic mode (<2 min)
  4. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions