zoomy-core 0.1.1__py3-none-any.whl → 0.1.3__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.

Potentially problematic release.


This version of zoomy-core might be problematic. Click here for more details.

Files changed (53) hide show
  1. zoomy_core/decorators/decorators.py +25 -0
  2. zoomy_core/fvm/flux.py +97 -0
  3. zoomy_core/fvm/nonconservative_flux.py +97 -0
  4. zoomy_core/fvm/ode.py +55 -0
  5. zoomy_core/fvm/solver_numpy.py +305 -0
  6. zoomy_core/fvm/timestepping.py +13 -0
  7. zoomy_core/mesh/mesh.py +1234 -0
  8. zoomy_core/mesh/mesh_extrude.py +168 -0
  9. zoomy_core/mesh/mesh_util.py +487 -0
  10. zoomy_core/misc/custom_types.py +6 -0
  11. zoomy_core/misc/interpolation.py +140 -0
  12. zoomy_core/misc/io.py +438 -0
  13. zoomy_core/misc/logger_config.py +18 -0
  14. zoomy_core/misc/misc.py +216 -0
  15. zoomy_core/misc/static_class.py +94 -0
  16. zoomy_core/model/analysis.py +147 -0
  17. zoomy_core/model/basefunction.py +113 -0
  18. zoomy_core/model/basemodel.py +512 -0
  19. zoomy_core/model/boundary_conditions.py +193 -0
  20. zoomy_core/model/initial_conditions.py +171 -0
  21. zoomy_core/model/model.py +63 -0
  22. zoomy_core/model/models/GN.py +70 -0
  23. zoomy_core/model/models/advection.py +53 -0
  24. zoomy_core/model/models/basisfunctions.py +181 -0
  25. zoomy_core/model/models/basismatrices.py +377 -0
  26. zoomy_core/model/models/core.py +564 -0
  27. zoomy_core/model/models/coupled_constrained.py +60 -0
  28. zoomy_core/model/models/poisson.py +41 -0
  29. zoomy_core/model/models/shallow_moments.py +757 -0
  30. zoomy_core/model/models/shallow_moments_sediment.py +378 -0
  31. zoomy_core/model/models/shallow_moments_topo.py +423 -0
  32. zoomy_core/model/models/shallow_moments_variants.py +1509 -0
  33. zoomy_core/model/models/shallow_water.py +266 -0
  34. zoomy_core/model/models/shallow_water_topo.py +111 -0
  35. zoomy_core/model/models/shear_shallow_flow.py +594 -0
  36. zoomy_core/model/models/sme_turbulent.py +613 -0
  37. zoomy_core/model/models/vam.py +455 -0
  38. zoomy_core/postprocessing/postprocessing.py +72 -0
  39. zoomy_core/preprocessing/openfoam_moments.py +452 -0
  40. zoomy_core/transformation/helpers.py +25 -0
  41. zoomy_core/transformation/to_amrex.py +238 -0
  42. zoomy_core/transformation/to_c.py +181 -0
  43. zoomy_core/transformation/to_jax.py +14 -0
  44. zoomy_core/transformation/to_numpy.py +115 -0
  45. zoomy_core/transformation/to_openfoam.py +254 -0
  46. zoomy_core/transformation/to_ufl.py +67 -0
  47. {zoomy_core-0.1.1.dist-info → zoomy_core-0.1.3.dist-info}/METADATA +2 -1
  48. zoomy_core-0.1.3.dist-info/RECORD +51 -0
  49. zoomy_core-0.1.3.dist-info/top_level.txt +1 -0
  50. zoomy_core-0.1.1.dist-info/RECORD +0 -5
  51. zoomy_core-0.1.1.dist-info/top_level.txt +0 -1
  52. {zoomy_core-0.1.1.dist-info → zoomy_core-0.1.3.dist-info}/WHEEL +0 -0
  53. {zoomy_core-0.1.1.dist-info → zoomy_core-0.1.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,140 @@
1
+ import numpy as np
2
+ from sympy import integrate, diff
3
+ from sympy.abc import x
4
+ from sympy import lambdify
5
+
6
+ import library.zoomy_core.mesh.mesh_util as mesh_util
7
+ # from library.zoomy_core.model.models.shallow_moments import Basis
8
+
9
+
10
+ def _find_bounding_element(mesh, position):
11
+ """
12
+ Strategy: the faces of the elements are outward facing. If I compute compte the intersection of the normal with the point,
13
+ resulting in alpha * normal = minimal_distance; then the alpha needs to be negative for all faces
14
+ see https://en.wikipedia.org/wiki/Hesse_normal_form
15
+ """
16
+ mesh_type = mesh.type
17
+ for i_elem, vertices in enumerate(mesh.element_vertices):
18
+ faces = mesh_util._face_order(vertices, mesh_type)
19
+ face_centers = [
20
+ mesh_util.center(mesh.vertex_coordinates, np.array(face)) for face in faces
21
+ ]
22
+ vector_origin_to_plane = [
23
+ face_center - position for face_center in face_centers
24
+ ]
25
+ face_normals = mesh.element_face_normals[i_elem]
26
+
27
+ if _is_point_inside_bounding_faces(face_normals, vector_origin_to_plane):
28
+ return i_elem
29
+
30
+ # outside of domain
31
+ assert False
32
+
33
+
34
+ def _is_point_inside_bounding_faces(outward_face_normals, vectors_OP):
35
+ for n, p in zip(outward_face_normals, vectors_OP):
36
+ if np.dot(n, p) < 0:
37
+ return False
38
+ return True
39
+
40
+
41
+ def to_new_mesh(fields, mesh_old, mesh_new, interp="const", map_fields=None):
42
+ assert interp == "const"
43
+
44
+ fields_new = np.zeros_like(fields)
45
+
46
+ for i_elem in range(mesh_new.n_elements):
47
+ element_center = mesh_new.element_center[i_elem]
48
+ i_elem_old = _find_bounding_element(mesh_old, element_center)
49
+ fields_new[i_elem] = fields[i_elem_old]
50
+ return fields_new
51
+
52
+
53
+ # # comute gradients based on FD using scattered pointwise data
54
+ # def compute_gradient_field_2d(points, fields):
55
+ # def in_hull(points, probe):
56
+ # n_points = points.shape[0]
57
+ # n_dim = points.shape[1]
58
+ # c = np.zeros(n_points)
59
+ # A = np.r_[points.T, np.ones((1, n_points))]
60
+ # b = np.r_[probe, np.ones(1)]
61
+ # lp = linprog(c, A_eq=A, b_eq=b)
62
+ # return lp.success
63
+
64
+ # assert points.shape[1] == 2
65
+ # grad = np.zeros((fields.shape[0], 2, fields.shape[1]))
66
+ # eps_x = (points[:, 0].max() - points[:, 0].min()) / 100.0
67
+ # eps_y = (points[:, 1].max() - points[:, 1].min()) / 100.00
68
+
69
+ # # generate evaluation 'stencil' for central differences
70
+ # xi_0 = np.array(points)
71
+ # xi_xp = np.array(points)
72
+ # xi_xp[:, 0] += eps_x
73
+ # xi_xm = np.array(points)
74
+ # xi_xm[:, 0] -= eps_x
75
+ # xi_yp = np.array(points)
76
+ # xi_yp[:, 1] += eps_y
77
+ # xi_ym = np.array(points)
78
+ # xi_ym[:, 1] -= eps_y
79
+ # factors_x = 2.0 * np.ones((points.shape[0]))
80
+ # factors_y = 2.0 * np.ones((points.shape[0]))
81
+ # # correct boundary points with single sided differences
82
+ # for i in range(xi_xp.shape[0]):
83
+ # if not in_hull(points, xi_xp[i]):
84
+ # xi_xp[i, 0] -= eps_x
85
+ # factors_x[i] = 1.0
86
+ # if not in_hull(points, xi_xm[i]):
87
+ # xi_xm[i, 0] += eps_x
88
+ # factors_x[i] = 1.0
89
+ # if not in_hull(points, xi_yp[i]):
90
+ # xi_yp[i, 1] -= eps_y
91
+ # factors_y[i] = 1.0
92
+ # if not in_hull(points, xi_ym[i]):
93
+ # xi_ym[i, 1] += eps_y
94
+ # factors_y[i] = 1.0
95
+
96
+ # for i_field, values in enumerate(fields):
97
+ # f = griddata(points, values, xi_0)
98
+ # f_xp = griddata(points, values, xi_xp)
99
+ # f_xm = griddata(points, values, xi_xm)
100
+ # f_yp = griddata(points, values, xi_yp)
101
+ # f_ym = griddata(points, values, xi_ym)
102
+
103
+ # dfdx = (f_xp - f_xm) / (factors_x * eps_x + 10 ** (-10))
104
+ # dfdy = (f_yp - f_ym) / (factors_y * eps_y + 10 ** (-10))
105
+
106
+ # grad[i_field, 0, :] = dfdx
107
+ # grad[i_field, 1, :] = dfdy
108
+
109
+ # assert (np.isnan(grad) == False).all()
110
+ # assert (np.isfinite(grad) == True).all()
111
+ # return grad
112
+
113
+
114
+ # # ps, vs: values at the boundary points
115
+ # # p0, v0, value at the cell_center
116
+ # def compute_gradient(ps, vs, p0, v0, limiter=lambda r: 1.0):
117
+ # points = np.zeros((ps.shape[0] + 1, 2))
118
+ # points[:-1, :] = ps[:, :2]
119
+ # points[-1, :] = p0[:2]
120
+ # values = np.zeros((vs.shape[0] + 1, vs.shape[1]))
121
+ # values[:-1, :] = vs
122
+ # values[-1, :] = v0
123
+
124
+ # f = LinearNDInterpolator(points, values)
125
+ # eps_x = (points[:, 0].max() - points[:, 0].min()) / 100.0
126
+ # eps_y = (points[:, 1].max() - points[:, 1].min()) / 100.00
127
+ # x0 = p0[0]
128
+ # y0 = p0[1]
129
+
130
+ # dfdx = (f(x0 + eps_x, y0) - f(x0 - eps_x, y0)) / (2 * eps_x + 10 ** (-10))
131
+ # rx = (f(x0, y0) - f(x0 - eps_x, y0)) / (f(x0 + eps_x, y0) - f(x0, y0) + 10 ** (-10))
132
+ # phix = limiter(rx)
133
+ # dfdy = (f(x0, y0 + eps_y) - f(x0, y0 - eps_y)) / (2 * eps_y + 10 ** (-10))
134
+ # ry = (f(x0, y0) - f(x0, y0 - eps_y)) / (f(x0, y0 + eps_y) - f(x0, y0) + 10 ** (-10))
135
+ # phiy = limiter(ry)
136
+
137
+ # grad = np.array([phix * dfdx, phiy * dfdy]).T
138
+ # assert (np.isnan(grad) == False).all()
139
+ # assert (np.isfinite(grad) == True).all()
140
+ # return grad
zoomy_core/misc/io.py ADDED
@@ -0,0 +1,438 @@
1
+ import os
2
+ import numpy as np
3
+ import json
4
+ import shutil
5
+
6
+ try:
7
+ import meshio
8
+
9
+ _HAVE_MESHIO = True
10
+ except:
11
+ _HAVE_MESHIO = False
12
+
13
+ try:
14
+ import h5py
15
+
16
+ _HAVE_H5PY = True
17
+ except ImportError:
18
+ _HAVE_H5PY = False
19
+
20
+ # import library.zoomy_core.mesh.fvm_mesh as fvm_mesh
21
+ from library.zoomy_core.mesh.mesh import Mesh
22
+ import library.zoomy_core.mesh.mesh_util as mesh_util
23
+ from library.zoomy_core.misc.misc import Zstruct, Settings
24
+ from library.zoomy_core.misc.logger_config import logger
25
+
26
+
27
+ def init_output_directory(path, clean):
28
+ main_dir = os.getenv("ZOOMY_DIR")
29
+ path = os.path.join(main_dir, path)
30
+ os.makedirs(path, exist_ok=True)
31
+ if clean:
32
+ filelist = [f for f in os.listdir(path)]
33
+ for f in filelist:
34
+ if os.path.isdir(os.path.join(path, f)):
35
+ shutil.rmtree(os.path.join(path, f))
36
+ else:
37
+ os.remove(os.path.join(path, f))
38
+
39
+
40
+ def get_hdf5_type(value):
41
+ out = type(value)
42
+ if isinstance(value, str):
43
+ out = h5py.string_dtype()
44
+ return out
45
+
46
+
47
+ def write_dict_to_hdf5(group, d):
48
+ for key, value in d.items():
49
+ if isinstance(value, dict):
50
+ subgroup = group.create_group(key)
51
+ write_dict_to_hdf5(subgroup, value)
52
+ elif isinstance(value, (str, int, float, bool)):
53
+ group.create_dataset(key, data=value, dtype=get_hdf5_type(value))
54
+ elif isinstance(value, (list, tuple)):
55
+ group.create_dataset(key, data=value)
56
+ elif isinstance(value, type(np.ndarray)):
57
+ group.create_dataset(key, data=value)
58
+ elif hasattr(value, "as_dict"):
59
+ subgroup = group.create_group(key)
60
+ write_dict_to_hdf5(subgroup, value.as_dict())
61
+ else:
62
+ logger.warning(f"Skipping unsupported type for key: {
63
+ key} -> {type(value)}")
64
+
65
+
66
+ def load_hdf5_to_dict(group):
67
+ d = {}
68
+ for key, value in group.items():
69
+ if isinstance(value, h5py.Group):
70
+ d[key] = load_hdf5_to_dict(value)
71
+ elif isinstance(value, h5py.Dataset):
72
+ if value.dtype == h5py.string_dtype():
73
+ d[key] = value[()].decode("utf-8")
74
+ else:
75
+ d[key] = value[()]
76
+ else:
77
+ logger.warning(f"Skipping unsupported type for key: {
78
+ key} -> {type(value)}")
79
+
80
+ return d
81
+
82
+
83
+ def save_settings(settings):
84
+ main_dir = os.getenv("ZOOMY_DIR")
85
+ filepath = os.path.join(main_dir, settings.output.directory)
86
+ with h5py.File(os.path.join(filepath, "settings.h5"), "w") as f:
87
+ write_dict_to_hdf5(f, settings.as_dict(recursive=True))
88
+
89
+
90
+ def load_settings(filepath):
91
+ main_dir = os.getenv("ZOOMY_DIR")
92
+ filepath = os.path.join(main_dir, filepath)
93
+ with h5py.File(os.path.join(filepath, "settings.h5"), "r") as f:
94
+ d = load_hdf5_to_dict(f)
95
+
96
+ settings = Settings.from_dict(d)
97
+ return settings
98
+
99
+
100
+ def load_settings2(filepath):
101
+ main_dir = os.getenv("ZOOMY_DIR")
102
+ filepath = os.path.join(main_dir, filepath)
103
+ with h5py.File(os.path.join(filepath, "settings.h5"), "r") as f:
104
+ model = f["model"]
105
+ solver = f["solver"]
106
+ output = f["output"]
107
+
108
+ d_model = {}
109
+ if "parameters" in model:
110
+ parameters = {k: v[()] for k, v in model["parameters"].items()}
111
+ parameters = Zstruct(**parameters)
112
+ for k in model.keys():
113
+ if k != "parameters":
114
+ v = model[k][()]
115
+ if isinstance(v, (str, int, float, bool)):
116
+ d_model[k] = v
117
+ else:
118
+ raise ValueError(
119
+ f"Unsupported type for model attribute {k}: {type(v)}"
120
+ )
121
+ d_model["parameters"] = parameters
122
+ model = Zstruct(**d_model)
123
+ d_solver = {}
124
+ for k in solver.keys():
125
+ v = solver[k][()]
126
+ if isinstance(v, (str, int, float, bool)):
127
+ d_solver[k] = v
128
+ else:
129
+ raise ValueError(
130
+ f"Unsupported type for solver attribute {k}: {type(v)}"
131
+ )
132
+ solver = Zstruct(**d_solver)
133
+
134
+ d_output = {}
135
+ for k in output.keys():
136
+ v = output[k][()]
137
+ if isinstance(v, (str, int, float, bool)):
138
+ d_output[k] = v
139
+ else:
140
+ raise ValueError(
141
+ f"Unsupported type for output attribute {k}: {type(v)}"
142
+ )
143
+ output = Zstruct(**d_output)
144
+
145
+ settings = Settings(model=model, solver=solver, output=output)
146
+
147
+ # parameters = {k: v[()] for k, v in f["parameters"].items()}
148
+ # name = f["name"][()]
149
+ # output_dir = f["output_dir"][()]
150
+ # output_snapshots = f["output_snapshots"][()]
151
+ # output_write_all = f["output_write_all"][()]
152
+ # output_clean_dir = f["output_clean_dir"][()]
153
+ # truncate_last_time_step = f["truncate_last_time_step"][()]
154
+ callbacks = f["callbacks"][()]
155
+ return settings
156
+
157
+
158
+ def clean_files(filepath, filename=".vtk"):
159
+ main_dir = os.getenv("ZOOMY_DIR")
160
+ abs_filepath = os.path.join(main_dir, filepath)
161
+ if os.path.exists(abs_filepath):
162
+ for file in os.listdir(abs_filepath):
163
+ if file.endswith(filename):
164
+ os.remove(os.path.join(abs_filepath, file))
165
+
166
+
167
+ def _save_fields_to_hdf5(filepath, i_snapshot, time, Q, Qaux=None, overwrite=True):
168
+ i_snap = int(i_snapshot)
169
+ main_dir = os.getenv("ZOOMY_DIR")
170
+ filepath = os.path.join(main_dir, filepath)
171
+ with h5py.File(filepath, "a") as f:
172
+ if i_snap == 0 and not "fields" in f.keys():
173
+ fields = f.create_group("fields")
174
+ else:
175
+ fields = f["fields"]
176
+ group_name = "iteration_" + str(i_snap)
177
+ if group_name in fields:
178
+ if overwrite:
179
+ del fields[group_name]
180
+ else:
181
+ raise ValueError(
182
+ f"Group {group_name} already exists in {filepath}")
183
+ attrs = fields.create_group(group_name)
184
+ attrs.create_dataset("time", data=time, dtype=float)
185
+ attrs.create_dataset("Q", data=Q)
186
+ if Qaux is not None:
187
+ attrs.create_dataset("Qaux", data=Qaux)
188
+ return i_snapshot + 1.0
189
+
190
+
191
+ def get_save_fields_simple(_filepath, write_all, overwrite=True):
192
+ def _save_hdf5(i_snapshot, time, Q, Qaux):
193
+ i_snap = int(i_snapshot)
194
+ main_dir = os.getenv("ZOOMY_DIR")
195
+ filepath = os.path.join(main_dir, _filepath)
196
+
197
+ with h5py.File(filepath, "a") as f:
198
+ if i_snap == 0 and not "fields" in f.keys():
199
+ fields = f.create_group("fields")
200
+ else:
201
+ fields = f["fields"]
202
+ group_name = "iteration_" + str(i_snap)
203
+ if group_name in fields:
204
+ if overwrite:
205
+ del fields[group_name]
206
+ else:
207
+ raise ValueError(
208
+ f"Group {group_name} already exists in {filepath}")
209
+ attrs = fields.create_group(group_name)
210
+ attrs.create_dataset("time", data=time, dtype=float)
211
+ attrs.create_dataset("Q", data=Q)
212
+ if Qaux is not None:
213
+ attrs.create_dataset("Qaux", data=Qaux)
214
+ return i_snapshot + 1.0
215
+
216
+ return _save_hdf5
217
+
218
+
219
+ def _save_hdf5(_filepath, i_snapshot, time, Q, Qaux, overwrite=True):
220
+ i_snap = int(i_snapshot)
221
+ main_dir = os.getenv("ZOOMY_DIR")
222
+ filepath = os.path.join(main_dir, _filepath)
223
+
224
+ with h5py.File(filepath, "a") as f:
225
+ if i_snap == 0 and not "fields" in f.keys():
226
+ fields = f.create_group("fields")
227
+ else:
228
+ fields = f["fields"]
229
+ group_name = "iteration_" + str(i_snap)
230
+ if group_name in fields:
231
+ if overwrite:
232
+ del fields[group_name]
233
+ else:
234
+ raise ValueError(
235
+ f"Group {group_name} already exists in {filepath}")
236
+ attrs = fields.create_group(group_name)
237
+ attrs.create_dataset("time", data=time, dtype=float)
238
+ attrs.create_dataset("Q", data=Q)
239
+ if Qaux is not None:
240
+ attrs.create_dataset("Qaux", data=Qaux)
241
+ return i_snapshot + 1.0
242
+
243
+
244
+ def get_save_fields(_filepath, write_all=False, overwrite=True):
245
+ if _HAVE_H5PY:
246
+
247
+ def save(time, next_write_at, i_snapshot, Q, Qaux):
248
+ if write_all or time >= next_write_at:
249
+ return _save_hdf5(
250
+ _filepath, i_snapshot, time, Q, Qaux, overwrite=overwrite
251
+ )
252
+ else:
253
+ return i_snapshot
254
+ else:
255
+
256
+ def save(time, next_write_at, i_snapshot, Q, Qaux):
257
+ if write_all or time >= next_write_at:
258
+ return i_snapshot + 1
259
+ else:
260
+ return i_snapshot
261
+
262
+ return save
263
+
264
+
265
+ def save_fields_test(a):
266
+ filepath, time, next_write_at, i_snapshot, Q, Qaux, write_all = a
267
+ if not write_all and time < next_write_at:
268
+ return i_snapshot
269
+
270
+ _save_fields_to_hdf5(filepath, i_snapshot, time, Q, Qaux)
271
+ return i_snapshot + 1
272
+
273
+
274
+ def load_mesh_from_hdf5(filepath):
275
+ mesh = Mesh.from_hdf5(filepath)
276
+ return mesh
277
+
278
+
279
+ def load_fields_from_hdf5(filepath, i_snapshot=-1):
280
+ main_dir = os.getenv("ZOOMY_DIR")
281
+ filepath = os.path.join(main_dir, filepath)
282
+ with h5py.File(filepath, "r") as f:
283
+ fields = f["fields"]
284
+ if i_snapshot == -1:
285
+ i_snapshot = len(fields.keys()) - 1
286
+ else:
287
+ i_snapshot = i_snapshot
288
+ group = fields[f"iteration_{i_snapshot}"]
289
+ time = group["time"][()]
290
+ Q = group["Q"][()]
291
+ Qaux = group["Qaux"][()]
292
+ return Q, Qaux, time
293
+
294
+
295
+ def load_timeline_of_fields_from_hdf5(filepath):
296
+ main_dir = os.getenv("ZOOMY_DIR")
297
+ filepath = os.path.join(main_dir, filepath)
298
+ l_time = []
299
+ l_Q = []
300
+ l_Qaux = []
301
+ mesh = Mesh.from_hdf5(filepath)
302
+ with h5py.File(filepath, "r") as f:
303
+ fields = f["fields"]
304
+ n_snapshots = len(fields.keys())
305
+ for i in range(n_snapshots):
306
+ group = fields[f"iteration_{i}"]
307
+ time = group["time"][()]
308
+ Q = group["Q"][()]
309
+ Qaux = group["Qaux"][()]
310
+ l_time.append(time)
311
+ l_Q.append(Q)
312
+ l_Qaux.append(Qaux)
313
+ return mesh.cell_centers[0], np.array(l_Q), np.array(l_Qaux), np.array(l_time)
314
+
315
+
316
+ def _write_to_vtk_from_vertices_edges(
317
+ filepath,
318
+ mesh_type,
319
+ vertex_coordinates,
320
+ cell_vertices,
321
+ fields=None,
322
+ field_names=None,
323
+ point_fields=None,
324
+ point_field_names=None,
325
+ ):
326
+ if not _HAVE_MESHIO:
327
+ raise RuntimeError(
328
+ "_write_to_vtk_from_vertices_edges requires meshio, which is not available."
329
+ )
330
+ assert (
331
+ mesh_type == "triangle"
332
+ or mesh_type == "quad"
333
+ or mesh_type == "wface"
334
+ or mesh_type == "hexahedron"
335
+ or mesh_type == "line"
336
+ or mesh_type == "tetra"
337
+ )
338
+ d_fields = {}
339
+ n_inner_elements = cell_vertices.shape[0]
340
+ if fields is not None:
341
+ if field_names is None:
342
+ field_names = [str(i) for i in range(fields.shape[0])]
343
+ for i_fields, _ in enumerate(fields):
344
+ d_fields[field_names[i_fields]] = [
345
+ fields[i_fields, :n_inner_elements]]
346
+ point_d_fields = {}
347
+ if point_fields is not None:
348
+ if point_field_names is None:
349
+ point_field_names = [str(i) for i in range(point_fields.shape[0])]
350
+ for i_fields, _ in enumerate(point_fields):
351
+ point_d_fields[point_field_names[i_fields]
352
+ ] = point_fields[i_fields]
353
+ meshout = meshio.Mesh(
354
+ vertex_coordinates,
355
+ [(mesh_util.convert_mesh_type_to_meshio_mesh_type(mesh_type), cell_vertices)],
356
+ cell_data=d_fields,
357
+ point_data=point_d_fields,
358
+ )
359
+ path, filename = os.path.split(filepath)
360
+ filename_base, filename_ext = os.path.splitext(filename)
361
+ os.makedirs(path, exist_ok=True)
362
+ meshout.write(filepath + ".vtk")
363
+
364
+
365
+ def generate_vtk(
366
+ filepath: str,
367
+ field_names=None,
368
+ aux_field_names=None,
369
+ skip_aux=False,
370
+ filename="out",
371
+ warp=False,
372
+ ):
373
+ main_dir = os.getenv("ZOOMY_DIR")
374
+ abs_filepath = os.path.join(main_dir, filepath)
375
+ path = os.path.dirname(abs_filepath)
376
+ full_filepath_out = os.path.join(path, filename)
377
+ # abs_filepath = os.path.join(main_dir, filepath)
378
+ # with h5py.File(os.path.join(filepath, 'mesh'), "r") as file_mesh, h5py.File(os.path.join(filepath, 'fields'), "r") as file_fields:
379
+ file = h5py.File(os.path.join(main_dir, filepath), "r")
380
+ file_fields = file["fields"]
381
+ mesh = Mesh.from_hdf5(abs_filepath)
382
+ snapshots = list(file_fields.keys())
383
+ # init timestamp file
384
+ vtk_timestamp_file = {"file-series-version": "1.0", "files": []}
385
+
386
+ def get_iteration_from_datasetname(name):
387
+ return int(name.split("_")[1])
388
+
389
+ # write out vtk files for each timestamp
390
+ for snapshot in snapshots:
391
+ time = file_fields[snapshot]["time"][()]
392
+ Q = file_fields[snapshot]["Q"][()]
393
+
394
+ if not skip_aux:
395
+ Qaux = file_fields[snapshot]["Qaux"][()]
396
+ else:
397
+ Qaux = np.empty((Q.shape[0], 0))
398
+ output_vtk = f"{filename}.{get_iteration_from_datasetname(snapshot)}"
399
+
400
+ # TODO callout to compute pointwise data?
401
+ point_fields = None
402
+ point_field_names = None
403
+
404
+ if field_names is None:
405
+ field_names = [str(i) for i in range(Q.shape[0])]
406
+ if aux_field_names is None:
407
+ aux_field_names = ["aux_{}".format(
408
+ str(i)) for i in range(Qaux.shape[0])]
409
+
410
+ fields = np.concatenate((Q, Qaux), axis=0)
411
+ field_names = field_names + aux_field_names
412
+
413
+ vertex_coordinates_3d = np.zeros((mesh.vertex_coordinates.shape[1], 3))
414
+ vertex_coordinates_3d[:, : mesh.dimension] = mesh.vertex_coordinates.T
415
+
416
+ _write_to_vtk_from_vertices_edges(
417
+ os.path.join(path, output_vtk),
418
+ mesh.type,
419
+ vertex_coordinates_3d,
420
+ mesh.cell_vertices.T,
421
+ fields=fields,
422
+ field_names=field_names,
423
+ point_fields=point_fields,
424
+ point_field_names=point_field_names,
425
+ )
426
+
427
+ vtk_timestamp_file["files"].append(
428
+ {
429
+ "name": output_vtk + ".vtk",
430
+ "time": time,
431
+ }
432
+ )
433
+
434
+ # finalize vtk
435
+ with open(os.path.join(path, f"{full_filepath_out}.vtk.series"), "w") as f:
436
+ json.dump(vtk_timestamp_file, f)
437
+
438
+ file.close()
@@ -0,0 +1,18 @@
1
+
2
+ import os
3
+ import sys
4
+ from loguru import logger
5
+
6
+ # Remove any default handlers
7
+ logger.remove()
8
+ # Check the ZoomyLog setting
9
+ zoomy_log_mode = os.getenv("ZoomyLog", "Default")
10
+
11
+ zoomy_log_level = os.getenv("ZoomyLogLevel", "INFO")
12
+
13
+ main_dir = os.getenv("ZOOMY_DIR", os.getcwd())
14
+
15
+ if zoomy_log_mode == "Default":
16
+ logger.add(sys.stderr, level=zoomy_log_level)
17
+ else:
18
+ logger.add(os.path.join(main_dir, "logs/log.log"), rotation="1 MB", retention="10 days", compression="zip")