Water Scarcity GFM
The Water Scarcity Gap Filling Module calculates the water scarcity footprint of food products by combining product-specific water consumption data with regional water stress indices. This approach accounts for the fact that water consumption in water-scarce regions has a greater environmental impact than the same consumption in water-abundant regions.
Quick Reference
| Property | Description |
|---|---|
| Runs on | ModeledActivityNode with FoodProductFlowNode parent containing a product name |
| Dependencies | OriginGapFillingWorker |
| Key Input | Product type (FoodEx2 term), origin country |
| Output | Scarce water consumption flow in cubic meters |
| Trigger | Product matched to a water scarcity footprint identifier |
When It Runs
The module triggers when:
- A
ModeledActivityNodehas a parentFoodProductFlowNodewith a product name - The product is matched to a water scarcity footprint identifier in the glossary
- The module is scheduled on the leaf Brightway node (at the origin)
Key Output
The module adds a scarce water consumption flow to the calculation graph:
- Scarce Water Consumption: Measured in cubic meters (m3) per kilogram of product
- Connected to an
ElementaryResourceEmissionNodefor impact calculation
Scientific Methodology
The water scarcity model uses Water Stress Index (WSI) factors provided by Scherer and Pfister (2016). This methodology explicitly includes regional water stress as a weighing factor for freshwater consumption, providing a more environmentally meaningful measure than raw water volume alone.
Water Stress Index Approach
The water scarcity footprint is calculated using the formula:
Scarce Water [L/kg] = Blue Water Consumption [L/kg] * Water Stress Index [dimensionless]
Where:
- Blue Water Consumption: The amount of surface and groundwater consumed during production
- Water Stress Index: A regional factor representing water scarcity (0 to 1 scale)
Regional Water Stress
Water stress depends on:
- The amount of water consumed in a region compared to naturally available water from precipitation
- Corrections for water that is returned to the watershed (for example, after cooling in electricity production)
The database includes differentiated water scarcity factors for 162 countries, allowing for accurate regional assessments.
Calculation Flow
Product Amount [g] -> Convert to [kg] -> WSI Factor [L scarce water/kg] -> Scarce Water [L]
The calculation is performed at the lowest graph level and aggregated up to the main product.
Implementation Details
Data Source
Water scarcity factors are stored in EDB_water_expected_wsi_per_kg_country_excel_corrected.xlsx, which contains:
- Product identifiers (WS_ID)
- Country-specific WSI factors for 162 countries
- Median values for fallback calculations
Matching Logic
Products are matched to water scarcity data through:
- FoodEx2 terms from the product name
- Glossary links that map term combinations to water scarcity identifiers
water_scarcity_term_uid = self.gfm_factory.linked_water_scarcity_terms.get(
frozenset([term.uid for term in parent_flow_product_name_terms])
)
Country Code Handling
The module handles country codes as follows:
- Retrieves the
flow_locationproperty from the product or parent nodes - Converts 3-letter ISO codes to 2-letter codes using
iso_3166_map_3_to_2_letter - Looks up the country-specific WSI factor
Fallback Behavior
| Scenario | Behavior |
|---|---|
| No origin found | Uses median of all available countries |
| Multiple origins found | Uses median of all available countries |
| Origin not in WSI table | Uses median for that product across all countries |
| Product not in WSI table | Water scarcity set to zero |
| Product has no WSI ID | Water scarcity set to zero |
Transport Exclusion
The module skips transport-related flows to avoid double-counting:
if product_name_term.sub_class_of == self.gfm_factory.root_transport_term.uid:
transport_term = True
if transport_term:
continue
Dried Product Handling
For ingredients that are subdivided into fresh and dried versions (via the Water Loss GFM):
- Water scarcity is calculated for the fresh ingredient amount
- Water scarcity is also calculated for the fresh ingredient amount corresponding to the dried version
- This correctly accounts for the greater amount of fresh product needed to produce dried versions
Graph Modifications
The module performs the following graph modifications:
Step 1: Remove Original Edge
remove_edge_mutation = RemoveEdgeMutation(
from_node_uid=parent_flow.uid,
to_node_uid=self.node.uid,
)
Step 2: Create Water Consumption Activity
water_consumption_activity = FoodProcessingActivityNode.model_construct(
uid=UuidStr(uuid4()),
production_amount=self.node.production_amount.duplicate(),
)
Step 3: Re-establish Flow Connections
The module creates a new food flow node between the water consumption activity and the original Brightway node.
Step 4: Add Scarce Water Flow
scarce_water_consumption_flow = FlowNode.model_construct(
uid=UuidStr(uuid4()),
product_name=NamesProp.unvalidated_construct(
terms=[
GlossaryTermProp.unvalidated_construct(
term_uid=self.gfm_factory.scarce_water_consumption_term.uid
)
]
),
amount_in_original_source_unit=QuantityProp.unvalidated_construct(
# Negative sign indicates consumption
value=-production_amount_in_kg * scarce_water_consumption_m3_per_kg,
unit_term_uid=self.gfm_factory.cubic_meter_term.uid,
for_reference=ReferenceAmountEnum.amount_for_activity_production_amount,
),
)
Step 5: Connect to Elementary Resource Node
The scarce water flow is connected to a shared ElementaryResourceEmissionNode for impact assessment.
Full Code Reference
Worker Scheduling Logic
def should_be_scheduled(self) -> bool:
"""Whether to schedule water scarcity gap filling worker."""
if (
isinstance(self.node, ModeledActivityNode)
and self.node.get_parent_nodes()
and any(
isinstance(parent_node, FoodProductFlowNode) and parent_node.product_name
for parent_node in self.node.get_parent_nodes()
)
):
return True
return False
Execution Readiness Check
def can_run_now(self) -> GapFillingWorkerStatusEnum:
"""Whether water scarcity gap filling worker can be executed."""
global_gfm_state = self.get_global_gfm_state()
# Wait for origin determination
if global_gfm_state.get(OriginGapFillingWorker.__name__, 0) == NodeGfmStateEnum.scheduled.value:
return GapFillingWorkerStatusEnum.reschedule
# Only run on leaf Brightway node
if any(isinstance(sub_node, FoodProductFlowNode) for sub_node in self.node.get_sub_nodes()):
return GapFillingWorkerStatusEnum.cancel
return GapFillingWorkerStatusEnum.ready
Water Scarcity Calculation
# Convert production amount to kilograms
production_amount_unit: Term = self.node.production_amount.get_unit_term()
production_amount_in_kg = UnitWeightConverter.convert_between_same_unit_types(
self.node.production_amount.value,
production_amount_unit,
self.gfm_factory.kilogram_term,
"mass-in-g",
)
# Look up country-specific factor
if flow_country_code in water_scarcity_term.data:
scarce_water_consumption_m3_per_kg = water_scarcity_term.data[flow_country_code]
else:
# Fallback to median
scarce_water_consumption_m3_per_kg = water_scarcity_term.data["median"]
# Calculate scarce water consumption
scarce_water_value = -production_amount_in_kg * scarce_water_consumption_m3_per_kg
Factory Initialization
The WaterScarcityGapFillingFactory initializes the following cached data:
Unit Terms
self.cubic_meter_term = self.service_provider.glossary_service.get_term_by_xid_ag_uid(
("EOS_cubic-meter", root_unit_term.access_group_uid)
)
self.liter_term = self.service_provider.glossary_service.get_term_by_xid_ag_uid(
("EOS_liter", root_unit_term.access_group_uid)
)
self.kilogram_term = self.service_provider.glossary_service.get_term_by_xid_ag_uid(
("EOS_kilogram", root_unit_term.access_group_uid)
)
Glossary Links Cache
water_scarcity_glossary_links = await self.service_provider.glossary_link_service.get_glossary_links_by_gfm(
gap_filling_module="WaterScarcity"
)
for water_scarcity_glossary_link in water_scarcity_glossary_links:
self.linked_water_scarcity_terms[
frozenset(water_scarcity_glossary_link.term_uids)
] = water_scarcity_glossary_link.linked_term_uid
Calculation Example
Scenario: 500g of tomatoes from Spain
Step 1: Convert to Kilograms
500g = 0.5 kg
Step 2: Look Up WSI Factor
From the water scarcity database for tomatoes in Spain:
WSI Factor = 142.3 L scarce water/kg
Step 3: Calculate Scarce Water
Scarce Water = 0.5 kg * 142.3 L/kg = 71.15 L scarce water
Step 4: Convert to Cubic Meters
71.15 L = 0.07115 m3 scarce water
Comparison by Origin
The same tomatoes from different origins would have different impacts:
| Origin | WSI Factor (L/kg) | Scarce Water (L) for 500g |
|---|---|---|
| Spain | 142.3 | 71.15 |
| Netherlands | 12.8 | 6.40 |
| Morocco | 285.6 | 142.80 |
| Italy | 98.4 | 49.20 |
This demonstrates why origin-specific water stress factors are critical for accurate environmental assessment.
Known Limitations
Data Coverage
- 162 countries covered: Most major food-producing countries are included
- Missing countries: Some countries may not have WSI data; median values are used as fallback
- Product coverage: Not all food products have assigned water scarcity IDs
Inheritance Limitations
The current implementation does not support inheritance of water scarcity IDs between related products:
- In the legacy system, products could inherit WSI IDs from linked products
- In the current implementation, products without a direct WSI ID receive zero water scarcity
- This may result in underestimation for some products (for example, specialty flours that could inherit from general flour)
Data Resolution
- Country-level resolution only (no sub-national differentiation)
- Does not account for seasonal variations in water stress
- Uses expected (average) values rather than actual year-specific data
Median Fallback
When median values are used (unknown origin, missing country data), no warning is displayed in the output. This is a known behavior documented in science reviews.
Data Sources
Primary Source
Scherer, L., & Pfister, S. (2016). Global water footprint assessment of hydropower. Renewable Energy, 99, 711-720.
The water scarcity data combines:
- Blue water consumption from Life Cycle Assessment databases
- Water Stress Index values based on watershed-level water availability
Database Structure
Water scarcity factors are stored in the Eaternity Database (EDB) with:
water-scarcity-footprint-id: Links products to WSI data entries- Country-specific values: Stored for each product-country combination
- Median values: Pre-calculated for fallback scenarios
References
-
Scherer, L., & Pfister, S. (2016). Global water footprint assessment of hydropower. Renewable Energy, 99, 711-720.
-
Pfister, S., Koehler, A., & Hellweg, S. (2009). Assessing the environmental impacts of freshwater consumption in LCA. Environmental Science and Technology, 43(11), 4098-4104.
-
Eaternity Database (EDB). Water Scarcity Footprint Data. Internal documentation.