From 987f1683579fecfe9a2fee183398b97f2f8abab1 Mon Sep 17 00:00:00 2001 From: Arthur van Dam Date: Wed, 29 Mar 2023 12:26:01 +0200 Subject: [PATCH 1/9] First version of prof_to_cross utility Done: * commandline argparse * callable for either mdu of prof* files * converts profloc Todo: * convert profdef * convert profdefxyz --- hydrolib/core/geometry/prof_to_cross.py | 167 ++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 hydrolib/core/geometry/prof_to_cross.py diff --git a/hydrolib/core/geometry/prof_to_cross.py b/hydrolib/core/geometry/prof_to_cross.py new file mode 100644 index 000000000..7d175ed39 --- /dev/null +++ b/hydrolib/core/geometry/prof_to_cross.py @@ -0,0 +1,167 @@ +import argparse +import re +import sys +from typing import Dict, List + +from hydrolib.core import __version__ +from hydrolib.core.basemodel import PathOrStr +from hydrolib.core.dflowfm import FMModel +from hydrolib.core.dflowfm.crosssection.models import ( + CrossDefModel, + CrossLocModel, + CrossSection, +) +from hydrolib.core.dflowfm.xyz.models import XYZModel + +_program: str = "prof_to_cross" +_verbose: bool = False + + +def read_profloc_data(proflocfile: PathOrStr) -> XYZModel: + global _verbose + + loc_as_xyz = XYZModel(proflocfile) + + if _verbose: + print(f"Read {len(loc_as_xyz.points)} profile locations from {proflocfile}.") + + return loc_as_xyz + + +def read_profdef_data(profdeffile: PathOrStr) -> List[Dict]: + defs = [] + linenr = 0 + with open(profdeffile) as file: + for line in file: + linenr = linenr + 1 + if line.startswith("*"): + continue + tokens = re.split("[=\s]+", line.strip()) + defs.append(dict(zip(tokens[::2], map(float, tokens[1::2])))) + + if _verbose: + print(f"Read {len(defs)} profile definitions from {profdeffile}.") + + return defs + + +def prof_to_cross_from_mdu(mdufile: PathOrStr): + global _verbose + + fmmodel = FMModel(mdufile, recurse=False) + proflocfile = fmmodel.geometry.proflocfile._resolved_filepath + profdeffile = fmmodel.geometry.profdeffile._resolved_filepath + profdefxyzfile = fmmodel.geometry.profdefxyzfile._resolved_filepath + if _verbose: + print("Using profile files found in MDU:") + print(f"* {proflocfile}") + print(f"* {profdeffile}") + if profdefxyzfile: + print(f"* {profdefxyzfile}") + + prof_to_cross(proflocfile, profdeffile, profdefxyzfile) + + +def prof_to_cross( + proflocfile: PathOrStr, + profdeffile: PathOrStr, + profdefxyzfile: PathOrStr = None, +): + print(proflocfile) + print(profdeffile) + print(profdefxyzfile) + + profloc_data = read_profloc_data(proflocfile) + # print(profloc_data.points) + profdef_data = read_profdef_data(profdeffile) + # print(profdef_data) + + crsloc_data = [] + crsdef_data = [] + + crsloc_data = [ + CrossSection( + id=f"PROFLOC{nr+1}", + x=profloc.x, + y=profloc.y, + definitionId=f"PROFNR{int(profloc.z)}", + ) + for nr, profloc in enumerate(profloc_data.points) + ] + + # print(crsloc_data) + + crsloc_model = CrossLocModel(crosssection=crsloc_data) + crsloc_model.filepath = "crsloc.ini" + crsloc_model.save() + + crsdef_model = CrossDefModel(definition=crsdef_data) + crsdef_model.filepath = "crsdef.ini" + crsdef_model.save() + + +def _get_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser( + prog=_program, + description="Convert D-Flow FM legacy profile files to cross section files.", + ) + + parser.add_argument("--version", "-v", action="version", version=__version__) + parser.add_argument( + "--verbose", action="store_true", help="also print diagnostic information" + ) + parser.add_argument( + "--mdufile", + "-m", + action="store", + help="automatically take profile filenames from MDUFILE", + ) + parser.add_argument( + "--proffiles", + "-p", + action="extend", + nargs="*", + metavar="PROFFILE", + help="2 or 3 profile files: PROFLOCFILE PROFDEFFILE [PROFDEFXYZFILE]", + ) + return parser + + +def main(args=None): + """ + Main entry point for prof_to_cross tool. + Args: + args : list + A of arguments as if they were input in the command line. Leave it + None to use sys.argv. + """ + global _verbose + + parser = _get_parser() + args = parser.parse_args(args) + _verbose = args.verbose + + if args.mdufile is not None and args.proffiles: + print("Error: use either input MDUFILE or PROFFILEs, not both.") + sys.exit(1) + + if args.proffiles is not None and not 2 <= len(args.proffiles) <= 3: + print("Error: Expecting at least 2, at most 3 profile files,") + print(" use: -p PROFLOCFILE PROFDEFFILE [PROFDEFXYZFILE]") + + sys.exit(1) + + if args.mdufile is not None: + prof_to_cross_from_mdu(args.mdufile) + elif args.proffiles is not None: + prof_to_cross(*args.proffiles) + else: + print("Error: Missing input file(s), use either -m or -p.") + + sys.exit(1) + + print(_program + ": done") + + +if __name__ == "__main__": + main() From 2eee1afb6cf86f2e58d4ee21c23ee6a07f282f6c Mon Sep 17 00:00:00 2001 From: Arthur van Dam Date: Tue, 4 Apr 2023 10:52:27 +0200 Subject: [PATCH 2/9] Working version of conversion, including all profdef and xyz data. * also added APIdocs * also added first version of end-user usage docs. --- docs/tools/prof_to_cross.md | 53 +++++ docs/tools/tools.md | 6 + hydrolib/core/geometry/prof_to_cross.py | 285 +++++++++++++++++++++++- 3 files changed, 334 insertions(+), 10 deletions(-) create mode 100644 docs/tools/prof_to_cross.md create mode 100644 docs/tools/tools.md diff --git a/docs/tools/prof_to_cross.md b/docs/tools/prof_to_cross.md new file mode 100644 index 000000000..733b4e76e --- /dev/null +++ b/docs/tools/prof_to_cross.md @@ -0,0 +1,53 @@ +prof_to_cross +============= +*Convert D-Flow FM legacy profile files to cross section files.* + +Directly jump to [Usage](#Usage). + +# Background +1D cross section specification in a D-Flow FM model used to go via two or three prof* files, the ones specified in the MDU file via `ProflocFile`, `ProfdefFile` +and optionally `ProfdefxyzFile`. They contain the location/placement and the type/geometry description, respectively. + +Similar input is still needed, but now has the officially supported via .ini files. +These are the ones now specified in the MDU file via `CrsLocFile` and `CrsDefFile`. +## Automatic conversion choices +### Location +Location continues to be specified via original *x,y* coordinate, no branchId is available. + +Vertical absolute placement (`ZMIN` vs. `shift`) still needs refinement. + +### Type + conveyance +The following table lists the mapping from old to new cross section types: +|PROFTYPE|meaning|type in crsdef.ini|conveyanceType in crsdef.ini| +| :--- | :--- | :--- | :--- | +|1|`PIPE`|`circle`||N/A| +|2|`RECTAN , HYDRAD = AREA / PERIMETER`|`rectangle`|N/A| +|3|`RECTAN , HYDRAD = 1D ANALYTIC CONVEYANCE`|`rectangle`|N/A| +|4|`V-SHAPE , HYDRAD = AREA / PERIMETER`|`yz`|`lumped`| +|5|`V-SHAPE , HYDRAD = 1D ANALYTIC CONVEYANCE`|`yz`|`segmented`| +|6|`TRAPEZOID, HYDRAD = AREA / PERIMETER`|`yz`|`lumped`| +|7|`TRAPEZOID, HYDRAD = 1D ANALYTIC CONVEYANCE`|`yz`|`segmented`| +|100|`YZPROF , HYDRAD = AREA / PERIMETER`|`yz`|`lumped`| +|101|`YZPROF , HYDRAD = 1D ANALYTIC CONVEYANCE METHOD`|`yz`|`segmented`| +|200|`XYZPROF , HYDRAD = AREA / PERIMETER`|`xyz`|`lumped`| +|201|`XYZPROF , HYDRAD = 1D ANALYTIC CONVEYANCE METHOD`|`xyz`|`segmented`| + +### Friction +Not yet available in converter. + +# Usage: + +```bash +usage: prof_to_cross [-h] [--version] [--verbose] [--mdufile MDUFILE] [--proffiles [PROFFILE [PROFFILE ...]]] + +``` + +# Arguments + +|short|long|default|help| +| :--- | :--- | :--- | :--- | +|`-h`|`--help`||show this help message and exit| +|`-v`|`--version`||show program's version number and exit| +||`--verbose`||also print diagnostic information| +|`-m`|`--mdufile`|`None`|automatically take profile filenames from MDUFILE| +|`-p`|`--proffiles`|`None`|2 or 3 profile files: PROFLOCFILE PROFDEFFILE [PROFDEFXYZFILE]| \ No newline at end of file diff --git a/docs/tools/tools.md b/docs/tools/tools.md new file mode 100644 index 000000000..930fd5e4b --- /dev/null +++ b/docs/tools/tools.md @@ -0,0 +1,6 @@ +# Introduction to tools + +HYDROLIB-core contains several utility tools built on top of the core I/O functionality. +These small tools may help with model conversion and inspection. + +* **[prof_to_cross](geometry/prof_to_cross.md)** - Convert D-Flow FM legacy profdef/profloc files to cross section files. diff --git a/hydrolib/core/geometry/prof_to_cross.py b/hydrolib/core/geometry/prof_to_cross.py index 7d175ed39..d46b294f4 100644 --- a/hydrolib/core/geometry/prof_to_cross.py +++ b/hydrolib/core/geometry/prof_to_cross.py @@ -1,16 +1,23 @@ import argparse +import math import re import sys -from typing import Dict, List +from typing import Dict, List, Optional, Tuple from hydrolib.core import __version__ from hydrolib.core.basemodel import PathOrStr from hydrolib.core.dflowfm import FMModel from hydrolib.core.dflowfm.crosssection.models import ( + CircleCrsDef, CrossDefModel, CrossLocModel, CrossSection, + CrossSectionDefinition, + RectangleCrsDef, + XYZCrsDef, + YZCrsDef, ) +from hydrolib.core.dflowfm.polyfile.models import PolyFile, PolyObject from hydrolib.core.dflowfm.xyz.models import XYZModel _program: str = "prof_to_cross" @@ -18,6 +25,14 @@ def read_profloc_data(proflocfile: PathOrStr) -> XYZModel: + """Read a legacy profile location file (.xyz) into a XYZModel object. + + Args: + proflocfile (PathOrStr): path to the profile location file (.xyz) + + Returns: + XYZModel: object with point list, z values are the profile numbers + that refer to the profile definitions.""" global _verbose loc_as_xyz = XYZModel(proflocfile) @@ -29,6 +44,15 @@ def read_profloc_data(proflocfile: PathOrStr) -> XYZModel: def read_profdef_data(profdeffile: PathOrStr) -> List[Dict]: + """Read a legacy profile definition file (.xyz). + + Args: + profdeffile (PathOrStr): path to the profile definition file (.txt) + + Returns: + List[Dict]: list of profile definitions, one per line in the file. + Each line in the file is a list item, each definition is a dict. + """ defs = [] linenr = 0 with open(profdeffile) as file: @@ -38,6 +62,7 @@ def read_profdef_data(profdeffile: PathOrStr) -> List[Dict]: continue tokens = re.split("[=\s]+", line.strip()) defs.append(dict(zip(tokens[::2], map(float, tokens[1::2])))) + defs[-1]["PROFNR"] = int(defs[-1]["PROFNR"]) if _verbose: print(f"Read {len(defs)} profile definitions from {profdeffile}.") @@ -45,6 +70,224 @@ def read_profdef_data(profdeffile: PathOrStr) -> List[Dict]: return defs +def read_profdefxyz_data(profdefxyzfile: PathOrStr) -> PolyFile: + """Read a legacy profile definition file for type xyz (.pliz) into + a PolyFile object. + + Args: + profdefxyzfile (PathOrStr): path to the profile definition file (.pliz) + + Returns: + PolyFile: entire contents of the .pliz file. Polyline names should be + of the form "PROFNR=", where profile numbers N refer to the + profile definitions. + """ + global _verbose + + profdefxyz = PolyFile(profdefxyzfile) + + if _verbose: + print( + f"Read {len(profdefxyz.objects)} xyz profile polylines from {profdefxyzfile}." + ) + + return profdefxyz + + +def _proftype_to_crsdeftype(proftype: int) -> Tuple[int, str]: + """Convert legacy profdef file type numbers to crsdef.ini type string. + + Args: + proftype (int): integer type as listed in TYPE= field. + Returns: + Tuple[int, str]: Tuple of: 1) normalized proftype (ignoring conveyance + type and closed-sign, possible values: 1, 2, 4, 6, 100, 200), + and 2) string type that can directly be used in type= field. + """ + + _proftype = abs(proftype) + if _proftype >= 2: + _proftype = math.floor(_proftype / 2.0) * 2 + + if _proftype == 1: # Pipe + crstype = "circle" + elif _proftype == 2: # Rectangle + crstype = "rectangle" + elif _proftype == 4: # V-shaped + crstype = "yz" + elif _proftype == 6: # Trapezoid + crstype = "yz" + elif _proftype == 100: # yz + crstype = "yz" + elif _proftype == 200: # xyz + crstype = "xyz" + else: + raise ValueError(f"Invalid legacy profile type given: TYPE={proftype}") + + return (_proftype, crstype) + + +def _proftype_to_conveyancetype(proftype: int) -> str: + """Convert legacy profdef file type numbers to conveyance type string. + Only applies to profile types that translate to yz type. + + Args: + proftype (int): integer type as listed in TYPE= field. + Returns: + str: string type that can directly be used in coveyance= field. + Return value is "segmented" for 1D analytic types, and "lumped" + for area/hydr.radius types. + """ + + _proftype = abs(proftype) + if 2 <= _proftype <= 201: + if (_proftype % 2) == 0: + convtype = "lumped" + else: + convtype = "segmented" + else: + raise ValueError(f"Invalid legacy profile type given: TYPE={proftype}") + + return convtype + + +def _convert_pipe_definition(profdef: dict) -> dict: + crsvalues = {"type": "circle", "diameter": profdef["WIDTH"]} + return crsvalues + + +def _convert_rectangle_definition(profdef: dict) -> dict: + crsvalues = { + "type": "rectangle", + "width": profdef["WIDTH"], + "height": profdef.get("HEIGHT", 999), + "closed": "yes" if profdef["TYPE"] < 0 else "no", + } + return crsvalues + + +def _convert_v_shape_definition(profdef: dict) -> dict: + dy_talud = profdef["WIDTH"] / 2.0 + + crsvalues = { + "type": "yz", + "y": [0, dy_talud, profdef["WIDTH"]], + "z": [profdef["HEIGHT"], 0, profdef["HEIGHT"]], + "yzCount": 3, + "conveyance": _proftype_to_conveyancetype(profdef["TYPE"]), + } + return crsvalues + + +def _convert_trapezoid_definition(profdef: dict) -> dict: + if ( + base := profdef.get("BASE") is None + and (talud := profdef.get("TALUD")) is not None + ): + base = max(0, profdef["WIDTH"] - 2 * profdef["HEIGHT"] * talud) + + dy_talud = (profdef["WIDTH"] - base) / 2.0 + + crsvalues = { + "type": "yz", + "yCoordinates": [0, dy_talud, dy_talud + base, profdef["WIDTH"]], + "zCoordinates": [profdef["HEIGHT"], 0, 0, profdef["HEIGHT"]], + "yzCount": 4, + "conveyance": _proftype_to_conveyancetype(profdef["TYPE"]), + } + return crsvalues + + +def _convert_xyz_definition(profdef: dict, profdefxyz: PolyObject) -> dict: + crsvalues = { + "type": "xyz", + "xCoordinates": [p.x for p in profdefxyz.points], + "yCoordinates": [p.y for p in profdefxyz.points], + "zCoordinates": [p.y for p in profdefxyz.points], + "xyzCount": len(profdefxyz.points), + "conveyance": _proftype_to_conveyancetype(profdef["TYPE"]), + } + return crsvalues + + +def convert_profdef( + profdef: dict, profdefxyzfile: Optional[PolyFile] = None +) -> CrossSectionDefinition: + """Convert a single profile definition, read as dict from a legacy + profdef.txt file into a CrossSectionDefinition (sub)class. + + The resulting crosssection definition can be stored in the official + .ini file format. + + Args: + profdef (dict): the key-value pairs read from profdef.txt. Must + contain several keys, depending on type, but at least: + PROFNR, TYPE, WIDTH, and optionally: ZMIN, BASE, TALUD, + FRCTP and FRCCF (all in uppercase). + profdefxyzfile (Optional[PolyFile]): A PolyFile (.pliz) containing + the x,y,z polyline points for all xyz profile definitions + (i.e., type=200/201). Polyline label must equal "PROFNR=", + corresponding to the same labels in the profdef.txt file. + + Returns: + CrossSectionDefinition: a cross section definition object, already + of the correct subclass, depending on the type, e.g., YZCrsDef. + + Raises: + ValueError: when profdef has a wrong profile type, or when xyz data + is missing. + """ + + (proftype, crstype) = _proftype_to_crsdeftype(profdef.get("TYPE")) + + crsdata = {} + if proftype == 1: + crsdata = _convert_pipe_definition(profdef) + elif proftype == 2: + crsdata = _convert_rectangle_definition(profdef) + elif proftype == 4: + crsdata = _convert_v_shape_definition(profdef) + elif proftype == 6: + crsdata = _convert_trapezoid_definition(profdef) + elif proftype == 100: + raise ValueError( + f"Type YZ found in input for PROFNR={profdef['PROFNR']}. Use XYZ instead." + ) + elif proftype == 200: + if profdefxyzfile is None: + raise ValueError( + f"Profdefxyzfile is missing. Required for xyz profile type (PROFNR={profdef['PROFNR']})." + ) + + # Find the single polyline object in profdefxyz file for this PROFNR + polyobj = next( + ( + polyobj + for polyobj in profdefxyzfile.objects + if polyobj.metadata.name == f"PROFNR={profdef['PROFNR']}" + ) + ) + + crsdata = _convert_xyz_definition(profdef, polyobj) + + crsdata["id"] = f"PROFNR{profdef['PROFNR']}" + crsdata["type"] = crstype + if crstype == "circle": + crsdeftype = CircleCrsDef + elif crstype == "rectangle": + crsdeftype = RectangleCrsDef + elif crstype == "yz": + crsdeftype = YZCrsDef + elif crstype == "xyz": + crsdeftype = XYZCrsDef + else: + crsdeftype = CrossSectionDefinition + + crsdef = crsdeftype(**crsdata) + + return crsdef + + def prof_to_cross_from_mdu(mdufile: PathOrStr): global _verbose @@ -66,37 +309,59 @@ def prof_to_cross( proflocfile: PathOrStr, profdeffile: PathOrStr, profdefxyzfile: PathOrStr = None, + crslocfile: PathOrStr = None, + crsdeffile: PathOrStr = None, ): - print(proflocfile) - print(profdeffile) - print(profdefxyzfile) + """The actual converter function for converting legacy profile files + into cross section .ini files. + Args: + proflocfile (PathOrStr): path to the profile location file (.xyz). + Must be parsable into a standard XYZModel. + profdeffile (PathOrStr): path to the profile definition file (.txt) + A free-formatted text value with space-separated key-value pairs. + profdefxyzfile (PathOrStr, optional): path to the xyz profile + geometry definition (.pliz). Must be parsable into a standard + PolyFile, including z-values. + crslocfile (PathOrStr, optional): path to the output location file. + Defaults to crsloc.ini in current working dir. + crsdeffile (PathOrStr, optional): path to the output definition file. + Defaults to crsdef.ini in current working dir. + """ profloc_data = read_profloc_data(proflocfile) - # print(profloc_data.points) profdef_data = read_profdef_data(profdeffile) - # print(profdef_data) + if profdefxyzfile: + profdefxyz_data = read_profdefxyz_data(profdefxyzfile) + else: + profdefxyz_data = None crsloc_data = [] crsdef_data = [] + # Part 1 of 2: crs location data crsloc_data = [ CrossSection( id=f"PROFLOC{nr+1}", x=profloc.x, y=profloc.y, - definitionId=f"PROFNR{int(profloc.z)}", + definitionid=f"PROFNR{int(profloc.z)}", ) for nr, profloc in enumerate(profloc_data.points) ] - # print(crsloc_data) + # TODO: profdef.ZMIN to shift in crsloc + # TODO: snap profloc.x/y to branchid if x/y does not work well. crsloc_model = CrossLocModel(crosssection=crsloc_data) - crsloc_model.filepath = "crsloc.ini" + crsloc_model.filepath = crslocfile crsloc_model.save() + # Part 2 of 2: crs definition data + crsdef_data = [ + convert_profdef(profdef, profdefxyz_data) for profdef in profdef_data + ] crsdef_model = CrossDefModel(definition=crsdef_data) - crsdef_model.filepath = "crsdef.ini" + crsdef_model.filepath = crsdeffile crsdef_model.save() From 324478e875b309071ef403d55b3204d7a5618ad8 Mon Sep 17 00:00:00 2001 From: Arthur van Dam Date: Tue, 4 Apr 2023 13:54:29 +0200 Subject: [PATCH 3/9] Fix prof_to_cross docs + include in mkdocs config --- docs/tools/prof_to_cross.md | 19 ++++++++++++------- docs/tools/tools.md | 4 ++-- mkdocs.yml | 3 +++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/tools/prof_to_cross.md b/docs/tools/prof_to_cross.md index 733b4e76e..779f7b865 100644 --- a/docs/tools/prof_to_cross.md +++ b/docs/tools/prof_to_cross.md @@ -5,22 +5,26 @@ prof_to_cross Directly jump to [Usage](#Usage). # Background -1D cross section specification in a D-Flow FM model used to go via two or three prof* files, the ones specified in the MDU file via `ProflocFile`, `ProfdefFile` +1D cross section specification in a D-Flow FM model used to go via two or three prof* files, +the ones specified in the MDU file under `[geometry]` via `ProflocFile`, `ProfdefFile` and optionally `ProfdefxyzFile`. They contain the location/placement and the type/geometry description, respectively. -Similar input is still needed, but now has the officially supported via .ini files. -These are the ones now specified in the MDU file via `CrsLocFile` and `CrsDefFile`. +Similar input is still needed, but now is officially supported via .ini files. +These are the ones now specified in the MDU file under `[geometry]` via `CrsLocFile` and `CrsDefFile`. + ## Automatic conversion choices +prof_to_cross makes the following automatic conversion choices. ### Location Location continues to be specified via original *x,y* coordinate, no branchId is available. -Vertical absolute placement (`ZMIN` vs. `shift`) still needs refinement. +Vertical absolute placement (`ZMIN` vs. `shift`) still needs refinement, is currently not converted. ### Type + conveyance The following table lists the mapping from old to new cross section types: -|PROFTYPE|meaning|type in crsdef.ini|conveyanceType in crsdef.ini| + +|Profdef TYPE|meaning|type in crsdef.ini|conveyanceType in crsdef.ini| | :--- | :--- | :--- | :--- | -|1|`PIPE`|`circle`||N/A| +|1|`PIPE`|`circle`|N/A| |2|`RECTAN , HYDRAD = AREA / PERIMETER`|`rectangle`|N/A| |3|`RECTAN , HYDRAD = 1D ANALYTIC CONVEYANCE`|`rectangle`|N/A| |4|`V-SHAPE , HYDRAD = AREA / PERIMETER`|`yz`|`lumped`| @@ -38,7 +42,8 @@ Not yet available in converter. # Usage: ```bash -usage: prof_to_cross [-h] [--version] [--verbose] [--mdufile MDUFILE] [--proffiles [PROFFILE [PROFFILE ...]]] +usage: python tools/prof_to_cross.py [-h] [--version] [--verbose] \ + [--mdufile MDUFILE] [--proffiles [PROFFILE [PROFFILE ...]]] ``` diff --git a/docs/tools/tools.md b/docs/tools/tools.md index 930fd5e4b..df28e21f9 100644 --- a/docs/tools/tools.md +++ b/docs/tools/tools.md @@ -1,6 +1,6 @@ # Introduction to tools -HYDROLIB-core contains several utility tools built on top of the core I/O functionality. +HYDROLIB-core also contains utility tools built on top of the core I/O functionality. These small tools may help with model conversion and inspection. -* **[prof_to_cross](geometry/prof_to_cross.md)** - Convert D-Flow FM legacy profdef/profloc files to cross section files. +* **[prof_to_cross](prof_to_cross.md)** - Convert D-Flow FM legacy profdef/profloc files to cross section files. diff --git a/mkdocs.yml b/mkdocs.yml index 2d9fd90fa..464cce805 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -94,6 +94,9 @@ nav: - topics/principles.md - topics/pydantic.md - topics/loadsave.md + - Tools: + - tools/tools.md + - tools/prof_to_cross.md - API Reference: - Introduction: - reference/glossary.md From 445af7288b36a41faeee8ae68d85ad35ea276e33 Mon Sep 17 00:00:00 2001 From: Arthur van Dam Date: Tue, 4 Apr 2023 14:09:08 +0200 Subject: [PATCH 4/9] Move prof_to_cross to hydrolib/tools + more docs --- docs/tools/prof_to_cross.md | 22 ++++++++++++++----- hydrolib/tools/__init__ .py | 1 + .../{core/geometry => tools}/prof_to_cross.py | 0 mkdocs.yml | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 hydrolib/tools/__init__ .py rename hydrolib/{core/geometry => tools}/prof_to_cross.py (100%) diff --git a/docs/tools/prof_to_cross.md b/docs/tools/prof_to_cross.md index 779f7b865..82ce8bee6 100644 --- a/docs/tools/prof_to_cross.md +++ b/docs/tools/prof_to_cross.md @@ -2,7 +2,7 @@ prof_to_cross ============= *Convert D-Flow FM legacy profile files to cross section files.* -Directly jump to [Usage](#Usage). +Directly jump to [Commandline usage](#Commandline-usage). # Background 1D cross section specification in a D-Flow FM model used to go via two or three prof* files, @@ -39,15 +39,14 @@ The following table lists the mapping from old to new cross section types: ### Friction Not yet available in converter. -# Usage: - +# Commandline usage: ```bash -usage: python tools/prof_to_cross.py [-h] [--version] [--verbose] \ +usage: python hydrolib/tools/prof_to_cross.py [-h] [--version] [--verbose] \ [--mdufile MDUFILE] [--proffiles [PROFFILE [PROFFILE ...]]] ``` -# Arguments +## Arguments |short|long|default|help| | :--- | :--- | :--- | :--- | @@ -55,4 +54,15 @@ usage: python tools/prof_to_cross.py [-h] [--version] [--verbose] \ |`-v`|`--version`||show program's version number and exit| ||`--verbose`||also print diagnostic information| |`-m`|`--mdufile`|`None`|automatically take profile filenames from MDUFILE| -|`-p`|`--proffiles`|`None`|2 or 3 profile files: PROFLOCFILE PROFDEFFILE [PROFDEFXYZFILE]| \ No newline at end of file +|`-p`|`--proffiles`|`None`|2 or 3 profile files: PROFLOCFILE PROFDEFFILE [PROFDEFXYZFILE]| + +# Python usage: +```python +from hydrolib.tools import prof_to_cross + +# Option 1: via MDU file: +prof_to_cross.prof_to_cross_from_mdu('FlowFM.mdu') + +# Option 2: directly via profile files: +prof_to_cross.prof_to_cross('profloc.xyz', 'profdef.txt', 'profdefxyz.pliz') +``` diff --git a/hydrolib/tools/__init__ .py b/hydrolib/tools/__init__ .py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/hydrolib/tools/__init__ .py @@ -0,0 +1 @@ + diff --git a/hydrolib/core/geometry/prof_to_cross.py b/hydrolib/tools/prof_to_cross.py similarity index 100% rename from hydrolib/core/geometry/prof_to_cross.py rename to hydrolib/tools/prof_to_cross.py diff --git a/mkdocs.yml b/mkdocs.yml index 464cce805..dc490275e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -96,7 +96,7 @@ nav: - topics/loadsave.md - Tools: - tools/tools.md - - tools/prof_to_cross.md + - "prof_to_cross": tools/prof_to_cross.md - API Reference: - Introduction: - reference/glossary.md From 6dfcfd48f789986c34dc97f9ecd995ace8516bed Mon Sep 17 00:00:00 2001 From: Arthur van Dam Date: Tue, 4 Apr 2023 14:45:34 +0200 Subject: [PATCH 5/9] Add option --outfiles --- docs/tools/prof_to_cross.md | 6 +++-- hydrolib/tools/prof_to_cross.py | 40 ++++++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/docs/tools/prof_to_cross.md b/docs/tools/prof_to_cross.md index 82ce8bee6..85272390d 100644 --- a/docs/tools/prof_to_cross.md +++ b/docs/tools/prof_to_cross.md @@ -42,8 +42,9 @@ Not yet available in converter. # Commandline usage: ```bash usage: python hydrolib/tools/prof_to_cross.py [-h] [--version] [--verbose] \ - [--mdufile MDUFILE] [--proffiles [PROFFILE [PROFFILE ...]]] - + [--mdufile MDUFILE] \ + [--proffiles [PROFFILE [PROFFILE ...]]] \ + [--outfiles CRSLOCFILE CRSDEFFILE] ``` ## Arguments @@ -55,6 +56,7 @@ usage: python hydrolib/tools/prof_to_cross.py [-h] [--version] [--verbose] \ ||`--verbose`||also print diagnostic information| |`-m`|`--mdufile`|`None`|automatically take profile filenames from MDUFILE| |`-p`|`--proffiles`|`None`|2 or 3 profile files: PROFLOCFILE PROFDEFFILE [PROFDEFXYZFILE]| +|`-o`|`--outfiles` |`crsloc.ini crsdef.ini`|save cross section locations and definitions to specified filenames| # Python usage: ```python diff --git a/hydrolib/tools/prof_to_cross.py b/hydrolib/tools/prof_to_cross.py index d46b294f4..7d7649ddc 100644 --- a/hydrolib/tools/prof_to_cross.py +++ b/hydrolib/tools/prof_to_cross.py @@ -288,7 +288,24 @@ def convert_profdef( return crsdef -def prof_to_cross_from_mdu(mdufile: PathOrStr): +def prof_to_cross_from_mdu( + mdufile: PathOrStr, + crslocfile: PathOrStr = None, + crsdeffile: PathOrStr = None, +): + """Wrapper converter function for converting legacy profile files + into cross section .ini files, for files listed in an MDU file. + + Args: + mdufile (PathOrStr): path to the D-Flow FM main input file (.mdu). + Must be parsable into a standard FMModel. + When this contains valid filenames for proflocfile, profdeffile + and optionally profdefxyzfile, conversion will be performed. + crslocfile (PathOrStr, optional): path to the output location file. + Defaults to crsloc.ini in current working dir. + crsdeffile (PathOrStr, optional): path to the output definition file. + Defaults to crsdef.ini in current working dir. + """ global _verbose fmmodel = FMModel(mdufile, recurse=False) @@ -302,7 +319,7 @@ def prof_to_cross_from_mdu(mdufile: PathOrStr): if profdefxyzfile: print(f"* {profdefxyzfile}") - prof_to_cross(proflocfile, profdeffile, profdefxyzfile) + prof_to_cross(proflocfile, profdeffile, profdefxyzfile, crslocfile, crsdeffile) def prof_to_cross( @@ -384,11 +401,19 @@ def _get_parser() -> argparse.ArgumentParser: parser.add_argument( "--proffiles", "-p", - action="extend", + action="store", nargs="*", metavar="PROFFILE", help="2 or 3 profile files: PROFLOCFILE PROFDEFFILE [PROFDEFXYZFILE]", ) + parser.add_argument( + "--outfiles", + "-o", + action="store", + nargs=2, + metavar=("CRSLOCFILE", "CRSDEFFILE"), + help="save cross section locations and definitions to specified filenames", + ) return parser @@ -416,10 +441,15 @@ def main(args=None): sys.exit(1) + outfiles = {"crslocfile": None, "crsdeffile": None} + if args.outfiles is not None: + outfiles["crslocfile"] = args.outfiles[0] + outfiles["crsdeffile"] = args.outfiles[1] + if args.mdufile is not None: - prof_to_cross_from_mdu(args.mdufile) + prof_to_cross_from_mdu(args.mdufile, **outfiles) elif args.proffiles is not None: - prof_to_cross(*args.proffiles) + prof_to_cross(*args.proffiles, **outfiles) else: print("Error: Missing input file(s), use either -m or -p.") From 14728bd2a07145aa6e85d65c6ad3dc7ad9f9f48c Mon Sep 17 00:00:00 2001 From: Arthur van Dam Date: Tue, 4 Apr 2023 16:55:35 +0200 Subject: [PATCH 6/9] Add two example testcases + unit tests + fix discovered bugs --- hydrolib/core/utils.py | 13 ++ hydrolib/tools/prof_to_cross.py | 22 +- tests/data/input/prof_to_cross/profdef.txt | 28 +++ .../input/prof_to_cross/profdef_withxyz.txt | 31 +++ .../data/input/prof_to_cross/profdefxyz.pliz | 11 + tests/data/input/prof_to_cross/profloc.xyz | 17 ++ .../input/prof_to_cross/profloc_withxyz.xyz | 20 ++ tests/data/input/prof_to_cross/tree1d2d.mdu | 213 ++++++++++++++++++ tests/data/reference/prof_to_cross/crsdef.ini | 162 +++++++++++++ .../prof_to_cross/crsdef_withxyz.ini | 191 ++++++++++++++++ tests/data/reference/prof_to_cross/crsloc.ini | 125 ++++++++++ .../prof_to_cross/crsloc_withxyz.ini | 146 ++++++++++++ tests/tools/test_prof_to_cross.py | 46 ++++ 13 files changed, 1020 insertions(+), 5 deletions(-) create mode 100644 tests/data/input/prof_to_cross/profdef.txt create mode 100644 tests/data/input/prof_to_cross/profdef_withxyz.txt create mode 100644 tests/data/input/prof_to_cross/profdefxyz.pliz create mode 100644 tests/data/input/prof_to_cross/profloc.xyz create mode 100644 tests/data/input/prof_to_cross/profloc_withxyz.xyz create mode 100644 tests/data/input/prof_to_cross/tree1d2d.mdu create mode 100644 tests/data/reference/prof_to_cross/crsdef.ini create mode 100644 tests/data/reference/prof_to_cross/crsdef_withxyz.ini create mode 100644 tests/data/reference/prof_to_cross/crsloc.ini create mode 100644 tests/data/reference/prof_to_cross/crsloc_withxyz.ini create mode 100644 tests/tools/test_prof_to_cross.py diff --git a/hydrolib/core/utils.py b/hydrolib/core/utils.py index a4686233a..83856e501 100644 --- a/hydrolib/core/utils.py +++ b/hydrolib/core/utils.py @@ -1,3 +1,5 @@ +import contextlib +import os import platform import re from enum import Enum, auto @@ -178,6 +180,17 @@ def get_operating_system() -> OperatingSystem: raise NotImplementedError(f"Operating system {operating_system} is not supported.") +@contextlib.contextmanager +def working_directory(path): + """Changes working directory and returns to previous on exit.""" + prev_cwd = Path.cwd() + os.chdir(path) + try: + yield + finally: + os.chdir(prev_cwd) + + class PathStyle(str, Enum): """Path style format.""" diff --git a/hydrolib/tools/prof_to_cross.py b/hydrolib/tools/prof_to_cross.py index 7d7649ddc..0445fff67 100644 --- a/hydrolib/tools/prof_to_cross.py +++ b/hydrolib/tools/prof_to_cross.py @@ -58,11 +58,23 @@ def read_profdef_data(profdeffile: PathOrStr) -> List[Dict]: with open(profdeffile) as file: for line in file: linenr = linenr + 1 - if line.startswith("*"): + if line.startswith("*") or len(line.strip()) == 0: continue - tokens = re.split("[=\s]+", line.strip()) + tokens = re.split(r"[=\s]+", line.strip()) + defs.append(dict(zip(tokens[::2], map(float, tokens[1::2])))) + + if "PROFNR" not in defs[-1]: + raise ValueError( + f"Invalid profile definition in {profdeffile}, line {linenr}: missing PROFNR=" + ) + if "TYPE" not in defs[-1]: + raise ValueError( + f"Invalid profile definition in {profdeffile}, line {linenr}: missing TYPE=" + ) + defs[-1]["PROFNR"] = int(defs[-1]["PROFNR"]) + defs[-1]["TYPE"] = int(defs[-1]["TYPE"]) if _verbose: print(f"Read {len(defs)} profile definitions from {profdeffile}.") @@ -171,8 +183,8 @@ def _convert_v_shape_definition(profdef: dict) -> dict: crsvalues = { "type": "yz", - "y": [0, dy_talud, profdef["WIDTH"]], - "z": [profdef["HEIGHT"], 0, profdef["HEIGHT"]], + "yCoordinates": [0, dy_talud, profdef["WIDTH"]], + "zCoordinates": [profdef["HEIGHT"], 0, profdef["HEIGHT"]], "yzCount": 3, "conveyance": _proftype_to_conveyancetype(profdef["TYPE"]), } @@ -203,7 +215,7 @@ def _convert_xyz_definition(profdef: dict, profdefxyz: PolyObject) -> dict: "type": "xyz", "xCoordinates": [p.x for p in profdefxyz.points], "yCoordinates": [p.y for p in profdefxyz.points], - "zCoordinates": [p.y for p in profdefxyz.points], + "zCoordinates": [p.z for p in profdefxyz.points], "xyzCount": len(profdefxyz.points), "conveyance": _proftype_to_conveyancetype(profdef["TYPE"]), } diff --git a/tests/data/input/prof_to_cross/profdef.txt b/tests/data/input/prof_to_cross/profdef.txt new file mode 100644 index 000000000..689d361e7 --- /dev/null +++ b/tests/data/input/prof_to_cross/profdef.txt @@ -0,0 +1,28 @@ +* TYPE=1 : PIPE +* TYPE=2 : RECTAN , HYDRAD = AREA / PERIMETER ALSO SPECIFY: HEIGHT= +* TYPE=3 : RECTAN , HYDRAD = 1D ANALYTIC CONVEYANCE = WATERDEPTH ALSO SPECIFY: HEIGHT= +* TYPE=4 : V-SHAPE , HYDRAD = AREA / PERIMETER ALSO SPECIFY: HEIGHT= +* TYPE=5 : V-SHAPE , HYDRAD = 1D ANALYTIC CONVEYANCE ALSO SPECIFY: HEIGHT= +* TYPE=6 : TRAPEZOID, HYDRAD = AREA / PERIMETER ALSO SPECIFY: HEIGHT= BASE= +* TYPE=7 : TRAPEZOID, HYDRAD = 1D ANALYTIC CONVEYANCE ALSO SPECIFY: HEIGHT= BASE= +* TYPE=100: YZPROF , HYDRAD = AREA / PERIMETER +* TYPE=101: YZPROF , HYDRAD = 1D ANALYTIC CONVEYANCE METHOD + +PROFNR=1 TYPE=7 WIDTH=800 HEIGHT=4 BASE=300 +PROFNR=2 TYPE=7 WIDTH=600 HEIGHT=4 BASE=200 +PROFNR=3 TYPE=7 WIDTH=400 HEIGHT=4 BASE=150 +PROFNR=4 TYPE=7 WIDTH=500 HEIGHT=4 BASE=180 +PROFNR=5 TYPE=7 WIDTH=400 HEIGHT=4 BASE=130 +PROFNR=6 TYPE=7 WIDTH=300 HEIGHT=4 BASE=100 +PROFNR=7 TYPE=7 WIDTH=200 HEIGHT=4 BASE=70 +PROFNR=8 TYPE=7 WIDTH=100 HEIGHT=4 BASE=30 +PROFNR=9 TYPE=7 WIDTH=250 HEIGHT=4 BASE=80 +PROFNR=10 TYPE=7 WIDTH=100 HEIGHT=4 BASE=3 +PROFNR=11 TYPE=7 WIDTH=250 HEIGHT=4 BASE=80 +PROFNR=12 TYPE=7 WIDTH=40 HEIGHT=4 BASE=10 +PROFNR=13 TYPE=7 WIDTH=24 HEIGHT=4 BASE=8 +PROFNR=14 TYPE=7 WIDTH=24 HEIGHT=4 BASE=8 +PROFNR=15 TYPE=5 WIDTH=24 HEIGHT=4 +PROFNR=16 TYPE=3 WIDTH=60 +PROFNR=17 TYPE=3 WIDTH=10 +PROFNR=18 TYPE=3 WIDTH=30 diff --git a/tests/data/input/prof_to_cross/profdef_withxyz.txt b/tests/data/input/prof_to_cross/profdef_withxyz.txt new file mode 100644 index 000000000..34ac57b20 --- /dev/null +++ b/tests/data/input/prof_to_cross/profdef_withxyz.txt @@ -0,0 +1,31 @@ +* TYPE=1 : PIPE +* TYPE=2 : RECTAN , HYDRAD = AREA / PERIMETER ALSO SPECIFY: HEIGHT= +* TYPE=3 : RECTAN , HYDRAD = 1D ANALYTIC CONVEYANCE = WATERDEPTH ALSO SPECIFY: HEIGHT= +* TYPE=4 : V-SHAPE , HYDRAD = AREA / PERIMETER ALSO SPECIFY: HEIGHT= +* TYPE=5 : V-SHAPE , HYDRAD = 1D ANALYTIC CONVEYANCE ALSO SPECIFY: HEIGHT= +* TYPE=6 : TRAPEZOID, HYDRAD = AREA / PERIMETER ALSO SPECIFY: HEIGHT= BASE= +* TYPE=7 : TRAPEZOID, HYDRAD = 1D ANALYTIC CONVEYANCE ALSO SPECIFY: HEIGHT= BASE= +* TYPE=100: YZPROF , HYDRAD = AREA / PERIMETER +* TYPE=101: YZPROF , HYDRAD = 1D ANALYTIC CONVEYANCE METHOD + +PROFNR=1 TYPE=7 WIDTH=800 HEIGHT=4 BASE=300 +PROFNR=2 TYPE=7 WIDTH=600 HEIGHT=4 BASE=200 +PROFNR=3 TYPE=7 WIDTH=400 HEIGHT=4 BASE=150 +PROFNR=4 TYPE=7 WIDTH=500 HEIGHT=4 BASE=180 +PROFNR=5 TYPE=7 WIDTH=400 HEIGHT=4 BASE=130 +PROFNR=6 TYPE=7 WIDTH=300 HEIGHT=4 BASE=100 +PROFNR=7 TYPE=7 WIDTH=200 HEIGHT=4 BASE=70 +PROFNR=8 TYPE=7 WIDTH=100 HEIGHT=4 BASE=30 +PROFNR=9 TYPE=7 WIDTH=250 HEIGHT=4 BASE=80 +PROFNR=10 TYPE=7 WIDTH=100 HEIGHT=4 BASE=3 +PROFNR=11 TYPE=7 WIDTH=250 HEIGHT=4 BASE=80 +PROFNR=12 TYPE=7 WIDTH=40 HEIGHT=4 BASE=10 +PROFNR=13 TYPE=7 WIDTH=24 HEIGHT=4 BASE=8 +PROFNR=14 TYPE=7 WIDTH=24 HEIGHT=4 BASE=8 +PROFNR=15 TYPE=5 WIDTH=24 HEIGHT=4 +PROFNR=16 TYPE=3 WIDTH=60 +PROFNR=17 TYPE=3 WIDTH=10 +PROFNR=18 TYPE=3 WIDTH=30 +PROFNR=20 TYPE=201 FRCTP=1 FRCCF=.035 +PROFNR=21 TYPE=201 FRCTP=1 FRCCF=.035 +PROFNR=22 TYPE=7 WIDTH=1500 HEIGHT=4 BASE=300 diff --git a/tests/data/input/prof_to_cross/profdefxyz.pliz b/tests/data/input/prof_to_cross/profdefxyz.pliz new file mode 100644 index 000000000..db378e155 --- /dev/null +++ b/tests/data/input/prof_to_cross/profdefxyz.pliz @@ -0,0 +1,11 @@ +PROFNR=20 + 4 3 + 4024.955566 3272.291016 4 + 3997.791992 3380.946777 0 + 3952.519043 3516.766113 0 + 3925.354980 3643.530762 4 +PROFNR=21 + 3 3 + 3092.332031 3562.039062 3 + 3119.496094 3625.421387 0 + 3182.877930 3706.913086 4 diff --git a/tests/data/input/prof_to_cross/profloc.xyz b/tests/data/input/prof_to_cross/profloc.xyz new file mode 100644 index 000000000..83543f2c7 --- /dev/null +++ b/tests/data/input/prof_to_cross/profloc.xyz @@ -0,0 +1,17 @@ + 4662.8916016 -85.1603546 1.0000000 + 4697.1044922 445.1416321 2.0000000 + 4714.2109375 2703.2016602 3.0000000 + 4799.7431641 3028.2253418 4.0000000 + 4936.5952148 3455.8884277 5.0000000 + 5244.5112305 3626.9533691 9.0000000 + 5254.6635742 4420.9370117 11.0000000 + 5278.7241211 4071.7229004 6.0000000 + 5620.8535156 4653.3442383 7.0000000 + 5644.4047852 6601.3857422 12.0000000 + 5844.1240234 5115.7324219 7.0000000 + 6507.7368164 6579.8984375 8.0000000 + 6938.0517578 4584.9184570 10.0000000 + 5840.6298828 4957.7465820 8.0000000 + 6778.2558594 5969.1093750 13.0000000 + 6500.6840820 6733.1904297 8.0000000 + 6606.0195312 7554.8085938 13.0000000 diff --git a/tests/data/input/prof_to_cross/profloc_withxyz.xyz b/tests/data/input/prof_to_cross/profloc_withxyz.xyz new file mode 100644 index 000000000..28de0968c --- /dev/null +++ b/tests/data/input/prof_to_cross/profloc_withxyz.xyz @@ -0,0 +1,20 @@ + 4662.8916016 -85.1603546 22.0000000 + 4697.1044922 445.1416321 2.0000000 + 4714.2109375 2703.2016602 3.0000000 + 4799.7431641 3028.2253418 4.0000000 + 4936.5952148 3455.8884277 5.0000000 + 5244.5112305 3626.9533691 9.0000000 + 5254.6635742 4420.9370117 11.0000000 + 5278.7241211 4071.7229004 6.0000000 + 5620.8535156 4653.3442383 7.0000000 + 5644.4047852 6601.3857422 12.0000000 + 5844.1240234 5115.7324219 7.0000000 + 6507.7368164 6579.8984375 1.0000000 + 6938.0517578 4584.9184570 10.0000000 + 5840.6298828 4957.7465820 1.0000000 + 6778.2558594 5969.1093750 13.0000000 + 6500.6840820 6733.1904297 1.0000000 + 6606.0195312 7554.8085938 13.0000000 + 3946.2695312 3408.1103516 20.0000000 + 3149.4648438 3670.6948242 21.0000000 + 4480.4907227 3281.3457031 20.0000000 diff --git a/tests/data/input/prof_to_cross/tree1d2d.mdu b/tests/data/input/prof_to_cross/tree1d2d.mdu new file mode 100644 index 000000000..20d462629 --- /dev/null +++ b/tests/data/input/prof_to_cross/tree1d2d.mdu @@ -0,0 +1,213 @@ +# D-Flow FM mdu-file, generated by Matlab on 11:31:44, 20-08-2015. +# This standardized mdu-file is intended to only be used for the testbench. + +[general] +Program = D-Flow FM # The program +Version = 1.1.148.41436 # The version of the program +MDUFormatVersion = 1.02 # File format version. Do not edit this. +AutoStart = 0 # Autostart simulation after loading MDU or not (0=no, 1=autostart, 2=autostartstop). + +[geometry] +NetFile = tree1d2d_net.nc # *_net.nc +BathymetryFile = # *.xyb +DryPointsFile = # Dry points file *.xyz, third column dummy z values, or polygon file *.pol with 3 columns: z value specifies inside/outside: 1/-1. +WaterLevIniFile = # Initial water levels sample file *.xyz +LandBoundaryFile = # Only for plotting +ThinDamFile = # *_thd.pli, Polyline(s) for tracing thin dams. +FixedWeirFile = # *_fxw.pliz, Polyline(s) x,y,z, z = fixed weir top levels (formerly fixed weir) +VertplizFile = # *_vlay.pliz), = pliz with x,y, Z, first Z =nr of layers, second Z = laytyp +ProflocFile = profloc_withxyz.xyz # *_proflocation.xyz) x,y,z, z = profile refnumber +ProfdefFile = profdef_withxyz.txt # *_profdefinition.def) definition for all profile nrs +ProfdefxyzFile = profdefxyz.pliz # *_profdefinition.def) definition for all profile nrs +StructureFile = # *.ini, Structure definitions file +ManholeFile = # File containing manholes (e.g. *.ini) +PartitionFile = # *_part.pol, polyline(s) x,y +Uniformwidth1D = 2. # Uniform width for 1D profiles not specified bij profloc +WaterLevIni = -10. # Initial water level +Bedlevuni = -5. # Uniform bottom level, (only if bedlevtype>=3, used at missing z values in netfile +Bedslope = 0. # bedslopeinclination, sets zk = bedlevuni + x*bedslope ans sets zbndz = xbndz*bedslope +BedlevType = 3 # 1: at cell center (tiles xz,yz,bl,bob=max(bl)), 2: at face (tiles xu,yu,blu,bob=blu), 3: at face (using mean node values), 4: at face (using min node values), 5: at face (using max node values), 6: with bl based on node values +Blmeanbelow = -999. # if not -999d0, below this level the cell centre bedlevel is the mean of surrouding netnodes +Blminabove = -999. # if not -999d0, above this level the cell centre bedlevel is the min of surrouding netnodes +AngLat = 0. # Angle of latitude S-N (deg), 0=no Coriolis +AngLon = 0. # Angle of longitude E-W (deg), 0=Greenwich +Conveyance2D = -1 # -1:R=HU,0:R=H, 1:R=A/P, 2:K=analytic-1D conv, 3:K=analytic-2D conv +Nonlin2D = 0 # Non-linear 2D volumes, only icm ibedlevtype = 3 and Conveyance2D>=1 +Sillheightmin = 0.5 # Weir treatment only if both sills larger than this value (m) +Makeorthocenters = 0 # 1=yes, 0=no switch from circumcentres to orthocentres in geominit +Dcenterinside = 1. # limit cell center; 1.0:in cell <-> 0.0:on c/g +Bamin = 1.d-6 # Minimum gridcell area , icm cutcells +OpenBoundaryTolerance = 3. # Search tolerance factor between boundary polyline and grid cells. Unit: in cell size units (i.e., not metres). +RenumberFlowNodes = 1 # Switch on or off (1/0) the renumbering of flow nodes for slight speedup. +Kmx = 0 # Max nr of vertical layers +Layertype = 1 # 1= all sigma, 2 = all z, 3 = use VertplizFile +Numtopsig = 0 # Nr of sigmalayers in top of Zlayer model +SigmaGrowthFactor = 1. # layer thickness growth factor from bed up + +[numerics] +CFLMax = 0.7 # Max. Courant nr. +AdvecType = 3 # Adv type, 0=no, 1= Wenneker, qu-udzt, 2=1, q(uio-u), 3=Perot q(uio-u), 4=Perot q(ui-u), 5=Perot q(ui-u) without itself +Lincontin = 0 # Default 0; Set to 1 for linearizing d(Hu)/dx; link to AdvecType +TimeStepType = 2 # 0=only transport, 1=transport + velocity update, 2=full implicit step_reduce, 3=step_jacobi, 4=explicit +Limtyphu = 0 # Limiter type for waterdepth in continuity eq., 0=no, 1=minmod,2=vanLeer,3=Kooren,4=Monotone Central +Limtypmom = 4 # Limiter type for cell center advection velocity, 0=no, 1=minmod,2=vanLeer,3=Kooren,4=Monotone Central +Limtypsa = 0 # Limiter type for salinity transport, 0=no, 1=minmod,2=vanLeer,3=Kooren,4=Monotone Central +TransportMethod = 1 # Transport method, 0=Herman method, 1=Sander method +Vertadvtypsal = 5 # Vertical advection type for salinity, 0=No, 1=UpwexpL, 2=Centralexpl, 3=UpwimpL, 4=CentraLimpL, 5=4 but 3 for neg. stratif., 6=higher order expl, no forester +Horadvtypzlayer = 0 # Horizontal advection treatment zlayer, 1=default, 2 = Sigma like +Icgsolver = 1 # Solver type , 1 = sobekGS_OMP, 2 = sobekGS_OMPthreadsafe, 3 = sobekGS, 4 = sobekGS + Saadilud, 5 = parallel/global Saad, 6 = parallel/Petsc, 7 = parallel/GS +Maxdegree = 6 # Maximum degree in Gauss elimination +FixedWeirScheme = 0 # 0 = no, 1 = compact stencil, 2 = whole tile lifted, full subgrid weir + factor +FixedWeirContraction = 1. # flow width = flow width*FixedWeirContraction +Fixedweirfrictscheme = 1 # Fixed weir friction scheme (0: friction based on hu, 1: friction based on subgrid weir friction scheme) +Fixedweirtopwidth = 3. # Uniform width of the groyne part of fixed weirs +Fixedweirtopfrictcoef = -999. # Uniform friction coefficient of the groyne part of fixed weirs +Fixedweirtalud = 0.25 # Uniform talud slope of fixed weirs +Izbndpos = 0 # Position of z boundary, 0=D3Dflow, 1=on net boundary, 2 = on specifiend polyline +Tlfsmo = 0. # Fourier smoothing time on waterlevel boundaries (s) +Slopedrop2D = 0. # Apply droplosses only if local bottom slope > Slopedrop2D, <=0 =no droplosses +Drop3D = 0. # Apply droplosses in 3D if z upwind below bob + 2/3 hu*drop3D +Chkadvd = 0.1 # Check advection terms if depth < chkadvdp, => less setbacks +Teta0 = 0.550000011920929 # Teta of time integration, 0.5 < Teta < 1d0 +Qhrelax = 1.d-2 # Relaxation qhbnd ( ) +Jbasqbnddownwindhs = 0 # 0 : original hu on qbnd, 1 = downwind hs on qbnd +cstbnd = 0 # Delft-3D type velocity treatment near boundaries for small coastal models (1) or not (0) +Maxitverticalforestersal = 100 # 0 : no vertical filter, > 0 = Max nr of iterations +Maxitverticalforestertem = 0 # 0 : no vertical filter for temp, > 0 = Max nr of iterations +Jaorgsethu = 1 # Velocity reconstruction scheme (0 : setumod, sethu, setau sequence, 1 : sethu, setau, setumod sequence (standard)) +Turbulencemodel = 3 # 0=no, 1 = constant, 2 = algebraic, 3 = k-eps, 4 = k-tau +Turbulenceadvection = 3 # 0=no, 3 = hor. expl., vert. impl. +AntiCreep = 0 # Include anti-creep calculation, (0=no, 1=yes) +Maxwaterleveldiff = 0. # upper bound (in m) on water level changes, <= 0: no bounds +Maxvelocitydiff = 0. # upper bound (in m/s) on velocity changes, <= 0: no bounds +Epshu = 1.d-4 # Input for threshold water depth for wet and dry cells + +[physics] +UnifFrictCoef = 2.3d-2 # Uniform friction coefficient, 0=no friction +UnifFrictType = 1 # 0=Chezy, 1=Manning, 2=White Colebrook, 3=idem, WAQUA style +UnifFrictCoef1D = 2.3d-2 # Uniform friction coefficient in 1D links, 0=no friction +UnifFrictCoefLin = 0. # Uniform linear friction coefficient for ocean models (m/s), 0=no +Umodlin = 0 # Use 1 for linear friction umod, for ifrctyp=4,5,6 +Vicouv = 0. # Uniform horizontal eddy viscosity (m2/s) +Dicouv = 1. # Uniform horizontal eddy diffusivity (m2/s) +Vicoww = 0. # Uniform vertical eddy viscosity (m2/s) +Dicoww = 5.d-5 # Uniform vertical eddy diffusivity (m2/s) +Vicwminb = 0. # Minimum visc in prod and buoyancy term (m2/s) +Smagorinsky = 0. # Add Smagorinsky horizontal turbulence : vicu = vicu + ( (Smagorinsky*dx)**2)*S, e.g. 0.1 +Elder = 0. # Add Elder contribution : vicu = vicu + Elder*kappa*ustar*H/6), e.g. 1.0 +irov = 0 # 0=free slip, 1 = partial slip using wall_ks +wall_ks = 0. # Nikuradse roughness for side walls, wall_z0=wall_ks/30 +Rhomean = 1000. # Average water density (kg/m3) +Idensform = 0 # Density calulation (0: uniform, 1: Eckard, 2: Unesco, 3: baroclinic case) +Ag = 9.81 # Gravitational acceleration +TidalForcing = 1 # Tidal forcing (0=no, 1=yes) (only for jsferic == 1) +Doodsonstart = 55.565 # TRIWAQ = 55.565D0 , D3D = 57.555D0 +Doodsonstop = 375.575 # TRIWAQ = 375.575D0 , D3D = 275.555D0 +Doodsoneps = 3.d-2 # TRIWAQ = 0.0 400 cmps , D3D = 0.03 60 cmps +Salinity = 0 # Include salinity, (0=no, 1=yes) +InitialSalinity = 0. # Inital salinity concentration (ppt) +Sal0abovezlev = -999. # Salinity 0 above level (m) +DeltaSalinity = -999. # for testcases +Backgroundsalinity = 30. # For eq of state (ppt) +Backgroundwatertemperature = 6. # For eq of state (deg C) +Temperature = 0 # Include temperature, (0=no, 1=only transport, 3=excess model of D3D, 5=heat flux model (5) of D3D) +InitialTemperature = 6. # Inital temperature (degC) +Secchidepth = 1. # Water clarity parameter (m) +Stanton = -1. # Coefficient for convective heat flux ( ) , if negative, Cd wind*abs(Stanton) +Dalton = -1. # Coefficient for evaporative heat flux ( ), if negative, Cd wind*abs(Dalton) +SecondaryFlow = 0 # Secondary flow (0=no, 1=yes) +EffectSpiral = 0. # Factor for weighing the effect of the spiral flow intensity on transport angle +BetaSpiral = 0. # Factor for weighing the effect of the spiral flow on flow dispersion stresses + +[grw] +Conductivity = 0. # non dimensionless K conductivity saturated (m/s), Q = K*A*i (m3/s) +h_aquiferuni = 20. # uniform height of carrying layer (m) +h_unsatini = 0.200000002980232 # initial level groundwater is bedlevel - h_unsatini (m) + +[wind] +ICdtyp = 2 # ( ),1=const, 2=S&B 2 breakpoints, 3= S&B 3 breakpoints, 4=Charnock constant +Cdbreakpoints = 6.3d-4 7.23d-3 # ( ), e.g. 0.00063 0.00723 +Windspeedbreakpoints = 0. 100. # (m/s), e.g. 0.0 100.0 +Rhoair = 1.20000004768372 # Air density (kg/m3) +PavBnd = 0. # Average air pressure on open boundaries, (N/m2), only applied if value > 0 +PavIni = 0. # Average air pressure for initial water level correction (N/m2) (only applied if > 0) +Gapres = 101325. # Only relevant for Spiderweb: Global Atmospheric Pressure, (N/m2) + +[waves] +Wavemodelnr = 0 # Wave model nr, 0=no, 1=fetch/depth limited hurdlestive, 2=youngverhagen, 3 = Delft3D-WAVE, 4=wave group forcing +WaveNikuradse = 1.d-2 # Wave friction Nikuradse ks coefficient, used in Krone Swart, e.g. 0.01 m +Rouwav = # Friction model for wave induced shear stress +Gammax = 1. # Maximum wave height/water depth ratio + +[time] +RefDate = 19920831 # Reference date (yyyymmdd) +Tzone = 0. # Data Sources in GMT are interrogated with time in minutes since refdat-Tzone*60 +DtUser = 40. # User timestep in seconds (interval for external forcing update & his/map output) +DtNodal = 0. # Timestep (days) for updating nodal factors in astronomical boundary conditions +DtMax = 40. # Max timestep in seconds +DtInit = 1. # Initial timestep in seconds +Tunit = S # Time units in MDU (D, H, M or S), only for Tstart and Tstop +TStart = 0. # Start time w.r.t. RefDate (in TUnit) +TStop = 8640000. # Stop time w.r.t. RefDate (in TUnit) + +[restart] +RestartFile = # Restart file, only from netcdf-file, hence: either *_rst.nc or *_map.nc +RestartDateTime = # Restart time (YYYYMMDDHHMMSS), only relevant in case of restart from *_map.nc + +[external forcing] +ExtForceFile = tree1d2d.ext # Old format for external forcings file *.ext, link with tim/cmp-format boundary conditions specification +ExtForceFileNew = # New format for external forcings file *.ext, link with bc -format boundary conditions specification + +[output] +OutputDir = dflowfmoutput # Output directory of map-, his-, rst-, dat- and timings-files, default: DFM_OUTPUT_. Set to . for no dir/current dir. +FlowGeomFile = # *_flowgeom.nc Flow geometry file in NetCDF format. +ObsFile = # *.xyn Coords+name of observation stations. +CrsFile = # *_crs.pli Polyline(s) definining cross section(s). +HisFile = # *_his.nc History file in NetCDF format. +HisInterval = 120. # History output, given as "interval" "start period" "end period" (s) +XLSInterval = 0. # Interval (s) between XLS history +MapFile = # *_map.nc Map file in NetCDF format. +MapInterval = 0. # Map file output, given as "interval" "start period" "end period" (s) +RstInterval = 0. # Restart file output, given as "interval" "start period" "end period" (s) +S1incinterval = 0. # Interval (m) in incremental file for waterlevels S1 +WaqFileBase = # Basename (without extension) for all Delwaq files to be written. +WaqInterval = 0. # Interval (in s) between Delwaq file outputs +StatsInterval = 0. # Interval (in s) between simulation statistics output. +Writebalancefile = 0 # Write Balancefile, 1=yes, 0=no +TimingsInterval = 0. # Timings output interval +TimeSplitInterval = 0X # Time splitting interval, after which a new output file is started. value+unit, e.g. '1 M', valid units: Y,M,D,h,m,s. +MapFormat = 1 # Map file format, 1: netCDF, 2: Tecplot, 3: netCFD and Tecplot, 4: NetCDF-UGRID +Wrihis_balance = 1 # Write mass balance totals to his file (1=yes, 0=no) +Wrihis_structure_gen = 1 # Write general structure parameters to his file (1=yes, 0=no) +Wrihis_structure_dam = 1 # Write dam parameters to his file (1=yes, 0=no) +Wrihis_structure_pump = 1 # Write pump parameters to his file (1=yes, 0=no) +Wrihis_structure_gate = 1 # Write gate parameters to his file (1=yes, 0=no) +Wrimap_waterlevel_s0 = 1 # Write water levels for previous time step to map file (1=yes, 0=no) +Wrimap_waterlevel_s1 = 1 # Write water levels to map file (1=yes, 0=no) +Wrimap_velocity_component_u0 = 1 # Write velocity component for previous time step to map file (1=yes, 0=no) +Wrimap_velocity_component_u1 = 1 # Write velocity component to map file (1=yes, 0=no) +Wrimap_velocity_vector = 1 # Write cell-center velocity vectors to map file (1=yes, 0=no) +Wrimap_upward_velocity_component = 1 # Write upward velocity component on cell interfaces (1=yes, 0=no) +Wrimap_density_rho = 1 # Write flow density to map file (1=yes, 0=no) +Wrimap_horizontal_viscosity_viu = 1 # Write horizontal viscosity to map file (1=yes, 0=no) +Wrimap_horizontal_diffusivity_diu = 1 # Write horizontal diffusivity to map file (1=yes, 0=no) +Wrimap_flow_flux_q1 = 1 # Write flow flux to map file (1=yes, 0=no) +Wrimap_spiral_flow = 1 # Write spiral flow to map file (1=yes, 0=no) +Wrimap_numlimdt = 1 # Write the number times a cell was Courant limiting to map file (1=yes, 0=no) +Wrimap_taucurrent = 1 # Write the shear stress to map file (1=yes, 0=no) +Wrimap_chezy = 1 # Write the chezy roughness to map file (1=yes, 0=no) +Wrimap_turbulence = 1 # Write vicww, k and eps to map-file (1=yes, 0=no, default=1) +Wrimap_wind = 1 # Write wind velocities to map file (1=yes, 0=no) +Wrimap_heat_fluxes = 0 # Write heat fluxes to map file (1=yes, 0=no) +Richardsononoutput = 0 # 1=yes,0=no +MapOutputTimeVector = # File (.mpt) containing fixed map output times (s) w.r.t. RefDate +FullGridOutput = 0 # 0:compact, 1:full time-varying grid data +EulerVelocities = 0 # 0:GLM, 1:Euler velocities +SnapshotDir = # Directory where snapshots/screendumps are saved. + +[trachytopes] +TrtRou = N # Include alluvial and vegetation roughness (trachytopes), (N=no, Y=yes) +TrtDef = # Filename (*.ttd) including trachytope definitions +Trtl = # Filename (*.arl) including distribution of trachytope definitions +DtTrt = # Interval (in s) between trachytope roughness updates + diff --git a/tests/data/reference/prof_to_cross/crsdef.ini b/tests/data/reference/prof_to_cross/crsdef.ini new file mode 100644 index 000000000..7c9b96e03 --- /dev/null +++ b/tests/data/reference/prof_to_cross/crsdef.ini @@ -0,0 +1,162 @@ +# written by HYDROLIB-core 0.4.1 + +[General] + fileVersion = 3.00 + fileType = crossDef + +[Definition] + id = PROFNR1 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 400.0 400.0 800.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR2 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 300.0 300.0 600.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR3 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 200.0 200.0 400.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR4 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 250.0 250.0 500.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR5 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 200.0 200.0 400.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR6 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 150.0 150.0 300.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR7 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 100.0 100.0 200.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR8 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 50.0 50.0 100.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR9 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 125.0 125.0 250.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR10 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 50.0 50.0 100.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR11 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 125.0 125.0 250.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR12 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 20.0 20.0 40.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR13 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 12.0 12.0 24.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR14 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 12.0 12.0 24.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR15 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 3 # Number of YZ-coordinates. + yCoordinates = 0.0 12.0 24.0 + zCoordinates = 4.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR16 # Unique cross-section definition id. + type = rectangle # Cross section type; must read rectangle + width = 60.0 # Width of the rectangle [m]. + height = 999.0 # Height of the rectangle [m]. + closed = 0 # no: Open channel, yes: Closed channel. + +[Definition] + id = PROFNR17 # Unique cross-section definition id. + type = rectangle # Cross section type; must read rectangle + width = 10.0 # Width of the rectangle [m]. + height = 999.0 # Height of the rectangle [m]. + closed = 0 # no: Open channel, yes: Closed channel. + +[Definition] + id = PROFNR18 # Unique cross-section definition id. + type = rectangle # Cross section type; must read rectangle + width = 30.0 # Width of the rectangle [m]. + height = 999.0 # Height of the rectangle [m]. + closed = 0 # no: Open channel, yes: Closed channel. + diff --git a/tests/data/reference/prof_to_cross/crsdef_withxyz.ini b/tests/data/reference/prof_to_cross/crsdef_withxyz.ini new file mode 100644 index 000000000..5ff71cb93 --- /dev/null +++ b/tests/data/reference/prof_to_cross/crsdef_withxyz.ini @@ -0,0 +1,191 @@ +# written by HYDROLIB-core 0.4.1 + +[General] + fileVersion = 3.00 + fileType = crossDef + +[Definition] + id = PROFNR1 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 400.0 400.0 800.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR2 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 300.0 300.0 600.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR3 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 200.0 200.0 400.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR4 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 250.0 250.0 500.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR5 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 200.0 200.0 400.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR6 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 150.0 150.0 300.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR7 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 100.0 100.0 200.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR8 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 50.0 50.0 100.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR9 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 125.0 125.0 250.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR10 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 50.0 50.0 100.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR11 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 125.0 125.0 250.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR12 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 20.0 20.0 40.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR13 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 12.0 12.0 24.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR14 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 12.0 12.0 24.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR15 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 3 # Number of YZ-coordinates. + yCoordinates = 0.0 12.0 24.0 + zCoordinates = 4.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + +[Definition] + id = PROFNR16 # Unique cross-section definition id. + type = rectangle # Cross section type; must read rectangle + width = 60.0 # Width of the rectangle [m]. + height = 999.0 # Height of the rectangle [m]. + closed = 0 # no: Open channel, yes: Closed channel. + +[Definition] + id = PROFNR17 # Unique cross-section definition id. + type = rectangle # Cross section type; must read rectangle + width = 10.0 # Width of the rectangle [m]. + height = 999.0 # Height of the rectangle [m]. + closed = 0 # no: Open channel, yes: Closed channel. + +[Definition] + id = PROFNR18 # Unique cross-section definition id. + type = rectangle # Cross section type; must read rectangle + width = 30.0 # Width of the rectangle [m]. + height = 999.0 # Height of the rectangle [m]. + closed = 0 # no: Open channel, yes: Closed channel. + +[Definition] + id = PROFNR20 # Unique cross-section definition id. + type = xyz # Cross section type; must read xyz + yCoordinates = 3272.291016 3380.946777 3516.766113 3643.530762 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + xyzCount = 4 # Number of XYZ-coordinates. + xCoordinates = 4024.955566 3997.791992 3952.519043 3925.35498 + +[Definition] + id = PROFNR21 # Unique cross-section definition id. + type = xyz # Cross section type; must read xyz + yCoordinates = 3562.039062 3625.421387 3706.913086 + zCoordinates = 3.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + xyzCount = 3 # Number of XYZ-coordinates. + xCoordinates = 3092.332031 3119.496094 3182.87793 + +[Definition] + id = PROFNR22 # Unique cross-section definition id. + type = yz # Cross section type; must read yz + yzCount = 4 # Number of YZ-coordinates. + yCoordinates = 0.0 750.0 750.0 1500.0 + zCoordinates = 4.0 0.0 0.0 4.0 + conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. + sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + diff --git a/tests/data/reference/prof_to_cross/crsloc.ini b/tests/data/reference/prof_to_cross/crsloc.ini new file mode 100644 index 000000000..f8c4450ad --- /dev/null +++ b/tests/data/reference/prof_to_cross/crsloc.ini @@ -0,0 +1,125 @@ +# written by HYDROLIB-core 0.4.1 + +[General] + fileVersion = 3.00 + fileType = crossLoc + +[CrossSection] + id = PROFLOC1 # Unique cross-section location id. + x = 4662.8916016 # x-coordinate of the location of the cross section. + y = -85.1603546 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR1 # Id of cross section definition. + +[CrossSection] + id = PROFLOC2 # Unique cross-section location id. + x = 4697.1044922 # x-coordinate of the location of the cross section. + y = 445.1416321 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR2 # Id of cross section definition. + +[CrossSection] + id = PROFLOC3 # Unique cross-section location id. + x = 4714.2109375 # x-coordinate of the location of the cross section. + y = 2703.2016602 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR3 # Id of cross section definition. + +[CrossSection] + id = PROFLOC4 # Unique cross-section location id. + x = 4799.7431641 # x-coordinate of the location of the cross section. + y = 3028.2253418 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR4 # Id of cross section definition. + +[CrossSection] + id = PROFLOC5 # Unique cross-section location id. + x = 4936.5952148 # x-coordinate of the location of the cross section. + y = 3455.8884277 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR5 # Id of cross section definition. + +[CrossSection] + id = PROFLOC6 # Unique cross-section location id. + x = 5244.5112305 # x-coordinate of the location of the cross section. + y = 3626.9533691 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR9 # Id of cross section definition. + +[CrossSection] + id = PROFLOC7 # Unique cross-section location id. + x = 5254.6635742 # x-coordinate of the location of the cross section. + y = 4420.9370117 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR11 # Id of cross section definition. + +[CrossSection] + id = PROFLOC8 # Unique cross-section location id. + x = 5278.7241211 # x-coordinate of the location of the cross section. + y = 4071.7229004 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR6 # Id of cross section definition. + +[CrossSection] + id = PROFLOC9 # Unique cross-section location id. + x = 5620.8535156 # x-coordinate of the location of the cross section. + y = 4653.3442383 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR7 # Id of cross section definition. + +[CrossSection] + id = PROFLOC10 # Unique cross-section location id. + x = 5644.4047852 # x-coordinate of the location of the cross section. + y = 6601.3857422 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR12 # Id of cross section definition. + +[CrossSection] + id = PROFLOC11 # Unique cross-section location id. + x = 5844.1240234 # x-coordinate of the location of the cross section. + y = 5115.7324219 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR7 # Id of cross section definition. + +[CrossSection] + id = PROFLOC12 # Unique cross-section location id. + x = 6507.7368164 # x-coordinate of the location of the cross section. + y = 6579.8984375 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR8 # Id of cross section definition. + +[CrossSection] + id = PROFLOC13 # Unique cross-section location id. + x = 6938.0517578 # x-coordinate of the location of the cross section. + y = 4584.918457 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR10 # Id of cross section definition. + +[CrossSection] + id = PROFLOC14 # Unique cross-section location id. + x = 5840.6298828 # x-coordinate of the location of the cross section. + y = 4957.746582 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR8 # Id of cross section definition. + +[CrossSection] + id = PROFLOC15 # Unique cross-section location id. + x = 6778.2558594 # x-coordinate of the location of the cross section. + y = 5969.109375 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR13 # Id of cross section definition. + +[CrossSection] + id = PROFLOC16 # Unique cross-section location id. + x = 6500.684082 # x-coordinate of the location of the cross section. + y = 6733.1904297 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR8 # Id of cross section definition. + +[CrossSection] + id = PROFLOC17 # Unique cross-section location id. + x = 6606.0195312 # x-coordinate of the location of the cross section. + y = 7554.8085938 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR13 # Id of cross section definition. + diff --git a/tests/data/reference/prof_to_cross/crsloc_withxyz.ini b/tests/data/reference/prof_to_cross/crsloc_withxyz.ini new file mode 100644 index 000000000..25c4f0c52 --- /dev/null +++ b/tests/data/reference/prof_to_cross/crsloc_withxyz.ini @@ -0,0 +1,146 @@ +# written by HYDROLIB-core 0.4.1 + +[General] + fileVersion = 3.00 + fileType = crossLoc + +[CrossSection] + id = PROFLOC1 # Unique cross-section location id. + x = 4662.8916016 # x-coordinate of the location of the cross section. + y = -85.1603546 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR22 # Id of cross section definition. + +[CrossSection] + id = PROFLOC2 # Unique cross-section location id. + x = 4697.1044922 # x-coordinate of the location of the cross section. + y = 445.1416321 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR2 # Id of cross section definition. + +[CrossSection] + id = PROFLOC3 # Unique cross-section location id. + x = 4714.2109375 # x-coordinate of the location of the cross section. + y = 2703.2016602 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR3 # Id of cross section definition. + +[CrossSection] + id = PROFLOC4 # Unique cross-section location id. + x = 4799.7431641 # x-coordinate of the location of the cross section. + y = 3028.2253418 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR4 # Id of cross section definition. + +[CrossSection] + id = PROFLOC5 # Unique cross-section location id. + x = 4936.5952148 # x-coordinate of the location of the cross section. + y = 3455.8884277 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR5 # Id of cross section definition. + +[CrossSection] + id = PROFLOC6 # Unique cross-section location id. + x = 5244.5112305 # x-coordinate of the location of the cross section. + y = 3626.9533691 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR9 # Id of cross section definition. + +[CrossSection] + id = PROFLOC7 # Unique cross-section location id. + x = 5254.6635742 # x-coordinate of the location of the cross section. + y = 4420.9370117 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR11 # Id of cross section definition. + +[CrossSection] + id = PROFLOC8 # Unique cross-section location id. + x = 5278.7241211 # x-coordinate of the location of the cross section. + y = 4071.7229004 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR6 # Id of cross section definition. + +[CrossSection] + id = PROFLOC9 # Unique cross-section location id. + x = 5620.8535156 # x-coordinate of the location of the cross section. + y = 4653.3442383 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR7 # Id of cross section definition. + +[CrossSection] + id = PROFLOC10 # Unique cross-section location id. + x = 5644.4047852 # x-coordinate of the location of the cross section. + y = 6601.3857422 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR12 # Id of cross section definition. + +[CrossSection] + id = PROFLOC11 # Unique cross-section location id. + x = 5844.1240234 # x-coordinate of the location of the cross section. + y = 5115.7324219 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR7 # Id of cross section definition. + +[CrossSection] + id = PROFLOC12 # Unique cross-section location id. + x = 6507.7368164 # x-coordinate of the location of the cross section. + y = 6579.8984375 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR1 # Id of cross section definition. + +[CrossSection] + id = PROFLOC13 # Unique cross-section location id. + x = 6938.0517578 # x-coordinate of the location of the cross section. + y = 4584.918457 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR10 # Id of cross section definition. + +[CrossSection] + id = PROFLOC14 # Unique cross-section location id. + x = 5840.6298828 # x-coordinate of the location of the cross section. + y = 4957.746582 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR1 # Id of cross section definition. + +[CrossSection] + id = PROFLOC15 # Unique cross-section location id. + x = 6778.2558594 # x-coordinate of the location of the cross section. + y = 5969.109375 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR13 # Id of cross section definition. + +[CrossSection] + id = PROFLOC16 # Unique cross-section location id. + x = 6500.684082 # x-coordinate of the location of the cross section. + y = 6733.1904297 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR1 # Id of cross section definition. + +[CrossSection] + id = PROFLOC17 # Unique cross-section location id. + x = 6606.0195312 # x-coordinate of the location of the cross section. + y = 7554.8085938 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR13 # Id of cross section definition. + +[CrossSection] + id = PROFLOC18 # Unique cross-section location id. + x = 3946.2695312 # x-coordinate of the location of the cross section. + y = 3408.1103516 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR20 # Id of cross section definition. + +[CrossSection] + id = PROFLOC19 # Unique cross-section location id. + x = 3149.4648438 # x-coordinate of the location of the cross section. + y = 3670.6948242 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR21 # Id of cross section definition. + +[CrossSection] + id = PROFLOC20 # Unique cross-section location id. + x = 4480.4907227 # x-coordinate of the location of the cross section. + y = 3281.3457031 # y-coordinate of the location of the cross section. + shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + definitionId = PROFNR20 # Id of cross section definition. + diff --git a/tests/tools/test_prof_to_cross.py b/tests/tools/test_prof_to_cross.py new file mode 100644 index 000000000..4f59a77bd --- /dev/null +++ b/tests/tools/test_prof_to_cross.py @@ -0,0 +1,46 @@ +import os + +from hydrolib.core.dflowfm.mdu.models import FMModel +from hydrolib.core.utils import working_directory +from hydrolib.tools import prof_to_cross +from tests.utils import ( + assert_files_equal, + test_input_dir, + test_output_dir, + test_reference_dir, +) + + +def test_prof_to_cross_from_proffiles(): + proflocfile = test_input_dir / "prof_to_cross" / "profloc.xyz" + profdeffile = test_input_dir / "prof_to_cross" / "profdef.txt" + + crsloc_outfile = test_output_dir / "test_prof_to_cross" / "crsloc.ini" + crsdef_outfile = test_output_dir / "test_prof_to_cross" / "crsdef.ini" + + crsloc_reffile = test_reference_dir / "prof_to_cross" / "crsloc.ini" + crsdef_reffile = test_reference_dir / "prof_to_cross" / "crsdef.ini" + prof_to_cross.prof_to_cross( + proflocfile, profdeffile, crslocfile=crsloc_outfile, crsdeffile=crsdef_outfile + ) + + assert_files_equal(crsloc_outfile, crsloc_reffile, [0]) + assert_files_equal(crsdef_outfile, crsdef_reffile, [0]) + + +def test_prof_to_cross_from_mdu(): + mdu_infile = test_input_dir / "prof_to_cross" / "tree1d2d.mdu" + + crsloc_outfile = test_output_dir / "test_prof_to_cross" / "crsloc_withxyz.ini" + crsdef_outfile = test_output_dir / "test_prof_to_cross" / "crsdef_withxyz.ini" + + crsloc_reffile = test_reference_dir / "prof_to_cross" / "crsloc_withxyz.ini" + crsdef_reffile = test_reference_dir / "prof_to_cross" / "crsdef_withxyz.ini" + + with working_directory(mdu_infile.parent): + prof_to_cross.prof_to_cross_from_mdu( + mdu_infile, crslocfile=crsloc_outfile, crsdeffile=crsdef_outfile + ) + + assert_files_equal(crsloc_outfile, crsloc_reffile, [0]) + assert_files_equal(crsdef_outfile, crsdef_reffile, [0]) From 0781a22032a078a2ca0fbff4bbc39c4f2e3514ac Mon Sep 17 00:00:00 2001 From: Arthur van Dam Date: Tue, 4 Apr 2023 20:33:07 +0200 Subject: [PATCH 7/9] Add friction support to converter. --- hydrolib/tools/prof_to_cross.py | 69 +++++++++++++++++++ .../input/prof_to_cross/profdef_withxyz.txt | 8 +-- .../prof_to_cross/crsdef_withxyz.ini | 8 +++ 3 files changed, 81 insertions(+), 4 deletions(-) diff --git a/hydrolib/tools/prof_to_cross.py b/hydrolib/tools/prof_to_cross.py index 0445fff67..7681ecf9a 100644 --- a/hydrolib/tools/prof_to_cross.py +++ b/hydrolib/tools/prof_to_cross.py @@ -163,6 +163,71 @@ def _proftype_to_conveyancetype(proftype: int) -> str: return convtype +def _frctp_to_frictiontype(frctp: int) -> str: + """Convert legacy profdef friction type numbers to crsdef.ini frictionType string. + + Args: + frctp (int): integer type as listed in FRCTP= field. + Returns: + str: Equivalent frictionType string value for use in a crsdef.ini. + """ + + if frctp == 0: + friction_type = "Chezy" + elif frctp == 1: + friction_type = "Manning" + elif frctp == 2: + friction_type = "WallLawNikuradse" + elif frctp == 3: + friction_type = "WhiteColebrook" + else: + raise ValueError(f"Invalid legacy profile friction type given: FRCTP={frctp}") + + return friction_type + + +def _crs_append_friction_definition( + profdef: dict, crsvalues: dict, plural: bool = False +): + """Append key-value pairs to a dict for a crsdef.ini-compatible friction + definition. + + Caller must specify whether the specific CrossSectionDefinition subtype, + for which this dict is intended, is expecting plural (list) friction input. + + + Args: + profdef (dict): the key-value pairs read from profdef.txt. Optional + friction keywords are: FRCCF and FRCTP. + crsvalues (dict): dict of CrossSectionDefinition fields, to which the + friction fields will be appended (in place, function has no return + value). + plural (bool, optional): whether intended CrossSectionDefinition + subtype is expecting plural/list-friction parameters or not. + Defaults to: False. + """ + prof_frccf = profdef.get("FRCCF") + prof_frctp = profdef.get("FRCTP") + + if prof_frccf is None and prof_frctp is None: + return + + if (prof_frccf is None) ^ (prof_frctp is None): + raise ValueError( + f"Missing friction input, FRCCF={prof_frccf}, FRCTP={prof_frctp} (both must be given)." + ) + + val_frctype = _frctp_to_frictiontype(prof_frctp) + + # Append input profile friction parameters to output crs values dict + if plural: + crsvalues.update( + {"frictionValues": [prof_frccf], "frictionTypes": [val_frctype]} + ) + else: + crsvalues.update({"frictionValue": prof_frccf, "frictionType": val_frctype}) + + def _convert_pipe_definition(profdef: dict) -> dict: crsvalues = {"type": "circle", "diameter": profdef["WIDTH"]} return crsvalues @@ -282,6 +347,10 @@ def convert_profdef( crsdata = _convert_xyz_definition(profdef, polyobj) + _crs_append_friction_definition( + profdef, crsdata, plural=(crstype == "yz" or crstype == "xyz") + ) + crsdata["id"] = f"PROFNR{profdef['PROFNR']}" crsdata["type"] = crstype if crstype == "circle": diff --git a/tests/data/input/prof_to_cross/profdef_withxyz.txt b/tests/data/input/prof_to_cross/profdef_withxyz.txt index 34ac57b20..9b549b065 100644 --- a/tests/data/input/prof_to_cross/profdef_withxyz.txt +++ b/tests/data/input/prof_to_cross/profdef_withxyz.txt @@ -16,16 +16,16 @@ PROFNR=5 TYPE=7 WIDTH=400 HEIGHT=4 BASE=130 PROFNR=6 TYPE=7 WIDTH=300 HEIGHT=4 BASE=100 PROFNR=7 TYPE=7 WIDTH=200 HEIGHT=4 BASE=70 PROFNR=8 TYPE=7 WIDTH=100 HEIGHT=4 BASE=30 -PROFNR=9 TYPE=7 WIDTH=250 HEIGHT=4 BASE=80 +PROFNR=9 TYPE=7 WIDTH=250 HEIGHT=4 BASE=80 FRCTP=3 FRCCF=0.10 PROFNR=10 TYPE=7 WIDTH=100 HEIGHT=4 BASE=3 PROFNR=11 TYPE=7 WIDTH=250 HEIGHT=4 BASE=80 PROFNR=12 TYPE=7 WIDTH=40 HEIGHT=4 BASE=10 PROFNR=13 TYPE=7 WIDTH=24 HEIGHT=4 BASE=8 PROFNR=14 TYPE=7 WIDTH=24 HEIGHT=4 BASE=8 PROFNR=15 TYPE=5 WIDTH=24 HEIGHT=4 -PROFNR=16 TYPE=3 WIDTH=60 +PROFNR=16 TYPE=3 WIDTH=60 FRCTP=0 FRCCF=55 PROFNR=17 TYPE=3 WIDTH=10 PROFNR=18 TYPE=3 WIDTH=30 -PROFNR=20 TYPE=201 FRCTP=1 FRCCF=.035 -PROFNR=21 TYPE=201 FRCTP=1 FRCCF=.035 +PROFNR=20 TYPE=201 FRCTP=1 FRCCF=.035 +PROFNR=21 TYPE=201 FRCTP=1 FRCCF=.035 PROFNR=22 TYPE=7 WIDTH=1500 HEIGHT=4 BASE=300 diff --git a/tests/data/reference/prof_to_cross/crsdef_withxyz.ini b/tests/data/reference/prof_to_cross/crsdef_withxyz.ini index 5ff71cb93..bdc3e379d 100644 --- a/tests/data/reference/prof_to_cross/crsdef_withxyz.ini +++ b/tests/data/reference/prof_to_cross/crsdef_withxyz.ini @@ -84,6 +84,8 @@ zCoordinates = 4.0 0.0 0.0 4.0 conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + frictionTypes = WhiteColebrook # Semicolon separated list of roughness types associated with the roughness sections. Either this parameter or frictionIds should be specified. Can be specified as a single value if all roughness sections use the same type. + frictionValues = 0.1 # Space separated list of roughness values; their meaning depends on the roughness types selected (only used if frictionTypes specified). [Definition] id = PROFNR10 # Unique cross-section definition id. @@ -145,6 +147,8 @@ width = 60.0 # Width of the rectangle [m]. height = 999.0 # Height of the rectangle [m]. closed = 0 # no: Open channel, yes: Closed channel. + frictionType = Chezy # Roughness type associated with this cross section Either this parameter or frictionId should be specified. + frictionValue = 55.0 # Roughness value; its meaning depends on the roughness type selected (only used if frictionType specified). [Definition] id = PROFNR17 # Unique cross-section definition id. @@ -167,6 +171,8 @@ zCoordinates = 4.0 0.0 0.0 4.0 conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + frictionTypes = Manning # Semicolon separated list of roughness types associated with the roughness sections. Either this parameter or frictionIds should be specified. Can be specified as a single value if all roughness sections use the same type. + frictionValues = 0.035 # Space separated list of roughness values; their meaning depends on the roughness types selected (only used if frictionTypes specified). xyzCount = 4 # Number of XYZ-coordinates. xCoordinates = 4024.955566 3997.791992 3952.519043 3925.35498 @@ -177,6 +183,8 @@ zCoordinates = 3.0 0.0 4.0 conveyance = segmented # lumped: Lumped, segmented: Vertically segmented. Only the default lumped option is allowed if singleValuedZ = no. In the case of lumped conveyance, only a single uniform roughness for the whole cross section is allowed, i.e., sectionCount must equal 1. sectionCount = 1 # Number of roughness sections. If the lumped conveyance is selected then sectionCount must equal 1. + frictionTypes = Manning # Semicolon separated list of roughness types associated with the roughness sections. Either this parameter or frictionIds should be specified. Can be specified as a single value if all roughness sections use the same type. + frictionValues = 0.035 # Space separated list of roughness values; their meaning depends on the roughness types selected (only used if frictionTypes specified). xyzCount = 3 # Number of XYZ-coordinates. xCoordinates = 3092.332031 3119.496094 3182.87793 From ed8ff78e3f908e733fe368e057e35e6c91e10f79 Mon Sep 17 00:00:00 2001 From: Arthur van Dam Date: Tue, 4 Apr 2023 20:55:41 +0200 Subject: [PATCH 8/9] Support ZMIN in profdef as shift in crsloc. --- hydrolib/tools/prof_to_cross.py | 8 +++++--- tests/data/input/prof_to_cross/profdef_withxyz.txt | 2 +- tests/data/reference/prof_to_cross/crsloc_withxyz.ini | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/hydrolib/tools/prof_to_cross.py b/hydrolib/tools/prof_to_cross.py index 7681ecf9a..14bb4dc71 100644 --- a/hydrolib/tools/prof_to_cross.py +++ b/hydrolib/tools/prof_to_cross.py @@ -443,13 +443,15 @@ def prof_to_cross( x=profloc.x, y=profloc.y, definitionid=f"PROFNR{int(profloc.z)}", + shift=next( + profdef.get("ZMIN") + for profdef in profdef_data + if profdef.get("PROFNR") == profloc.z + ), ) for nr, profloc in enumerate(profloc_data.points) ] - # TODO: profdef.ZMIN to shift in crsloc - # TODO: snap profloc.x/y to branchid if x/y does not work well. - crsloc_model = CrossLocModel(crosssection=crsloc_data) crsloc_model.filepath = crslocfile crsloc_model.save() diff --git a/tests/data/input/prof_to_cross/profdef_withxyz.txt b/tests/data/input/prof_to_cross/profdef_withxyz.txt index 9b549b065..072bfc96a 100644 --- a/tests/data/input/prof_to_cross/profdef_withxyz.txt +++ b/tests/data/input/prof_to_cross/profdef_withxyz.txt @@ -28,4 +28,4 @@ PROFNR=17 TYPE=3 WIDTH=10 PROFNR=18 TYPE=3 WIDTH=30 PROFNR=20 TYPE=201 FRCTP=1 FRCCF=.035 PROFNR=21 TYPE=201 FRCTP=1 FRCCF=.035 -PROFNR=22 TYPE=7 WIDTH=1500 HEIGHT=4 BASE=300 +PROFNR=22 TYPE=7 WIDTH=1500 HEIGHT=4 BASE=300 ZMIN=-123 diff --git a/tests/data/reference/prof_to_cross/crsloc_withxyz.ini b/tests/data/reference/prof_to_cross/crsloc_withxyz.ini index 25c4f0c52..351ccbbd6 100644 --- a/tests/data/reference/prof_to_cross/crsloc_withxyz.ini +++ b/tests/data/reference/prof_to_cross/crsloc_withxyz.ini @@ -8,7 +8,7 @@ id = PROFLOC1 # Unique cross-section location id. x = 4662.8916016 # x-coordinate of the location of the cross section. y = -85.1603546 # y-coordinate of the location of the cross section. - shift = 0.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. + shift = -123.0 # Vertical shift of the cross section definition [m]. Defined positive upwards. definitionId = PROFNR22 # Id of cross section definition. [CrossSection] From 16b149b1abcc39b71c1ff53bc9b843240dd95cc2 Mon Sep 17 00:00:00 2001 From: Arthur van Dam Date: Tue, 4 Apr 2023 21:01:58 +0200 Subject: [PATCH 9/9] Document the new support for friction and zmin. --- docs/tools/prof_to_cross.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/tools/prof_to_cross.md b/docs/tools/prof_to_cross.md index 85272390d..1516b35c4 100644 --- a/docs/tools/prof_to_cross.md +++ b/docs/tools/prof_to_cross.md @@ -17,7 +17,8 @@ prof_to_cross makes the following automatic conversion choices. ### Location Location continues to be specified via original *x,y* coordinate, no branchId is available. -Vertical absolute placement (`ZMIN` vs. `shift`) still needs refinement, is currently not converted. +Vertical absolute placement (`ZMIN` in profile *definition* file) only has a basic conversion +(as direct `shift` in crosssection *location* file). ### Type + conveyance The following table lists the mapping from old to new cross section types: @@ -37,7 +38,15 @@ The following table lists the mapping from old to new cross section types: |201|`XYZPROF , HYDRAD = 1D ANALYTIC CONVEYANCE METHOD`|`xyz`|`segmented`| ### Friction -Not yet available in converter. +The following table lists the mapping from old to new friction types: + +|Profdef FRCTP|frictionType in crsdef.ini +| :--- | :--- | +|`0`|`Chezy`| +|`1`|`Manning`| +|`2`|`WallLawNikuradse` (a.k.a. White-Colebrook Delft3D-style)| +|`3`|`WhiteColebrook`| + # Commandline usage: ```bash