Skip to content

Flow Mapping

Flow mapping is the process of linking elementary flows in your LCA databases to characterization factors in your LCIA methods. Good mapping coverage is essential for accurate LCIA results.

Different databases and methods use different names for the same substance. For example, “Carbon dioxide, fossil” in EcoSpold 2 might be “CO2 (fossil)” in an ILCD method. VoLCA resolves these differences automatically through a matching cascade.

For each characterization factor in a method, VoLCA tries to match it to a database flow in this order; the first hit wins, and the strategy that matched is recorded:

StepStrategyDescription
1UUIDexact elementary-flow UUID match
2CASCAS-number match (compartment-aware)
3Namenormalized-name match (compartment-aware)
4Synonymmatched via a loaded synonym group (e.g. "CO2""Carbon dioxide, fossil")
-Unmatchednone of the above hit - the flow stays uncharacterized and contributes nothing to the score

The cascade above runs once, when a method is loaded: it attaches each of the method’s factor lines to a database flow. Scoring asks the opposite question, one flow at a time: which factor applies to this flow? That lookup has more rungs, because a flow can be reached without any factor line having resolved to it. In order:

StepFound byDescription
1flow idthe method declares a factor for this exact flow
2same unita factor line declared in this flow’s own unit, for a name that carries a unit suffix
3exact namename and compartment match a factor line
4long-term defaulta delayed emission takes the method’s long-term default
5compartment defaultthe method’s default for the whole compartment, when it sets none for this subcompartment
6CASa factor for the same substance, found by CAS number
7any subcompartmentthe factor is the same in every subcompartment here, so the subcompartment does not matter
8base substancethe flow’s name ends in a region the method does not distinguish
9energy contentan energy resource takes its family’s factor per unit of energy, bridged by the calorific value in its name
10base elementa graded ore takes the factor of the element its amount measures

Steps 2 and 5 to 8 are refused when the flow’s subcompartment says the factor does not belong there: a freshwater factor never reaches an emission to the sea if the method names sea water anywhere, and a surface-water toxicity factor never reaches a long-term groundwater emission.

Both cascades leave a trail, and one call reads it back:

Terminal window
GET /api/v1/db/{db}/method/{method}/explain-cf/{flow}

The explanation field is a list of sentences the engine writes itself. Show them as they are rather than rewording the codes:

The method sets no factor for this flow’s subcompartment, so its default for the whole compartment, “Carbon dioxide, fossil”, applies.

That line was tied to this flow’s name through a known synonym when the method was loaded.

The factor applied is 1.0 kg CO2 eq per kg.

Alongside them, match names the rung, the method line and the strategy that attached it, stepsTried lists the rungs walked before the one that answered (including any refused by a subcompartment rule), and outcome is one of three:

  • characterized, a factor applies;
  • conversion_refused, a factor was found but the flow’s unit cannot be converted to the basis the factor is written in, so the flow scores nothing while looking characterized;
  • no_factor, nothing in the method reaches this flow.

In the web interface, the same answer opens under any row of the Contributing Flows table. Each row also carries the short version, the “Found by” column, so a whole table is annotated without asking per row. A blank there means the method’s tables never walked that flow, which a flow arriving from a dependency database has not been; it does not mean the flow is uncharacterized.

Terminal window
# Summary: matched/unmatched counts and rates
volca --config volca.toml --db ecoinvent flow-mapping <METHOD_UUID>
# Detailed: which CFs matched and by what strategy
volca --config volca.toml --db ecoinvent flow-mapping <METHOD_UUID> --matched
# Gaps: CFs with no database match
volca --config volca.toml --db ecoinvent flow-mapping <METHOD_UUID> --unmatched
# Gaps: database flows with no characterization
volca --config volca.toml --db ecoinvent flow-mapping <METHOD_UUID> --uncharacterized

Bridged names: coverage an exact-name tool would miss

Section titled “Bridged names: coverage an exact-name tool would miss”

The cascade above is a strength when you compute in VoLCA, but it hides a portability trap. When a database names a substance differently from the method that characterizes it - Bromomethane versus Methane, bromo-, Halon 1001, same CAS number - VoLCA still scores the flow by matching on the CAS number or a synonym. A tool that matches factors by their exact name, as SimaPro and many downstream consumers do, has no such bridge: it scores that flow as zero, without warning.

The characterization-coverage report lists exactly those flows - the ones a method scores only through a bridge - grouped under the name the method itself uses, so the fix is to rename the database’s flow to that name. It reports one entry per loaded method collection, so two versions of a method can be compared side by side.

Terminal window
# Every flow a method scores only through a name bridge, per loaded collection
GET /api/v1/db/{db}/characterization-coverage

Flow synonym sets teach VoLCA how to translate flow names between systems. You can:

  1. Use a pre-built synonym set (shipped with VoLCA for common database/method combinations)
  2. Add a custom CSV synonym set

Register a custom set in volca.toml (see Configuration):

[[flow-synonyms]]
name = "my-synonyms"
path = "/data/my-synonyms.csv"
active = true

The CSV has a name1,name2 header - one synonym pair per row. A running server can also accept one at runtime through the web UI or POST /api/v1/flow-synonyms/upload.

When you have multiple databases loaded (e.g. ecoinvent + agribalyse), VoLCA can link flows between them using depends in the config:

[[databases]]
name = "agribalyse"
path = "/data/agribalyse4.csv"
load = true
depends = ["ecoinvent"] # background flows resolved in ecoinvent

After loading, finalize the cross-database links:

Terminal window
# Via API
POST /api/v1/db/agribalyse/finalize

This resolves agribalyse’s background activities against ecoinvent, enabling full inventory computation across databases.

GET /api/v1/db/{db}/method/{methodId}/mapping - coverage stats
GET /api/v1/db/{db}/method/{methodId}/flow-mapping - per-flow mapping detail
GET /api/v1/db/{db}/characterization-coverage - flows scored only through a name bridge
GET /api/v1/db/{db}/method/{methodId}/explain-cf/{flowId} - why one flow scores with its factor
{ "name": "get_flow_mapping", "arguments": { "database": "ecoinvent", "method_id": "..." } }
{ "name": "get_characterization_coverage", "arguments": { "database": "agribalyse" } }
{ "name": "explain_cf", "arguments": { "database": "ecoinvent", "method_id": "...", "flow_id": "..." } }
  • Flow Mapping Audit - detect and close mapping gaps using the post-scoring suggester, compare_impacts, and the PubChem synonym snapshot.