zoomy-core 0.1.11__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/__init__.py +7 -0
- zoomy_core/decorators/decorators.py +25 -0
- zoomy_core/fvm/flux.py +52 -0
- zoomy_core/fvm/nonconservative_flux.py +97 -0
- zoomy_core/fvm/ode.py +55 -0
- zoomy_core/fvm/solver_numpy.py +297 -0
- zoomy_core/fvm/timestepping.py +13 -0
- zoomy_core/mesh/mesh.py +1236 -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/interpolation.py +140 -0
- zoomy_core/misc/io.py +439 -0
- zoomy_core/misc/logger_config.py +18 -0
- zoomy_core/misc/misc.py +213 -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/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/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.11.dist-info/METADATA +225 -0
- zoomy_core-0.1.11.dist-info/RECORD +51 -0
- zoomy_core-0.1.11.dist-info/WHEEL +5 -0
- zoomy_core-0.1.11.dist-info/licenses/LICENSE +674 -0
- zoomy_core-0.1.11.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
try:
|
|
2
|
+
_HAVE_MATPLOTLIB = True
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
except ImportError:
|
|
5
|
+
_HAVE_MATPLOTLIB = False
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
from copy import deepcopy
|
|
9
|
+
import os
|
|
10
|
+
from scipy.spatial import KDTree
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
import pyvista as pv
|
|
14
|
+
|
|
15
|
+
_HAVE_PYVISTA = True
|
|
16
|
+
except ImportError:
|
|
17
|
+
_HAVE_PYVISTA = False
|
|
18
|
+
|
|
19
|
+
from zoomy_core.mesh.fvm_mesh import Mesh
|
|
20
|
+
from zoomy_core.misc.io import _save_fields_to_hdf5 as save_fields_to_hdf5
|
|
21
|
+
import zoomy_core.misc.io as io
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
main_dir = os.getenv("ZOOMY_DIR")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def load_file(filename):
|
|
28
|
+
if not _HAVE_PYVISTA:
|
|
29
|
+
raise ImportError("pyvista is required for load_file function.")
|
|
30
|
+
reader = pv.get_reader(filename)
|
|
31
|
+
# get(0) gets us the internal (not boundary) data. The boundary data is non-existant anyways in our case
|
|
32
|
+
vtkfile = reader.read().get(0)
|
|
33
|
+
return vtkfile
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_fields(vtkfile, fieldnames):
|
|
37
|
+
fields = []
|
|
38
|
+
for fieldname in fieldnames:
|
|
39
|
+
# point field)s
|
|
40
|
+
# field = vtkfile.point_data[fieldname]
|
|
41
|
+
field = vtkfile.cell_data[fieldname]
|
|
42
|
+
fields.append(np.array(field))
|
|
43
|
+
return fields
|
|
44
|
+
# return np.array(fields)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def get_coordinates(vtkfile):
|
|
48
|
+
# point coordinates
|
|
49
|
+
# return np.array(vtkfile.points)
|
|
50
|
+
# cell centers
|
|
51
|
+
return vtkfile.cell_centers().points
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def get_time(vtkfile):
|
|
55
|
+
return vtkfile.field_data["TimeValue"][0]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def sort_data(coordinates, fields):
|
|
59
|
+
# Sort by z, y, x
|
|
60
|
+
order = np.lexsort((coordinates[:, 0], coordinates[:, 1], coordinates[:, 2]))
|
|
61
|
+
return order
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def apply_order(coordinates, fields, order):
|
|
65
|
+
coordinates_copy = np.array(coordinates)
|
|
66
|
+
fields_copy = deepcopy(fields)
|
|
67
|
+
for d in range(coordinates.shape[1]):
|
|
68
|
+
coordinates[:, d] = coordinates_copy[order, d]
|
|
69
|
+
for field, field_copy in zip(fields, fields_copy):
|
|
70
|
+
field[:] = field_copy[order]
|
|
71
|
+
return coordinates, fields
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_number_of_layers_and_elements_in_plane(coordinates):
|
|
75
|
+
layers = len(np.unique(coordinates[:, 2]))
|
|
76
|
+
n_elements_plane = int(coordinates[:, 0].size / layers)
|
|
77
|
+
return layers, n_elements_plane
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def get_layer(data, layer, n_elements_plane):
|
|
81
|
+
return data[layer * n_elements_plane : (layer + 1) * n_elements_plane]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def compute_height(
|
|
85
|
+
alpha, n_layers, n_elements_per_layer, total_height=1.0, threshold=0.5
|
|
86
|
+
):
|
|
87
|
+
height = np.zeros(n_elements_per_layer)
|
|
88
|
+
active = np.ones(n_elements_per_layer, dtype=bool)
|
|
89
|
+
dh = total_height / n_layers
|
|
90
|
+
for i in range(n_layers):
|
|
91
|
+
alpha_layer = get_layer(alpha, i, n_elements_per_layer)
|
|
92
|
+
height += np.where(np.logical_and((alpha_layer >= threshold), active), dh, 0)
|
|
93
|
+
return height
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def extract_faces(mesh):
|
|
97
|
+
faces = []
|
|
98
|
+
i, offset = 0, 0
|
|
99
|
+
cc = mesh.cells # fetch up front
|
|
100
|
+
while i < mesh.n_cells:
|
|
101
|
+
nn = cc[offset]
|
|
102
|
+
faces.append(cc[offset + 1 : offset + 1 + nn])
|
|
103
|
+
offset += nn + 1
|
|
104
|
+
i += 1
|
|
105
|
+
return np.array(faces)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def sort_faces(faces, order):
|
|
109
|
+
for face in faces:
|
|
110
|
+
for i, point in enumerate(face):
|
|
111
|
+
face[i] = order[point]
|
|
112
|
+
faces = faces[order]
|
|
113
|
+
return faces
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def add_noslip_layer(U, n_elements_per_layer):
|
|
117
|
+
Unew = np.zeros((U.shape[0] + n_elements_per_layer, U.shape[1]))
|
|
118
|
+
for d in range(U.shape[1]):
|
|
119
|
+
Unew[n_elements_per_layer:, d] = U[:, d]
|
|
120
|
+
return Unew
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def extract_velocity_column_at_coordinate(U, n_elements_per_layer, n_layer, coordinate):
|
|
124
|
+
u = np.array(
|
|
125
|
+
[
|
|
126
|
+
get_layer(U[:, 0], i, n_elements_per_layer)[coordinate]
|
|
127
|
+
for i in range(n_layer + 1)
|
|
128
|
+
]
|
|
129
|
+
)
|
|
130
|
+
v = np.array(
|
|
131
|
+
[
|
|
132
|
+
get_layer(U[:, 1], i, n_elements_per_layer)[coordinate]
|
|
133
|
+
for i in range(n_layer + 1)
|
|
134
|
+
]
|
|
135
|
+
)
|
|
136
|
+
w = np.array(
|
|
137
|
+
[
|
|
138
|
+
get_layer(U[:, 2], i, n_elements_per_layer)[coordinate]
|
|
139
|
+
for i in range(n_layer + 1)
|
|
140
|
+
]
|
|
141
|
+
)
|
|
142
|
+
return u, v, w
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def shift_integration_interval(xi):
|
|
146
|
+
return (xi + 1) / 2
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def plot_basis(basis_generator):
|
|
150
|
+
fig, ax = plt.subplots()
|
|
151
|
+
basis = [basis_generator(n) for n in range(0, 8)]
|
|
152
|
+
X = np.linspace(0, 1, 100)
|
|
153
|
+
for i in range(8):
|
|
154
|
+
ax.plot(basis[i](X), X)
|
|
155
|
+
return fig, ax
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def moment_projection(field, n_layers, basis, integration_order=None):
|
|
159
|
+
if integration_order is None:
|
|
160
|
+
integration_order = max(len(basis), n_layers)
|
|
161
|
+
xi, wi = np.polynomial.legendre.leggauss(integration_order)
|
|
162
|
+
xi = shift_integration_interval(xi)
|
|
163
|
+
dz = 1 / (n_layers)
|
|
164
|
+
xp = np.arange(dz / 2, 1 - dz / 2, dz)
|
|
165
|
+
xp = np.insert(xp, 0, 0)
|
|
166
|
+
fp = field
|
|
167
|
+
field_xi = np.interp(xi, xp, fp)
|
|
168
|
+
basis_xi = [basis[i](xi) for i in range(len(basis))]
|
|
169
|
+
projections = np.zeros(len(basis))
|
|
170
|
+
for i in range(len(basis)):
|
|
171
|
+
projections[i] = np.sum(field_xi * basis_xi[i] * wi)
|
|
172
|
+
return projections
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def convert_openfoam_to_moments_single(filename, n_levels):
|
|
176
|
+
vtkfile = load_file(filename)
|
|
177
|
+
coordinates = get_coordinates(vtkfile)
|
|
178
|
+
n_layer, n_elements_per_layer = get_number_of_layers_and_elements_in_plane(
|
|
179
|
+
coordinates
|
|
180
|
+
)
|
|
181
|
+
fields = get_fields(vtkfile, ["alpha.water", "U"])
|
|
182
|
+
sort_order = sort_data(coordinates, fields)
|
|
183
|
+
coordinates, fields = apply_order(coordinates, fields, sort_order)
|
|
184
|
+
fields[1] = add_noslip_layer(fields[1], n_elements_per_layer)
|
|
185
|
+
time = get_time(vtkfile)
|
|
186
|
+
Q, basis = compute_shallow_moment_projection(fields, coordinates, n_levels)
|
|
187
|
+
return coordinates, Q, time, basis
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def convert_openfoam_to_moments(
|
|
191
|
+
filepath, n_levels, filepath_mesh_for_order, meshtype_order="triganle"
|
|
192
|
+
):
|
|
193
|
+
filepath_vtk = os.path.join(filepath, "VTK")
|
|
194
|
+
filename = "fields_openfoam.hdf5"
|
|
195
|
+
sort_order = None
|
|
196
|
+
|
|
197
|
+
# file order
|
|
198
|
+
file_number_list = []
|
|
199
|
+
file_start = ""
|
|
200
|
+
for i_file, file in enumerate(os.listdir(filepath_vtk)):
|
|
201
|
+
if file.endswith(".vtm"):
|
|
202
|
+
file_start = file.split("_")[0]
|
|
203
|
+
file_start = file.rsplit("_", 1)[0]
|
|
204
|
+
index = int(file.rsplit("_", 1)[1].split(".")[0])
|
|
205
|
+
# index = int(re.findall(r'\d+', file)[-1])
|
|
206
|
+
file_number_list.append(index)
|
|
207
|
+
|
|
208
|
+
file_number_list.sort()
|
|
209
|
+
print(file_number_list)
|
|
210
|
+
|
|
211
|
+
# first iteration
|
|
212
|
+
file0 = (
|
|
213
|
+
os.path.join(filepath_vtk, file_start) + "_" + str(file_number_list[0]) + ".vtm"
|
|
214
|
+
)
|
|
215
|
+
coordinates, Q, time, basis = convert_openfoam_to_moments_single(file0, n_levels)
|
|
216
|
+
mesh_order = Mesh.load_gmsh(filepath_mesh_for_order, meshtype_order)
|
|
217
|
+
Q, sort_order = sort_fields_by_mesh(mesh_order, coordinates, Q)
|
|
218
|
+
if os.path.exists(os.path.join(filepath, filename)):
|
|
219
|
+
os.remove(os.path.join(filepath, filename))
|
|
220
|
+
save_fields_to_hdf5(filepath, 0, time, Q.T, Qaux=None, filename=filename)
|
|
221
|
+
|
|
222
|
+
# loop iterations
|
|
223
|
+
iter = 1
|
|
224
|
+
total = len(file_number_list)
|
|
225
|
+
print(f"Conversion {iter}/{total} completed.")
|
|
226
|
+
iter += 1
|
|
227
|
+
# loop iterations
|
|
228
|
+
for i, i_file in enumerate(file_number_list[1:]):
|
|
229
|
+
file = os.path.join(filepath_vtk, file_start) + "_" + str(i_file) + ".vtm"
|
|
230
|
+
coordinates, Q, time, basis = convert_openfoam_to_moments_single(file, n_levels)
|
|
231
|
+
Q = apply_order_to_fields(sort_order, Q)
|
|
232
|
+
save_fields_to_hdf5(filepath, i + 1, time, Q.T, Qaux=None, filename=filename)
|
|
233
|
+
print(f"Conversion {iter}/{total} completed.")
|
|
234
|
+
iter += 1
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def sort_fields_by_mesh(mesh, coordinates, Q):
|
|
238
|
+
# coordinates are still 3d, while Q is 2d and the mesh is 2d
|
|
239
|
+
n_layers, n_elements_per_layer = get_number_of_layers_and_elements_in_plane(
|
|
240
|
+
coordinates
|
|
241
|
+
)
|
|
242
|
+
coords_2d = coordinates[:n_elements_per_layer, :2]
|
|
243
|
+
coords_ordered = mesh.element_center
|
|
244
|
+
# Construct a KDTree from coords_2d
|
|
245
|
+
tree = KDTree(coords_2d)
|
|
246
|
+
|
|
247
|
+
# Find the indices of the nearest points in coords_2d to the points in coords_ordered
|
|
248
|
+
_, indices = tree.query(coords_ordered)
|
|
249
|
+
|
|
250
|
+
# Use these indices to sort Q and coords_2d
|
|
251
|
+
Q_sorted = Q[:, indices]
|
|
252
|
+
return Q_sorted, indices
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def apply_order_to_fields(order, Q):
|
|
256
|
+
return Q[:, order]
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def plot_contour(coordinates, field):
|
|
260
|
+
if not _HAVE_MATPLOTLIB:
|
|
261
|
+
raise ImportError("matplotlib is required for plot_contour function.")
|
|
262
|
+
fig, ax = plt.subplots()
|
|
263
|
+
n_layer, n_elements_per_layer = get_number_of_layers_and_elements_in_plane(
|
|
264
|
+
coordinates
|
|
265
|
+
)
|
|
266
|
+
X = get_layer(coordinates[:, 0], 0, n_elements_per_layer)
|
|
267
|
+
Y = get_layer(coordinates[:, 1], 0, n_elements_per_layer)
|
|
268
|
+
# Z = get_layer(fields[1][:, 0], 1, n_elements_per_layer)
|
|
269
|
+
# Z = get_layer(fields[0], 12, n_elements_per_layer)
|
|
270
|
+
# Z = compute_height(fields[0], n_layer, n_elements_per_layer)
|
|
271
|
+
Z = field
|
|
272
|
+
colorbar = ax.tricontourf(X, Y, Z)
|
|
273
|
+
ax.set_aspect("equal")
|
|
274
|
+
|
|
275
|
+
circle = plt.Circle((0.5, 1), radius=0.2, fc="silver", zorder=10, edgecolor="k")
|
|
276
|
+
plt.gca().add_patch(circle)
|
|
277
|
+
fig.colorbar(colorbar)
|
|
278
|
+
return fig, ax
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def basis_legendre(i):
|
|
282
|
+
def f(x):
|
|
283
|
+
basis = np.polynomial.legendre.Legendre.basis(i, domain=[0, 1], window=[-1, 1])
|
|
284
|
+
return basis(x) * basis(0)
|
|
285
|
+
|
|
286
|
+
return f
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def compute_shallow_moment_projection(
|
|
290
|
+
fields, coordinates, n_levels, basis_generator=basis_legendre
|
|
291
|
+
):
|
|
292
|
+
n_layers, n_elements_per_layer = get_number_of_layers_and_elements_in_plane(
|
|
293
|
+
coordinates
|
|
294
|
+
)
|
|
295
|
+
height = compute_height(fields[0], n_layers, n_elements_per_layer)
|
|
296
|
+
basis = [basis_generator(n) for n in range(0, n_levels + 1)]
|
|
297
|
+
alphas = np.zeros((n_elements_per_layer, n_levels + 1))
|
|
298
|
+
betas = np.zeros((n_elements_per_layer, n_levels + 1))
|
|
299
|
+
for i in range(n_elements_per_layer):
|
|
300
|
+
u, v, w = extract_velocity_column_at_coordinate(
|
|
301
|
+
fields[1], n_elements_per_layer, n_layers, i
|
|
302
|
+
)
|
|
303
|
+
alphas[i] = moment_projection(u, n_layers + 1, basis)
|
|
304
|
+
betas[i] = moment_projection(v, n_layers + 1, basis)
|
|
305
|
+
return np.concatenate(
|
|
306
|
+
(height.reshape((n_elements_per_layer, 1)), alphas, betas), axis=1
|
|
307
|
+
).T, basis
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def plot_data_vs_moments(fields, coordinates, Q, basis, coordinate_index):
|
|
311
|
+
if _HAVE_MATPLOTLIB is False:
|
|
312
|
+
raise ImportError("matplotlib is required for plot_data_vs_moments function.")
|
|
313
|
+
n_layers, n_elements_per_layer = get_number_of_layers_and_elements_in_plane(
|
|
314
|
+
coordinates
|
|
315
|
+
)
|
|
316
|
+
n_levels = int((Q.shape[0] - 1) / 2) - 1
|
|
317
|
+
X = np.linspace(0, 1, 100)
|
|
318
|
+
U = np.array(
|
|
319
|
+
[basis[i](X) * Q[1 + i, coordinate_index] for i in range(len(basis))]
|
|
320
|
+
).sum(axis=0)
|
|
321
|
+
V = np.array(
|
|
322
|
+
[
|
|
323
|
+
basis[i](X) * Q[1 + n_levels + 1 + i, coordinate_index]
|
|
324
|
+
for i in range(len(basis))
|
|
325
|
+
]
|
|
326
|
+
).sum(axis=0)
|
|
327
|
+
dz = 1 / (n_layers)
|
|
328
|
+
x = np.linspace(dz / 2, 1 - dz / 2, n_layers)
|
|
329
|
+
x = np.insert(x, 0, 0)
|
|
330
|
+
u, v, w = extract_velocity_column_at_coordinate(
|
|
331
|
+
fields[1], n_elements_per_layer, n_layers, coordinate_index
|
|
332
|
+
)
|
|
333
|
+
fig, ax = plt.subplots(2)
|
|
334
|
+
ax[0].plot(U, X)
|
|
335
|
+
ax[0].plot(u, x)
|
|
336
|
+
ax[1].plot(V, X)
|
|
337
|
+
ax[1].plot(v, x)
|
|
338
|
+
return fig, ax
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def load_openfoam_file(filepath):
|
|
342
|
+
vtkfile = load_file(filepath)
|
|
343
|
+
coordinates = get_coordinates(vtkfile)
|
|
344
|
+
n_layer, n_elements_per_layer = get_number_of_layers_and_elements_in_plane(
|
|
345
|
+
coordinates
|
|
346
|
+
)
|
|
347
|
+
fields = get_fields(vtkfile, ["alpha.water", "U"])
|
|
348
|
+
sort_order = sort_data(coordinates, fields)
|
|
349
|
+
coordinates, fields = apply_order(coordinates, fields, sort_order)
|
|
350
|
+
fields[1] = add_noslip_layer(fields[1], n_elements_per_layer)
|
|
351
|
+
time = get_time(vtkfile)
|
|
352
|
+
return coordinates, fields, time
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def test_load():
|
|
356
|
+
filepath = os.path.join(
|
|
357
|
+
os.path.join(main_dir, "openfoam_data/channelflow_coarse"),
|
|
358
|
+
"channelflow_coarse_0.vtm",
|
|
359
|
+
)
|
|
360
|
+
coordinates, fields, time = load_openfoam_file(filepath)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def test_moment_projection():
|
|
364
|
+
filepath = os.path.join(
|
|
365
|
+
os.path.join(main_dir, "openfoam_data/channelflow_coarse"),
|
|
366
|
+
"channelflow_coarse_0.vtm",
|
|
367
|
+
)
|
|
368
|
+
coordinates, fields, time = load_openfoam_file(filepath)
|
|
369
|
+
Q, basis = compute_shallow_moment_projection(fields, coordinates, 3)
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def test_convert_openfoam_single():
|
|
373
|
+
filepath = os.path.join(
|
|
374
|
+
os.path.join(main_dir, "openfoam_data/channelflow_coarse"),
|
|
375
|
+
"channelflow_coarse_0.vtm",
|
|
376
|
+
)
|
|
377
|
+
X, Q, t, basis = convert_openfoam_to_moments_single(filepath, 3)
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def test_plots():
|
|
381
|
+
if _HAVE_MATPLOTLIB is False:
|
|
382
|
+
raise ImportError("matplotlib is required for test_plots function.")
|
|
383
|
+
filepath = os.path.join(
|
|
384
|
+
os.path.join(main_dir, "openfoam_data/channelflow_coarse"),
|
|
385
|
+
"channelflow_coarse_0.vtm",
|
|
386
|
+
)
|
|
387
|
+
coordinates, fields, time = load_openfoam_file(filepath)
|
|
388
|
+
X, Q, t, basis = convert_openfoam_to_moments_single(filepath, 3)
|
|
389
|
+
fig, ax = plot_data_vs_moments(fields, coordinates, Q, basis, 0)
|
|
390
|
+
plt.show()
|
|
391
|
+
fig, ax = plot_basis(basis_legendre)
|
|
392
|
+
plt.show()
|
|
393
|
+
fig, ax = plot_contour(coordinates, Q[0])
|
|
394
|
+
plt.show()
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def test_sort():
|
|
398
|
+
filepath = os.path.join(
|
|
399
|
+
os.path.join(main_dir, "openfoam_data/channelflow_coarse"),
|
|
400
|
+
"channelflow_coarse_0.vtm",
|
|
401
|
+
)
|
|
402
|
+
filepath_gmsh = os.path.join(
|
|
403
|
+
os.path.join(main_dir, "meshes/channel_openfoam/mesh_coarse_2d.msh")
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
mesh_gmsh = Mesh.load_gmsh(filepath_gmsh, "triangle")
|
|
407
|
+
mesh_gmsh.write_to_hdf5(
|
|
408
|
+
os.path.join(os.path.join(main_dir, "openfoam_data/channelflow_coarse"))
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
filepath_hdf_mesh = os.path.join(
|
|
412
|
+
os.path.join(main_dir, "openfoam_data/channelflow_coarse/mesh.hdf5")
|
|
413
|
+
)
|
|
414
|
+
mesh = Mesh.from_hdf5(filepath_hdf_mesh)
|
|
415
|
+
|
|
416
|
+
coordinates, fields, time = load_openfoam_file(filepath)
|
|
417
|
+
Q, basis = compute_shallow_moment_projection(fields, coordinates, 3)
|
|
418
|
+
|
|
419
|
+
# mesh_comparison = Mesh.load_gmsh(os.path.join(main_dir, 'meshes/channel_openfoam/mesh_coarse_3d.msh'), 'tetra')
|
|
420
|
+
|
|
421
|
+
sort_fields_by_mesh(mesh, coordinates, Q)
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def test_convert_openfoam_to_moments(level=0):
|
|
425
|
+
# filepath = os.path.join(main_dir, 'openfoam_data/channelflow_coarse')
|
|
426
|
+
foam_sim = os.getenv("FOAM_SIM")
|
|
427
|
+
filepath = os.path.join(foam_sim, "multiphase/interFoam/RAS/channelflow_mid")
|
|
428
|
+
filepath_target_mesh = os.path.join(
|
|
429
|
+
os.path.join(main_dir, "meshes/simple_openfoam/mesh_2d_mid.msh")
|
|
430
|
+
)
|
|
431
|
+
convert_openfoam_to_moments(
|
|
432
|
+
filepath, level, filepath_target_mesh, meshtype_order="triangle"
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
if __name__ == "__main__":
|
|
437
|
+
# test_load()
|
|
438
|
+
# test_moment_projection()
|
|
439
|
+
# test_convert_openfoam_single()
|
|
440
|
+
# test_plots()
|
|
441
|
+
# test_sort()
|
|
442
|
+
test_convert_openfoam_to_moments(level=1)
|
|
443
|
+
filepath = os.path.join(main_dir, "openfoam_data/channelflow_mid")
|
|
444
|
+
filepath_mesh = os.path.join(main_dir, "meshes/simple_openfoam/mesh_2d_mid.msh")
|
|
445
|
+
io.generate_vtk(
|
|
446
|
+
filepath,
|
|
447
|
+
filepath_gmsh=filepath_mesh,
|
|
448
|
+
gmsh_mesh_type="triangle",
|
|
449
|
+
filename_fields="fields_openfoam.hdf5",
|
|
450
|
+
filename_out="fields_openfoam_vtk",
|
|
451
|
+
skip_aux=True,
|
|
452
|
+
)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from sympy import MatrixSymbol, fraction, cancel, Matrix
|
|
2
|
+
|
|
3
|
+
from zoomy_core.misc.misc import Zstruct
|
|
4
|
+
|
|
5
|
+
def regularize_denominator(expr, regularization_constant = 10**(-4), regularize = False):
|
|
6
|
+
if not regularize:
|
|
7
|
+
return expr
|
|
8
|
+
def regularize(expr):
|
|
9
|
+
(nom, den) = fraction(cancel(expr))
|
|
10
|
+
return nom * den / (den*2 + regularization_constant)
|
|
11
|
+
for i in range(expr.shape[0]):
|
|
12
|
+
for j in range(expr.shape[1]):
|
|
13
|
+
expr[i,j] = regularize(expr[i,j])
|
|
14
|
+
return expr
|
|
15
|
+
|
|
16
|
+
def substitute_sympy_attributes_with_symbol_matrix(expr: Matrix, attr: Zstruct, attr_matrix: MatrixSymbol):
|
|
17
|
+
if expr is None:
|
|
18
|
+
return None
|
|
19
|
+
if type(attr) is Zstruct:
|
|
20
|
+
assert attr.length() <= attr_matrix.shape[0]
|
|
21
|
+
for i, k in enumerate(attr.get_list()):
|
|
22
|
+
expr = Matrix(expr).subs(k, attr_matrix[i])
|
|
23
|
+
else:
|
|
24
|
+
expr = Matrix(expr).subs(attr, attr_matrix)
|
|
25
|
+
return expr
|