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.
- zoomy_core/decorators/decorators.py +25 -0
- zoomy_core/fvm/flux.py +97 -0
- zoomy_core/fvm/nonconservative_flux.py +97 -0
- zoomy_core/fvm/ode.py +55 -0
- zoomy_core/fvm/solver_numpy.py +305 -0
- zoomy_core/fvm/timestepping.py +13 -0
- zoomy_core/mesh/gmsh_loader.py +301 -0
- zoomy_core/mesh/mesh.py +1192 -0
- zoomy_core/mesh/mesh_extrude.py +168 -0
- zoomy_core/mesh/mesh_util.py +487 -0
- zoomy_core/misc/custom_types.py +6 -0
- zoomy_core/misc/gui.py +61 -0
- zoomy_core/misc/interpolation.py +140 -0
- zoomy_core/misc/io.py +401 -0
- zoomy_core/misc/logger_config.py +18 -0
- zoomy_core/misc/misc.py +216 -0
- zoomy_core/misc/static_class.py +94 -0
- zoomy_core/model/analysis.py +147 -0
- zoomy_core/model/basefunction.py +113 -0
- zoomy_core/model/basemodel.py +512 -0
- zoomy_core/model/boundary_conditions.py +193 -0
- zoomy_core/model/initial_conditions.py +171 -0
- zoomy_core/model/model.py +63 -0
- zoomy_core/model/models/GN.py +70 -0
- zoomy_core/model/models/advection.py +53 -0
- zoomy_core/model/models/basisfunctions.py +181 -0
- zoomy_core/model/models/basismatrices.py +377 -0
- zoomy_core/model/models/core.py +564 -0
- zoomy_core/model/models/coupled_constrained.py +60 -0
- zoomy_core/model/models/old_smm copy.py +867 -0
- zoomy_core/model/models/poisson.py +41 -0
- zoomy_core/model/models/shallow_moments.py +757 -0
- zoomy_core/model/models/shallow_moments_sediment.py +378 -0
- zoomy_core/model/models/shallow_moments_topo.py +423 -0
- zoomy_core/model/models/shallow_moments_variants.py +1509 -0
- zoomy_core/model/models/shallow_water.py +266 -0
- zoomy_core/model/models/shallow_water_topo.py +111 -0
- zoomy_core/model/models/shear_shallow_flow.py +594 -0
- zoomy_core/model/models/sme_turbulent.py +613 -0
- zoomy_core/model/models/swe_old.py +1018 -0
- zoomy_core/model/models/vam.py +455 -0
- zoomy_core/postprocessing/postprocessing.py +72 -0
- zoomy_core/preprocessing/openfoam_moments.py +452 -0
- zoomy_core/transformation/helpers.py +25 -0
- zoomy_core/transformation/to_amrex.py +238 -0
- zoomy_core/transformation/to_c.py +181 -0
- zoomy_core/transformation/to_jax.py +14 -0
- zoomy_core/transformation/to_numpy.py +115 -0
- zoomy_core/transformation/to_openfoam.py +254 -0
- zoomy_core/transformation/to_ufl.py +67 -0
- {zoomy_core-0.1.1.dist-info → zoomy_core-0.1.2.dist-info}/METADATA +1 -1
- zoomy_core-0.1.2.dist-info/RECORD +55 -0
- zoomy_core-0.1.2.dist-info/top_level.txt +1 -0
- zoomy_core-0.1.1.dist-info/RECORD +0 -5
- zoomy_core-0.1.1.dist-info/top_level.txt +0 -1
- {zoomy_core-0.1.1.dist-info → zoomy_core-0.1.2.dist-info}/WHEEL +0 -0
- {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")
|