[in2TopoHyd]: Module for computing hydraulic inital conditions - #90
[in2TopoHyd]: Module for computing hydraulic inital conditions#90JuLa96 wants to merge 2 commits into
Conversation
initial conditions in time-dependent release mode Add documentation Add test case
❌ 1 blocking issue (1 total)
|
| thicknessRC = ratingCurve["thickness"] | ||
| flowAreaRC = ratingCurve["flowArea"] | ||
| # fetch debris-flow surface elevation | ||
| surfElevRC = ratingCurve["surfElev"] |
|
Coverage Impact This PR will not change total coverage. 🚦 See full report on Qlty Cloud »🛟 Help
|
| # inputDir = avaDir / "Outputs" / "in2TopoHyd" / "peakFiles" | ||
| # peakFilesDF = fU.makeSimDF(inputDir, avaDir=avaDir) |
There was a problem hiding this comment.
| # inputDir = avaDir / "Outputs" / "in2TopoHyd" / "peakFiles" | |
| # peakFilesDF = fU.makeSimDF(inputDir, avaDir=avaDir) |
|
|
||
| # Get csv-file with initial conditions | ||
| debrisDir = pathlib.Path(debrisDir) | ||
| inputDir = debrisDir / "Outputs" / "in2TopoHyd" / "peakFiles" |
There was a problem hiding this comment.
| inputDir = debrisDir / "Outputs" / "in2TopoHyd" / "peakFiles" | |
| outputDir = debrisDir / "Outputs" / "in2TopoHyd" / "peakFiles" |
There was a problem hiding this comment.
Is this the same DEM as in debrisParabolaChanneled? Then, I suggest adding POINTS and REL into this debris data folder.
|
|
||
| The :py:mod:`in2TopoHyd` module requires a | ||
|
|
||
| * **digital elevation model as raster file**, | ||
|
|
||
| * **a time-dependent discharge hydrograph**, | ||
|
|
||
| * **a release line**, | ||
|
|
||
| * **and levee points**. | ||
|
|
||
| :py:mod:`in2TopoHyd` calculations are performed within a process directory, organized with the | ||
| folder structure described in the `AvaFrame documentation <https://docs.avaframe.org/en/latest/moduleCom1DFA.html#input>`_. |
There was a problem hiding this comment.
I suggest defining the directory structure of the inputs directly here instead of referencing to avaframe, similar to https://docs.avaframe.org/en/latest/moduleCom1DFA.html#input
| ^^^^^^^^^^^^ | ||
|
|
||
| The release line is read from the ``Inputs/REL`` directory. It must contain **exactly two points**, representing the starting and ending point of the release line. | ||
| If a ``releaseScenario`` is specified in ``local_c1TIFCfg.ini``, this file is used (**with** extension .shp). Otherwise, the module searches the ``REL`` directory for a release file. |
There was a problem hiding this comment.
| If a ``releaseScenario`` is specified in ``local_c1TIFCfg.ini``, this file is used (**with** extension .shp). Otherwise, the module searches the ``REL`` directory for a release file. | |
| If a ``releaseScenario`` is specified in ``(local_)c1TIFCfg.ini``, this file is used (**with** extension .shp). Otherwise, the module searches the ``REL`` directory for a release file. |
| ^^^^^^^^^^^^ | ||
|
|
||
| The release line is read from the ``Inputs/REL`` directory. It must contain **exactly two points**, representing the starting and ending point of the release line. | ||
| If a ``releaseScenario`` is specified in ``local_c1TIFCfg.ini``, this file is used (**with** extension .shp). Otherwise, the module searches the ``REL`` directory for a release file. |
There was a problem hiding this comment.
releaseScenario or timeDependentReleaseScenarios, I could not find releaseScenario in c1TIFCfg.ini
|
|
||
| # get file name of release line | ||
| # first, check if name is provided in the c1TIF-config file | ||
| fname = debrisCfg["com1DFA_com1DFA_override"]["releaseScenario"] |
There was a problem hiding this comment.
In debrisCfg["com1DFA_com1DFA_override"] there is no "releaseScenario".
python runIni.. raises an error!
There was a problem hiding this comment.
this file ends with "Levee", below in the documentation it says, the file needs to end with "levee" (lower case).
When running the example, I get this error:
File not found or there are more than one levee files in POINTS-folder!
Ensure that there is exactly one point-shapefile including the ending *levee.shp!
| raise ValueError(message) | ||
|
|
||
| # get file name of levee points | ||
| fname = debrisDir + "/Inputs/POINTS/*levee.shp" |
There was a problem hiding this comment.
I suggest providing the levee points in a folder "LEVEE", instead of considering the name within the file.
There was a problem hiding this comment.
I suggest moving the hydrograph csv file to a different folder (e.g., HYDR ??)
The csv file in the REL folder is the input file for c1TIF.
| # if the tickness at the very left and the very right cell is still > 0, | ||
| # there are remaining subareas on both sides that have to be considered | ||
| left, right = idx[0], idx[-1] | ||
| diffElevLeft = elevation[left - 1] - elevation[left] |
There was a problem hiding this comment.
This assumes that the channel is strictly interior, right? Is that validated before? Does that assumption always hold?
If the levee point is the first (or last) cell, eg.left -1 becomes -1 and then elevation would be wrapped...
| raise ValueError(message) | ||
|
|
||
| # get file name of levee points | ||
| fname = debrisDir + "/Inputs/POINTS/*levee.shp" |
There was a problem hiding this comment.
If file is wanted, I suggest pathlib.Path(debrisDir, "Inputs", "POINTS").glob("*levee.shp") as this works both with pathlib path and str (as mentioned in the docstring)
| @@ -0,0 +1,861 @@ | |||
| """ | |||
| Get initial conditions for hydrograph | |||
There was a problem hiding this comment.
I think this module should be tested by pytests. If it is too much for this PR, open an issue and adress it in a latter PR...
|
|
||
| # calculate unit normal vectors on left- and right-handside | ||
| # of direction vector | ||
| n1 = np.array([-dy, dx]) / magnitude |
There was a problem hiding this comment.
Lines 244 to 249 are duplicates of 468 to 473. I suggest extracting a shared helper
| Returns | ||
| -------- | ||
| thickness: 1D-array | ||
| flow thickness and velocity values as starting condition |
There was a problem hiding this comment.
flowVel is missing from the returns
| v = 2.1 * math.pow(q, 0.33) * math.pow(slope, 0.33) | ||
| flowVel.append(v) | ||
|
|
||
| #TODO: add addtional methods for calculating the flow velocity |
| the elevation of the cross-section cells, | ||
| the path along (distance) along the cross-section cells | ||
| ratingCurve: dict | ||
| dictionary containing the miminimum elevation of cross section (channel) |
| # assign levee points to neares cross-section coordinates | ||
| crossSection = assignCrossSectionCoords(leveePoints, crossSection) | ||
|
|
||
| # export cross section cell centers as points for plausability check |
| # compute rating curve | ||
| ratingCurve = computeRatingCurve(crossSection, topoHydCfg) | ||
|
|
||
| # plot cross section and rating curve for plausability check |
| crossSectionY + (csz - modulus)) | ||
|
|
||
| # get indices of cross-section cells | ||
| col = np.int32(np.array((crossSectionX - xllcenter) / csz)) |
There was a problem hiding this comment.
Why not use the same convention avaframe's own readLine uses (int(np.floor((x - xllcenter) / csz))) ?
col = np.int32(np.round((crossSectionX - xllcenter) / csz))
row = np.int32(np.round((crossSectionY - yllcenter) / csz)) As I think your combination shifts the cell if the center is not a (half-)multiple of cellsize.
assignRasterCoords snaps x to the nearest multiple of cellsize.
getCrossSectionCells converts to an index with np.int32(...), which truncates (chops off the decimal)
rather than rounds.
| # assign raster cell coord to starting and ending point of release line | ||
| xcoord = [] | ||
| ycoord = [] | ||
| for i in range(len(releaseLine["x"])): |
There was a problem hiding this comment.
simpler would be:
| for i in range(len(releaseLine["x"])): | |
| for x, y in zip(releaseLine["x"], releaseLine["y"]): |
below you can just use x, y instead of releaseLine["x"][i], releaseLine["y"][i]
|
|
||
| return crossSection | ||
|
|
||
| def assignRasterCoords(cellSize, releaseLine): |
There was a problem hiding this comment.
why don't you use avaframe.in3Utils.geoTrans.getCellsAlongLine() instead?
| crossSection: dict | ||
| dictionaray containing x,y-coordinates of cross-section cells, | ||
| the elevation of the cross-section cells, | ||
| the path along (distance) along the cross-section cells |
There was a problem hiding this comment.
typo (one along is enough)
| # horizontal distance between neighbouring cells | ||
| distance = crossSection["s"] | ||
| # get elevation steps | ||
| dElev = float(topoHydCfg["GENERAL"]["dElev"]) |
There was a problem hiding this comment.
| dElev = float(topoHydCfg["GENERAL"]["dElev"]) | |
| dElev = topoHydCfg["GENERAL"].getfloat("dElev") |
| left, right = idx[0], idx[-1] | ||
| diffElevLeft = elevation[left - 1] - elevation[left] | ||
| dsLeft = distance[left] - distance[left - 1] | ||
| slopeLeft = diffElevLeft / dsLeft |
There was a problem hiding this comment.
would it make sense to compute the slope as:
(elevation[left+1]) - elevation[left-1]) / (distance[left + 1] - distance[left-1])
|
|
||
| return thickness, flowVel | ||
|
|
||
| def getCrossSectionCells(dem, releaseLine): |
There was a problem hiding this comment.
Could you use avaframe.in3Utils.geoTrans.getCellsAlongLine() to simplify this function?
|
|
||
| Returns | ||
| -------- | ||
| flowDir: 1D-array |
There was a problem hiding this comment.
| flowDir: 1D-array | |
| flwDir: 1D-array |
| crossSection: dict | ||
| dictionary containing x,y-coordinates of cross-section cells, | ||
| the elevation of the cross-section cells, | ||
| the path along (distance) along the cross-section cells |
| # combine to 3D-unit-normal vector | ||
| flwDir = np.append(flwDir, nz) | ||
| magnitude = np.sqrt(flwDir[0]**2 + flwDir[1]**2 + nz**2) | ||
| flwDir = flwDir / magnitude |
There was a problem hiding this comment.
Do you want to normalize flwDir here?
Then also use DFAtls.normalize ?
| flwDir = np.append(flwDir, nz) | ||
| magnitude = np.sqrt(flwDir[0]**2 + flwDir[1]**2 + nz**2) |
There was a problem hiding this comment.
| flwDir = np.append(flwDir, nz) | |
| magnitude = np.sqrt(flwDir[0]**2 + flwDir[1]**2 + nz**2) | |
| flwDir = np.append(flwDir, nz) | |
| magnitude = np.sqrt(flwDir[0]**2 + flwDir[1]**2 + flwDir[2]**2) |
??

in2TopoHydis an input module for deriving initial hydraulic conditions for thec1TIFcomputation modulefor a debris-flow hydrograph at a prescribed release line. The module combines the topography of the release area with
a time-dependent discharge hydrograph (Topo-Hydrograph) to calculate the corresponding flow thickness and flow velocity at the release line.
The hydraulic conditions are derived from the terrain cross section along the release line.
A rating curve is calculated from the cross-sectional geometry, relating flow thickness to flow area.
For each discharge value of the input hydrograph, the module determines the corresponding mean flow velocity and flow thickness.
The flow thickness is then distributed over the wetted cells of the release cross section.
The resulting initial conditions contain the flow thickness as well as the velocity components in x, y and z direction for every wet cell and every hydrograph timestep.
closes #85
Compiled doc : https://docs.debrisframe.org/en/jl_addtopohydmodule/