energy_penalty() applies the capture energy penalty to only one of six technologies
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 68/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- python
- Área
- build-system, data
Línea de trabajo
Comience en scripts/compile_cost_assumptions.py, en energy_penalty(), y siga el bucle de seis tecnologías, las ramas de dispatch y la asignación duplicada de VOM. Verifique que se procese cada tecnología de captura de carbono enumerada, que el biogás utilice su rama prevista y que los valores de outputs/costs_2050.csv generados incluyan los ajustes esperados de inversión, VOM y eficiencia.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
energy_penalty() exits after the first technology: five of six CC technologies never get the capture energy penalty
Note: Claude found this issue, so below is a summary by it.
Summary
In scripts/compile_cost_assumptions.py, energy_penalty() loops over six carbon-capture technologies and adds an auxiliary steam boiler to cover the heat demand of the capture unit, rescaling investment, VOM, efficiency and (for CHPs) heat efficiency accordingly.
The loop body contains a break where pass appears to have been intended. central solid biomass CHP CC is the first item in the list and has a non-zero VOM, so the loop exits during the first iteration — after the investment update but before the VOM, efficiency and efficiency-heat updates.
The net effect on the published outputs/costs_*.csv:
central solid biomass CHP CCreceives the investment uplift but keeps its unpenalized electrical and heat efficiency and its unadjusted VOM.waste CHP CC,solid biomass boiler steam CC,direct firing solid fuels CC,direct firing gas CCandbiogas CCreceive nothing at all — their investment, VOM and efficiency are identical to their non-CC counterparts.
Downstream this makes carbon capture cheaper and more efficient than the function intends, which matters for any study comparing BECCS routes against each other or against unabated conversion.
Location
scripts/compile_cost_assumptions.py, in energy_penalty() — the if begins at line 3313 on current master:
if cost_dataframe.loc[(tech_name, "VOM"), "value"]:
break
else:
cost_dataframe.loc[(tech_name, "VOM"), "value"] = 0.0
Everything after this block — the VOM rescaling, efficiency = eta_main, and the if "CHP" in tech_name heat-efficiency block — is unreachable for every technology whose VOM is non-zero, and unreachable for all subsequent technologies regardless.
The same code is present at least as far back as v0.11.0, so the outputs have been affected for a long time.
Evidence in the shipped outputs
The source field records which lines executed, because the function overwrites it with "Combination of <tech> and <boiler>". From outputs/costs_2050.csv:
| technology | parameter | value | source |
|---|---|---|---|
| central solid biomass CHP CC | investment | 6003.1610 | Combination of central solid biomass CHP CC and solid biomass boiler steam |
| central solid biomass CHP CC | efficiency | 0.2652 | Danish Energy Agency, inputs/technology_data_for_el_and_dh.xlsx |
| central solid biomass CHP CC | VOM | 6.2350 | Danish Energy Agency, inputs/technology_data_for_el_and_dh.xlsx |
| waste CHP CC | investment | 9442.6408 | Danish Energy Agency, inputs/technology_data_for_el_and_dh.xlsx |
The first row shows the investment line ran; the second and third show the loop had already exited; the fourth shows the second technology was never reached. waste CHP CC, solid biomass boiler steam CC, direct firing solid fuels CC, direct firing gas CC and biogas CC all carry investment and efficiency values identical to their non-CC rows.
Magnitude
Re-running the intended arithmetic on costs_2050.csv (capture heat-input 0.66 MWh/tCO₂; boiler efficiencies 0.90 solid biomass / 0.94 gas; CO₂ intensities 0.3667 solid biomass, 0.198 gas):
| technology | investment now | intended | Δ | efficiency now | intended | Δ |
|---|---|---|---|---|---|---|
| central solid biomass CHP CC | 6003 | 6003 (already applied) | — | 0.2652 | 0.2090 | −21.2 % |
| waste CHP CC | 9443 | 12 741 | +34.9 % | 0.2165 | 0.1706 | −21.2 % |
| solid biomass boiler steam CC | 679 | 1044 | +53.8 % | 0.9000 | 0.7093 | −21.2 % |
| direct firing solid fuels CC | 279 | 518 | +85.9 % | 1.0000 | 0.7881 | −21.2 % |
| direct firing gas CC | 19 | 29 | +53.5 % | 1.0000 | 0.8779 | −12.2 % |
| biogas CC | 1091 | 1250 | +14.6 % | 1.0000 | 0.8779 | −12.2 % |
Heat efficiencies also change for the two CHPs: central solid biomass CHP CC 0.8294 → 0.9433, waste CHP CC 0.7625 → 0.8906.
So the shipped cost data understates capture-inclusive investment by 15–86 % for five technologies, and overstates the conversion efficiency of all six by 12–21 %.
Secondary issues in the same function
1. The elif "biogas" branch is unreachable. The dispatch is ordered
if "powerboost" in tech_name: ...
elif "gas" in tech_name: ...
elif "biogas" in tech_name: ...
else: ...
"gas" in "biogas CC" is True, so biogas CC is always caught by the "gas" branch and takes the natural-gas CO₂ intensity (0.198 tCO₂/MWh) instead of its own CO2 stored (0.1447 tCO₂/MWh). Once the break is fixed, this changes biogas CC from investment 1250 / efficiency 0.8779 to 1207 / 0.9078. Testing "biogas" before "gas" would fix it.
2. The "powerboost" branch is dead. central solid biomass CHP powerboost CC is defined in the sheet mappings but is absent from the technology list the loop iterates over, so the branch never runs.
3. The heat-efficiency block hardcodes the solid-biomass CO₂ intensity.
if "CHP" in tech_name:
cost_dataframe.loc[(tech_name, "efficiency-heat"), "value"] = (
cost_dataframe.loc[(tech_name, "efficiency-heat"), "value"] * scalingFactor
+ cost_dataframe.loc[("solid biomass", "CO2 intensity"), "value"] * (...)
)
This uses solid biomass rather than the branch's own co2_capture, which is wrong for waste CHP CC (whose capture is applied to the oil CO₂ intensity downstream in PyPSA-Eur).
4. feedstock is assigned in three branches and never read, and is not assigned in the "biogas" branch — harmless today, but it suggests the dispatch was refactored at some point and the break is a leftover from that.
Suggested fix
- if cost_dataframe.loc[(tech_name, "VOM"), "value"]:
- break
- else:
+ if not cost_dataframe.loc[(tech_name, "VOM"), "value"]:
cost_dataframe.loc[(tech_name, "VOM"), "value"] = 0.0
and, for the dispatch:
if "powerboost" in tech_name:
...
- elif "gas" in tech_name:
- ...
elif "biogas" in tech_name:
boiler = "gas boiler steam"
co2_capture = cost_dataframe.loc[(tech_name, "CO2 stored"), "value"]
+ elif "gas" in tech_name:
+ ...
else:
...
There is also a duplicated VOM assignment block later in the function — the identical rescaling appears twice, once immediately after the break and again after the efficiency-heat block. It is currently harmless because the loop never reaches either, but once the break is fixed the second occurrence would apply the rescaling a second time, so one of them should go.
- Lenguaje dominante
- Python
- Estrellas
- 132
- Forks
- 59
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Sin guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de PyPSA/technology-data
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
PyPSA/technology-data#271 ·
-
data: Add ACER's CONE studyAbierto
Dificultad 3/5 1-2 días Aptitud para principiantes 45/100
PyPSA/technology-data#284 ·
-
feature
Dificultad 4/5 3-5 días Aptitud para principiantes 38/100
PyPSA/technology-data#282 · 4 comentarios ·
-
bug
Dificultad 5/5 Más de una semana Aptitud para principiantes 25/100
PyPSA/technology-data#281 ·
-
Dificultad 3/5 1-2 días Aptitud para principiantes 48/100
PyPSA/technology-data#276 · 1 comentario ·
Todos los issues de PyPSA/technology-data
Issues similares
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 85/100
Vector35/community-plugins#376 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
py-econometrics/pyfixest#1883 ·
Los mantenedores suelen responder en 1 día
-
bad links in rfc5890.htmlAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
ietf-tools/rfc2html#81 ·
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
mysql/mysql-operator#60 ·
-
Python: Bug: split_plaintext_paragraph / split_markdown_paragraph can return a chunk larger than max_tokensPosiblemente ocupada @xThreeh la tomó hoy. Abiertopython triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
microsoft/semantic-kernel#14566 ·
Los mantenedores suelen responder en 4 días