# -*- coding: utf-8 -*-
"""
Created on Wed Oct 25 09:18:25 2023
@author: mathi
Sequences to determine GHG emissions' from cement industry (combination of IPCC
equations and extensions added to them.
"""
from logging import getLogger
import bonsai_ipcc
from . import elementary
from ._data import concordance, dimension, parameter
logger = getLogger("root")
####################################################################################
# --------------------- Sequence on cement production ---------------------------- #
####################################################################################
[docs]
def production_cement(
year=2011,
region="US",
cement_type="portland",
uncertainty="def",
):
"""
This function calculates different factors related to the production of
cement, namely: the mass of clinker needed to produce the cement considered (in
tonnes), the electricity needed in kWh, the energy (heat) needed in GJ, the gypsum
needed (in tonne), the production of CKD (Cwement Kiln Dust, in tonnes), and of
cement waste during construction (in tonnes).
Parameters
----------
year : integer, optional
Year of the cement production. The default is 2011.
region : string, optional
Region of the cement production. The default is "US".
cement_type : string, optional
Type of cement that is produced. The default is "portland".
uncertainty : string, optional
Defined the type of uncertianty that we want to consider in the calculation. The
default is "def".
Returns
-------
Python object
A Python object os created with different attrobutes that contain the results
mentioned in the description above.
"""
# Initalize variable instance
seq = bonsai_ipcc.industry.mineral.sequence.Sequence(
dimension, parameter, elementary, concordance, uncert=uncertainty
)
logger.info("cement-production sequence started --->")
seq.store_signature(locals())
seq.read_parameter(
name="mass_cement",
table="cement_prod_world",
coords=[year, region],
)
seq.read_parameter(
name="clink_on_cem",
table="c_cl",
coords=[year, region, cement_type],
)
# Mass clinker
mass_clinker = seq.elementary.mass_clinker(
mass_cement=seq.step.mass_cement.value, clink_on_cem=seq.step.clink_on_cem.value
)
seq.store_result(
name="mass_clinker",
value=mass_clinker,
unit="tonnes",
year=year,
)
seq.read_parameter(
name="elec_cement",
table="elec_use",
coords=[year, region],
)
# Electricity consumption for cement production (combining
# calcination + cement mill):
elec_use_cement = seq.elementary.elec_use_cement(
mass_cement=seq.step.mass_cement.value,
elec_intensity=seq.step.elec_cement.value,
)
seq.store_result(
name="elec_use_cement",
value=elec_use_cement,
unit="kWh",
year=year,
)
# Energy needs for the cement production (heat)
seq.read_parameter(
name="energy_cement",
table="energy_cement",
coords=[year, region, cement_type],
)
# energy_need_cement = seq.step.energy_cement.value * seq.step.mass_cement.value
energy_need_cement = seq.elementary.energy_need_cement(
mass_cement=seq.step.mass_cement.value,
energy_cement=seq.step.energy_cement.value,
)
seq.store_result(
name="energy_need_cement",
value=energy_need_cement,
unit="GJ",
year=year,
)
# Gypsum consumption in the cement mill process
seq.read_parameter(
name="gypsum_coeff",
table="gypsum_coeff",
coords=[year, region],
)
gypsum_use_cement = seq.elementary.gypsum_use_cement_mill(
mass_cement=seq.step.mass_cement.value,
gyp_intensity=seq.step.gypsum_coeff.value,
)
seq.store_result(
name="gypsum_use_cement",
value=gypsum_use_cement,
unit="tonnes",
year=year,
)
# Production of CKD that will be sent to landfill
seq.read_parameter(
name="ckd_on_clinker",
table="ckd_on_clinker",
coords=[year, region],
)
seq.read_parameter(
name="coeff_ckd_landfill",
table="coeff_ckd_landfill",
coords=[year, region],
)
ckd_landfill = seq.elementary.ckd_landfill(
mass_clinker=seq.step.mass_clinker.value,
ckd_on_clinker=seq.step.ckd_on_clinker.value,
coeff_ckd_landfill=seq.step.coeff_ckd_landfill.value,
)
seq.store_result(
name="ckd_landfill",
value=ckd_landfill,
unit="tonnes",
year=year,
)
# Waste production from cement during construction
seq.read_parameter(
name="loss_coeff",
table="cement_loss_construction",
coords=[year, region],
)
waste_cement_construction = seq.elementary.waste_cement_construction(
mass_cement=seq.step.mass_cement.value, loss_coeff=seq.step.loss_coeff.value
)
seq.store_result(
name="waste_cement_construction",
value=waste_cement_construction,
unit="tonnes",
year=year,
)
logger.info("---> cement model finished.")
return seq.step
####################################################################################
# --------------- Sequence on mass & carbon balances on cement ------------------- #
####################################################################################
[docs]
def mass_carbon_balance_cement(
year=2011,
region="US",
cement_type="portland",
uncertainty="def",
):
"""
This sequence function checks the carbon and mass balance of the cement production.
More details can be found in the technical documentation on cement.
Parameters
----------
year : integer, optional
Year of the cement production. The default is 2011.
region : string, optional
Region of the cement production. The default is "US".
cement_type : string, optional
Type of cement that is produced. The default is "portland".
uncertainty : string, optional
Defined the type of uncertianty that we want to consider in the calculation. The
default is "def".
Returns
-------
Python object
A Python object os created with different attrobutes that contain the results
mentioned in the description above.
"""
# Initalize variable instance
seq = bonsai_ipcc.industry.mineral.sequence.Sequence(
dimension, parameter, elementary, concordance, uncert=uncertainty
)
logger.info("mass_carbon_balance_cement sequence started --->")
seq.store_signature(locals())
seq.read_parameter(
name="mass_cement",
table="cement_prod_world",
coords=[year, region],
)
seq.read_parameter(
name="clink_on_cem",
table="c_cl",
coords=[year, region, cement_type],
)
seq.read_parameter(
name="cao_in_clinker",
table="cao_in_clinker",
coords=[year, region],
)
# Mass and carbon balances:
m_caco3_supply, delta_mass, delta_c = seq.elementary.mass_carbon_balance(
mass_clinker=seq.step.mass_cement.value * seq.step.clink_on_cem.value,
f_cao_on_clinker=seq.step.cao_in_clinker.value,
)
seq.store_result(
name="m_caco3_supply",
value=m_caco3_supply,
unit="tonnes",
year=year,
)
seq.store_result(
name="carbon_balance",
value=delta_c,
unit="tonnes",
year=year,
)
seq.store_result(
name="mass_balance",
value=delta_mass,
unit="tonnes",
year=year,
)
logger.info("---> cement model finished.")
return seq.step
####################################################################################
# --------------------- Sequence on carbonation on cement ------------------------ #
####################################################################################
[docs]
def carbonation_cement_concrete(
year=2011,
lifetime_use_cement=10,
region="US",
cement_type="portland",
uncertainty="def",
exposure_condition="Exposed outdoor",
compressive_strength="16-23 Mpa",
structure="Wall",
cement_product="concrete",
):
"""
This sequence function calculates the amount of carbonation that takes place in
concrete, depending on the lifetime of use. A global result (over the whole
lifetime) and a yearly result (for each year) is calculated in tonnes of
CO2-absorbed.
Parameters
----------
year : integer, optional
Year of cement production (and by assumption concrete). The default is 2011.
lifetime_use_cement : integer, optional
Number of years that the concrete is used. The default is 10.
region : string, optional
Region where the concrete is used. The default is "US".
cement_type : string, optional
Type of cement that is used to later produce concrete. The default is "portland".
uncertainty : string, optional
Defines the type of uncertainty we want to consider. The default is "def".
exposure_condition : string, optional
Defines the exposure condition of concrete. The default is "Exposed outdoor".
compressive_strength : string, optional
Defines the compressive stremght of concrete. The default is "16-23 Mpa".
structure : string, optional
Defines the type of structure in which the concrete is used. The default is
"Wall".
cement_product : string, optional
Defined the type of cement-product that is considered (in this case, concrete).
The default is "concrete".
Returns
-------
Python object
The Python object contains attributes with the results mentioned in the
description above.
"""
# Initalize variable instance
seq = bonsai_ipcc.industry.mineral.sequence.Sequence(
dimension, parameter, elementary, concordance, uncert=uncertainty
)
logger.info("cement-test sequence started --->")
seq.store_signature(locals())
seq.read_parameter(
name="mass_cement",
table="cement_prod_world",
coords=[year, region],
)
seq.read_parameter(
name="cao_in_clinker",
table="cao_in_clinker",
coords=[year, region],
)
seq.read_parameter(
name="clink_on_cem",
table="c_cl",
coords=[year, region, cement_type],
)
seq.read_parameter(
name="cement_distrib",
table="cement_distrib",
coords=[year, region, cement_product],
)
seq.read_parameter(
name="amount_of_addition",
table="amount_of_addition",
coords=[year, region, cement_type],
)
# Mass clinker
mass_clinker = seq.elementary.mass_clinker(
mass_cement=seq.step.mass_cement.value, clink_on_cem=seq.step.clink_on_cem.value
)
seq.store_result(
name="mass_clinker",
value=mass_clinker,
unit="tonnes",
year=year,
)
# # Calculation of the sponge effect - Option 1: averaged data
# sponge_effect_relative = seq.elementary.calculate_relative_average_sponge_effect(
# cement_production_sponge_effect=seq.parameter.cement_production_sponge_effect,
# sponge_effect_1930_2021=seq.parameter.sponge_effect_1930_2021,
# )
# seq.store_result(
# name="sponge_effect_relative",
# value=sponge_effect_relative,
# unit="none",
# year=year,
# )
# average_co2_uptake = seq.elementary.calculate_average_sponge_effect_through_time(
# sponge_effect_relative=sponge_effect_relative
# )
# seq.store_result(
# name="average_co2_uptake", value=average_co2_uptake, unit="none", year=year
# )
# co2_uptake_var, list_years = seq.elementary.calculate_sponge_effect(
# mass_cement=seq.step.mass_cement.value,
# year=year,
# average_co2_uptake=average_co2_uptake,
# lifetime_use_cement=lifetime_use_cement,
# )
# seq.store_result(
# name="CO2_carbonated",
# value=co2_uptake_var,
# unit="tonnes CO2-eq",
# year=list_years,
# )
# Calculation of the sponge effect - Option 2: Approach with detailed equations
seq.read_parameter(
name="carb_coeff_env",
table="carb_coeff_env",
coords=[year, region, exposure_condition, compressive_strength],
)
seq.read_parameter(
name="carb_coeff_add",
table="carb_coeff_add",
coords=[year, region, seq.step.amount_of_addition.value],
)
seq.read_parameter(
name="carb_coeff_co2",
table="carb_coeff_co2",
coords=[year, region],
)
seq.read_parameter(
name="carb_coeff_cc",
table="carb_coeff_cc",
coords=[year, region],
)
carbonation_rate_concrete = seq.elementary.carbonation_rate(
carb_coeff_env=seq.step.carb_coeff_env.value,
carb_coeff_add=seq.step.carb_coeff_add.value,
carb_coeff_co2=seq.step.carb_coeff_co2.value,
carb_coeff_cc=seq.step.carb_coeff_cc.value,
)
seq.store_result(
name="carbonation_rate_concrete",
value=carbonation_rate_concrete,
unit="mm/year",
year=year,
)
seq.read_parameter(
name="expo_use_life",
table="expo_use_life",
coords=[year, region],
)
carbonation_depth = seq.elementary.carbonation_depth(
carbonation_rate=seq.step.carbonation_rate_concrete.value,
react_time=lifetime_use_cement,
)
seq.store_result(
name="carbonation_depth",
value=carbonation_depth,
unit="mm",
year=year,
)
seq.read_parameter(
name="cement_on_concrete",
table="cement_on_concrete",
coords=[year, region, compressive_strength],
)
seq.read_parameter(
name="thickness",
table="thickness_concrete",
coords=[year, region, structure],
)
concrete_carbonated = seq.elementary.concrete_carbonated(
carbonation_depth=seq.step.carbonation_depth.value,
cement_on_concrete=seq.step.cement_on_concrete.value,
thick=seq.step.thickness.value,
)
seq.store_result(
name="concrete_carbonated",
value=concrete_carbonated,
unit="kg",
year=year,
)
seq.read_parameter(
name="cao_converted_to_caco3",
table="cao_converted_to_caco3",
coords=[year, region],
)
# Option 1: global value over the full lifetime of concrete
co2_carbonated_concrete = seq.elementary.co2_carbonated_concrete(
cement_on_concrete=seq.step.cement_on_concrete.value,
carbonation_rate=seq.step.carbonation_rate_concrete.value,
clink_on_cem=seq.step.clink_on_cem.value,
cao_in_clinker=seq.step.cao_in_clinker.value,
cao_to_caco3=seq.step.cao_converted_to_caco3.value,
thick=seq.step.thickness.value,
react_time=lifetime_use_cement,
mass_cement=seq.step.mass_cement.value,
cement_distrib=seq.step.cement_distrib.value,
)
seq.store_result(
name="co2_carbonated_concrete_global",
value=co2_carbonated_concrete,
unit="kg",
year=year,
)
# Option 2: we want the values for each year over the cement's lifetime
# loop over the lifetime years:
co2_carbonated_concrete_per_year = []
year_list = []
# lifetime_use_cement = seq.step.expo_use_life.value
for y in list(range(1, lifetime_use_cement + 1)):
# Calculation of the CO2 absorbed for the current year
co2_carbonated_concrete_y1 = seq.elementary.co2_carbonated_concrete(
cement_on_concrete=seq.step.cement_on_concrete.value,
carbonation_rate=seq.step.carbonation_rate_concrete.value,
clink_on_cem=seq.step.clink_on_cem.value,
cao_in_clinker=seq.step.cao_in_clinker.value,
cao_to_caco3=seq.step.cao_converted_to_caco3.value,
thick=seq.step.thickness.value,
react_time=y,
mass_cement=seq.step.mass_cement.value,
cement_distrib=seq.step.cement_distrib.value,
)
# Calculation of the CO2 absorbed for the previous year (so we can make the
# difference and get the value for each year and not the accumulated value).
co2_carbonated_concrete_y0 = seq.elementary.co2_carbonated_concrete(
cement_on_concrete=seq.step.cement_on_concrete.value,
carbonation_rate=seq.step.carbonation_rate_concrete.value,
clink_on_cem=seq.step.clink_on_cem.value,
cao_in_clinker=seq.step.cao_in_clinker.value,
cao_to_caco3=seq.step.cao_converted_to_caco3.value,
thick=seq.step.thickness.value,
react_time=y - 1,
mass_cement=seq.step.mass_cement.value,
cement_distrib=seq.step.cement_distrib.value,
)
co2_carbonated_concrete_per_year.append(
round(co2_carbonated_concrete_y1 - co2_carbonated_concrete_y0, 2)
)
year_list.append(year + (y - 1))
seq.store_result(
name="co2_carbonated_concrete_per_year",
value=co2_carbonated_concrete_per_year,
unit="kg",
year=year_list,
)
logger.info("---> cement model finished.")
return seq.step
[docs]
def carbonation_cement_mortar(
year=2011,
lifetime_use_cement=10,
region="US",
cement_type="portland",
uncertainty="def",
mortar_type="rendering",
exposure_condition="Exposed outdoor",
compressive_strength="16-23 Mpa",
structure="Wall",
cement_product="mortar",
):
"""
This sequence function calculates the amount of carbonation that takes place in
mortar, depending on the lifetime of use. A global result (over the whole
lifetime) and a yearly result (for each year) is calculated in tonnes of
CO2-absorbed.
Parameters
----------
year : integer, optional
Year of cement production (and by assumption concrete). The default is 2011.
lifetime_use_cement : integer, optional
Number of years that the concrete is used. The default is 10.
region : string, optional
Region where the concrete is used. The default is "US".
cement_type : string, optional
Type of cement that is used to later produce concrete. The default is "portland".
uncertainty : string, optional
Defines the type of uncertainty we want to consider. The default is "def".
mortar_type : string, optional
Defined the type of mortar that is considered. The default is "rendering".
exposure_condition : string, optional
Defines the exposure condition of mortar. The default is "Exposed outdoor".
compressive_strength : string, optional
Defines the compressive stremght of mortar. The default is "16-23 Mpa".
structure : string, optional
Defines the type of structure in which the mortar is used. The default is
"Wall".
cement_product : string, optional
Defined the type of cement-product that is considered (in this case, mortar).
The default is "mortar".
Returns
-------
Python object
The Python object contains attributes with the results mentioned in the
description above
"""
# Initalize variable instance
seq = bonsai_ipcc.industry.mineral.sequence.Sequence(
dimension, parameter, elementary, concordance, uncert=uncertainty
)
logger.info("cement-carbonation-rendering-mortar sequence started --->")
seq.store_signature(locals())
seq.read_parameter(
name="mass_cement",
table="cement_prod_world",
coords=[year, region],
)
seq.read_parameter(
name="cao_in_clinker",
table="cao_in_clinker",
coords=[year, region],
)
seq.read_parameter(
name="clink_on_cem",
table="c_cl",
coords=[year, region, cement_type],
)
seq.read_parameter(
name="coeff_mortar_on_cement",
table="cement_distrib",
coords=[year, region, cement_product],
)
seq.read_parameter(
name="type_mortar_use",
table="type_mortar_use",
coords=[year, region, mortar_type],
)
seq.read_parameter(
name="carbonation_rate_rendering_mortar",
table="carb_coeff_mortar",
coords=[year, region, cement_type, compressive_strength, exposure_condition],
)
seq.read_parameter(
name="thickness",
table="thickness_mortar",
coords=[year, region, mortar_type],
)
seq.read_parameter(
name="cao_converted_to_caco3",
table="cao_converted_to_caco3",
coords=[year, region],
)
seq.read_parameter(
name="expo_use_life",
table="expo_use_life",
coords=[year, region],
)
# Option 1: global value over the full lifetime of cement
co2_carbonated_mortar = seq.elementary.co2_carbonated_mortar(
mass_cement=seq.step.mass_cement.value,
coeff_mortar_on_cement=seq.step.coeff_mortar_on_cement.value,
ratio_mortar_type=seq.step.type_mortar_use.value,
carb_coeff_mortar=seq.step.carbonation_rate_rendering_mortar.value,
react_time=lifetime_use_cement,
thick=seq.step.thickness.value,
clink_on_cem=seq.step.clink_on_cem.value,
cao_in_clinker=seq.step.cao_in_clinker.value,
cao_to_caco3=seq.step.cao_converted_to_caco3.value,
)
seq.store_result(
name="co2_carbonated_mortar_global",
value=co2_carbonated_mortar,
unit="kg",
year=year,
)
# Option 2: we want the values for each year over the cement's lifetime
# loop over the lifetime years:
co2_carbonated_mortar_per_year = []
year_list = []
# lifetime_use_cement = seq.step.expo_use_life.value
for y in list(range(1, lifetime_use_cement + 1)):
# Calculation of the CO2 absorbed for the current year
co2_carbonated_mortar_y1 = seq.elementary.co2_carbonated_mortar(
mass_cement=seq.step.mass_cement.value,
coeff_mortar_on_cement=seq.step.coeff_mortar_on_cement.value,
ratio_mortar_type=seq.step.type_mortar_use.value,
carb_coeff_mortar=seq.step.carbonation_rate_rendering_mortar.value,
react_time=y,
thick=seq.step.thickness.value,
clink_on_cem=seq.step.clink_on_cem.value,
cao_in_clinker=seq.step.cao_in_clinker.value,
cao_to_caco3=seq.step.cao_converted_to_caco3.value,
)
# Calculation of the CO2 absorbed for the previous year (so we can make the
# difference and get the value for each year and not the accumulated value).
co2_carbonated_mortar_y0 = seq.elementary.co2_carbonated_mortar(
mass_cement=seq.step.mass_cement.value,
coeff_mortar_on_cement=seq.step.coeff_mortar_on_cement.value,
ratio_mortar_type=seq.step.type_mortar_use.value,
carb_coeff_mortar=seq.step.carbonation_rate_rendering_mortar.value,
react_time=y - 1,
thick=seq.step.thickness.value,
clink_on_cem=seq.step.clink_on_cem.value,
cao_in_clinker=seq.step.cao_in_clinker.value,
cao_to_caco3=seq.step.cao_converted_to_caco3.value,
)
co2_carbonated_mortar_per_year.append(
round(
co2_carbonated_mortar_y1 - co2_carbonated_mortar_y0,
2,
)
)
year_list.append(year + (y - 1))
seq.store_result(
name="co2_carbonated_mortar_per_year",
value=co2_carbonated_mortar_per_year,
unit="kg",
year=year_list,
)
logger.info("---> cement model finished.")
return seq.step