bw2calc.partitioned_lca#

Classes#

PartitionedMonteCarloLCA

Monte Carlo LCA that pre-solves a static background system once.

Functions#

_find_production_exchanges(mm)

Run all production-exchange heuristics and return whatever was found.

Module Contents#

class bw2calc.partitioned_lca.PartitionedMonteCarloLCA(demand: dict[int, float], static_databases: list, data_objs: list, seed_override: int | None = None)[source]#

Bases: collections.abc.Iterator

Monte Carlo LCA that pre-solves a static background system once.

Splits the full system into a static (background) part and a stochastic (foreground) part. The static system is solved deterministically for each product demanded across the static/stochastic boundary (interface products), producing aggregated biosphere vectors. These are stored in an in-memory dynamic datapackage that is combined with the stochastic packages for each Monte Carlo iteration.

This avoids rebuilding and solving the (typically large) background matrix on every iteration — only the foreground matrix is resampled.

Parameters:
  • demand (dict) – Functional unit: {activity_or_product_id: amount}. Must be in the stochastic system.

  • static_databases (list[str]) – Names of databases to treat as static (e.g. ["biosphere3", "ecoinvent 3.10"]).

  • data_objs (list) – All datapackages: stochastic LCI + static LCI + LCIA method. Packages for databases listed in static_databases are identified by their metadata["name"] field, which must equal bw_processing.clean_datapackage_name(database_name).

  • seed_override (int, optional) – RNG seed passed to the inner stochastic LCA.

Notes

All LCI datapackages must contain a database_dependencies key in their metadata, which is written by bw2data >= 4.7.

Design note: composition vs. subclassing#

This class uses composition: it builds an internal ._lca instance from the stochastic packages plus the pre-solved dynamic datapackage, and delegates properties to it. An alternative would be to subclass LCA and override load_lci_data() to perform the same partitioning — classify packages, pre-solve the static system, inject the dynamic datapackage, replace self.packages, then call super().load_lci_data(). That approach would give full inheritance of all current and future LCA attributes without explicit delegation.

The reason composition was chosen instead:

  • Package list mutation. The override would need to replace self.packages (set from data_objs in __init__) with the filtered stochastic+dynamic list mid-lifecycle, which is non-obvious and makes self.packages inconsistent with self.data_objs.

  • Matrix semantics. Whether composed or subclassed, technosphere_matrix is the reduced aggregated-proxy matrix, not the full combined static+stochastic system. Subclassing makes this less visible rather than resolving it.

_build_dynamic_datapackage() bw_processing.DatapackageBase[source]#

Solve the static system for each interface product; return dynamic datapackage.

static _check_for_cycles(graph: dict) None[source]#
_classify_packages(packages)[source]#

Classify packages into static LCI, stochastic LCI, and method buckets.

Classification happens at the resource-group level so that a single datapackage containing groups for different matrices or different databases is split correctly. Each resource group has a single matrix label, so we use dp.groups to iterate and dp.exclude({"group": name}) to produce filtered sub-packages.

Group-to-database matching uses the bw2data naming convention where a group is named clean_datapackage_name(db_name + " " + matrix_type) — i.e. it starts with clean_datapackage_name(db_name) followed by _. If no group-name match is found, the check falls back to the package-level metadata["name"].

_validate() None[source]#
keep_first_iteration() None[source]#
lci() None[source]#

Pre-solve the static system, build the dynamic datapackage, and run the first LCI.

lcia() None[source]#
property biosphere_matrix[source]#
property characterization_matrix[source]#
property characterized_inventory[source]#
demand[source]#
property dicts[source]#
property inventory[source]#
property score: float[source]#
seed_override = None[source]#
static_databases[source]#
property supply_array[source]#
property technosphere_matrix[source]#
bw2calc.partitioned_lca._find_production_exchanges(mm: matrix_utils.MappedMatrix)[source]#

Run all production-exchange heuristics and return whatever was found.

Same logic as bw_graph_tools.guess_production_exchanges but does not raise UnclearProductionExchange when some columns are unresolved. This is intentional: we call this on a non-square stochastic-only matrix whose unresolved rows are exactly the interface products we want to identify.

Retains the other checks from guess_production_exchanges: raises ValueError for an empty matrix or mismatched row/column result arrays.

Returns (row_indices, col_indices) — integer arrays of matrix row/column indices where production exchanges were found. Unresolved columns are simply absent.