Skip to content

External forcings file

The external forcing .ext file contains the forcing data for a D-Flow FM model. This includes open boundaries, lateral discharges and meteorological forcings. The documentation below only concerns the 'new' format (ExtForceFileNew in the MDU file).

Model

Boundary

Bases: INIBasedModel

A [Boundary] block for use inside an external forcings file, i.e., a ExtModel.

All lowercased attributes match with the boundary input as described in UM Sec.C.5.2.1.

Source code in hydrolib/core/dflowfm/ext/models.py
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
class Boundary(INIBasedModel):
    """
    A `[Boundary]` block for use inside an external forcings file,
    i.e., a [ExtModel][hydrolib.core.dflowfm.ext.models.ExtModel].

    All lowercased attributes match with the boundary input as described in
    [UM Sec.C.5.2.1](https://content.oss.deltares.nl/delft3dfm1d2d/D-Flow_FM_User_Manual_1D2D.pdf#subsection.C.5.2.1).
    """

    _disk_only_file_model_should_not_be_none = (
        validator_set_default_disk_only_file_model_when_none()
    )

    _header: Literal["Boundary"] = "Boundary"
    quantity: str = Field(alias="quantity")
    nodeid: Optional[str] = Field(alias="nodeId")
    locationfile: DiskOnlyFileModel = Field(
        default_factory=lambda: DiskOnlyFileModel(None), alias="locationFile"
    )
    forcingfile: ForcingModel = Field(alias="forcingFile")
    bndwidth1d: Optional[float] = Field(alias="bndWidth1D")
    bndbldepth: Optional[float] = Field(alias="bndBlDepth")

    def is_intermediate_link(self) -> bool:
        return True

    @classmethod
    def _is_valid_locationfile_data(
        cls, elem: Union[None, str, Path, DiskOnlyFileModel]
    ) -> bool:
        return isinstance(elem, Path) or (
            isinstance(elem, DiskOnlyFileModel) and elem.filepath is not None
        )

    @root_validator
    @classmethod
    def check_nodeid_or_locationfile_present(cls, values: Dict):
        """
        Verifies that either nodeid or locationfile properties have been set.

        Args:
            values (Dict): Dictionary with values already validated.

        Raises:
            ValueError: When none of the values are present.

        Returns:
            Dict: Validated dictionary of values for Boundary.
        """
        node_id = values.get("nodeid", None)
        location_file = values.get("locationfile", None)
        if str_is_empty_or_none(node_id) and not cls._is_valid_locationfile_data(
            location_file
        ):
            raise ValueError(
                "Either nodeId or locationFile fields should be specified."
            )
        return values

    def _get_identifier(self, data: dict) -> Optional[str]:
        """
        Retrieves the identifier for a boundary, which is the nodeid

        Args:
            data (dict): Dictionary of values for this boundary.

        Returns:
            str: The nodeid value or None if not found.
        """
        return data.get("nodeid")

    @property
    def forcing(self) -> ForcingBase:
        """Retrieves the corresponding forcing data for this boundary.

        Returns:
            ForcingBase: The corresponding forcing data. None when this boundary does not have a forcing file or when the data cannot be found.
        """

        if self.forcingfile is None:
            return None

        for forcing in self.forcingfile.forcing:

            if self.nodeid != forcing.name:
                continue

            for quantity in forcing.quantityunitpair:
                if quantity.quantity.startswith(self.quantity):
                    return forcing

        return None

forcing property

Retrieves the corresponding forcing data for this boundary.

Returns:

Name Type Description
ForcingBase ForcingBase

The corresponding forcing data. None when this boundary does not have a forcing file or when the data cannot be found.

check_nodeid_or_locationfile_present(values) classmethod

Verifies that either nodeid or locationfile properties have been set.

Parameters:

Name Type Description Default
values Dict

Dictionary with values already validated.

required

Raises:

Type Description
ValueError

