zoomy-core 0.1.1__py3-none-any.whl → 0.1.2__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 (57) 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/gmsh_loader.py +301 -0
  8. zoomy_core/mesh/mesh.py +1192 -0
  9. zoomy_core/mesh/mesh_extrude.py +168 -0
  10. zoomy_core/mesh/mesh_util.py +487 -0
  11. zoomy_core/misc/custom_types.py +6 -0
  12. zoomy_core/misc/gui.py +61 -0
  13. zoomy_core/misc/interpolation.py +140 -0
  14. zoomy_core/misc/io.py +401 -0
  15. zoomy_core/misc/logger_config.py +18 -0
  16. zoomy_core/misc/misc.py +216 -0
  17. zoomy_core/misc/static_class.py +94 -0
  18. zoomy_core/model/analysis.py +147 -0
  19. zoomy_core/model/basefunction.py +113 -0
  20. zoomy_core/model/basemodel.py +512 -0
  21. zoomy_core/model/boundary_conditions.py +193 -0
  22. zoomy_core/model/initial_conditions.py +171 -0
  23. zoomy_core/model/model.py +63 -0
  24. zoomy_core/model/models/GN.py +70 -0
  25. zoomy_core/model/models/advection.py +53 -0
  26. zoomy_core/model/models/basisfunctions.py +181 -0
  27. zoomy_core/model/models/basismatrices.py +377 -0
  28. zoomy_core/model/models/core.py +564 -0
  29. zoomy_core/model/models/coupled_constrained.py +60 -0
  30. zoomy_core/model/models/old_smm copy.py +867 -0
  31. zoomy_core/model/models/poisson.py +41 -0
  32. zoomy_core/model/models/shallow_moments.py +757 -0
  33. zoomy_core/model/models/shallow_moments_sediment.py +378 -0
  34. zoomy_core/model/models/shallow_moments_topo.py +423 -0
  35. zoomy_core/model/models/shallow_moments_variants.py +1509 -0
  36. zoomy_core/model/models/shallow_water.py +266 -0
  37. zoomy_core/model/models/shallow_water_topo.py +111 -0
  38. zoomy_core/model/models/shear_shallow_flow.py +594 -0
  39. zoomy_core/model/models/sme_turbulent.py +613 -0
  40. zoomy_core/model/models/swe_old.py +1018 -0
  41. zoomy_core/model/models/vam.py +455 -0
  42. zoomy_core/postprocessing/postprocessing.py +72 -0
  43. zoomy_core/preprocessing/openfoam_moments.py +452 -0
  44. zoomy_core/transformation/helpers.py +25 -0
  45. zoomy_core/transformation/to_amrex.py +238 -0
  46. zoomy_core/transformation/to_c.py +181 -0
  47. zoomy_core/transformation/to_jax.py +14 -0
  48. zoomy_core/transformation/to_numpy.py +115 -0
  49. zoomy_core/transformation/to_openfoam.py +254 -0
  50. zoomy_core/transformation/to_ufl.py +67 -0
  51. {zoomy_core-0.1.1.dist-info → zoomy_core-0.1.2.dist-info}/METADATA +1 -1
  52. zoomy_core-0.1.2.dist-info/RECORD +55 -0
  53. zoomy_core-0.1.2.dist-info/top_level.txt +1 -0
  54. zoomy_core-0.1.1.dist-info/RECORD +0 -5
  55. zoomy_core-0.1.1.dist-info/top_level.txt +0 -1
  56. {zoomy_core-0.1.1.dist-info → zoomy_core-0.1.2.dist-info}/WHEEL +0 -0
  57. {zoomy_core-0.1.1.dist-info → zoomy_core-0.1.2.dist-info}/licenses/LICENSE +0 -0
