bw2calc
#
Submodules#
Package Contents#
Classes#
An LCI or LCIA calculation. |
|
Solve overdetermined technosphere matrix with more products than activities using least-squares approximation. |
|
Wrapper class for performing LCA calculations with many functional units and LCIA methods. |
|
Traverse a supply chain, following paths of greatest impact. Can handle the differentiation between products and activities, and makes no assumptions about multifunctionality, substitution, or the special status of numbers on the diagonal. |
- class bw2calc.DenseLCA(demand: dict, method: Optional[tuple] = None, weighting: Optional[str] = None, normalization: Optional[str] = None, data_objs: Optional[Iterable[Union[pathlib.Path, fs.base.FS, bw_processing.DatapackageBase]]] = None, remapping_dicts: Optional[Iterable[dict]] = None, log_config: Optional[dict] = None, seed_override: Optional[int] = None, use_arrays: bool = False, use_distributions: bool = False)[source]#
Bases:
bw2calc.lca.LCA
An LCI or LCIA calculation.
Compatible with Brightway2 and 2.5 semantics. Can be static, stochastic, or iterative (scenario-based), depending on the
data_objs
input data..Create a new LCA calculation.
- Parameters
demand (*) – The demand or functional unit. Needs to be a dictionary to indicate amounts, e.g.
{7: 2.5}
.method (*) – LCIA Method tuple, e.g.
("My", "great", "LCIA", "method")
. Can be omitted if only interested in calculating the life cycle inventory.
- Returns
A new LCA object
- solve_linear_system()#
Master solution function for linear system \(Ax=B\).
To most numerical analysts, matrix inversion is a sin.
—Nicolas Higham, Accuracy and Stability of Numerical Algorithms, Society for Industrial and Applied Mathematics, Philadelphia, PA, USA, 2002, p. 260.
We use UMFpack, which is a very fast solver for sparse matrices.
If the technosphere matrix has already been factorized, then the decomposed technosphere (
self.solver
) is reused. Otherwise the calculation is redone completely.
- class bw2calc.LeastSquaresLCA(demand: dict, method: Optional[tuple] = None, weighting: Optional[str] = None, normalization: Optional[str] = None, data_objs: Optional[Iterable[Union[pathlib.Path, fs.base.FS, bw_processing.DatapackageBase]]] = None, remapping_dicts: Optional[Iterable[dict]] = None, log_config: Optional[dict] = None, seed_override: Optional[int] = None, use_arrays: bool = False, use_distributions: bool = False)[source]#
Bases:
bw2calc.lca.LCA
Solve overdetermined technosphere matrix with more products than activities using least-squares approximation.
See also:
Create a new LCA calculation.
- Parameters
demand (*) – The demand or functional unit. Needs to be a dictionary to indicate amounts, e.g.
{7: 2.5}
.method (*) – LCIA Method tuple, e.g.
("My", "great", "LCIA", "method")
. Can be omitted if only interested in calculating the life cycle inventory.
- Returns
A new LCA object
- abstract decompose_technosphere() None #
Factorize the technosphere matrix into lower and upper triangular matrices, \(A=LU\). Does not solve the linear system \(Ax=B\).
Doesn’t return anything, but creates
self.solver
.Warning
Incorrect results could occur if a technosphere matrix was factorized, and then a new technosphere matrix was constructed, as
self.solver
would still be the factorized older technosphere matrix. You are responsible for deletingself.solver
when doing these types of advanced calculations.
- solve_linear_system(solver=lsmr) numpy.ndarray #
Master solution function for linear system \(Ax=B\).
To most numerical analysts, matrix inversion is a sin.
—Nicolas Higham, Accuracy and Stability of Numerical Algorithms, Society for Industrial and Applied Mathematics, Philadelphia, PA, USA, 2002, p. 260.
We use UMFpack, which is a very fast solver for sparse matrices.
If the technosphere matrix has already been factorized, then the decomposed technosphere (
self.solver
) is reused. Otherwise the calculation is redone completely.
- class bw2calc.MultiLCA(cs_name, log_config=None)[source]#
Wrapper class for performing LCA calculations with many functional units and LCIA methods.
Needs to be passed a
calculation_setup
name.This class does not subclass the LCA class, and performs all calculations upon instantiation.
Initialization creates self.results, which is a NumPy array of LCA scores, with rows of functional units and columns of LCIA methods. Ordering is the same as in the calculation_setup.
- property all#
Get all possible databases by merging all functional units
- class bw2calc.MultifunctionalGraphTraversal[source]#
Traverse a supply chain, following paths of greatest impact. Can handle the differentiation between products and activities, and makes no assumptions about multifunctionality, substitution, or the special status of numbers on the diagonal.
As soon as non-diagonal values are allowed, we lose any concept of a reference product. This means that we can trace the edges for an activity (both inputs and outputs, though in the matrix there is no functional difference), but we can’t for a product, as we can’t use the graph structure to determine which activity produced the product. There could be more than one, or even zero, depending on how your mental model of substitution works. Our algorithm is therefore:
Start with products (initially the products in the functional unit)
2. For each product, determine which activities produced it by solving the linear system 3a. For each of these activities, add on to our list of products to consider by looking at the edges for that activity, and excluding the edge which led to our original product 3b. If we have already examined this activity, don’t visit it again 4. Keep iterating over the list of products until we run out of activities or hit our calculation limit
The
.calculate()
function therefore returns the following:{ 'counter': int, # Number of LCA calculations done, 'products': { id: { # id is either the database integer id (if `translate_indices` is True) or the matrix row index 'amount': float # Total amount of this product produced to satisfy the functional unit 'supply_chain_score': float # The total impact of producing this product } }, 'activities': { id: { # id is either the database integer id (if `translate_indices` is True) or the matrix column index 'amount': float # Total amount of this activity produced to satisfy the entire functional unit 'direct_score': float # The impact of the direct emissions associated to this activity and its amount }, 'edges': [{ 'target': int, # product id if type is activity else activity id 'source': int, # activity id if type is product else product id 'type': str, # 'product' or 'activity' 'amount': float, # Total amount of the flow 'exc_amount': float, # Value given in the technosphere matrix 'supply_chain_score': float, # Total impact from the production of this product. Only for type 'product' 'direct_score': float, # Impact from direct emissions of this activity. Only for type 'activity' }] }
As in AssumedDiagonalGraphTraversal, we use a priority queue to examine products in order of their total impact.
This class is written in a functional style, with only class methods.
- classmethod calculate(lca: bw2calc.LCA, cutoff: float = 0.005, max_calc: int = 100000.0, translate_indices: bool = True)#
Traverse the supply chain graph.
- Parameters
lca (*) – An instance of
bw2calc.lca.LCA
.cutoff (*) – Cutoff criteria to stop LCA calculations. Relative score of total, i.e. 0.005 will cutoff if a dataset has a score less than 0.5 percent of the total.
max_calc (*) – Maximum number of LCA calculations to perform.
- Returns
Dictionary of nodes, edges, and number of LCA calculations.
- classmethod clean_small_values(data, kind=dict, cutoff=5e-16)#
- classmethod consolidate_edges(edges)#
- classmethod initialize_heap(lca: bw2calc.LCA, solver: CachingSolver, translate_indices: bool, counter: int)#
Create a priority queue or
heap
to store inventory datasets, sorted by LCA score.Populates the heap with each activity in
demand
. Initial nodes are the functional unit, i.e. the complete demand, and each activity in the functional unit. Initial edges are inputs from each activity into the functional unit.The functional unit is an abstract dataset (as it doesn’t exist in the matrix), and is assigned the index
-1
.
- classmethod traverse(heap: list, solver: CachingSolver, activities: dict, products: dict, edges: list, max_calc: int, cutoff: float, total_score: float, lca: bw2calc.LCA, translate_indices: bool, counter: int)#
Build a directed graph by traversing the supply chain.
Node ids are actually technosphere row/col indices, which makes lookup easier.
- Returns
(nodes, edges, number of calculations)
- classmethod visit_activity(heap: list, activity_index: int, counter: int, activities: dict, products: dict, edges: list, lca: bw2calc.LCA, characterized_biosphere: scipy.sparse.csr_matrix, solver: CachingSolver, cutoff_score: float, origin_product_index: int, translate_indices: bool)#