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/initdata.py
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
import tilupy.make_topo
|
|
8
|
+
import tilupy.make_mass
|
|
9
|
+
import tilupy.raster
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def create_topo_constant_slope(folder_out: str,
|
|
13
|
+
xmax: int = 30,
|
|
14
|
+
ymax: int = 25,
|
|
15
|
+
cell_size: float = 0.5,
|
|
16
|
+
theta: int = 5,
|
|
17
|
+
mass_type: str = 'r',
|
|
18
|
+
r_center: tuple = (7.5, 12.5),
|
|
19
|
+
r_radius: tuple = (3.75, 3.75),
|
|
20
|
+
s_vertex: list = [0, 5, 0, 25],
|
|
21
|
+
h_max: float = 3.75,
|
|
22
|
+
description: str = "No informations."
|
|
23
|
+
) -> list[str, np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
|
|
24
|
+
"""
|
|
25
|
+
Generates a synthetic topography and initial mass, saves them as ASCII files,
|
|
26
|
+
and stores all configuration parameters in a dedicated folder.
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
folder_out : str
|
|
31
|
+
Output folder.
|
|
32
|
+
xmax : int
|
|
33
|
+
Domain length in the X direction (in meters).
|
|
34
|
+
ymax : int
|
|
35
|
+
Domain length in the Y direction (in meters).
|
|
36
|
+
cell_size : float
|
|
37
|
+
Spatial resolution of the grid (in meters).
|
|
38
|
+
theta : int
|
|
39
|
+
Slope angle of the topography (in degrees).
|
|
40
|
+
mass_type : str
|
|
41
|
+
Shape of the initial mass: 'r' for ellipse, 's' for rectangle.
|
|
42
|
+
r_center : tuple
|
|
43
|
+
Center (x, y) of the elliptical initial mass.
|
|
44
|
+
r_radius : tuple
|
|
45
|
+
Radii (rx, ry) of the elliptical initial mass.
|
|
46
|
+
s_vertex : list
|
|
47
|
+
Rectangle boundaries [xmin, xmax, ymin, ymax] for the rectangular mass.
|
|
48
|
+
h_max : float
|
|
49
|
+
Maximum height of the initial mass.
|
|
50
|
+
description : str
|
|
51
|
+
Text description of the configuration.
|
|
52
|
+
|
|
53
|
+
Returns
|
|
54
|
+
-------
|
|
55
|
+
list[str, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray]
|
|
56
|
+
folder_path : str
|
|
57
|
+
Absolute path to the output directory.
|
|
58
|
+
x, y : numpy.ndarray, numpy.ndarray
|
|
59
|
+
Meshgrid coordinates.
|
|
60
|
+
z : numpy.ndarray
|
|
61
|
+
Topography data.
|
|
62
|
+
m : numpy.ndarray
|
|
63
|
+
Initial mass distribution.
|
|
64
|
+
"""
|
|
65
|
+
# Create mesh
|
|
66
|
+
x = np.linspace(0, xmax, int(np.round(xmax / cell_size)) + 1)
|
|
67
|
+
y = np.linspace(0, ymax, int(np.round(ymax / cell_size)) + 1)
|
|
68
|
+
xmesh, ymesh = np.meshgrid(x, y)
|
|
69
|
+
|
|
70
|
+
# Topography slope
|
|
71
|
+
slope = np.tan(np.deg2rad(theta))
|
|
72
|
+
|
|
73
|
+
# Topography array
|
|
74
|
+
z = -slope * (xmesh - xmax)
|
|
75
|
+
|
|
76
|
+
# Initial mass
|
|
77
|
+
if mass_type != 'r' and mass_type != 's':
|
|
78
|
+
mass_type = 'r'
|
|
79
|
+
|
|
80
|
+
p = dict(
|
|
81
|
+
hmax=h_max,
|
|
82
|
+
mass_type=mass_type,
|
|
83
|
+
r_center = r_center if mass_type=='r' else None,
|
|
84
|
+
r_radius = r_radius if mass_type=='r' else None,
|
|
85
|
+
s_vertex = s_vertex if mass_type=='s' else None,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
if p["mass_type"] == 'r':
|
|
89
|
+
m = (
|
|
90
|
+
1
|
|
91
|
+
- (xmesh - p["r_center"][0]) ** 2 / p["r_radius"][0] ** 2
|
|
92
|
+
- (ymesh - p["r_center"][1]) ** 2 / p["r_radius"][1] ** 2
|
|
93
|
+
)
|
|
94
|
+
m = np.maximum(m * p["hmax"], 0)
|
|
95
|
+
|
|
96
|
+
elif p["mass_type"] == 's':
|
|
97
|
+
xmin_r, xmax_r, ymin_r, ymax_r = p["s_vertex"]
|
|
98
|
+
in_x = np.logical_and(xmesh >= xmin_r, xmesh <= xmax_r)
|
|
99
|
+
in_y = np.logical_and(ymesh >= ymin_r, ymesh <= ymax_r)
|
|
100
|
+
mask = np.logical_and(in_x, in_y)
|
|
101
|
+
m = np.zeros_like(z)
|
|
102
|
+
m[mask] = p["hmax"]
|
|
103
|
+
|
|
104
|
+
nbr_cell = np.count_nonzero(m > 0)
|
|
105
|
+
|
|
106
|
+
p["nbr_cell"] = nbr_cell
|
|
107
|
+
|
|
108
|
+
folder_name = f"x{xmax}_y{ymax}_" + "dx{:04.2f}_".format(cell_size).replace(".", "p") + "theta{:02.0f}_".format(theta) + mass_type + f"{nbr_cell}"
|
|
109
|
+
folder_path = os.path.join(folder_out, folder_name)
|
|
110
|
+
|
|
111
|
+
# Create folder
|
|
112
|
+
if not os.path.isdir(folder_path):
|
|
113
|
+
os.mkdir(folder_path)
|
|
114
|
+
print(f"Create folder: {folder_name}")
|
|
115
|
+
else:
|
|
116
|
+
print(f"Existing topography: {folder_name}")
|
|
117
|
+
|
|
118
|
+
# Create parameters file
|
|
119
|
+
with open(os.path.join(folder_path, "parameters.txt"), "w") as file:
|
|
120
|
+
file.write(f"xmax {xmax}\nymax {ymax}\ncell_size {cell_size}\ntheta {theta}\n\n")
|
|
121
|
+
|
|
122
|
+
for param, value in p.items():
|
|
123
|
+
file.write(f"{param} {value}\n")
|
|
124
|
+
|
|
125
|
+
file.write("\n")
|
|
126
|
+
file.write(description)
|
|
127
|
+
|
|
128
|
+
# Save topography
|
|
129
|
+
file_topo_out = os.path.join(folder_path, "topography.asc")
|
|
130
|
+
file_mass_out = os.path.join(folder_path, "init_mass.asc")
|
|
131
|
+
|
|
132
|
+
tilupy.raster.write_ascii(x, y, z, file_topo_out)
|
|
133
|
+
tilupy.raster.write_ascii(x, y, m, file_mass_out)
|
|
134
|
+
|
|
135
|
+
return folder_path, x, y, z, m
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def gray99_topo_mass(dx: float = 0.1,
|
|
139
|
+
dy: float = 0.1,
|
|
140
|
+
res_type: str = "true_normal"
|
|
141
|
+
) -> list[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
|
|
142
|
+
"""Create Gray99 topographic and mass test.
|
|
143
|
+
|
|
144
|
+
Create an initial spherical calotte above the topography, resulting as a mass with a
|
|
145
|
+
height of 0.22 m and a radius of 0.32 m (more precisely it is the length in the downslope
|
|
146
|
+
direction), following the indications in Gray et al 99 (p. 1859).
|
|
147
|
+
The correspondig radius of the sphere, and the offset from the topography in the topography
|
|
148
|
+
normal direction (norm_offset) are deduced from these parameters.
|
|
149
|
+
|
|
150
|
+
See also Gig 3 in Wieland, Gray and Hutter (1999)
|
|
151
|
+
|
|
152
|
+
Parameters
|
|
153
|
+
----------
|
|
154
|
+
dx : float, optional
|
|
155
|
+
Cell size of the x axis, by default 0.1
|
|
156
|
+
dy : float, optional
|
|
157
|
+
Cell size of the y axis, by default 0.1
|
|
158
|
+
res_type : str, optional
|
|
159
|
+
Type of thickness output:
|
|
160
|
+
|
|
161
|
+
- 'true_normal': Real thickness in the direction normal to the topography.
|
|
162
|
+
- 'vertical': Thickness in the vertical direction.
|
|
163
|
+
- 'projected_normal': Thickness normal to the topography is computed from the vertical
|
|
164
|
+
thickness projected on the axe normal to the topography.
|
|
165
|
+
|
|
166
|
+
The default is 'true_normal'.
|
|
167
|
+
|
|
168
|
+
Returns
|
|
169
|
+
-------
|
|
170
|
+
list[numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray]
|
|
171
|
+
X : numpy.ndarray
|
|
172
|
+
Mesh of X coordinates in the cartesian frame (nx*ny).
|
|
173
|
+
Y : numpy.ndarray
|
|
174
|
+
Mesh of Y coordinates in the cartesian frame (nx*ny).
|
|
175
|
+
Z : numpy.ndarray
|
|
176
|
+
Mesh of Z coordinates in the cartesian frame (nx*ny).
|
|
177
|
+
M : numpy.ndarray
|
|
178
|
+
Array of mass height, in the direction normal to topography.
|
|
179
|
+
"""
|
|
180
|
+
# Initiate topography
|
|
181
|
+
X, Y, Z = tilupy.make_topo.gray99(dx=dx, dy=dy)
|
|
182
|
+
|
|
183
|
+
x0 = 0.06 * np.cos(np.deg2rad(40))
|
|
184
|
+
hmass = 0.22
|
|
185
|
+
wmass = 0.32
|
|
186
|
+
radius = (wmass**2 + hmass**2) / (2 * hmass)
|
|
187
|
+
norm_offset = (wmass**2 - hmass**2) / (2 * hmass)
|
|
188
|
+
# Z = -np.tile(X, [len(Y), 1])*np.tan(np.deg2rad(20))
|
|
189
|
+
|
|
190
|
+
M = tilupy.make_mass.calotte(X,
|
|
191
|
+
Y,
|
|
192
|
+
Z,
|
|
193
|
+
x0,
|
|
194
|
+
0,
|
|
195
|
+
radius,
|
|
196
|
+
norm_offset=norm_offset,
|
|
197
|
+
res_type=res_type)
|
|
198
|
+
|
|
199
|
+
return X, Y, Z, M
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
"""
|
|
203
|
+
if __name__ == "__main__":
|
|
204
|
+
x, y, z, m = gray99_topo_mass(dx=0.01, dy=0.01)
|
|
205
|
+
axe = pytopomap.plot.plot_data_on_topo(x, y, z, m, topo_kwargs=dict(level_min=0.1))
|
|
206
|
+
plt.show()
|
|
207
|
+
"""
|
tilupy/initsimus.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import importlib
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def write(model_name: str,
|
|
7
|
+
raster_topo: str,
|
|
8
|
+
raster_mass: str,
|
|
9
|
+
tmax : float,
|
|
10
|
+
dt_im : float,
|
|
11
|
+
rheology_type: str,
|
|
12
|
+
rheology_params: dict = None,
|
|
13
|
+
folder_out: str = None,
|
|
14
|
+
**kwargs
|
|
15
|
+
):
|
|
16
|
+
"""
|
|
17
|
+
Dynamically imports the corresponding initiation module from
|
|
18
|
+
:data:`tilupy.models.<code>.initsimus` and use the corresponding :data:`write_simu()` function.
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
model_name : str
|
|
23
|
+
Model to create simulation files.
|
|
24
|
+
raster_topo : str, optional
|
|
25
|
+
Path for an ASCII topography.
|
|
26
|
+
raster_mass : str, optional
|
|
27
|
+
Path for an ASCII initial mass.
|
|
28
|
+
tmax : float
|
|
29
|
+
Maximum simulation time.
|
|
30
|
+
dt_im : float
|
|
31
|
+
Output image interval (in time steps).
|
|
32
|
+
rheology_type : str
|
|
33
|
+
Rheology to use for the simulation.
|
|
34
|
+
rheology_params : dict
|
|
35
|
+
Parameters specific to the selected rheology.
|
|
36
|
+
folder_out : str, optional
|
|
37
|
+
Output folder where simulation inputs will be saved.
|
|
38
|
+
**kwargs
|
|
39
|
+
Additional arguments for specific models.
|
|
40
|
+
"""
|
|
41
|
+
module = importlib.import_module("tilupy.models." + model_name + ".initsimus")
|
|
42
|
+
|
|
43
|
+
module.write_simu(raster_topo=raster_topo,
|
|
44
|
+
raster_mass=raster_mass,
|
|
45
|
+
tmax=tmax,
|
|
46
|
+
dt_im=dt_im,
|
|
47
|
+
rheology_type=rheology_type,
|
|
48
|
+
rheology_params=rheology_params,
|
|
49
|
+
folder_out=folder_out,
|
|
50
|
+
**kwargs)
|
tilupy/make_mass.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def calotte(x: np.ndarray,
|
|
7
|
+
y: np.ndarray,
|
|
8
|
+
z: np.ndarray,
|
|
9
|
+
x0: float,
|
|
10
|
+
y0: float,
|
|
11
|
+
radius: float,
|
|
12
|
+
norm_offset: float = 0,
|
|
13
|
+
res_type: str = 'projected_normal'
|
|
14
|
+
) -> np.ndarray:
|
|
15
|
+
"""Construct mass on topography as volume between sphere and topography.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
x : numpy.ndarray
|
|
20
|
+
X-axis array, with length nx.
|
|
21
|
+
y : numpy.ndarray
|
|
22
|
+
Y-axis array, with length ny.
|
|
23
|
+
z : numpy.ndarray
|
|
24
|
+
Array of altitudes, of size (ny, nx). z[0, 0] has coordinates
|
|
25
|
+
(x[0], y[-1]).
|
|
26
|
+
x0 : float
|
|
27
|
+
X position of the calotte.
|
|
28
|
+
y0 : float
|
|
29
|
+
Y position of the calotte.
|
|
30
|
+
radius : float
|
|
31
|
+
Radius of the shpere.
|
|
32
|
+
norm_offset : float, optional
|
|
33
|
+
Downwards offset between the sphere center and the topography, in the
|
|
34
|
+
direction normal to the topography, by default 0.
|
|
35
|
+
res_type : string, optional
|
|
36
|
+
Type of thickness output:
|
|
37
|
+
|
|
38
|
+
- 'true_normal': Real thickness in the direction normal to the topography.
|
|
39
|
+
- 'vertical': Thickness in the vertical direction.
|
|
40
|
+
- 'projected_normal': Thickness normal to the topography is computed from the vertical
|
|
41
|
+
thickness projected on the axe normal to the topography.
|
|
42
|
+
|
|
43
|
+
The default is 'projected_normal'.
|
|
44
|
+
|
|
45
|
+
Returns
|
|
46
|
+
-------
|
|
47
|
+
numpy.ndarray
|
|
48
|
+
Array of mass height, in the direction normal to topography.
|
|
49
|
+
"""
|
|
50
|
+
z = np.flip(z, axis=0).T
|
|
51
|
+
|
|
52
|
+
xmesh, ymesh = np.meshgrid(x, y, indexing='ij')
|
|
53
|
+
nx = len(x)
|
|
54
|
+
ny = len(y)
|
|
55
|
+
|
|
56
|
+
# Get altitude of mass center on topography
|
|
57
|
+
i0 = np.unravel_index(np.argmin(np.abs(x-x0), axis=None), (nx,))
|
|
58
|
+
j0 = np.unravel_index(np.argmin(np.abs(y-y0), axis=None), (ny,))
|
|
59
|
+
z0 = z[i0, j0]
|
|
60
|
+
# Topography gradient
|
|
61
|
+
[Fx, Fy] = np.gradient(z, x, y, edge_order=2)
|
|
62
|
+
Fz = np.ones((nx, ny))
|
|
63
|
+
c = 1/np.sqrt(1+Fx**2+Fy**2)
|
|
64
|
+
Fx = -Fx*c
|
|
65
|
+
Fy = -Fy*c
|
|
66
|
+
Fz = Fz*c
|
|
67
|
+
# Correct position from offset (shpere is moved downward,
|
|
68
|
+
# perpendicular to topography)
|
|
69
|
+
x0 = x0-norm_offset*Fx[i0, j0]
|
|
70
|
+
y0 = y0-norm_offset*Fy[i0, j0]
|
|
71
|
+
z0 = z0-norm_offset*Fz[i0, j0]
|
|
72
|
+
|
|
73
|
+
# Compute mass height only where relevant (ie around the mass center)
|
|
74
|
+
dist_to_mass = (xmesh-x0)**2+(ymesh-y0)**2
|
|
75
|
+
ind = (dist_to_mass <= radius**2)
|
|
76
|
+
|
|
77
|
+
B = 2*(Fx*(xmesh-x0)+Fy * (ymesh-y0)+Fz*(z-z0))
|
|
78
|
+
C = (xmesh-x0)**2+(ymesh-y0)**2+(z-z0)**2-radius**2
|
|
79
|
+
D = B**2-4*C
|
|
80
|
+
|
|
81
|
+
# Intersection between shpere and normal to the topography, solution of
|
|
82
|
+
# t**2+B*t+C=0
|
|
83
|
+
m = np.zeros((nx, ny))
|
|
84
|
+
|
|
85
|
+
if res_type == 'true_normal':
|
|
86
|
+
# B = 2*(Fx[ind]*(xmesh[ind]-x0)+Fy[ind] *
|
|
87
|
+
# (ymesh[ind]-y0)+Fz[ind]*(z[ind]-z0))
|
|
88
|
+
# C = (xmesh[ind]-x0)**2+(ymesh[ind]-y0)**2+(z[ind]-z0)**2-radius**2
|
|
89
|
+
# D = B**2-4*C
|
|
90
|
+
B = 2*(Fx*(xmesh-x0)+Fy *
|
|
91
|
+
(ymesh-y0)+Fz*(z-z0))
|
|
92
|
+
C = (xmesh-x0)**2+(ymesh-y0)**2+(z-z0)**2-radius**2
|
|
93
|
+
D = B**2-4*C
|
|
94
|
+
ind = D > 0
|
|
95
|
+
t1 = (-B-np.sqrt(D))/2
|
|
96
|
+
t2 = (-B+np.sqrt(D))/2
|
|
97
|
+
ind2 = t1*t2 < 0
|
|
98
|
+
m[ind2] = np.maximum(t1[ind2], t2[ind2])
|
|
99
|
+
|
|
100
|
+
# Vertical thickness of calotte.
|
|
101
|
+
if res_type in ['vertical', 'projected_normal']:
|
|
102
|
+
zs = z0 + np.sqrt(radius**2 - (xmesh - x0)**2 - (ymesh - y0)**2)
|
|
103
|
+
zi = z0 - np.sqrt(radius**2 - (xmesh - x0)**2 - (ymesh - y0)**2)
|
|
104
|
+
ind = (z < zs) & (z > zi)
|
|
105
|
+
m[ind] = zs[ind] - z[ind]
|
|
106
|
+
if res_type == 'projected_normal':
|
|
107
|
+
m = m * c
|
|
108
|
+
|
|
109
|
+
m = np.flip(m.T, axis=0)
|
|
110
|
+
|
|
111
|
+
return m
|