LCA Calculations#
Single Functional Unit and LCIA Set#
How do I define a functional unit?#
A functional unit is some amount of one or more products. Because chimaera process+products act like products (see the overview documentation), they can also be used as functional units.
Brightway wants functional units to be provided as a dictionary, with keys given the product Nodes
, and values giving the amount of each product. A single functional unit can have one or more products.
{my_node: 42, my_other_node: 7}
How do I calculate an life cycle inventory?#
my_functional_unit, data_objs, _ = bd.prepare_lca_inputs({my_node: 42})
my_lca = bc.LCA(demand=my_functional_unit, data_objs=data_objs)
my_lca.lci()
This will create my_lca.inventory
, a matrix with the life cycle inventory data, with rows of biosphere flows and columns of processes.
How do I calculate a characterized inventory?#
my_functional_unit, data_objs, _ = bd.prepare_lca_inputs(
{my_node: 42},
method=('<impact>', '<category>')
)
my_lca = bc.LCA(demand=my_functional_unit, data_objs=data_objs)
my_lca.lci()
my_lca.lcia()
This will create my_lca.characterized_inventory
, a matrix with the life cycle inventory data, with rows or biosphere flows and columns of processes.
How do I calculate a normalized inventory?#
my_functional_unit, data_objs, _ = bd.prepare_lca_inputs(
{my_node: 42},
method=('<impact>', '<category>'),
normalization=('<normalization>', '<factors>')
)
my_lca = bc.LCA(demand=my_functional_unit, data_objs=data_objs)
my_lca.lci()
my_lca.lcia()
This will create my_lca.normalized_inventory
, a matrix with the normalized life cycle inventory data, with rows or biosphere flows and columns of processes.
How do I calculate a weighted inventory?#
my_functional_unit, data_objs, _ = bd.prepare_lca_inputs(
{my_node: 42},
method=('<impact>', '<category>'),
weighting=('<weighting>', '<factors>')
)
my_lca = bc.LCA(demand=my_functional_unit, data_objs=data_objs)
my_lca.lci()
my_lca.lcia()
This will create my_lca.weighted_inventory
, a matrix with the weighted life cycle inventory data, with rows or biosphere flows and columns of processes.
Weighting can be done with normalization, but does not require normalization.
How do I get the LCA score after calculating a characterized inventory, possibly including normalization and/or weighting?#
my_lca.score
How do I see the most important elements in the result matrix?#
my_lca.to_dataframe(matrix_label="characterized_inventory")
See bw2calc.lca.LCA.to_dataframe
for more information on this functionality.
How do I filter down to a row in the inventory
or <any>_inventory
matrix?#
Rows in these matrices are biosphere flows.
row_index = lca.dicts.biosphere[my_biosphere_flow_node.id]
filtered_matrix = lca.inventory[row_index, :]
filtered_matrix = lca.characterized_inventory[row_index, :]
filtered_matrix = lca.normalized_inventory[row_index, :]
filtered_matrix = lca.weighted_inventory[row_index, :]
How do I filter down to a column in the inventory
or characterized_inventory
matrix?#
Columns in these matrices are processes.
col_index = lca.dicts.activity[my_process_node.id]
filtered_matrix = lca.inventory[:, col_index]
filtered_matrix = lca.characterized_inventory[:, col_index]
filtered_matrix = lca.normalized_inventory[:, col_index]
filtered_matrix = lca.weighted_inventory[:, col_index]
How do I go from matrix indices to Node
objects?#
First, you need to find out what kind of object you need to look up. Assuming you have created an LCA instance lca_instance
:
In the
technosphere_matrix
,inventory
, and all<any>_inventory
matrices, columns are processes. Uselca_instance.dicts.activity
.In the
technosphere_matrix
, and in thedemand_array
, rows are products. Uselca_instance.dicts.product
.In the
biosphere_matrix
,inventory
, and all<any>_inventory
matrices, rows are biosphere flows. Uselca_instance.dicts.biosphere
.The
characterization_matrix
,normalization_matrix
, andweighting_matrix
are all diagonal matrices, with both rows and columns being biosphere flows. Uselca_instance.dicts.biosphere
.
You can then use dicts.<foo>.reversed
to go from row or column indices to Nodes
:
bd.get_node(id=my_lca.dicts.activity.reversed[my_column_index])
bd.get_node(id=my_lca.dicts.product.reversed[my_row_index])
Multiple Functional Units and LCIA Sets#
How do I calculate an life cycle inventory for multiple functional units?#
For the MultiLCA
class, we need to label each functional unit:
functional_units = {
"Ξ³": {node_1.id: 3.9},
"Ξ΅": {node_2.id: 6.2},
}
data_objs = bd.get_multilca_data_objs(functional_units, {})
lca = bc.MultiLCA(
demands=functional_units,
method_config={},
data_objs=data_objs,
)
lca.lci()
Functional unit data types
In MultiLCA
functional units, the keys must be integer ids, not Node
instances
If your functional units will only have a single product node, you can use the Node
object itself as the dictionary key:
functional_units = {
node_1: {node_1.id: 4.88},
node_2: {node_2.id: 11},
}
This will create lca.inventories
, a dictionary which gives inventory matrices for each combination of functional unit label and impact category.
{
("Ξ³",): sparse_matrix,
("Ξ΅",): sparse_matrix,
}
How do I calculate a life cycle impact assessment for multiple functional units and a combination of LCIA impact categories, normalizations, and weightings?#
We start by describing how the impact categories, normalization, and weightings are related. The safest way to do this is by creating an instance of bw2calc.MethodConfig
; the bw2calc.method_config.MethodConfig
documentation describes how to provide this data.
method_config = bc.MethodConfig(<some_data>)
For the MultiLCA
class, we need to label each functional unit in a dictionary:
functional_units = {
"Ξ³": {node_1.id: 1},
"Ξ΅": {node_2.id: 2},
}
Finally, we need to get the datapackages needed for all inventory databases and LCIA steps. We can then create a MultiLCA
instance:
data_objs = bd.get_multilca_data_objs(functional_units, method_config)
lca = bc.MultiLCA(
demands=functional_units,
method_config=impact_categories,
data_objs=data_objs,
)
lca.lci()
lca.lcia()
You should also do lca.normalization()
and lca.weighting()
if those steps have data given in method_config
.
The results are provided as dictionaries, with keys showing which weighting, normalization, and characterization methods were applied for each functional unit. For example, if method_config
was:
method_config = bd.MethodConfig(
impact_categories=[
('<impact_category>', '<a>'),
('<impact_category>', '<b>'),
]
)
Then lca.characterized_inventories
would be the following dictionary:
{
(('<impact_category>', '<a>'), "Ξ³"): sparse_matrix,
(('<impact_category>', '<a>'), "Ξ΅"): sparse_matrix,
(('<impact_category>', '<b>'), "Ξ³"): sparse_matrix,
(('<impact_category>', '<b>'), "Ξ΅"): sparse_matrix,
}
Additional elements would be added to the dictionary keys if normalization and weighting were included.
As these dictionaries have multiple matrices at each calculation step, the MultiLCA
attributes are plural:
supply_array
βsupply_arrays
inventory
βinventories
characterized_inventory
βcharacterized_inventories
normalized_inventory
βnormalized_inventories
weighted_inventory
βweighted_inventories
score
βscores
Stochastic LCA Calculations (Monte Carlo)#
Both LCA
and MultiLCA
classes support stochastic calculations using Monte Carlo. New values for all matrices can be generated from probability distribution functions, or from pre-calculated arrays of sample or population values.
How do I use probability distribution functions in stochastic LCA?#
bc.LCA(..., use_distributions=True)
bc.MultiLCA(..., use_distributions=True)
How do I use presampled values from arrays in my datapackages?#
bc.LCA(..., use_arrays=True)
bc.MultiLCA(..., use_arrays=True)
You can use both use_distributions
and use_arrays
in a calculation.
How do I generate a new set of results when doing stochastic LCA?#
next(lca_object)
This will draw new data samples and generate new versions of all matrices defined, including characterization, normalization, and weighting, solve the linear system, and generate all result matrices.
You can also use this in anything that needs the iterator protocol, like list comprehensions:
results = [lca.score for _ in zip(lca, range(10))]
But you can also advance the lca
object manually:
for _ in range(10):
next(lca)
do_something_with_lca_result_matrices(lca)