added perennials and green biorefining in compile_cost_assumptions.py - #255
added perennials and green biorefining in compile_cost_assumptions.py#255BertoGBG wants to merge 15 commits into
Conversation
| perennials gbr,VOM,43.2317,EUR/tDM,https://doi.org/10.1016/B978-0-323-95879-0.50147-8,Includes purchase of perennials and revenue from protein concentrate; incl. wages/maintenance/aux costs (R1),2015.0,, | ||
| perennials gbr,biogas-output,0.1947,MWh/tDM,https://doi.org/10.1016/B978-0-323-95879-0.50147-8,,2015.0,, | ||
| perennials gbr,electricity-input,0.0733,MWh/tDM,https://doi.org/10.1016/B978-0-323-95879-0.50147-8,,2015.0,, | ||
| perennials gbr,investment,1371509.7864,EUR/tDM/h,https://doi.org/10.1016/B978-0-323-95879-0.50147-8,Includes GBR plant and scaled biogas plant without upgrading,2015.0,, |
There was a problem hiding this comment.
Could you add a little more detail in the commentary how the concrete value for the investment was obtained from the paper? Thanks!
There was a problem hiding this comment.
I added comments about the investments and VOM (mostly the reference table), the code/function with in compile_cost_assumptions.py contains direct reference to the tables in the source ( and the link to the course as a comment) so that the calculations are traceable.
|
Hej @BertoGBG , is the PR ready for another round of review? |
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The PR was just rebased and it is ready for review. Heads up: CI on master itself is currently failing — test_get_sheet_location, test_get_data_from_dea, and test_add_carbon_capture fail on a clean master checkout (KeyError: ('cement capture', 'Variable O&M')). |
…ituted by perennials
Matches the corresponding rename on pypsa-eur's perennialisation_PR branch (costs.at["perennials refining", ...] lookups). Renamed the identifier, the function add_perennials_gbr -> add_perennials_refining, its docstring, and the "Upcoming Release" note for this PR (PyPSA#255). Left the "GBR" abbreviation for "green biorefining" untouched elsewhere (docstring summary, comments) since that's legitimate domain terminology describing the process, not the technology's registry name. Regenerated outputs/costs_*.csv and outputs/US/costs_*.csv via `snakemake -f compile_cost_assumptions[_usa]` per this repo's workflow rule (never hand-edit outputs). Diff is exactly the renamed rows, no other values changed. Full test suite (52 tests) and ruff both pass clean on this branch. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mh2EaBSg63Gsi4epA1Rmky
euronion
left a comment
There was a problem hiding this comment.
I don't have access to the publication so I couldn't check the data coming from the paper. Some small comments to be addressed still.
| ethanol from wheat,efficiency,2020,0.295,t_ethanol/t_wheat,2020,"JRC Technical Report doi:10.2760/69179 Table 93","assuming LHV ethanol 7.447 MWh/t and wheat grain moisture 13.5% (Eurostat standard humidity 14%)" | ||
| ethanol from sugar beet,efficiency,2020,0.07777,t_ethanol/t_sugarbeet,2020,"JRC Technical Report doi:10.2760/69179 Table 133","assuming LHV ethanol 7.447 MWh/t and sugar content 16% (Eurostat standard: fresh beet)" | ||
| biodiesel from rapeseed,efficiency,2020,0.4176,t_biodiesel/t_rapeseed,2020,"JRC Technical Report doi:10.2760/69179 Tables 155+159","calculated as: t_crude_oil/t_rapeseed 9% moisture (Eurostat standard humidity 9%) x crude-to-FAME (1/1.0063)" |
There was a problem hiding this comment.
Are you interested in the other process inputs from the JRC document, e.g. electricity or steam input?
|
|
||
| # --- Write to dataframe (match repo conventions) --- | ||
| new_technology_dataframe.loc[(tech_name, "investment"), years] = investment | ||
| new_technology_dataframe.loc[(tech_name, "investment"), "unit"] = "EUR/(tDM h)" |
There was a problem hiding this comment.
| new_technology_dataframe.loc[(tech_name, "investment"), "unit"] = "EUR/(tDM h)" | |
| new_technology_dataframe.loc[(tech_name, "investment"), "unit"] = "EUR/(t_DM*h)" |
| new_technology_dataframe.loc[(tech_name, "FOM"), "currency_year"] = 2020 | ||
|
|
||
| new_technology_dataframe.loc[(tech_name, "VOM"), years] = VOM | ||
| new_technology_dataframe.loc[(tech_name, "VOM"), "unit"] = "EUR/tDM" |
There was a problem hiding this comment.
| new_technology_dataframe.loc[(tech_name, "VOM"), "unit"] = "EUR/tDM" | |
| new_technology_dataframe.loc[(tech_name, "VOM"), "unit"] = "EUR/t_DM" |
| tech_name = "perennials refining" | ||
|
|
||
| # References (store also in "source" below) | ||
| source_r1 = "https://doi.org/10.1016/B978-0-323-95879-0.50147-8" |
There was a problem hiding this comment.
| source_r1 = "https://doi.org/10.1016/B978-0-323-95879-0.50147-8" | |
| source_r1 = "Andrade, Ambye-Jensen: Process Integration and Techno-Economic Assessment of a Green Biorefinery Demonstration Scale Platform for Leaf Protein Production (2022), https://doi.org/10.1016/B978-0-323-95879-0.50147-8" |
There was a problem hiding this comment.
Gives a clearer understanding what the source is in case someone can't infer from the doi
| electricity_input_flow / perennials_input_flow | ||
| ) | ||
| new_technology_dataframe.loc[(tech_name, "electricity-input"), "unit"] = ( | ||
| "MWh/tDM" # verify! |
There was a problem hiding this comment.
| "MWh/tDM" # verify! | |
| "MWh/t_DM" # verify! |
|
|
||
| # Per-variable descriptions (optional but often nice) | ||
| new_technology_dataframe.loc[(tech_name, "investment"), "further description"] = ( | ||
| "DM (Dry Matter or perennial crops). The investment includes green biorefinery plant and a scaleup in capacity for biogas plant without upgrading, Table 4" |
There was a problem hiding this comment.
Can you add the explanation what 'DM' stands for to the further_description of all other entries that use 'DM' in their unit as well? I don't think that people will know without the comment what 'DM' stands for.
| ) | ||
|
|
||
| # Own assumption | ||
| FOM = 0 # %/year |
There was a problem hiding this comment.
Is this realistic? Or would a generic guesstimate of e.g. 2%/year like for many other chemistry-related plants be reasonable?
| # --- Mass & energy balance assumptions (R1) --- | ||
| DM_perennials = 0.18 # dry matter content (t_DM / t_wet) | ||
| ch4_mass_fraction_in_biogas = ( | ||
| 0.348 # mass fraction CH4 in biogas (check definition in R1) | ||
| ) | ||
| flh_y = 4200 # full-load hours per year (green crops harvest May–Oct) | ||
|
|
||
| perennials_input_flow = 40 * DM_perennials # t_DM/h | ||
| perennials_input_annual = perennials_input_flow * flh_y # t_DM/y | ||
|
|
||
| protein_output_flow = 1.4 # t_DM/h (protein concentrate on DM basis) | ||
| protein_output_annual = protein_output_flow * flh_y # t_DM/y | ||
|
|
||
| # (t_biogas / t_DM) * (mass fraction CH4) * (MWh/t_CH4) | ||
| biogas_output_flow = ( | ||
| 0.29 * ch4_mass_fraction_in_biogas * LHV_ch4 | ||
| ) # MWh/h (per t_DM/h basis) | ||
|
|
||
| # electricity input | ||
| electricity_input_flow = 7.33 / 100 * perennials_input_flow |
There was a problem hiding this comment.
You make some assumptions here that I think would be good to have in the further_description or as their own row entries, such that people can understand the values in their context needing to look through the code. Would you agree? If yes, please add some more detail. If no we can also merge without.
| new_technology_dataframe.loc[(tech_name, "biogas-output"), years] = ( | ||
| biogas_output_flow / perennials_input_flow | ||
| ) | ||
| new_technology_dataframe.loc[(tech_name, "biogas-output"), "unit"] = "MWh/tDM" |
There was a problem hiding this comment.
| new_technology_dataframe.loc[(tech_name, "biogas-output"), "unit"] = "MWh/tDM" | |
| new_technology_dataframe.loc[(tech_name, "biogas-output"), "unit"] = "MWh/t_DM" |
Closes # (if applicable).
Changes proposed in this Pull Request
This PR added the technology perennials and green biorefining as "perennials gbr". The technology produces additional biogas from perennial crops.
the changes are implemented in compile_cost_assumptions.py via the function add_perennials_gbr (which is structured similarly to add_carbon_capture)
Checklist
doc.environment.yaml(if applicable).doc/release_notes.rstof the upcoming release is included.