When none of the values are present.

Returns:

Name Type Description
Dict

Validated dictionary of values for Boundary.

Source code in hydrolib/core/dflowfm/ext/models.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
@root_validator
@classmethod
def check_nodeid_or_locationfile_present(cls, values: Dict):
    """
    Verifies that either nodeid or locationfile properties have been set.

    Args:
        values (Dict): Dictionary with values already validated.

    Raises:
        ValueError: When none of the values are present.

    Returns:
        Dict: Validated dictionary of values for Boundary.
    """
    node_id = values.get("nodeid", None)
    location_file = values.get("locationfile", None)
    if str_is_empty_or_none(node_id) and not cls._is_valid_locationfile_data(
        location_file
    ):
        raise ValueError(
            "Either nodeId or locationFile fields should be specified."
        )
    return values

ExtGeneral

Bases: INIGeneral

The external forcing file's [General] section with file meta data.

Source code in hydrolib/core/dflowfm/ext/models.py
287
288
289
290
291
292
class ExtGeneral(INIGeneral):
    """The external forcing file's `[General]` section with file meta data."""

    _header: Literal["General"] = "General"
    fileversion: str = Field("2.01", alias="fileVersion")
    filetype: Literal["extForce"] = Field("extForce", alias="fileType")

ExtModel

Bases: INIModel

The overall external forcings model that contains the contents of one external forcings file (new format).

This model is typically referenced under a FMModel.external_forcing.extforcefilenew.

Attributes:

Name Type Description
general ExtGeneral

[General] block with file metadata.

boundary List[Boundary]

List of [Boundary] blocks for all boundary conditions.

lateral List[Lateral]

List of [Lateral] blocks for all lateral discharges.

meteo List[Meteo]

List of [Meteo] blocks for all meteorological forcings.

Source code in hydrolib/core/dflowfm/ext/models.py
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
class ExtModel(INIModel):
    """
    The overall external forcings model that contains the contents of one external forcings file (new format).

    This model is typically referenced under a [FMModel][hydrolib.core.dflowfm.mdu.models.FMModel]`.external_forcing.extforcefilenew`.

    Attributes:
        general (ExtGeneral): `[General]` block with file metadata.
        boundary (List[Boundary]): List of `[Boundary]` blocks for all boundary conditions.
        lateral (List[Lateral]): List of `[Lateral]` blocks for all lateral discharges.
        meteo (List[Meteo]): List of `[Meteo]` blocks for all meteorological forcings.
    """

    general: ExtGeneral = ExtGeneral()
    boundary: List[Boundary] = []
    lateral: List[Lateral] = []
    meteo: List[Meteo] = []
    serializer_config: INISerializerConfig = INISerializerConfig(
        section_indent=0, property_indent=0
    )
    _split_to_list = make_list_validator("boundary", "lateral", "meteo")

    @classmethod
    def _ext(cls) -> str:
        return ".ext"

    @classmethod
    def _filename(cls) -> str:
        return "bnd"

Lateral

Bases: INIBasedModel

A [Lateral] block for use inside an external forcings file, i.e., a ExtModel.

All lowercased attributes match with the lateral input as described in UM Sec.C.5.2.2.

