Skip to content

Friction

1D roughness .ini files

The friction module provides the specific logic for accessing friction/1D roughness files for a D-Flow FM model.

Generic parsing and serializing functionality comes from the generic hydrolib.core.dflowfm.ini modules.

A 1D roughness file is described by the classes below.

Model

FrictBranch

Bases: INIBasedModel

A [Branch] block for use inside a friction file.

Each block can define the roughness value(s) on a particular branch.

Source code in hydrolib/core/dflowfm/friction/models.py
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
class FrictBranch(INIBasedModel):
    """A `[Branch]` block for use inside a friction file.

    Each block can define the roughness value(s) on a particular branch.
    """

    class Comments(INIBasedModel.Comments):
        branchid: Optional[str] = Field("The name of the branch.", alias="branchId")
        frictiontype: Optional[str] = Field(
            "The roughness type to be used on this branch.", alias="frictionType"
        )
        functiontype: Optional[str] = Field(
            "Function type for the calculation of the value. "
            + "Possible values: constant, timeSeries, absDischarge, waterlevel.",
            alias="functionType",
        )
        timeseriesid: Optional[str] = Field(
            "Refers to a data block in the <*.bc> frictionValuesFile. "
            + "Only if functionType = timeSeries.",
            alias="timeSeriesId",
        )
        numlevels: Optional[str] = Field(
            "Number of levels in table. Only if functionType is not constant.",
            alias="numLevels",
        )
        levels: Optional[str] = Field(
            "Space separated list of discharge [m3/s] or water level [m AD] values. "
            + "Only if functionType is absDischarge or waterLevel."
        )
        numlocations: Optional[str] = Field(
            "Number of locations on branch. The default 0 implies branch uniform values.",
            alias="numLocations",
        )
        chainage: Optional[str] = Field(
            "Space separated list of locations on the branch [m]. Locations sorted by "
            + "increasing chainage. The keyword must be specified if numLocations>0."
        )
        frictionvalues: Optional[str] = Field(
            "numLevels lines containing space separated lists of roughness values: "
            + "numLocations values per line. If the functionType is constant, then a "
            + "single line is required. For a uniform roughness per branch "
            + "(numLocations = 0) a single entry per line is required. The meaning "
            + "of the values depends on the roughness type selected (see frictionType).",
            alias="frictionValues",
        )

    comments: Comments = Comments()
    _header: Literal["Branch"] = "Branch"
    branchid: str = Field(alias="branchId")
    frictiontype: FrictionType = Field(alias="frictionType")
    functiontype: Optional[str] = Field("constant", alias="functionType")
    timeseriesid: Optional[str] = Field(alias="timeSeriesId")
    numlevels: Optional[PositiveInt] = Field(alias="numLevels")
    levels: Optional[List[float]]
    numlocations: Optional[NonNegativeInt] = Field(0, alias="numLocations")
    chainage: Optional[List[float]]
    frictionvalues: Optional[List[float]] = Field(
        alias="frictionValues"
    )  # TODO: turn this into List[List[float]], see issue #143.

    _split_to_list = get_split_string_on_delimiter_validator(
        "levels",
        "chainage",
        "frictionvalues",
    )

    _frictiontype_validator = get_enum_validator("frictiontype", enum=FrictionType)

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

    @validator("levels", always=True)
    @classmethod
    def _validate_levels(cls, v, values):
        if v is not None and (
            values["numlevels"] is None or len(v) != values["numlevels"]
        ):
            raise ValueError(
                f"Number of values for levels should be equal to the numLevels value (branchId={values.get('branchid', '')})."
            )

        return v

    @validator("chainage", always=True)
    @classmethod
    def _validate_chainage(cls, v, values):
        if v is not None and len(v) != values["numlocations"]:
            raise ValueError(
                f"Number of values for chainage should be equal to the numLocations value (branchId={values.get('branchid', '')})."
            )

        return v

    @validator("frictionvalues", always=True)
    @classmethod
    def _validate_frictionvalues(cls, v, values):
        # number of values should be equal to numlocations*numlevels
        numlevels = (
            1
            if (
                "numlevels" not in values
                or values["numlevels"] is None
                or values["numlevels"] == 0
            )
            else values["numlevels"]
        )
        numvals = max(1, values["numlocations"]) * numlevels
        if v is not None and len(v) != numvals:
            raise ValueError(
                f"Number of values for frictionValues should be equal to the numLocations*numLevels value (branchId={values.get('branchid', '')})."
            )

        return v

FrictGeneral

Bases: INIGeneral

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

