tilupy 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tilupy/__init__.py +23 -0
- tilupy/analytic_sol.py +2403 -0
- tilupy/benchmark.py +1563 -0
- tilupy/calibration.py +134 -0
- tilupy/cmd.py +177 -0
- tilupy/compare.py +195 -0
- tilupy/download_data.py +68 -0
- tilupy/initdata.py +207 -0
- tilupy/initsimus.py +50 -0
- tilupy/make_mass.py +111 -0
- tilupy/make_topo.py +468 -0
- tilupy/models/__init__.py +0 -0
- tilupy/models/lave2D/__init__.py +0 -0
- tilupy/models/lave2D/initsimus.py +665 -0
- tilupy/models/lave2D/read.py +264 -0
- tilupy/models/ravaflow/__init__.py +0 -0
- tilupy/models/ravaflow/initsimus.py +192 -0
- tilupy/models/ravaflow/read.py +273 -0
- tilupy/models/saval2D/__init__.py +0 -0
- tilupy/models/saval2D/read.py +298 -0
- tilupy/models/shaltop/__init__.py +0 -0
- tilupy/models/shaltop/initsimus.py +375 -0
- tilupy/models/shaltop/read.py +613 -0
- tilupy/notations.py +866 -0
- tilupy/plot.py +234 -0
- tilupy/raster.py +199 -0
- tilupy/read.py +2588 -0
- tilupy/utils.py +656 -0
- tilupy-2.0.0.dist-info/METADATA +876 -0
- tilupy-2.0.0.dist-info/RECORD +34 -0
- tilupy-2.0.0.dist-info/WHEEL +5 -0
- tilupy-2.0.0.dist-info/entry_points.txt +3 -0
- tilupy-2.0.0.dist-info/licenses/LICENSE +516 -0
- tilupy-2.0.0.dist-info/top_level.txt +1 -0
tilupy/make_topo.py
ADDED
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import scipy
|
|
5
|
+
|
|
6
|
+
import pytopomap.plot
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def gray99(nx: int = None,
|
|
10
|
+
ny: int = None,
|
|
11
|
+
dx: float = 0.01,
|
|
12
|
+
dy: float = 0.01,
|
|
13
|
+
xmin: float = -0.4,
|
|
14
|
+
x1: float = 1.75,
|
|
15
|
+
x2: float = 2.15,
|
|
16
|
+
xmax: float = 3.2,
|
|
17
|
+
ymax: float = 0.6,
|
|
18
|
+
R: float = 1.1,
|
|
19
|
+
theta1: float = 40,
|
|
20
|
+
theta2: float = 0,
|
|
21
|
+
maxz: float = None,
|
|
22
|
+
plot: bool = False,
|
|
23
|
+
) -> list[np.ndarray]:
|
|
24
|
+
"""Construct channel as in Gray et all 99.
|
|
25
|
+
|
|
26
|
+
Input coordinates are in curvilinear coordinates along the reference
|
|
27
|
+
topography following the channel bottom. Output coordinates are in the
|
|
28
|
+
fixed cartesian frame.
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
nx : int
|
|
33
|
+
Size of the grid in x direction.
|
|
34
|
+
ny : int
|
|
35
|
+
Size of the grid in y direction.
|
|
36
|
+
dx : float, optional
|
|
37
|
+
Cell size of the x axis. if specified, nx is recomputed. By default 0.01.
|
|
38
|
+
dy : float, optional
|
|
39
|
+
Cell size of the y axis. if specified, ny is recomputed. By default 0.01.
|
|
40
|
+
xmin : float, optional
|
|
41
|
+
Minimum x coordinate, by default -0.4.
|
|
42
|
+
x1 : float, optional
|
|
43
|
+
Min coordinate of the channel outlet (transition zone), by default 1.75.
|
|
44
|
+
x2 : float, optional
|
|
45
|
+
Max coordinate of the channel outlet (transition zone), by default 2.15.
|
|
46
|
+
xmax : float, optional
|
|
47
|
+
Maximum x coordinate, by default 3.2.
|
|
48
|
+
ymax : float, optional
|
|
49
|
+
Maximum y coordinate, the final y axis spans from -ymax to ymax, by default 0.5.
|
|
50
|
+
R : float, optional
|
|
51
|
+
Radius of curvature of the channel, by default 1.1.
|
|
52
|
+
theta1 : float, optional
|
|
53
|
+
Slope of the channel in degree, by default 40.
|
|
54
|
+
theta2 : float, optional
|
|
55
|
+
Slope after the channel, by default 0.
|
|
56
|
+
maxz : float, optional
|
|
57
|
+
Maximum z coordinate, by default None.
|
|
58
|
+
plot : bool, optional
|
|
59
|
+
Plot result, by default False.
|
|
60
|
+
|
|
61
|
+
Returns
|
|
62
|
+
-------
|
|
63
|
+
list[numpy.ndarray, numpy.ndarray, numpy.ndarray]
|
|
64
|
+
Xout : numpy.ndarray
|
|
65
|
+
Mesh of X coordinates in the cartesian frame (nx*ny).
|
|
66
|
+
Yout : numpy.ndarray
|
|
67
|
+
Mesh of Y coordinates in the cartesian frame (nx*ny).
|
|
68
|
+
Zout : numpy.ndarray
|
|
69
|
+
Mesh of Z coordinates in the cartesian frame (nx*ny).
|
|
70
|
+
"""
|
|
71
|
+
theta1 = np.deg2rad(theta1)
|
|
72
|
+
theta2 = np.deg2rad(theta2)
|
|
73
|
+
|
|
74
|
+
if nx is None:
|
|
75
|
+
x = np.arange(xmin, xmax + dx / 2, dx)
|
|
76
|
+
nx = len(x)
|
|
77
|
+
else:
|
|
78
|
+
x = np.linspace(xmin, xmax, nx)
|
|
79
|
+
|
|
80
|
+
if ny is None:
|
|
81
|
+
y = np.arange(-ymax, ymax + dy / 2, dy)
|
|
82
|
+
ny = len(y)
|
|
83
|
+
else:
|
|
84
|
+
y = np.linspace(-ymax, ymax, ny)
|
|
85
|
+
|
|
86
|
+
ycurv = np.tile(y.reshape((1, ny)), (nx, 1))
|
|
87
|
+
|
|
88
|
+
# Superficial topography : channel
|
|
89
|
+
# alpha=1/(2*R)*np.sin(0.5*np.pi*(x-x2)/(x1-x2))**2
|
|
90
|
+
# alpha=1/(2*R)*np.abs(x-x2)**1/np.abs(x1-x2)**1
|
|
91
|
+
alpha = (1
|
|
92
|
+
/ (2 * R)
|
|
93
|
+
* (3 * ((x - x2) / (x1 - x2)) ** 2 - 2 * ((x - x2) / (x1 - x2)) ** 3)
|
|
94
|
+
)
|
|
95
|
+
alpha[x > x2] = 0
|
|
96
|
+
alpha[x < x1] = 1 / (2 * R)
|
|
97
|
+
alpha = np.tile(alpha.reshape((nx, 1)), (1, ny))
|
|
98
|
+
|
|
99
|
+
zchannel = alpha * np.abs(ycurv) ** 2
|
|
100
|
+
# plt.figure()
|
|
101
|
+
# plt.imshow(zchannel)
|
|
102
|
+
|
|
103
|
+
# del alpha
|
|
104
|
+
|
|
105
|
+
if not maxz:
|
|
106
|
+
maxz = R / 2
|
|
107
|
+
|
|
108
|
+
zchannel[zchannel > maxz] = maxz
|
|
109
|
+
|
|
110
|
+
# Base topography in curvilinear system.
|
|
111
|
+
# The transition zone between x1 and x2 is a cylindre
|
|
112
|
+
zbase = -np.sin(theta2) * (x - xmax)
|
|
113
|
+
|
|
114
|
+
ind = (x <= x2) & (x >= x1)
|
|
115
|
+
angle = (x[ind] - x1) / (x2 - x1) * (theta2 - theta1) + theta1
|
|
116
|
+
R2 = (x2 - x1) / (theta1 - theta2)
|
|
117
|
+
z2 = -np.sin(theta2) * (x2 - xmax)
|
|
118
|
+
zbase[ind] = R2 * (1 - np.cos(angle)) - R2 * (1 - np.cos(theta2)) + z2
|
|
119
|
+
|
|
120
|
+
ind = x <= x1
|
|
121
|
+
z1 = R2 * (1 - np.cos(theta1)) - R2 * (1 - np.cos(theta2)) + z2
|
|
122
|
+
zbase[ind] = -np.sin(theta1) * (x[ind] - x1) + z1
|
|
123
|
+
zbase = np.tile(zbase.reshape((nx, 1)), (1, ny))
|
|
124
|
+
|
|
125
|
+
# Conversion in fixed cartesian frame
|
|
126
|
+
zd = np.gradient(zbase, x[1] - x[0], edge_order=2, axis=0)
|
|
127
|
+
Xd = np.sqrt(1 - zd**2)
|
|
128
|
+
X = scipy.integrate.cumulative_trapezoid(Xd, x, axis=0, initial=0)
|
|
129
|
+
X = X + xmin * np.cos(theta1)
|
|
130
|
+
|
|
131
|
+
# plt.figure()
|
|
132
|
+
# plt.plot(X[:,0])
|
|
133
|
+
|
|
134
|
+
del Xd
|
|
135
|
+
|
|
136
|
+
# Topography conversion in fixed cartesian frame
|
|
137
|
+
[Fx, Fy] = np.gradient(zbase, X[:, 0], ycurv[0, :], edge_order=2)
|
|
138
|
+
Fz = np.ones(zbase.shape)
|
|
139
|
+
costh = 1 / np.sqrt(Fx**2 + Fy**2 + 1) # Slope angle
|
|
140
|
+
Fx = -Fx * costh
|
|
141
|
+
Fy = -Fy * costh
|
|
142
|
+
Fz = Fz * costh
|
|
143
|
+
Z = zbase + zchannel * Fz
|
|
144
|
+
Xmesh = X + zchannel * Fx
|
|
145
|
+
Ymesh = ycurv + zchannel * Fy
|
|
146
|
+
|
|
147
|
+
# Reconstruction of regular cartesian mesh
|
|
148
|
+
Xout = np.linspace(Xmesh.min(), Xmesh.max(), nx)
|
|
149
|
+
Xout = np.tile(Xout.reshape((nx, 1)), (1, ny))
|
|
150
|
+
Yout = np.linspace(Ymesh.min(), Ymesh.max(), ny)
|
|
151
|
+
Yout = np.tile(Yout.reshape((1, ny)), (nx, 1))
|
|
152
|
+
Zout = scipy.interpolate.griddata((Xmesh.reshape(nx * ny), Ymesh.reshape(nx * ny)),
|
|
153
|
+
Z.reshape(nx * ny),
|
|
154
|
+
(Xout, Yout),
|
|
155
|
+
method="cubic")
|
|
156
|
+
Ztmp = scipy.interpolate.griddata((Xmesh.reshape(nx * ny), Ymesh.reshape(nx * ny)),
|
|
157
|
+
Z.reshape(nx * ny),
|
|
158
|
+
(Xout, Yout),
|
|
159
|
+
method="nearest")
|
|
160
|
+
ind = np.isnan(Zout)
|
|
161
|
+
Zout[ind] = Ztmp[ind]
|
|
162
|
+
|
|
163
|
+
del Ztmp
|
|
164
|
+
# fz=scipy.interpolate.Rbf(Xmesh,Ymesh,Z)
|
|
165
|
+
# Zout=fz(Xout,Yout)
|
|
166
|
+
|
|
167
|
+
if plot:
|
|
168
|
+
if theta2 == 0:
|
|
169
|
+
blod, thin = pytopomap.plot.get_contour_intervals(np.nanmin(Zout),
|
|
170
|
+
np.nanmax(Zout))
|
|
171
|
+
level_min = thin
|
|
172
|
+
else:
|
|
173
|
+
level_min = None
|
|
174
|
+
pytopomap.plot.plot_topo(Zout.T,
|
|
175
|
+
Xout[:, 1],
|
|
176
|
+
Yout[1, :],
|
|
177
|
+
level_min=level_min)
|
|
178
|
+
|
|
179
|
+
return Xout[:, 1], Yout[1, :], Zout.T
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def channel(nx: int = None,
|
|
183
|
+
ny: int = None,
|
|
184
|
+
dx: float = None,
|
|
185
|
+
dy: float = None,
|
|
186
|
+
xmin: float = -0.4,
|
|
187
|
+
xmax: float = 3.6,
|
|
188
|
+
ymax: float = 0.5,
|
|
189
|
+
xstart_channel: float = 0.65,
|
|
190
|
+
xend_channel: float = 2.3,
|
|
191
|
+
xstart_trans: float = 0.4,
|
|
192
|
+
xend_trans: float = 2.75,
|
|
193
|
+
R: float = 1.1,
|
|
194
|
+
bend: float = 0.2,
|
|
195
|
+
nbends: int = 1,
|
|
196
|
+
theta_start: float = 40,
|
|
197
|
+
theta_channel: float = 40,
|
|
198
|
+
theta_end: float = 0,
|
|
199
|
+
plot: bool = False,
|
|
200
|
+
maxh: float = None,
|
|
201
|
+
interp_method: str = "linear",
|
|
202
|
+
) -> list[np.ndarray]:
|
|
203
|
+
"""Generate channel with potential multiple bends.
|
|
204
|
+
|
|
205
|
+
Input coordinates are curvilinear along the flattened topography.
|
|
206
|
+
|
|
207
|
+
Parameters
|
|
208
|
+
----------
|
|
209
|
+
nx : int, optinal
|
|
210
|
+
Size of the grid in x direction, by default None.
|
|
211
|
+
ny : int, optinal
|
|
212
|
+
Size of the grid in y direction, by default None.
|
|
213
|
+
dx : float, optional
|
|
214
|
+
Cell size of the x axis. if specified, nx is recomputed, by default 0.01.
|
|
215
|
+
dy : float, optional
|
|
216
|
+
Cell size of the y axis. if specified, ny is recomputed, by default 0.01.
|
|
217
|
+
xmin : float, optional
|
|
218
|
+
Minimum x coordinate, by default -0.4.
|
|
219
|
+
xmax : float, optional
|
|
220
|
+
Maximum x coordinate, by default 3.2.
|
|
221
|
+
ymax : float, optional
|
|
222
|
+
Maximum y coordinate, the final y axis spans from -ymax to ymax, by default 0.5.
|
|
223
|
+
xstart_channel : float, optional
|
|
224
|
+
Start of the channel, by default 0.65.
|
|
225
|
+
xend_channel : float, optional
|
|
226
|
+
End of the channel, by default 2.3.
|
|
227
|
+
xstart_trans : float, optional
|
|
228
|
+
Start of the transition zone before the channel start, by default 0.4.
|
|
229
|
+
xend_trans : float, optional
|
|
230
|
+
End of the transition zone after the channel end, by default 2.75.
|
|
231
|
+
R : float, optional
|
|
232
|
+
Radius of curvature of the channel, by default 1.1.
|
|
233
|
+
bend : float, optional
|
|
234
|
+
Width of the channel bend, by default 0.2.
|
|
235
|
+
nbends : ind, optional
|
|
236
|
+
Number of bends, by default 1.
|
|
237
|
+
theta_start : float, optional
|
|
238
|
+
Slope before the channel, by default 40.
|
|
239
|
+
theta_channel : float, optional
|
|
240
|
+
Slope of the channel, by default 40.
|
|
241
|
+
theta_end : float, optional
|
|
242
|
+
Slope after the channel, by default 0.
|
|
243
|
+
plot : bool, optional
|
|
244
|
+
Plot generated topography, by default False.
|
|
245
|
+
maxh : float, optional
|
|
246
|
+
Depth of the channel, by default None.
|
|
247
|
+
interp_method : string, optional
|
|
248
|
+
Interpolation method for converting the topography from curvilinear
|
|
249
|
+
coordinates to cartesian coordinates, by default 'linear'.
|
|
250
|
+
|
|
251
|
+
Returns
|
|
252
|
+
-------
|
|
253
|
+
list[numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray]
|
|
254
|
+
Xout : numpy.ndarray
|
|
255
|
+
Mesh of X coordinates in the cartesian frame (nx*ny).
|
|
256
|
+
Yout : numpy.ndarray
|
|
257
|
+
Mesh of Y coordinates in the cartesian frame (nx*ny).
|
|
258
|
+
Zout : numpy.ndarray
|
|
259
|
+
Mesh of Z coordinates in the cartesian frame (nx*ny).
|
|
260
|
+
thalweg : numpy.ndarray
|
|
261
|
+
"""
|
|
262
|
+
|
|
263
|
+
theta_start = np.deg2rad(theta_start)
|
|
264
|
+
theta_channel = np.deg2rad(theta_channel)
|
|
265
|
+
theta_end = np.deg2rad(theta_end)
|
|
266
|
+
|
|
267
|
+
if ny is None and dy is None:
|
|
268
|
+
dy = ymax / 100
|
|
269
|
+
|
|
270
|
+
if nx is None and dx is None:
|
|
271
|
+
if dy is not None:
|
|
272
|
+
dx = dy
|
|
273
|
+
else:
|
|
274
|
+
raise ValueError("nx or dx must be specified as input")
|
|
275
|
+
|
|
276
|
+
# x and y coordinates in the flattened topography
|
|
277
|
+
if nx is None:
|
|
278
|
+
xtopo = np.arange(xmin, xmax + dx / 2, dx)
|
|
279
|
+
nx = len(xtopo)
|
|
280
|
+
else:
|
|
281
|
+
xtopo = np.linspace(xmin, xmax, nx)
|
|
282
|
+
|
|
283
|
+
if ny is None:
|
|
284
|
+
ytopo = np.arange(-ymax, ymax + dy / 2, dy)
|
|
285
|
+
ny = len(ytopo)
|
|
286
|
+
else:
|
|
287
|
+
ytopo = np.linspace(-ymax, ymax, ny)
|
|
288
|
+
|
|
289
|
+
xtopo = np.tile(xtopo[:, np.newaxis], (1, ny))
|
|
290
|
+
ytopo = np.tile(ytopo[np.newaxis, :], (nx, 1))
|
|
291
|
+
|
|
292
|
+
# Height above flattened topography is a channel
|
|
293
|
+
# in alpha(x)*(y-thalweg(x))**2,
|
|
294
|
+
|
|
295
|
+
# alpha(x) is 1/2R in the channel, and depends on a transition
|
|
296
|
+
# function in the transition zones
|
|
297
|
+
def trans_function(x, x1, x2):
|
|
298
|
+
xx = 3 * ((x - x2) / (x1 - x2)) ** 2 - 2 * ((x - x2) / (x1 - x2)) ** 3
|
|
299
|
+
return xx
|
|
300
|
+
|
|
301
|
+
alpha = np.zeros((nx, ny))
|
|
302
|
+
|
|
303
|
+
ind = (xtopo > xstart_channel) & (xtopo < xend_channel)
|
|
304
|
+
alpha[ind] = 1 / (2 * R)
|
|
305
|
+
|
|
306
|
+
ind = (xtopo > xstart_trans) & (xtopo <= xstart_channel)
|
|
307
|
+
alpha[ind] = (1 / (2 * R) * trans_function(xtopo[ind], xstart_channel, xstart_trans))
|
|
308
|
+
|
|
309
|
+
ind = (xtopo >= xend_channel) & (xtopo < xend_trans)
|
|
310
|
+
alpha[ind] = (1 / (2 * R) * trans_function(xtopo[ind], xend_channel, xend_trans))
|
|
311
|
+
|
|
312
|
+
# the thalweg is centered on y=0 outside [xstart_channel,xend_channel]. Inbetween,
|
|
313
|
+
# it is given by a cos**2
|
|
314
|
+
def end_bend(x, x1, x2):
|
|
315
|
+
yy = (bend / 2) * (1 + np.cos(np.pi * (x - x2) / (x1 - x2)))
|
|
316
|
+
return yy
|
|
317
|
+
|
|
318
|
+
def mid_bend(x, x1, x2):
|
|
319
|
+
yy = bend * np.cos(np.pi * (x - x1) / (x2 - x1))
|
|
320
|
+
return yy
|
|
321
|
+
|
|
322
|
+
thalweg = np.zeros((nx, ny))
|
|
323
|
+
|
|
324
|
+
if nbends > 0:
|
|
325
|
+
step = (xend_channel - xstart_channel) / nbends
|
|
326
|
+
|
|
327
|
+
ind = (xtopo > xstart_channel) & (xtopo < xstart_channel + step / 2)
|
|
328
|
+
thalweg[ind] = end_bend(xtopo[ind],
|
|
329
|
+
xstart_channel,
|
|
330
|
+
xstart_channel + step / 2)
|
|
331
|
+
|
|
332
|
+
ind = (xtopo >= xend_channel - step / 2) & (xtopo < xend_channel)
|
|
333
|
+
thalweg[ind] = (-1) ** (nbends + 1) * end_bend(xtopo[ind],
|
|
334
|
+
xend_channel,
|
|
335
|
+
xend_channel - step / 2)
|
|
336
|
+
|
|
337
|
+
if nbends > 1:
|
|
338
|
+
ind = (xtopo >= xstart_channel + step / 2) & (
|
|
339
|
+
xtopo < xend_channel - step / 2
|
|
340
|
+
)
|
|
341
|
+
thalweg[ind] = mid_bend(xtopo[ind],
|
|
342
|
+
xstart_channel + step / 2,
|
|
343
|
+
xstart_channel + (3 / 2) * step)
|
|
344
|
+
|
|
345
|
+
htopo = alpha * (ytopo - thalweg) ** 2
|
|
346
|
+
|
|
347
|
+
if not maxh:
|
|
348
|
+
maxh = R / 2
|
|
349
|
+
|
|
350
|
+
htopo[htopo > maxh] = maxh
|
|
351
|
+
|
|
352
|
+
# Reconstruction of bz the basal topography. The real topo is given by
|
|
353
|
+
# bz+\vec{n}*htopo. Slopes of bz are given by theta_* outside the transition
|
|
354
|
+
# zones. We use a cylinder shape inbetween. This is done by computing the slope
|
|
355
|
+
# angle of bz, and using then -sin(slope_angle)=d(bz)/d(xtopo)
|
|
356
|
+
|
|
357
|
+
slope_angle = np.zeros((nx, ny))
|
|
358
|
+
|
|
359
|
+
ind = xtopo < xstart_trans
|
|
360
|
+
slope_angle[ind] = theta_start
|
|
361
|
+
|
|
362
|
+
ind = xtopo >= xend_trans
|
|
363
|
+
slope_angle[ind] = theta_end
|
|
364
|
+
|
|
365
|
+
ind = (xtopo >= xstart_channel) & (xtopo < xend_channel)
|
|
366
|
+
slope_angle[ind] = theta_channel
|
|
367
|
+
|
|
368
|
+
ind = (xtopo >= xstart_trans) & (xtopo < xstart_channel)
|
|
369
|
+
slope_angle[ind] = (xtopo[ind] - xstart_trans) / (xstart_channel - xstart_trans)
|
|
370
|
+
slope_angle[ind] = (slope_angle[ind] * (theta_channel - theta_start) + theta_start)
|
|
371
|
+
|
|
372
|
+
ind = (xtopo >= xend_channel) & (xtopo < xend_trans)
|
|
373
|
+
slope_angle[ind] = (xtopo[ind] - xend_trans) / (xend_channel - xend_trans)
|
|
374
|
+
slope_angle[ind] = (slope_angle[ind] * (theta_channel - theta_end) + theta_end)
|
|
375
|
+
|
|
376
|
+
bz = scipy.integrate.cumulative_trapezoid(-np.sin(slope_angle),
|
|
377
|
+
xtopo,
|
|
378
|
+
axis=0,
|
|
379
|
+
initial=0)
|
|
380
|
+
bz = bz - np.min(bz)
|
|
381
|
+
|
|
382
|
+
# Get the coordinates of (xtopo,ytopo) in the cartesian reference frame
|
|
383
|
+
# by=ytopo
|
|
384
|
+
bx = scipy.integrate.cumulative_trapezoid(np.cos(slope_angle),
|
|
385
|
+
xtopo,
|
|
386
|
+
axis=0,
|
|
387
|
+
initial=0)
|
|
388
|
+
bx = bx + xmin * np.cos(theta_start)
|
|
389
|
+
|
|
390
|
+
# Vector normal to topography in cartesian coordinates
|
|
391
|
+
# (nx,ny,nz)=(-sin(theta),0,cos(theta))
|
|
392
|
+
# as the topography does vary in the y direction
|
|
393
|
+
# The real topography is thus given in cartesian coordinates by
|
|
394
|
+
# (xcart,ycart,zcart)=(bx,by,bz)+htopo(nx,ny,nz)
|
|
395
|
+
xcart = bx + htopo * np.sin(slope_angle)
|
|
396
|
+
zcart = bz + htopo * np.cos(slope_angle)
|
|
397
|
+
|
|
398
|
+
# Reconstruct regular mesh for interpolation
|
|
399
|
+
Xout = np.linspace(xcart[0, 0], xcart[-1, 0], nx)
|
|
400
|
+
Yout = ytopo
|
|
401
|
+
Xout = np.tile(Xout[:, np.newaxis], (1, ny))
|
|
402
|
+
Zout = scipy.interpolate.griddata((xcart.reshape(nx * ny), ytopo.reshape(nx * ny)),
|
|
403
|
+
zcart.reshape(nx * ny),
|
|
404
|
+
(Xout, Yout),
|
|
405
|
+
method=interp_method)
|
|
406
|
+
Ztmp = scipy.interpolate.griddata((xcart.reshape(nx * ny), ytopo.reshape(nx * ny)),
|
|
407
|
+
zcart.reshape(nx * ny),
|
|
408
|
+
(Xout, Yout),
|
|
409
|
+
method="nearest")
|
|
410
|
+
ind = np.isnan(Zout)
|
|
411
|
+
Zout[ind] = Ztmp[ind]
|
|
412
|
+
|
|
413
|
+
if plot:
|
|
414
|
+
if theta_end == 0:
|
|
415
|
+
blod, thin = pytopomap.plot.get_contour_intervals(np.nanmin(Zout),
|
|
416
|
+
np.nanmax(Zout))
|
|
417
|
+
level_min = thin
|
|
418
|
+
else:
|
|
419
|
+
level_min = None
|
|
420
|
+
pytopomap.plot.plot_topo(Zout.T,
|
|
421
|
+
Xout[:, 1],
|
|
422
|
+
Yout[1, :],
|
|
423
|
+
level_min=level_min)
|
|
424
|
+
|
|
425
|
+
return Xout[:, 1], Yout[1, :], Zout.T, thalweg
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
"""
|
|
429
|
+
if __name__ == "__main__":
|
|
430
|
+
# %% Test gray99
|
|
431
|
+
X, Y, Z = gray99(plot=True)
|
|
432
|
+
|
|
433
|
+
# %% Test synthetic channel
|
|
434
|
+
bend = 0.25
|
|
435
|
+
R = 0.2
|
|
436
|
+
|
|
437
|
+
nx = 600
|
|
438
|
+
ny = 300
|
|
439
|
+
|
|
440
|
+
xmin = 0.1
|
|
441
|
+
xmax = 4.5
|
|
442
|
+
xstart_trans = -0.3
|
|
443
|
+
xstart_channel = 0.2
|
|
444
|
+
xend_channel = 2.3
|
|
445
|
+
xend_trans = 2.75
|
|
446
|
+
ymax = 1
|
|
447
|
+
|
|
448
|
+
theta_start = 10
|
|
449
|
+
theta_channel = 10
|
|
450
|
+
theta_end = 0
|
|
451
|
+
x, y, z, t = channel(
|
|
452
|
+
nx,
|
|
453
|
+
ny,
|
|
454
|
+
xmin=xmin,
|
|
455
|
+
xmax=xmax,
|
|
456
|
+
ymax=ymax,
|
|
457
|
+
xstart_channel=xstart_channel,
|
|
458
|
+
xend_channel=xend_channel,
|
|
459
|
+
xstart_trans=xstart_trans,
|
|
460
|
+
theta_start=theta_start,
|
|
461
|
+
theta_end=theta_end,
|
|
462
|
+
theta_channel=theta_channel,
|
|
463
|
+
R=R,
|
|
464
|
+
bend=bend,
|
|
465
|
+
maxh=R,
|
|
466
|
+
plot=True,
|
|
467
|
+
)
|
|
468
|
+
"""
|
|
File without changes
|
|
File without changes
|