Source code in hydrolib/core/dflowfm/ext/models.py
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
class Lateral(INIBasedModel):
    """
    A `[Lateral]` block for use inside an external forcings file,
    i.e., a [ExtModel][hydrolib.core.dflowfm.ext.models.ExtModel].

    All lowercased attributes match with the lateral input as described in
    [UM Sec.C.5.2.2](https://content.oss.deltares.nl/delft3dfm1d2d/D-Flow_FM_User_Manual_1D2D.pdf#subsection.C.5.2.2).
    """

    _header: Literal["Lateral"] = "Lateral"
    id: str = Field(alias="id")
    name: str = Field("", alias="name")
    locationtype: Optional[str] = Field(alias="locationType")
    nodeid: Optional[str] = Field(alias="nodeId")
    branchid: Optional[str] = Field(alias="branchId")
    chainage: Optional[float] = Field(alias="chainage")
    numcoordinates: Optional[int] = Field(alias="numCoordinates")
    xcoordinates: Optional[List[float]] = Field(alias="xCoordinates")
    ycoordinates: Optional[List[float]] = Field(alias="yCoordinates")
    discharge: ForcingData = Field(alias="discharge")

    def is_intermediate_link(self) -> bool:
        return True

    _split_to_list = get_split_string_on_delimiter_validator(
        "xcoordinates", "ycoordinates"
    )

    @root_validator(allow_reuse=True)
    def validate_that_location_specification_is_correct(cls, values: Dict) -> Dict:
        """Validates that the correct location specification is given."""
        return validate_location_specification(
            values, config=LocationValidationConfiguration(minimum_num_coordinates=1)
        )

    def _get_identifier(self, data: dict) -> Optional[str]:
        return data.get("id") or data.get("name")

    @validator("locationtype")
    @classmethod
    def validate_location_type(cls, v: str) -> str:
        """
        Method to validate whether the specified location type is correct.

        Args:
            v (str): Given value for the locationtype field.

        Raises:
            ValueError: When the value given for locationtype is unknown.

        Returns:
            str: Validated locationtype string.
        """
        possible_values = ["1d", "2d", "all"]
        if v.lower() not in possible_values:
            raise ValueError(
                "Value given ({}) not accepted, should be one of: {}".format(
                    v, ", ".join(possible_values)
                )
            )
        return v

validate_location_type(v) classmethod

Method to validate whether the specified location type is correct.

Parameters:

Name Type Description Default
v str

Given value for the locationtype field.

required

Raises:

Type Description
ValueError

When the value given for locationtype is unknown.

Returns:

Name Type Description
str str

Validated locationtype string.

Source code in hydrolib/core/dflowfm/ext/models.py
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
@validator("locationtype")
@classmethod
def validate_location_type(cls, v: str) -> str:
    """
    Method to validate whether the specified location type is correct.

    Args:
        v (str): Given value for the locationtype field.

    Raises:
        ValueError: When the value given for locationtype is unknown.

    Returns:
        str: Validated locationtype string.
    """
    possible_values = ["1d", "2d", "all"]
    if v.lower() not in possible_values:
        raise ValueError(
            "Value given ({}) not accepted, should be one of: {}".format(
                v, ", ".join(possible_values)
            )
        )
    return v

validate_that_location_specification_is_correct(values)

Validates that the correct location specification is given.

Source code in hydrolib/core/dflowfm/ext/models.py
154
155
156
157
158
159
@root_validator(allow_reuse=True)
def validate_that_location_specification_is_correct(cls, values: Dict) -> Dict:
    """Validates that the correct location specification is given."""
    return validate_location_specification(
        values, config=LocationValidationConfiguration(minimum_num_coordinates=1)
    )

Meteo

Bases: INIBasedModel

A [Meteo] block for use inside an external forcings file, i.e., a ExtModel.

All lowercased attributes match with the meteo input as described in UM Sec.C.5.2.3.