Source code in hydrolib/core/dflowfm/friction/models.py
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
class FrictGeneral(INIGeneral):
    """The friction file's `[General]` section with file meta data."""

    class Comments(INIBasedModel.Comments):
        fileversion: Optional[str] = Field(
            "File version. Do not edit this.", alias="fileVersion"
        )
        filetype: Optional[str] = Field(
            "File type. Should be 'roughness'. Do not edit this.",
            alias="fileType",
        )
        frictionvaluesfile: Optional[str] = Field(
            "Name of <*.bc> file containing the timeseries with friction values. "
            + "Only needed for functionType = timeSeries.",
            alias="frictionValuesFile",
        )

    comments: Comments = Comments()
    _header: Literal["General"] = "General"
    fileversion: str = Field("3.01", alias="fileVersion")
    filetype: Literal["roughness"] = Field("roughness", alias="fileType")
    frictionvaluesfile: DiskOnlyFileModel = Field(
        default_factory=lambda: DiskOnlyFileModel(None), alias="frictionValuesFile"
    )

    _disk_only_file_model_should_not_be_none = (
        validator_set_default_disk_only_file_model_when_none()
    )

FrictGlobal

Bases: INIBasedModel

A [Global] block for use inside a friction file.

Multiple of such blocks may be present to define multiple frictionId classes.

Source code in hydrolib/core/dflowfm/friction/models.py
 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
class FrictGlobal(INIBasedModel):
    """A `[Global]` block for use inside a friction file.

    Multiple of such blocks may be present to define multiple frictionId classes.
    """

    class Comments(INIBasedModel.Comments):
        frictionid: Optional[str] = Field(
            "Name of the roughness variable.", alias="frictionId"
        )
        frictiontype: Optional[str] = Field(
            "The global roughness type for this variable, which is used "
            + "if no branch specific roughness definition is given.",
            alias="frictionType",
        )
        frictionvalue: Optional[str] = Field(
            "The global default value for this roughness variable.",
            alias="frictionValue",
        )

    comments: Comments = Comments()
    _header: Literal["Global"] = "Global"
    frictionid: str = Field(alias="frictionId")
    frictiontype: FrictionType = Field(alias="frictionType")
    frictionvalue: float = Field(alias="frictionValue")

    _frictiontype_validator = get_enum_validator("frictiontype", enum=FrictionType)

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

FrictionModel

Bases: INIModel

The overall friction model that contains the contents of one friction file.

This model is typically referenced under a FMModel.geometry.frictfile[..].

Attributes:

Name Type Description
general FrictGeneral

[General] block with file metadata.

global_ List[FrictGlobal]

Definitions of [Global] friction classes.

branch List[FrictBranch]

Definitions of [Branch] friction values.

Source code in hydrolib/core/dflowfm/friction/models.py
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
class FrictionModel(INIModel):
    """
    The overall friction model that contains the contents of one friction file.

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

    Attributes:
        general (FrictGeneral): `[General]` block with file metadata.
        global_ (List[FrictGlobal]): Definitions of `[Global]` friction classes.
        branch (List[FrictBranch]): Definitions of `[Branch]` friction values.
    """

    general: FrictGeneral = FrictGeneral()
    global_: List[FrictGlobal] = Field([], alias="global")  # to circumvent built-in kw
    branch: List[FrictBranch] = []

    _split_to_list = make_list_validator(
        "global_",
        "branch",
    )

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

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

FrictionType

Bases: StrEnum

Enum class containing the valid values for the frictionType attribute in several subclasses of Structure/CrossSection/friction.models.

Source code in hydrolib/core/dflowfm/friction/models.py
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class FrictionType(StrEnum):
    """
    Enum class containing the valid values for the frictionType
    attribute in several subclasses of Structure/CrossSection/friction.models.
    """

    chezy = "Chezy"
    """str: Chézy C [m 1/2 /s]"""

    manning = "Manning"
    """str: Manning n [s/m 1/3 ]"""

    walllawnikuradse = "wallLawNikuradse"
    """str: Nikuradse k_n [m]"""

    whitecolebrook = "WhiteColebrook"
    """str: Nikuradse k_n [m]"""

    stricklernikuradse = "StricklerNikuradse"
    """str: Nikuradse k_n [m]"""

    strickler = "Strickler"
    """str: Strickler k_s [m 1/3 /s]"""

    debosbijkerk = "deBosBijkerk"
    """str: De Bos-Bijkerk γ [1/s]"""

chezy = 'Chezy' class-attribute instance-attribute

str: Chézy C [m 1/2 /s]

debosbijkerk = 'deBosBijkerk' class-attribute instance-attribute

str: De Bos-Bijkerk γ [1/s]

manning = 'Manning' class-attribute instance-attribute

str: Manning n [s/m 1/3 ]

strickler = 'Strickler' class-attribute instance-attribute

str: Strickler k_s [m 1/3 /s]

stricklernikuradse = 'StricklerNikuradse' class-attribute instance-attribute

str: Nikuradse k_n [m]

walllawnikuradse = 'wallLawNikuradse' class-attribute instance-attribute

str: Nikuradse k_n [m]

whitecolebrook = 'WhiteColebrook' class-attribute instance-attribute

str: Nikuradse k_n [m]