zoomy_core/misc/gui.py ADDED
@@ -0,0 +1,61 @@
1
+ # go though all files in curent directory
2
+ # check the docstring of all functions and classes in thhese files
3
+ # parse the docstring using the docstring_parser module and print out all gui tags
4
+
5
+ import os
6
+ import inspect
7
+ from docstring_parser.rest import parse
8
+ import yaml
9
+
10
+ import importlib.util
11
+
12
+
13
+ def import_module_from_path(path):
14
+ spec = importlib.util.spec_from_file_location(
15
+ os.path.splitext(os.path.basename(path))[0], path
16
+ )
17
+ module = importlib.util.module_from_spec(spec)
18
+ spec.loader.exec_module(module)
19
+ return module
20
+
21
+
22
+ # Go through all files in library
23
+ # go though all files and files of subdirectories until you find a .py file
24
+ def browse_all_gui_tags(path):
25
+ for root, dirs, files in os.walk(path):
26
+ for file in files:
27
+ get_gui_tags(os.path.join(root, file))
28
+ for dir in dirs:
29
+ browse_all_gui_tags(os.path.join(root, dir))
30
+
31
+
32
+ def get_gui_tags(path):
33
+ # Import the module
34
+ if not path.endswith(".py"):
35
+ return
36
+ try:
37
+ module = import_module_from_path(path)
38
+
39
+ # Check the docstring of all functions and classes in these files
40
+ for name, obj in inspect.getmembers(module):
41
+ if (
42
+ inspect.isfunction(obj) or inspect.isclass(obj)
43
+ ) and obj.__module__ == module.__name__:
44
+ docstring = inspect.getdoc(obj)
45
+ if docstring:
46
+ # Parse the docstring using the docstring_parser module
47
+ parsed_docstring = parse(docstring)
48
+
49
+ # Print out all 'gui' tags
50
+ for meta in parsed_docstring.meta:
51
+ if meta.args == ["gui"]:
52
+ yml = yaml.safe_load(meta.description)
53
+ print(os.path.basename(path), obj.__name__, yml)
54
+ except:
55
+ print(f"Could not import module from {path}")
56
+ pass
57
+
58
+
59
+ if __name__ == "__main__":
60
+ main_dir = os.getenv("ZOOMY_DIR")
61
+ browse_all_gui_tags(os.path.join(main_dir, "library"))
@@ -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,401 @@
1
+ import os
2
+ import numpy as np
3
+ import meshio
4
+ import json
5
+ import shutil
6
+
7
+ try:
8
+ import h5py
9
+ _HAVE_H5PY = True
10
+ except ImportError:
11
+ _HAVE_H5PY = False
12
+
13
+ # import library.zoomy_core.mesh.fvm_mesh as fvm_mesh
14
+ from library.zoomy_core.mesh.mesh import Mesh
15
+ import library.zoomy_core.mesh.mesh_util as mesh_util
16
+ from library.zoomy_core.misc.misc import Zstruct, Settings
17
+ from library.zoomy_core.misc.logger_config import logger
18
+
19
+
20
+
21
+ def init_output_directory(path, clean):
22
+ main_dir = os.getenv("ZOOMY_DIR")
23
+ path = os.path.join(main_dir, path)
24
+ os.makedirs(path, exist_ok=True)
25
+ if clean:
26
+ filelist = [f for f in os.listdir(path)]
27
+ for f in filelist:
28
+ if os.path.isdir(os.path.join(path, f)):
29
+ shutil.rmtree(os.path.join(path, f))
30
+ else:
31
+ os.remove(os.path.join(path, f))
32
+
33
+ def get_hdf5_type(value):
34
+ out = type(value)
35
+ if isinstance(value, str):
36
+ out = h5py.string_dtype()
37
+ return out
38
+
39
+ def write_dict_to_hdf5(group, d):
40
+ for key, value in d.items():
41
+ if isinstance(value, dict):
42
+ subgroup = group.create_group(key)
43
+ write_dict_to_hdf5(subgroup, value)
44
+ elif isinstance(value, (str, int, float, bool)):
45
+ group.create_dataset(key, data=value, dtype=get_hdf5_type(value))
46
+ elif isinstance(value, (list, tuple)):
47
+ group.create_dataset(key, data=value)
48
+ elif isinstance(value, type(np.ndarray)):
49
+ group.create_dataset(key, data=value)
50
+ elif hasattr(value, "as_dict"):
51
+ subgroup = group.create_group(key)
52
+ write_dict_to_hdf5(subgroup, value.as_dict())
53
+ else:
54
+ logger.warning(f"Skipping unsupported type for key: {key} -> {type(value)}")
55
+
56
+ def load_hdf5_to_dict(group):
57
+ d = {}
58
+ for key, value in group.items():
59
+ if isinstance(value, h5py.Group):
60
+ d[key] = load_hdf5_to_dict(value)
61
+ elif isinstance(value, h5py.Dataset):
62
+ if value.dtype == h5py.string_dtype():
63
+ d[key] = value[()].decode('utf-8')
64
+ else:
65
+ d[key] = value[()]
66
+ else:
67
+ logger.warning(f"Skipping unsupported type for key: {key} -> {type(value)}")
68
+
69
+ return d
70
+
71
+
72
+ def save_settings(settings):
73
+ main_dir = os.getenv("ZOOMY_DIR")
74
+ filepath = os.path.join(main_dir, settings.output.directory)
75
+ with h5py.File(os.path.join(filepath, "settings.h5"), "w") as f:
76
+ write_dict_to_hdf5(f, settings.as_dict(recursive=True))
77
+
78
+ def load_settings(filepath):
79
+ main_dir = os.getenv("ZOOMY_DIR")
80
+ filepath = os.path.join(main_dir, filepath)
81
+ with h5py.File(os.path.join(filepath, "settings.h5"), "r") as f:
82
+ d = load_hdf5_to_dict(f)
83
+
84
+ settings = Settings.from_dict(d)
85
+ return settings
86
+
87
+ def load_settings2(filepath):
88
+ main_dir = os.getenv("ZOOMY_DIR")
89
+ filepath = os.path.join(main_dir, filepath)
90
+ with h5py.File(os.path.join(filepath, "settings.h5"), "r") as f:
91
+ model = f["model"]
92
+ solver = f["solver"]
93
+ output = f["output"]
94
+
95
+ d_model = {}
96
+ if 'parameters' in model:
97
+ parameters = {k: v[()] for k, v in model["parameters"].items()}
98
+ parameters = Zstruct(**parameters)
99
+ for k in model.keys():
100
+ if k != 'parameters':
101
+ v = model[k][()]
102
+ if isinstance(v, (str, int, float, bool)):
103
+ d_model[k] = v
104
+ else:
105
+ raise ValueError(f"Unsupported type for model attribute {k}: {type(v)}")
106
+ d_model['parameters'] = parameters
107
+ model = Zstruct(**d_model)
108
+ d_solver = {}
109
+ for k in solver.keys():
110
+ v = solver[k][()]
111
+ if isinstance(v, (str, int, float, bool)):
112
+ d_solver[k] = v
113
+ else:
114
+ raise ValueError(f"Unsupported type for solver attribute {k}: {type(v)}")
115
+ solver = Zstruct(**d_solver)
116
+
117
+ d_output = {}
118
+ for k in output.keys():
119
+ v = output[k][()]
120
+ if isinstance(v, (str, int, float, bool)):
121
+ d_output[k] = v
122
+ else:
123
+ raise ValueError(f"Unsupported type for output attribute {k}: {type(v)}")
124
+ output = Zstruct(**d_output)
125
+
126
+ settings = Settings(model=model, solver=solver, output=output)
127
+
128
+
129
+ # parameters = {k: v[()] for k, v in f["parameters"].items()}
130
+ # name = f["name"][()]
131
+ # output_dir = f["output_dir"][()]
132
+ # output_snapshots = f["output_snapshots"][()]
133
+ # output_write_all = f["output_write_all"][()]
134
+ # output_clean_dir = f["output_clean_dir"][()]
135
+ # truncate_last_time_step = f["truncate_last_time_step"][()]
136
+ callbacks = f["callbacks"][()]
137
+ return settings
138
+
139
+
140
+ def clean_files(filepath, filename=".vtk"):
141
+ main_dir = os.getenv("ZOOMY_DIR")
142
+ abs_filepath = os.path.join(main_dir, filepath)
143
+ if os.path.exists(abs_filepath):
144
+ for file in os.listdir(abs_filepath):
145
+ if file.endswith(filename):
146
+ os.remove(os.path.join(abs_filepath, file))
147
+
148
+
149
+ def _save_fields_to_hdf5(filepath, i_snapshot, time, Q, Qaux=None, overwrite=True):
150
+ i_snap = int(i_snapshot)
151
+ main_dir = os.getenv("ZOOMY_DIR")
152
+ filepath = os.path.join(main_dir, filepath)
153
+ with h5py.File(filepath, "a") as f:
154
+ if i_snap == 0 and not "fields" in f.keys():
155
+ fields = f.create_group("fields")
156
+ else:
157
+ fields = f["fields"]
158
+ group_name = "iteration_" + str(i_snap)
159
+ if group_name in fields:
160
+ if overwrite:
161
+ del fields[group_name]
162
+ else:
163
+ raise ValueError(f"Group {group_name} already exists in {filepath}")
164
+ attrs = fields.create_group(group_name)
165
+ attrs.create_dataset("time", data=time, dtype=float)
166
+ attrs.create_dataset("Q", data=Q)
167
+ if Qaux is not None:
168
+ attrs.create_dataset("Qaux", data=Qaux)
169
+ return i_snapshot + 1.0
170
+
171
+ def get_save_fields_simple(_filepath, write_all, overwrite=True):
172
+ def _save_hdf5(i_snapshot, time, Q, Qaux):
173
+ i_snap = int(i_snapshot)
174
+ main_dir = os.getenv("ZOOMY_DIR")
175
+ filepath = os.path.join(main_dir, _filepath)
176
+
177
+ with h5py.File(filepath, "a") as f:
178
+ if i_snap == 0 and not "fields" in f.keys():
179
+ fields = f.create_group("fields")
180
+ else:
181
+ fields = f["fields"]
182
+ group_name = "iteration_" + str(i_snap)
183
+ if group_name in fields:
184
+ if overwrite:
185
+ del fields[group_name]
186
+ else:
187
+ raise ValueError(f"Group {group_name} already exists in {filepath}")
188
+ attrs = fields.create_group(group_name)
189
+ attrs.create_dataset("time", data=time, dtype=float)
190
+ attrs.create_dataset("Q", data=Q)
191
+ if Qaux is not None:
192
+ attrs.create_dataset("Qaux", data=Qaux)
193
+ return i_snapshot + 1.0
194
+ return _save_hdf5
195
+
196
+ def _save_hdf5(_filepath, i_snapshot, time, Q, Qaux, overwrite=True):
197
+ i_snap = int(i_snapshot)
198
+ main_dir = os.getenv("ZOOMY_DIR")
199
+ filepath = os.path.join(main_dir, _filepath)
200
+
201
+ with h5py.File(filepath, "a") as f:
202
+ if i_snap == 0 and not "fields" in f.keys():
203
+ fields = f.create_group("fields")
204
+ else:
205
+ fields = f["fields"]
206
+ group_name = "iteration_" + str(i_snap)
207
+ if group_name in fields:
208
+ if overwrite:
209
+ del fields[group_name]
210
+ else:
211
+ raise ValueError(f"Group {group_name} already exists in {filepath}")
212
+ attrs = fields.create_group(group_name)
213
+ attrs.create_dataset("time", data=time, dtype=float)
214
+ attrs.create_dataset("Q", data=Q)
215
+ if Qaux is not None:
216
+ attrs.create_dataset("Qaux", data=Qaux)
217
+ return i_snapshot + 1.0
218
+
219
+ def get_save_fields(_filepath, write_all=False, overwrite=True):
220
+ if _HAVE_H5PY:
221
+ def save(time, next_write_at, i_snapshot, Q, Qaux):
222
+ if write_all or time >= next_write_at:
223
+ return _save_hdf5(_filepath, i_snapshot, time, Q, Qaux, overwrite=overwrite)
224
+ else:
225
+ return i_snapshot
226
+ else:
227
+ def save(time, next_write_at, i_snapshot, Q, Qaux):
228
+ if write_all or time >= next_write_at:
229
+ return i_snapshot + 1
230
+ else:
231
+ return i_snapshot
232
+ return save
233
+
234
+
235
+ def save_fields_test(a):
236
+ filepath, time, next_write_at, i_snapshot, Q, Qaux, write_all = a
237
+ if not write_all and time < next_write_at:
238
+ return i_snapshot
239
+
240
+ _save_fields_to_hdf5(filepath, i_snapshot, time, Q, Qaux)
241
+ return i_snapshot + 1
242
+
243
+ def load_mesh_from_hdf5(filepath):
244
+ mesh = Mesh.from_hdf5(filepath)
245
+ return mesh
246
+
247
+
248
+ def load_fields_from_hdf5(filepath, i_snapshot=-1):
249
+ main_dir = os.getenv("ZOOMY_DIR")
250
+ filepath = os.path.join(main_dir, filepath)
251
+ with h5py.File(filepath, "r") as f:
252
+ fields = f["fields"]
253
+ if i_snapshot == -1:
254
+ i_snapshot = len(fields.keys()) - 1
255
+ else:
256
+ i_snapshot = i_snapshot
257
+ group = fields[f"iteration_{i_snapshot}"]
258
+ time = group["time"][()]
259
+ Q = group["Q"][()]
260
+ Qaux = group["Qaux"][()]
261
+ return Q, Qaux, time
262
+
263
+
264
+ def load_timeline_of_fields_from_hdf5(filepath):
265
+ main_dir = os.getenv("ZOOMY_DIR")
266
+ filepath = os.path.join(main_dir, filepath)
267
+ l_time = []
268
+ l_Q = []
269
+ l_Qaux = []
270
+ mesh = Mesh.from_hdf5(filepath)
271
+ with h5py.File(filepath, "r") as f:
272
+ fields = f["fields"]
273
+ n_snapshots = len(fields.keys())
274
+ for i in range(n_snapshots):
275
+ group = fields[f"iteration_{i}"]
276
+ time = group["time"][()]
277
+ Q = group["Q"][()]
278
+ Qaux = group["Qaux"][()]
279
+ l_time.append(time)
280
+ l_Q.append(Q)
281
+ l_Qaux.append(Qaux)
282
+ return mesh.cell_centers[0], np.array(l_Q), np.array(l_Qaux), np.array(l_time)
283
+
284
+
285
+ def _write_to_vtk_from_vertices_edges(
286
+ filepath,
287
+ mesh_type,
288
+ vertex_coordinates,
289
+ cell_vertices,
290
+ fields=None,
291
+ field_names=None,
292
+ point_fields=None,
293
+ point_field_names=None,
294
+ ):
295
+ assert (
296
+ mesh_type == "triangle"
297
+ or mesh_type == "quad"
298
+ or mesh_type == "wface"
299
+ or mesh_type == "hexahedron"
300
+ or mesh_type == "line"
301
+ or mesh_type == "tetra"
302
+ )
303
+ d_fields = {}
304
+ n_inner_elements = cell_vertices.shape[0]
305
+ if fields is not None:
306
+ if field_names is None:
307
+ field_names = [str(i) for i in range(fields.shape[0])]
308
+ for i_fields, _ in enumerate(fields):
309
+ d_fields[field_names[i_fields]] = [fields[i_fields, :n_inner_elements]]
310
+ point_d_fields = {}
311
+ if point_fields is not None:
312
+ if point_field_names is None:
313
+ point_field_names = [str(i) for i in range(point_fields.shape[0])]
314
+ for i_fields, _ in enumerate(point_fields):
315
+ point_d_fields[point_field_names[i_fields]] = point_fields[i_fields]
316
+ meshout = meshio.Mesh(
317
+ vertex_coordinates,
318
+ [(mesh_util.convert_mesh_type_to_meshio_mesh_type(mesh_type), cell_vertices)],
319
+ cell_data=d_fields,
320
+ point_data=point_d_fields,
321
+ )
322
+ path, filename = os.path.split(filepath)
323
+ filename_base, filename_ext = os.path.splitext(filename)
324
+ os.makedirs(path, exist_ok=True)
325
+ meshout.write(filepath + ".vtk")
326
+
327
+
328
+ def generate_vtk(
329
+ filepath: str,
330
+ field_names=None,
331
+ aux_field_names=None,
332
+ skip_aux=False,
333
+ filename="out",
334
+ warp=False
335
+ ):
336
+ main_dir = os.getenv("ZOOMY_DIR")
337
+ abs_filepath = os.path.join(main_dir, filepath)
338
+ path = os.path.dirname(abs_filepath)
339
+ full_filepath_out = os.path.join(path, filename)
340
+ # abs_filepath = os.path.join(main_dir, filepath)
341
+ # with h5py.File(os.path.join(filepath, 'mesh'), "r") as file_mesh, h5py.File(os.path.join(filepath, 'fields'), "r") as file_fields:
342
+ file = h5py.File(os.path.join(main_dir, filepath), "r")
343
+ file_fields = file["fields"]
344
+ mesh = Mesh.from_hdf5(abs_filepath)
345
+ snapshots = list(file_fields.keys())
346
+ # init timestamp file
347
+ vtk_timestamp_file = {"file-series-version": "1.0", "files": []}
348
+
349
+ def get_iteration_from_datasetname(name):
350
+ return int(name.split("_")[1])
351
+
352
+ # write out vtk files for each timestamp
353
+ for snapshot in snapshots:
354
+ time = file_fields[snapshot]["time"][()]
355
+ Q = file_fields[snapshot]["Q"][()]
356
+
357
+ if not skip_aux:
358
+ Qaux = file_fields[snapshot]["Qaux"][()]
359
+ else:
360
+ Qaux = np.empty((Q.shape[0], 0))
361
+ output_vtk = f"{filename}.{get_iteration_from_datasetname(snapshot)}"
362
+
363
+ # TODO callout to compute pointwise data?
364
+ point_fields = None
365
+ point_field_names = None
366
+
367
+ if field_names is None:
368
+ field_names = [str(i) for i in range(Q.shape[0])]
369
+ if aux_field_names is None:
370
+ aux_field_names = ["aux_{}".format(str(i)) for i in range(Qaux.shape[0])]
371
+
372
+ fields = np.concatenate((Q, Qaux), axis=0)
373
+ field_names = field_names + aux_field_names
374
+
375
+ vertex_coordinates_3d = np.zeros((mesh.vertex_coordinates.shape[1], 3))
376
+ vertex_coordinates_3d[:, : mesh.dimension] = mesh.vertex_coordinates.T
377
+
378
+
379
+ _write_to_vtk_from_vertices_edges(
380
+ os.path.join(path, output_vtk),
381
+ mesh.type,
382
+ vertex_coordinates_3d,
383
+ mesh.cell_vertices.T,
384
+ fields=fields,
385
+ field_names=field_names,
386
+ point_fields=point_fields,
387
+ point_field_names=point_field_names,
388
+ )
389
+
390
+ vtk_timestamp_file["files"].append(
391
+ {
392
+ "name": output_vtk + ".vtk",
393
+ "time": time,
394
+ }
395
+ )
396
+
397
+ # finalize vtk
398
+ with open(os.path.join(path, f"{full_filepath_out}.vtk.series"), "w") as f:
399
+ json.dump(vtk_timestamp_file, f)
400
+
401
+ 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")