Source code in hydrolib/core/dflowfm/ext/models.py
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
class Meteo(INIBasedModel):
    """
    A `[Meteo]` block for use inside an external forcings file,
    i.e., a [ExtModel][hydrolib.core.dflowfm.ext.models.ExtModel].

    All lowercased attributes match with the meteo input as described in
    [UM Sec.C.5.2.3](https://content.oss.deltares.nl/delft3dfm1d2d/D-Flow_FM_User_Manual_1D2D.pdf#subsection.C.5.2.3).
    """

    class Comments(INIBasedModel.Comments):
        quantity: Optional[str] = Field(
            "Name of the quantity. See UM Section C.5.3", alias="quantity"
        )
        forcingfile: Optional[str] = Field(
            "Name of file containing the forcing for this meteo quantity.",
            alias="forcingFile",
        )
        forcingfiletype: Optional[str] = Field(
            "Type of forcingFile.", alias="forcingFileType"
        )
        targetmaskfile: Optional[str] = Field(
            "Name of <*.pol> file to be used as mask. Grid parts inside any polygon will receive the meteo forcing.",
            alias="targetMaskFile",
        )
        targetmaskinvert: Optional[str] = Field(
            "Flag indicating whether the target mask should be inverted, i.e., outside of all polygons: no or yes.",
            alias="targetMaskInvert",
        )
        interpolationmethod: Optional[str] = Field(
            "Type of (spatial) interpolation.", alias="interpolationMethod"
        )

    comments: Comments = Comments()

    @classmethod
    def _get_unknown_keyword_error_manager(cls) -> Optional[UnknownKeywordErrorManager]:
        """
        The Meteo does not currently support raising an error on unknown keywords.
        """
        return None

    _disk_only_file_model_should_not_be_none = (
        validator_set_default_disk_only_file_model_when_none()
    )

    _header: Literal["Meteo"] = "Meteo"
    quantity: str = Field(alias="quantity")
    forcingfile: Union[TimModel, ForcingModel, DiskOnlyFileModel] = Field(
        alias="forcingFile"
    )
    forcingfiletype: MeteoForcingFileType = Field(alias="forcingFileType")
    targetmaskfile: Optional[PolyFile] = Field(None, alias="targetMaskFile")
    targetmaskinvert: Optional[bool] = Field(None, alias="targetMaskInvert")
    interpolationmethod: Optional[MeteoInterpolationMethod] = Field(
        alias="interpolationMethod"
    )

    def is_intermediate_link(self) -> bool:
        return True

    forcingfiletype_validator = get_enum_validator(
        "forcingfiletype", enum=MeteoForcingFileType
    )
    interpolationmethod_validator = get_enum_validator(
        "interpolationmethod", enum=MeteoInterpolationMethod
    )

MeteoForcingFileType

Bases: StrEnum

Enum class containing the valid values for the forcingFileType attribute in Meteo class.

Source code in hydrolib/core/dflowfm/ext/models.py
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
class MeteoForcingFileType(StrEnum):
    """
    Enum class containing the valid values for the forcingFileType
    attribute in Meteo class.
    """

    bcascii = "bcAscii"
    """str: Space-uniform time series in <*.bc> file."""

    netcdf = "netcdf"
    """str: NetCDF, either with gridded data, or multiple station time series."""

    uniform = "uniform"
    """str: Space-uniform time series in <*.tim> file."""

    allowedvaluestext = "Possible values: bcAscii, netcdf, uniform."

bcascii = 'bcAscii' class-attribute instance-attribute

str: Space-uniform time series in <*.bc> file.

netcdf = 'netcdf' class-attribute instance-attribute

str: NetCDF, either with gridded data, or multiple station time series.

uniform = 'uniform' class-attribute instance-attribute

str: Space-uniform time series in <*.tim> file.

MeteoInterpolationMethod

Bases: StrEnum

Enum class containing the valid values for the interpolationMethod attribute in Meteo class.

Source code in hydrolib/core/dflowfm/ext/models.py
207
208
209
210
211
212
213
214
215
216
class MeteoInterpolationMethod(StrEnum):
    """
    Enum class containing the valid values for the interpolationMethod
    attribute in Meteo class.
    """

    nearestnb = "nearestNb"
    """str: Nearest-neighbour interpolation, only with station-data in forcingFileType=netcdf"""

    allowedvaluestext = "Possible values: nearestNb (only with station data in forcingFileType=netcdf ). "

nearestnb = 'nearestNb' class-attribute instance-attribute

str: Nearest-neighbour interpolation, only with station-data in forcingFileType=netcdf