-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #114 from Deltares/DEI-185-depth-average-rule
Dei 185 depth average rule
- Loading branch information
Showing
83 changed files
with
982 additions
and
209 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
decoimpact/business/entities/rules/depth_average_rule.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# This file is part of D-EcoImpact | ||
# Copyright (C) 2022-2024 Stichting Deltares | ||
# This program is free software distributed under the | ||
# GNU Affero General Public License version 3.0 | ||
# A copy of the GNU Affero General Public License can be found at | ||
# https://github.com/Deltares/D-EcoImpact/blob/main/LICENSE.md | ||
""" | ||
Module for DepthAverageRule class | ||
Classes: | ||
DepthAverageRule | ||
""" | ||
from typing import Dict | ||
|
||
import xarray as _xr | ||
|
||
from decoimpact.business.entities.rules.i_multi_array_based_rule import ( | ||
IMultiArrayBasedRule, | ||
) | ||
from decoimpact.business.entities.rules.rule_base import RuleBase | ||
from decoimpact.crosscutting.i_logger import ILogger | ||
from decoimpact.crosscutting.delft3d_specific_data import ( | ||
INTERFACES_NAME, | ||
BED_LEVEL_NAME, | ||
WATER_LEVEL_NAME, | ||
) | ||
|
||
|
||
class DepthAverageRule(RuleBase, IMultiArrayBasedRule): | ||
"""Implementation for the depth average rule""" | ||
|
||
def execute( | ||
self, value_arrays: Dict[str, _xr.DataArray], logger: ILogger | ||
) -> _xr.DataArray: | ||
"""Calculate depth average of assumed z-layers. | ||
Args: | ||
value_array (DataArray): Values to multiply | ||
Returns: | ||
DataArray: Averaged values | ||
""" | ||
|
||
# The first DataArray in our value_arrays contains the values to be averaged | ||
# but the name of the key is given by the user, and is unknown here, so | ||
# just used the first value. | ||
variables = next(iter(value_arrays.values())) | ||
|
||
# depths interfaces = borders of the layers in terms of depth | ||
depths_interfaces = value_arrays[INTERFACES_NAME] | ||
water_level_values = value_arrays[WATER_LEVEL_NAME] | ||
bed_level_values = value_arrays[BED_LEVEL_NAME] | ||
|
||
# Get the dimension names for the interfaces and for the layers | ||
dim_interfaces_name = list(depths_interfaces.dims)[0] | ||
interfaces_len = depths_interfaces[dim_interfaces_name].size | ||
|
||
dim_layer_name = [ | ||
d for d in variables.dims if d not in water_level_values.dims | ||
][0] | ||
layer_len = variables[dim_layer_name].size | ||
|
||
# interface dimension should always be one larger than layer dimension | ||
# Otherwise give an error to the user | ||
if interfaces_len != layer_len + 1: | ||
logger.log_error( | ||
f"The number of interfaces should be number of layers + 1. Number of" | ||
f"interfaces = {interfaces_len}. Number of layers = {layer_len}." | ||
) | ||
return variables | ||
|
||
# Deal with open layer system at water level and bed level | ||
depths_interfaces.values[depths_interfaces.values.argmin()] = -100000 | ||
depths_interfaces.values[depths_interfaces.values.argmax()] = 100000 | ||
|
||
# Broadcast the depths to the dimensions of the bed levels. Then make a | ||
# correction for the depths to the bed level, in other words all depths lower | ||
# than the bed level will be corrected to the bed level. | ||
depths_interfaces_broadcasted = depths_interfaces.broadcast_like( | ||
bed_level_values | ||
) | ||
|
||
corrected_depth_bed = depths_interfaces_broadcasted.where( | ||
bed_level_values < depths_interfaces_broadcasted, bed_level_values | ||
) | ||
|
||
# Make a similar correction for the waterlevels (first broadcast to match | ||
# dimensions and then replace all values higher than waterlevel with | ||
# waterlevel) | ||
corrected_depth_bed = corrected_depth_bed.broadcast_like(water_level_values) | ||
corrected_depth_bed = corrected_depth_bed.where( | ||
water_level_values > corrected_depth_bed, water_level_values | ||
) | ||
|
||
# Calculate the layer heights between depths | ||
layer_heights = corrected_depth_bed.diff(dim=dim_interfaces_name) | ||
layer_heights = layer_heights.rename({dim_interfaces_name: dim_layer_name}) | ||
|
||
# Use the NaN filtering of the variables to set the correct depth per column | ||
layer_heights = layer_heights.where(variables.notnull()) | ||
|
||
# Calculate depth average using relative value | ||
relative_values = variables * layer_heights | ||
|
||
# Calculate average | ||
return relative_values.sum(dim=dim_layer_name) / layer_heights.sum( | ||
dim=dim_layer_name | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# This file is part of D-EcoImpact | ||
# Copyright (C) 2022-2024 Stichting Deltares | ||
# This program is free software distributed under the | ||
# GNU Affero General Public License version 3.0 | ||
# A copy of the GNU Affero General Public License can be found at | ||
# https://github.com/Deltares/D-EcoImpact/blob/main/LICENSE.md | ||
""" | ||
Configuration file for hardcoded delft3d variable names | ||
""" | ||
|
||
INTERFACES_NAME = "mesh2d_interface_z" | ||
BED_LEVEL_NAME = "mesh2d_flowelem_bl" | ||
WATER_LEVEL_NAME = "mesh2d_s1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# This file is part of D-EcoImpact | ||
# Copyright (C) 2022-2024 Stichting Deltares | ||
# This program is free software distributed under the | ||
# GNU Affero General Public License version 3.0 | ||
# A copy of the GNU Affero General Public License can be found at | ||
# https://github.com/Deltares/D-EcoImpact/blob/main/LICENSE.md | ||
""" | ||
Module for IDepthAverageRuleData interface | ||
Interfaces: | ||
IDepthAverageRuleData | ||
""" | ||
|
||
|
||
from abc import ABC, abstractmethod | ||
from typing import List | ||
|
||
from decoimpact.data.api.i_rule_data import IRuleData | ||
|
||
|
||
class IDepthAverageRuleData(IRuleData, ABC): | ||
"""Data for a DepthAverageRule""" | ||
|
||
@property | ||
@abstractmethod | ||
def input_variables(self) -> List[str]: | ||
"""List with input variable name and standard depth name""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.