Skip to content

added perennials and green biorefining in compile_cost_assumptions.py - #255

Open
BertoGBG wants to merge 15 commits into
PyPSA:masterfrom
BertoGBG:perennialization_PR
Open

added perennials and green biorefining in compile_cost_assumptions.py#255
BertoGBG wants to merge 15 commits into
PyPSA:masterfrom
BertoGBG:perennialization_PR

Conversation

@BertoGBG

Copy link
Copy Markdown
Contributor

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

  • [Y ] Code changes are sufficiently documented; i.e. new functions contain docstrings and further explanations may be given in doc.
  • [ Y] Data source for new technologies is clearly stated.
  • Newly introduced dependencies are added to environment.yaml (if applicable).
  • A note for the release notes doc/release_notes.rst of the upcoming release is included.
  • [Y ] I consent to the release of this PR's code under the GPLv3 license.

Comment thread outputs/US/costs_2025.csv Outdated
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,,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a little more detail in the commentary how the concrete value for the investment was obtained from the paper? Thanks!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@euronion

euronion commented May 6, 2026

Copy link
Copy Markdown
Collaborator

Hej @BertoGBG , is the PR ready for another round of review?

@BertoGBG

Copy link
Copy Markdown
Contributor Author

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')).
My rebased PR inherits this, so their CI failure isn't from my changes — the snakemake build and output
regeneration pass. They should go green once master's tests are fixed.

@BertoGBG
BertoGBG requested a review from fneum June 15, 2026 16:01
BertoGBG and others added 4 commits June 23, 2026 18:14
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
@BertoGBG

BertoGBG commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

I changed the perennials names in the output csv from "perennials gbr" to "perennials refining", to match the PR on perennialisation on pypsa-eur.
ready for another round of review @fneum @euronion

@euronion euronion left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread docs/release_notes.rst Outdated
Comment thread inputs/manual_input.csv
Comment on lines +750 to +752
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)"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has this been verified?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"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"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this realistic? Or would a generic guesstimate of e.g. 2%/year like for many other chemistry-related plants be reasonable?

Comment on lines +2782 to +2801
# --- 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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
new_technology_dataframe.loc[(tech_name, "biogas-output"), "unit"] = "MWh/tDM"
new_technology_dataframe.loc[(tech_name, "biogas-output"), "unit"] = "MWh/t_DM"

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants