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.
@@ -0,0 +1,264 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import os
4
+
5
+ import numpy as np
6
+ import tilupy.read
7
+
8
+ from scipy.interpolate import RegularGridInterpolator
9
+
10
+
11
+ # Classify results
12
+ AVAILABLE_OUTPUT = ["h", "hvert", "u", "hu", "hu2"]
13
+ """All output available for a shaltop simulation.
14
+
15
+ Implemented states:
16
+
17
+ - h : Flow thickness (normal to the surface)
18
+ - u : Norm of the velocity (from ux and uy)
19
+
20
+ Output computed from other output:
21
+
22
+ - hvert : True vertical flow thickness
23
+ - hu : Momentum flux (from h and u)
24
+ - hu2 : Convective momentum flux (from h and u)
25
+ """
26
+
27
+
28
+ class Results(tilupy.read.Results):
29
+ """Results of lave2D simulations.
30
+
31
+ This class is the results class for lave2D. Reading results from lave2D outputs
32
+ are done in this class.
33
+
34
+ This class has all the global and quick attributes of the parent class. The quick
35
+ attributes are only computed if needed and can be deleted to clean memory.
36
+
37
+ In addition to these attributes, there are those necessary for the operation of
38
+ reading the lave2D results.
39
+
40
+ Parameters
41
+ ----------
42
+ folder : str
43
+ Path to the folder containing the simulation files.
44
+ name : str
45
+ Simulation/Project name.
46
+ raster : str
47
+ Raster name.
48
+ grid : str, optional
49
+ - If grid=="cell", use cell, output nx and ny sizes are the size of topography raster, minus 1.
50
+ - If grid=="edges" (default), use edges, output will have same dimension as topography raster.
51
+
52
+ Attributes
53
+ ----------
54
+ _name : str
55
+ Name of the lave2D project.
56
+ _grid : str
57
+ - If _grid=="cell", use cell, output nx and ny sizes are the size of topography raster, minus 1.
58
+ - If _grid=="edges", use edges, output will have same dimension as topography raster.
59
+ _raster : str
60
+ Path to the raster file.
61
+ _params : dict
62
+ Dictionary storing all simulation parameters.
63
+ """
64
+ def __init__(self, folder, name, raster, grid="edges"):
65
+ super().__init__()
66
+ self._code = "lave2D"
67
+
68
+ if folder is None:
69
+ folder = os.getcwd()
70
+ self._folder = folder
71
+ self._folder_output = folder
72
+ # Results are in the same folder than simulation data
73
+
74
+ self._name = name
75
+
76
+ if not raster.endswith(".asc"):
77
+ raster = raster + ".asc"
78
+ self._raster = raster
79
+
80
+ self._x, self._y, self._zinit = tilupy.raster.read_ascii(os.path.join(folder, self._raster))
81
+ self._nx, self._ny = len(self._x), len(self._y)
82
+ self._dx = self._x[1] - self._x[0]
83
+ self._dy = self._y[1] - self._y[0]
84
+
85
+ # grid=='edges' -> use edges, output will have same dimension as
86
+ # topography raster
87
+ # grid=='cell' -> use cell, output nx and ny sizes are the size of
88
+ # topography raster, minus 1
89
+ self._grid = grid
90
+ if self._grid == "cells":
91
+ fz = RegularGridInterpolator((self._y, self._x),
92
+ self._zinit,
93
+ method="linear",
94
+ bounds_error=False,
95
+ fill_value=None,
96
+ )
97
+ self._x = self._x[1:] - self._dx / 2
98
+ self._y = self._y[1:] - self._dy / 2
99
+ x_mesh, y_mesh = np.meshgrid(self._x, self._y)
100
+ self._zinit = fz((y_mesh, x_mesh))
101
+
102
+ self._params = dict()
103
+
104
+ self._params["nx"] = len(self._x)
105
+ self._params["ny"] = len(self._y)
106
+
107
+ # Rheology
108
+ rheol = np.loadtxt(os.path.join(folder, self._name + ".rhe"))
109
+ self._params["tau/rho"] = rheol[0]
110
+ self._params["K/tau"] = rheol[1]
111
+
112
+ # Numerical parameters
113
+ with open(os.path.join(folder, "DONLEDD1.DON"), "r") as fid:
114
+ for line in fid:
115
+ name = line[:34].strip(" ")
116
+ value = line[34:]
117
+ if len(value) == 1:
118
+ value = int(value)
119
+ else:
120
+ value = float(value)
121
+ self._params[name] = value
122
+
123
+ # Create self._tim
124
+ self._extract_output("X")
125
+
126
+
127
+ def _extract_output(self,
128
+ name: str,
129
+ **kwargs
130
+ ) -> tilupy.read.TemporalResults2D | tilupy.read.AbstractResults:
131
+ """Result extraction for lave2D files.
132
+
133
+ Parameters
134
+ ----------
135
+ name : str
136
+ Wanted output. Can access to variables in :data:`AVAILABLE_OUTPUT`.
137
+
138
+ Returns
139
+ -------
140
+ tilupy.read.TemporalResults2D | tilupy.read.TemporalResults0D | tilupy.read.AbstractResults
141
+ Wanted output. If no output computed, return an object of :class:`tilupy.read.AbstractResults`.
142
+ """
143
+ d = None
144
+ t = None
145
+ notation = None
146
+
147
+ # read initial mass
148
+ h_init = np.loadtxt(os.path.join(self._folder, self._name + ".cin"), skiprows=1)
149
+
150
+ # Read results
151
+ file_res = os.path.join(self._folder, self._name + ".asc")
152
+ n_times = int(self._params["tmax"] / self._params["dtsorties"])
153
+ tim = [0]
154
+
155
+ if self._grid == "edges":
156
+ ny_out = self._params["ny"] - 1
157
+ x_out = self._x[1:] - self._dx / 2
158
+ y_out = self._y[1:] - self._dy / 2
159
+ x_mesh, y_mesh = np.meshgrid(self._x, self._y)
160
+ h_init = h_init.reshape(self._params["ny"] - 1, self._params["nx"] - 1)
161
+ fh = RegularGridInterpolator((y_out, x_out),
162
+ h_init,
163
+ method="linear",
164
+ bounds_error=False,
165
+ fill_value=None)
166
+ h_init = fh((y_mesh, x_mesh))
167
+ else:
168
+ ny_out = self._params["ny"]
169
+ h_init = h_init.reshape(self._params["ny"], self._params["nx"])
170
+
171
+ x_mesh_out, y_mesh_out = np.meshgrid(self._x[1:] - self._dx / 2,
172
+ self._y[1:] - self._dy / 2)
173
+
174
+ h = np.zeros((self._params["ny"], self._params["nx"], n_times + 1))
175
+ h[:, :, 0] = np.flip(h_init, axis=0)
176
+ u = np.zeros((self._params["ny"], self._params["nx"], n_times + 1))
177
+
178
+ with open(file_res, "r") as fid:
179
+ lines = fid.readlines()
180
+ n_lines = 2 * (ny_out) + 8 # Number of lines per time step
181
+ for i_time in range(n_times):
182
+ i_start = n_lines * i_time
183
+ i_start_h = i_start + 7
184
+ i_stop_h = i_start + ny_out + 7
185
+ i_start_u = i_start + ny_out + 8
186
+ i_stop_u = i_start + 2 * ny_out + 8
187
+ tim.append(float(lines[i_start]))
188
+ h_out = np.loadtxt(lines[i_start_h:i_stop_h])
189
+ u_out = np.loadtxt(lines[i_start_u:i_stop_u])
190
+
191
+ if self._grid == "edges":
192
+ fh = RegularGridInterpolator((y_out, x_out),
193
+ h_out,
194
+ method="linear",
195
+ bounds_error=False,
196
+ fill_value=None)
197
+ h[:, :, i_time + 1] = fh((y_mesh, x_mesh))
198
+
199
+ fu = RegularGridInterpolator((y_out, x_out),
200
+ u_out,
201
+ method="linear",
202
+ bounds_error=False,
203
+ fill_value=None)
204
+ u[:, :, i_time + 1] = fu((y_mesh, x_mesh))
205
+ else:
206
+ h[:, :, i_time + 1] = h_out
207
+ u[:, :, i_time + 1] = u_out
208
+
209
+ if self._tim is None:
210
+ self._tim = np.array(tim)
211
+
212
+ extracted_outputs = {"h": h[:],
213
+ "u": u[:],
214
+ }
215
+
216
+ if name in ["h", "u"]:
217
+ d = extracted_outputs[name]
218
+ t = self._tim
219
+
220
+ if name == "hu":
221
+ d = extracted_outputs['h'] * extracted_outputs['u']
222
+ t = self._tim
223
+
224
+ elif name == "hu2":
225
+ d = extracted_outputs['h'] * extracted_outputs['u'] * extracted_outputs['u']
226
+ t = self._tim
227
+
228
+ elif name == "hvert":
229
+ if self._costh is None:
230
+ self._costh = self.compute_costh()
231
+ d = extracted_outputs["h"] / self._costh[:, :, np.newaxis]
232
+ t = self._tim
233
+
234
+ # if name == "ek":
235
+ # if self._costh is None:
236
+ # self._costh = self.compute_costh()
237
+
238
+ # d = []
239
+ # for i in range(len(self._tim)):
240
+ # d.append(np.sum((available_outputs['h'][:, :, i]
241
+ # * available_outputs['u'][:, :, i]
242
+ # * available_outputs['u'][:, :, i])
243
+ # / self._costh[:, :]))
244
+ # d = np.array(d)
245
+ # t = self._tim
246
+
247
+ if t is None:
248
+ return tilupy.read.AbstractResults(name, d, notation=notation)
249
+
250
+ else:
251
+ if d.ndim == 3:
252
+ return tilupy.read.TemporalResults2D(name,
253
+ d,
254
+ t,
255
+ notation=notation,
256
+ x=self._x,
257
+ y=self._y,
258
+ z=self._zinit)
259
+ return None
260
+
261
+
262
+ def _read_from_file(self, *args, **kwargs):
263
+ """Not useful"""
264
+ return "No _read_from_file for Lave2D."
File without changes
@@ -0,0 +1,192 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created on Wed May 26 11:03:56 2021
5
+
6
+ @author: peruzzetto
7
+ """
8
+
9
+ import os
10
+ import numpy as np
11
+
12
+ import tilupy.notations
13
+
14
+ readme_param_match = dict(tmax='tmax',
15
+ CFL='cflhyp',
16
+ h_min='eps0',
17
+ dt_im_output='dt_im')
18
+
19
+
20
+ def readme_to_params(folder_data: str) -> dict:
21
+ """Read a README.txt file and convert it to a parameters dictionary.
22
+
23
+ Each line of the README file should contain a key and a value separated
24
+ by whitespace. The function parses the file and returns a dictionary
25
+ mapping keys to their corresponding string values.
26
+
27
+ Parameters
28
+ ----------
29
+ folder_data : str
30
+ Path to the folder containing the README.txt file.
31
+
32
+ Returns
33
+ -------
34
+ dict
35
+ Dictionary where keys are parameter names (str) and values are
36
+ their corresponding values (str) read from the file.
37
+ """
38
+ params = dict()
39
+ with open(os.path.join(folder_data, 'README.txt'), 'r') as f:
40
+ for line in f:
41
+ (key, val) = line.split()
42
+ params[key] = val
43
+ return params
44
+
45
+
46
+ def write_params(params: dict) -> str:
47
+ """Convert a parameters dictionary to a formatted string for RavaFlow input.
48
+
49
+ Generates a single string in the form "key1=val1 key2=val2 ...",
50
+ suitable for passing as command-line arguments to RavaFlow.
51
+
52
+ Parameters
53
+ ----------
54
+ params : dict
55
+ Dictionary of parameters, where keys and values are strings.
56
+
57
+ Returns
58
+ -------
59
+ str
60
+ Formatted string containing all parameters in "key=value" format,
61
+ separated by spaces.
62
+ """
63
+ txt = ''
64
+ for key in params:
65
+ txt += '{:s}={:s} '.format(key, params[key])
66
+ return txt[:-1]
67
+
68
+
69
+ def make_simus(law: str, rheol_params: dict, folder_files: str, folder_out: str, readme_file: str) -> None:
70
+ """Write ravaflow initial file for simple slope test case
71
+
72
+ Reads simulation parameters from a README file and input
73
+ ASCII rasters, sets topography and mass, prepares numerical and rheological
74
+ parameters, and generates a shell script to execute simulations. Supports
75
+ multiple combinations of rheology parameters.
76
+
77
+ Parameters
78
+ ----------
79
+ law : str
80
+ Rheological law to use, e.g., "coulomb" or "voellmy".
81
+ rheol_params : dict of list
82
+ Dictionary of rheology parameters, each key maps to a list of values
83
+ defining multiple simulation runs.
84
+ folder_files : str
85
+ Path to folder containing input ASCII files "topo.asc" and "mass.asc".
86
+ folder_out : str
87
+ Path to the folder where output simulation folders and run scripts
88
+ will be created.
89
+ readme_file : str
90
+ Path to the README.txt file containing simulation metadata and parameters.
91
+
92
+ Returns
93
+ -------
94
+ None
95
+ """
96
+ # Parameters from README.txt file
97
+ params_readme = tilupy.notations.readme_to_params(readme_file)
98
+ # Parameters for simulation
99
+ params = dict()
100
+ # Directory where run script will be created
101
+ folder_law = os.path.join(folder_out, law)
102
+ os.makedirs(folder_law, exist_ok=True)
103
+
104
+ # Prepare simulation parameters
105
+
106
+ # Topography and initial mass
107
+ params['elevation'] = 'elev'
108
+ params['hrelease'] = 'minit'
109
+
110
+ # Control parameters
111
+ params["controls"] = '0,0,0,0,0,0'
112
+
113
+ # Thresholds parameters
114
+ # (min thicknees for output, min flow knetic energy for output,
115
+ # min flow pressure for output, min thickness in simulation)
116
+ h0 = np.float(params_readme['h_min'])
117
+ params["thresholds"] = "{:.2E},{:.2E},{:.2E},{:.2E}".format(h0, h0, h0, h0)
118
+
119
+ # CFL parameters
120
+ # (CFL condition, initial time step when CFL not applicable)
121
+ params['cfl'] = "{:.2E},0.0001".format(np.float(params_readme['CFL']))
122
+
123
+ # Output time parameters
124
+ params['time'] = "{:.3f},{:.2f}".format(np.float(params_readme['dt_im_output']),
125
+ np.float(params_readme['tmax']))
126
+
127
+ # Simulation phases
128
+ params['phases'] = 's'
129
+
130
+ # Write bash run file
131
+ file_txt = ""
132
+ file_path = os.path.join(folder_law, 'run.avaflow.sh')
133
+
134
+ # Set region
135
+ grid_params = dict()
136
+ with open(os.path.join(folder_files, 'topo.asc'), 'r') as fid:
137
+ for i in range(6):
138
+ tmp = fid.readline().split()
139
+ grid_params[tmp[0]] = float(tmp[1])
140
+ e = grid_params['cellsize']*grid_params['ncols']
141
+ n = grid_params['cellsize']*grid_params['nrows']
142
+ tmp = 'g.region s=0 w=0 e={:.2f} n={:.2f} res={:.4f}\n'
143
+ file_txt += tmp.format(e, n, grid_params['cellsize'])
144
+ file_txt += 'g.region -s\n\n'
145
+
146
+ # Read ascii files for mass and topography
147
+ # Get relative path to topo and mass file, from the fodler
148
+ # where simulations will be run. Find position of folder_files in
149
+ # folder_out path. Simulations are run in folder_out/law/
150
+ path = os.path.normpath(folder_out)
151
+ ffs = path.split(os.sep)
152
+ _, folder_topo = os.path.split(folder_files)
153
+ n_up = len(ffs) - ffs.index(folder_topo)
154
+ path_up = '../'*n_up
155
+ zfile = path_up + 'topo.asc'
156
+ mfile = path_up + 'mass.asc'
157
+ file_txt += 'r.in.gdal --overwrite input={:s} output=elev\n'.format(zfile)
158
+ file_txt += 'r.in.gdal --overwrite input={:s} output=minit\n'.format(mfile)
159
+
160
+ # prefix for output folder
161
+ prefixs = tilupy.notations.make_rheol_string(rheol_params, law)
162
+
163
+ param_names = [param for param in rheol_params]
164
+
165
+ txt_friction = '{:.2f},{:.2f},{:.2f}'
166
+
167
+ for i in range(len(rheol_params[param_names[0]])):
168
+
169
+ simu_prefix = prefixs[i]
170
+ if law == 'coulomb':
171
+ delta1 = rheol_params['delta1'][i]
172
+ params['friction'] = txt_friction.format(delta1, delta1, 0)
173
+
174
+ if law == 'voellmy':
175
+ delta1 = rheol_params['delta1'][i]
176
+ ksi = rheol_params['ksi'][i]
177
+ params['friction'] = txt_friction.format(delta1, delta1,
178
+ np.log10(ksi))
179
+
180
+ params['prefix'] = simu_prefix
181
+
182
+ file_txt += '\n'
183
+ file_txt += 'start_time=`date +%s`\n'
184
+ file_txt += 'r.avaflow -e ' + write_params(params) + '\n'
185
+ file_txt += 'end_time=`date +%s`\n'
186
+ file_txt += 'elapsed_time=$(($end_time - $start_time))\n'
187
+ file_txt += ('string_time="${start_time} ' +
188
+ simu_prefix + ' ${elapsed_time}"\n')
189
+ file_txt += 'echo ${string_time} >> simulation_duration.txt\n\n'
190
+
191
+ with open(file_path, "w") as fid:
192
+ fid.write(file_txt)