emerge 1.0.3__py3-none-any.whl → 1.0.4__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 emerge might be problematic. Click here for more details.
- emerge/__init__.py +7 -3
- emerge/_emerge/elements/femdata.py +5 -1
- emerge/_emerge/elements/ned2_interp.py +73 -30
- emerge/_emerge/elements/nedelec2.py +1 -0
- emerge/_emerge/emerge_update.py +63 -0
- emerge/_emerge/geo/operations.py +2 -1
- emerge/_emerge/geo/polybased.py +26 -5
- emerge/_emerge/geometry.py +5 -0
- emerge/_emerge/logsettings.py +26 -1
- emerge/_emerge/material.py +29 -8
- emerge/_emerge/mesh3d.py +16 -13
- emerge/_emerge/mesher.py +70 -3
- emerge/_emerge/physics/microwave/assembly/assembler.py +5 -4
- emerge/_emerge/physics/microwave/assembly/curlcurl.py +0 -1
- emerge/_emerge/physics/microwave/assembly/generalized_eigen.py +1 -2
- emerge/_emerge/physics/microwave/assembly/generalized_eigen_hb.py +1 -1
- emerge/_emerge/physics/microwave/assembly/robin_abc_order2.py +0 -1
- emerge/_emerge/physics/microwave/microwave_3d.py +37 -16
- emerge/_emerge/physics/microwave/microwave_bc.py +6 -4
- emerge/_emerge/physics/microwave/microwave_data.py +14 -11
- emerge/_emerge/plot/pyvista/cmap_maker.py +70 -0
- emerge/_emerge/plot/pyvista/display.py +93 -36
- emerge/_emerge/simmodel.py +75 -21
- emerge/_emerge/simulation_data.py +22 -4
- emerge/_emerge/solver.py +63 -32
- {emerge-1.0.3.dist-info → emerge-1.0.4.dist-info}/METADATA +2 -3
- {emerge-1.0.3.dist-info → emerge-1.0.4.dist-info}/RECORD +30 -28
- {emerge-1.0.3.dist-info → emerge-1.0.4.dist-info}/WHEEL +0 -0
- {emerge-1.0.3.dist-info → emerge-1.0.4.dist-info}/entry_points.txt +0 -0
- {emerge-1.0.3.dist-info → emerge-1.0.4.dist-info}/licenses/LICENSE +0 -0
emerge/__init__.py
CHANGED
|
@@ -18,7 +18,7 @@ along with this program; if not, see
|
|
|
18
18
|
"""
|
|
19
19
|
import os
|
|
20
20
|
|
|
21
|
-
__version__ = "1.0.
|
|
21
|
+
__version__ = "1.0.4"
|
|
22
22
|
|
|
23
23
|
############################################################
|
|
24
24
|
# HANDLE ENVIRONMENT VARIABLES #
|
|
@@ -30,8 +30,11 @@ os.environ["EMERGE_FILE_LOGLEVEL"] = os.getenv("EMERGE_FILE_LOGLEVEL", default="
|
|
|
30
30
|
os.environ["OMP_NUM_THREADS"] = os.getenv("OMP_NUM_THREADS", default="1")
|
|
31
31
|
os.environ["MKL_NUM_THREADS"] = os.getenv("MKL_NUM_THREADS", default="4")
|
|
32
32
|
os.environ["OPENBLAS_NUM_THREADS"] = NTHREADS
|
|
33
|
+
os.environ["VECLIB_NUM_THREADS"] = NTHREADS
|
|
33
34
|
os.environ["VECLIB_MAXIMUM_THREADS"] = NTHREADS
|
|
34
35
|
os.environ["NUMEXPR_NUM_THREADS"] = NTHREADS
|
|
36
|
+
os.environ["NUMBA_NUM_THREADS"] = "4"
|
|
37
|
+
os.environ.setdefault("NUMBA_THREADING_LAYER", "workqueue")
|
|
35
38
|
|
|
36
39
|
############################################################
|
|
37
40
|
# IMPORT MODULES #
|
|
@@ -44,6 +47,7 @@ LOG_CONTROLLER.set_default()
|
|
|
44
47
|
logger.debug('Importing modules')
|
|
45
48
|
LOG_CONTROLLER._set_log_buffer()
|
|
46
49
|
|
|
50
|
+
import gmsh
|
|
47
51
|
from ._emerge.simmodel import Simulation
|
|
48
52
|
from ._emerge.material import Material, FreqCoordDependent, FreqDependent, CoordDependent
|
|
49
53
|
from ._emerge import bc
|
|
@@ -53,12 +57,12 @@ from ._emerge.coord import Line
|
|
|
53
57
|
from ._emerge import geo
|
|
54
58
|
from ._emerge.selection import Selection, FaceSelection, DomainSelection, EdgeSelection
|
|
55
59
|
from ._emerge.geometry import select
|
|
56
|
-
|
|
60
|
+
from ._emerge.mth.common_functions import norm, coax_rout, coax_rin
|
|
57
61
|
from ._emerge.periodic import RectCell, HexCell
|
|
58
62
|
from ._emerge.mesher import Algorithm2D, Algorithm3D
|
|
59
63
|
from . import lib
|
|
60
64
|
from ._emerge.howto import _HowtoClass
|
|
61
|
-
|
|
65
|
+
from ._emerge.emerge_update import update_emerge
|
|
62
66
|
howto = _HowtoClass()
|
|
63
67
|
|
|
64
68
|
logger.debug('Importing complete!')
|
|
@@ -61,7 +61,7 @@ class FEMBasis:
|
|
|
61
61
|
return matmul(ibasis, np.array(self.interpolate(field, xyzg[0,:], xyzg[1,:], xyzg[2,:], tetids)))
|
|
62
62
|
return func
|
|
63
63
|
|
|
64
|
-
def interpolate(self, field: np.ndarray, xs: np.ndarray, ys: np.ndarray, zs: np.ndarray, tetids: np.ndarray | None = None) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
64
|
+
def interpolate(self, field: np.ndarray, xs: np.ndarray, ys: np.ndarray, zs: np.ndarray, tetids: np.ndarray | None = None, usenan: bool = True) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
65
65
|
raise NotImplementedError()
|
|
66
66
|
|
|
67
67
|
def interpolate_curl(self, field: np.ndarray, xs: np.ndarray, ys: np.ndarray, zs: np.ndarray, constants: np.ndarray, tetids: np.ndarray | None = None, usenan: bool = True) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
@@ -70,6 +70,10 @@ class FEMBasis:
|
|
|
70
70
|
"""
|
|
71
71
|
raise NotImplementedError()
|
|
72
72
|
|
|
73
|
+
def interpolate_error(self, field: np.ndarray, xs: np.ndarray, ys: np.ndarray, zs: np.ndarray, tetids: np.ndarray | None = None, cs: tuple[float, float] = (1.0, 1.0)) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
74
|
+
raise NotImplementedError()
|
|
75
|
+
|
|
76
|
+
|
|
73
77
|
def empty_tet_matrix(self) -> np.ndarray:
|
|
74
78
|
nnz = self.n_tets*self.n_tet_dofs**2
|
|
75
79
|
matrix = np.empty((nnz,), dtype=np.complex128)
|
|
@@ -192,6 +192,7 @@ def ned2_tet_interp(coords: np.ndarray,
|
|
|
192
192
|
Exl = np.zeros(x.shape, dtype=np.complex128)
|
|
193
193
|
Eyl = np.zeros(x.shape, dtype=np.complex128)
|
|
194
194
|
Ezl = np.zeros(x.shape, dtype=np.complex128)
|
|
195
|
+
V1 = (216*V**3)
|
|
195
196
|
for ie in range(6):
|
|
196
197
|
Em1, Em2 = Em1s[ie], Em2s[ie]
|
|
197
198
|
edgeids = l_edge_ids[:, ie]
|
|
@@ -202,11 +203,12 @@ def ned2_tet_interp(coords: np.ndarray,
|
|
|
202
203
|
x1, x2 = xvs[edgeids]
|
|
203
204
|
y1, y2 = yvs[edgeids]
|
|
204
205
|
z1, z2 = zvs[edgeids]
|
|
205
|
-
|
|
206
|
+
F1 = (a1 + b1*x + c1*y + d1*z)
|
|
207
|
+
F2 = (a2 + b2*x + c2*y + d2*z)
|
|
206
208
|
L = np.sqrt((x1 - x2)**2 + (y1 - y2)**2 + (z1 - z2)**2)
|
|
207
|
-
ex = L*(Em1*
|
|
208
|
-
ey = L*(Em1*
|
|
209
|
-
ez = L*(Em1*
|
|
209
|
+
ex = L*(Em1*F1 + Em2*F2)*(b1*F2 - b2*F1)/V1
|
|
210
|
+
ey = L*(Em1*F1 + Em2*F2)*(c1*F2 - c2*F1)/V1
|
|
211
|
+
ez = L*(Em1*F1 + Em2*F2)*(d1*F2 - d2*F1)/V1
|
|
210
212
|
|
|
211
213
|
Exl += ex
|
|
212
214
|
Eyl += ey
|
|
@@ -226,10 +228,16 @@ def ned2_tet_interp(coords: np.ndarray,
|
|
|
226
228
|
|
|
227
229
|
L1 = np.sqrt((x1-x3)**2 + (y1-y3)**2 + (z1-z3)**2)
|
|
228
230
|
L2 = np.sqrt((x1-x2)**2 + (y1-y2)**2 + (z1-z2)**2)
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
231
|
+
|
|
232
|
+
F1 = (a1 + b1*x + c1*y + d1*z)
|
|
233
|
+
F2 = (a2 + b2*x + c2*y + d2*z)
|
|
234
|
+
F3 = (a3 + b3*x + c3*y + d3*z)
|
|
235
|
+
|
|
236
|
+
Q1 = Em1*L1*F2
|
|
237
|
+
Q2 = Em2*L2*F3
|
|
238
|
+
ex = (-Q1*(b1*F3 - b3*F1) + Q2*(b1*F2 - b2*F1))/V1
|
|
239
|
+
ey = (-Q1*(c1*F3 - c3*F1) + Q2*(c1*F2 - c2*F1))/V1
|
|
240
|
+
ez = (-Q1*(d1*F3 - d3*F1) + Q2*(d1*F2 - d2*F1))/V1
|
|
233
241
|
|
|
234
242
|
Exl += ex
|
|
235
243
|
Eyl += ey
|
|
@@ -322,6 +330,10 @@ def ned2_tet_interp_curl(coords: np.ndarray,
|
|
|
322
330
|
Exl = np.zeros(x.shape, dtype=np.complex128)
|
|
323
331
|
Eyl = np.zeros(x.shape, dtype=np.complex128)
|
|
324
332
|
Ezl = np.zeros(x.shape, dtype=np.complex128)
|
|
333
|
+
|
|
334
|
+
V1 = (216*V**3)
|
|
335
|
+
V2 = (72*V**3)
|
|
336
|
+
|
|
325
337
|
for ie in range(6):
|
|
326
338
|
Em1, Em2 = Em1s[ie], Em2s[ie]
|
|
327
339
|
edgeids = l_edge_ids[:, ie]
|
|
@@ -334,9 +346,35 @@ def ned2_tet_interp_curl(coords: np.ndarray,
|
|
|
334
346
|
z1, z2 = zvs[edgeids]
|
|
335
347
|
|
|
336
348
|
L = np.sqrt((x1 - x2)**2 + (y1 - y2)**2 + (z1 - z2)**2)
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
349
|
+
C1 = Em1*a1
|
|
350
|
+
C2 = Em1*b1
|
|
351
|
+
C3 = Em1*c1
|
|
352
|
+
C4 = Em1*c2
|
|
353
|
+
C5 = Em2*a2
|
|
354
|
+
C6 = Em2*b2
|
|
355
|
+
C7 = Em2*c1
|
|
356
|
+
C8 = Em2*c2
|
|
357
|
+
C9 = Em1*b2
|
|
358
|
+
C10 = Em2*b1
|
|
359
|
+
D1 = c1*d2
|
|
360
|
+
D2 = c2*d1
|
|
361
|
+
D3 = d1*d2
|
|
362
|
+
D4 = d1*d1
|
|
363
|
+
D5 = c2*d2
|
|
364
|
+
D6 = d2*d2
|
|
365
|
+
D7 = b1*d2
|
|
366
|
+
D8 = b2*d1
|
|
367
|
+
D9 = c1*d1
|
|
368
|
+
D10 = b2*d2
|
|
369
|
+
D11 = b1*c2
|
|
370
|
+
D12 = b2*c1
|
|
371
|
+
D13 = c1*c2
|
|
372
|
+
D14 = c1*c1
|
|
373
|
+
D15 = b2*c2
|
|
374
|
+
|
|
375
|
+
ex = L*(-C1*D1 + C1*D2 - C2*D1*x + C2*D2*x - C3*D1*y + C3*D2*y - C3*D3*z + C4*D4*z - C5*D1 + C5*D2 - C6*D1*x + C6*D2*x - C7*D5*y - C7*D6*z + C8*D2*y + C8*D3*z)/V2
|
|
376
|
+
ey = L*(C1*D7 - C1*D8 + C2*D7*x - C2*D8*x + C2*D1*y + C2*D3*z - C9*D9*y - C9*D4*z + C5*D7 - C5*D8 + C10*D10*x + C10*D5*y + C10*D6*z - C6*D8*x - C6*D2*y - C6*D3*z)/V2
|
|
377
|
+
ez = L*(-C1*D11 + C1*D12 - C2*D11*x + C2*D12*x - C2*D13*y - C2*D2*z + C9*D14*y + C9*D9*z - C5*D11 + C5*D12 - C10*D15*x - C10*c2*c2*y - C10*D5*z + C6*D12*x + C6*D13*y + C6*D1*z)/V2
|
|
340
378
|
Exl += ex
|
|
341
379
|
Eyl += ey
|
|
342
380
|
Ezl += ez
|
|
@@ -355,10 +393,28 @@ def ned2_tet_interp_curl(coords: np.ndarray,
|
|
|
355
393
|
|
|
356
394
|
L1 = np.sqrt((x1-x3)**2 + (y1-y3)**2 + (z1-z3)**2)
|
|
357
395
|
L2 = np.sqrt((x1-x2)**2 + (y1-y2)**2 + (z1-z2)**2)
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
396
|
+
F1 = (a3 + b3*x + c3*y + d3*z)
|
|
397
|
+
F2 = (a1 + b1*x + c1*y + d1*z)
|
|
398
|
+
F3 = (a2 + b2*x + c2*y + d2*z)
|
|
399
|
+
N1 = (d1*F1 - d3*F2)
|
|
400
|
+
N2 = (c1*F1 - c3*F2)
|
|
401
|
+
N3 = (c1*d3 - c3*d1)
|
|
402
|
+
N4 = (d1*F3 - d2*F2)
|
|
403
|
+
N5 = (c1*F3 - c2*F2)
|
|
404
|
+
D1 = c1*d2
|
|
405
|
+
D2 = c2*d1
|
|
406
|
+
N6 = (D1 - D2)
|
|
407
|
+
N7 = (b1*F1 - b3*F2)
|
|
408
|
+
N8 = (b1*d3 - b3*d1)
|
|
409
|
+
N9 = (b1*F3 - b2*F2)
|
|
410
|
+
D7 = b1*d2
|
|
411
|
+
D8 = b2*d1
|
|
412
|
+
N10 = (D7 - D8)
|
|
413
|
+
D11 = b1*c2
|
|
414
|
+
D12 = b2*c1
|
|
415
|
+
ex = (Em1*L1*(-c2*N1 + d2*N2 + 2*N3*F3) - Em2*L2*(-c3*N4 + d3*N5 + 2*N6*F1))/V1
|
|
416
|
+
ey = (-Em1*L1*(-b2*N1 + d2*N7 + 2*N8*F3) + Em2*L2*(-b3*N4 + d3*N9 + 2*N10*F1))/V1
|
|
417
|
+
ez = (Em1*L1*(-b2*N2 + c2*N7 + 2*(b1*c3 - b3*c1)*F3) - Em2*L2*(-b3*N5 + c3*N9 + 2*(D11 - D12)*F1))/V1
|
|
362
418
|
|
|
363
419
|
Exl += ex
|
|
364
420
|
Eyl += ey
|
|
@@ -445,8 +501,7 @@ def ned2_tri_interp(coords: np.ndarray,
|
|
|
445
501
|
|
|
446
502
|
Exl = np.zeros(x.shape, dtype=np.complex128)
|
|
447
503
|
Eyl = np.zeros(x.shape, dtype=np.complex128)
|
|
448
|
-
|
|
449
|
-
|
|
504
|
+
|
|
450
505
|
for ie in range(3):
|
|
451
506
|
Em1, Em2 = Em1s[ie], Em2s[ie]
|
|
452
507
|
edgeids = l_edge_ids[:, ie]
|
|
@@ -534,17 +589,11 @@ def ned2_tri_interp_full(coords: np.ndarray,
|
|
|
534
589
|
yvs = nodes[1, tris[:,itri]]
|
|
535
590
|
|
|
536
591
|
a_s, b_s, c_s, A = tri_coefficients(xvs, yvs)
|
|
537
|
-
|
|
538
592
|
e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14 = Etri
|
|
539
593
|
|
|
540
594
|
a1, a2, a3 = a_s
|
|
541
595
|
b1, b2, b3 = b_s
|
|
542
596
|
c1, c2, c3 = c_s
|
|
543
|
-
|
|
544
|
-
# original Nedelec-1 order 2 formulation
|
|
545
|
-
# ex = (e1*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) + e2*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a2 + b2*x + c2*y) + e3*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) - e4*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e5*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e6*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a3 + b3*x + c3*y) + e7*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + e8*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y))/(8*A**3)
|
|
546
|
-
# ey = (e1*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) + e2*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a2 + b2*x + c2*y) + e3*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) - e4*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e5*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e6*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a3 + b3*x + c3*y) + e7*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + e8*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y))/(8*A**3)
|
|
547
|
-
# ez = (a1 + b1*x + c1*y)*(e10*(-A + a1 + b1*x + c1*y) + e11*(-A + a1 + b1*x + c1*y) + e12*(a2 + b2*x + c2*y) + e13*(a2 + b2*x + c2*y) + e14*(a2 + b2*x + c2*y) + e9*(-A + a1 + b1*x + c1*y))/(2*A**2)
|
|
548
597
|
|
|
549
598
|
# New Nedelec-1 order 2 formulation
|
|
550
599
|
ex = (-2*A*(e1*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y)) + e2*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y)) + e3*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))) - e4*((b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + (b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a1 + b1*x + c1*y)) - e5*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a1 - a2 + b1*x - b2*x + c1*y - c2*y) - e6*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a2 - a3 + b2*x - b3*x + c2*y - c3*y) - e7*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a1 - a3 + b1*x - b3*x + c1*y - c3*y) + e8*((b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + (b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y)))/(8*A**3)
|
|
@@ -617,18 +666,12 @@ def ned2_tri_interp_curl(coords: np.ndarray,
|
|
|
617
666
|
yvs = nodes[1, tris[:,itri]]
|
|
618
667
|
|
|
619
668
|
a_s, b_s, c_s, A = tri_coefficients(xvs, yvs)
|
|
620
|
-
|
|
621
669
|
e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14 = Etri
|
|
622
670
|
|
|
623
671
|
a1, a2, a3 = a_s
|
|
624
672
|
b1, b2, b3 = b_s
|
|
625
673
|
c1, c2, c3 = c_s
|
|
626
674
|
|
|
627
|
-
# original Nedelec-1 order 2 formulation
|
|
628
|
-
#hx = (4*A*(c1*(e10*(-A + a1 + b1*x + c1*y) + e11*(-A + a1 + b1*x + c1*y) + e12*(a2 + b2*x + c2*y) + e13*(a2 + b2*x + c2*y) + e14*(a2 + b2*x + c2*y) + e9*(-A + a1 + b1*x + c1*y)) + (a1 + b1*x + c1*y)*(c1*e10 + c1*e11 + c1*e9 + c2*e12 + c2*e13 + c2*e14)) + jB*(e1*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) + e2*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a2 + b2*x + c2*y) + e3*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) - e4*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e5*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e6*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a3 + b3*x + c3*y) + e7*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + e8*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y)))/(8*A**3)
|
|
629
|
-
# hy = (4*A*(b1*(e10*(-A + a1 + b1*x + c1*y) + e11*(-A + a1 + b1*x + c1*y) + e12*(a2 + b2*x + c2*y) + e13*(a2 + b2*x + c2*y) + e14*(a2 + b2*x + c2*y) + e9*(-A + a1 + b1*x + c1*y)) + (a1 + b1*x + c1*y)*(b1*e10 + b1*e11 + b1*e9 + b2*e12 + b2*e13 + b2*e14)) - jB*(e1*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) + e2*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a2 + b2*x + c2*y) + e3*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) - e4*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e5*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e6*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a3 + b3*x + c3*y) + e7*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + e8*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y)))/(8*A**3)
|
|
630
|
-
# hz = (-3*a1*b1*c2*e1 - 3*a1*b1*c3*e3 + 3*a1*b2*c1*e1 + a1*b2*c3*e4 + a1*b2*c3*e8 + 3*a1*b3*c1*e3 - a1*b3*c2*e4 - a1*b3*c2*e8 - 3*a2*b1*c2*e5 + 2*a2*b1*c3*e4 - a2*b1*c3*e8 + 3*a2*b2*c1*e5 - 3*a2*b2*c3*e2 - 2*a2*b3*c1*e4 + a2*b3*c1*e8 + 3*a2*b3*c2*e2 + a3*b1*c2*e4 - 2*a3*b1*c2*e8 - 3*a3*b1*c3*e7 - a3*b2*c1*e4 + 2*a3*b2*c1*e8 - 3*a3*b2*c3*e6 + 3*a3*b3*c1*e7 + 3*a3*b3*c2*e6 - 3*b1**2*c2*e1*x - 3*b1**2*c3*e3*x + 3*b1*b2*c1*e1*x - 3*b1*b2*c2*e5*x + 3*b1*b2*c3*e4*x + 3*b1*b3*c1*e3*x - 3*b1*b3*c2*e8*x - 3*b1*b3*c3*e7*x - 3*b1*c1*c2*e1*y - 3*b1*c1*c3*e3*y - 3*b1*c2**2*e5*y + 3*b1*c2*c3*e4*y - 3*b1*c2*c3*e8*y - 3*b1*c3**2*e7*y + 3*b2**2*c1*e5*x - 3*b2**2*c3*e2*x - 3*b2*b3*c1*e4*x + 3*b2*b3*c1*e8*x + 3*b2*b3*c2*e2*x - 3*b2*b3*c3*e6*x + 3*b2*c1**2*e1*y + 3*b2*c1*c2*e5*y + 3*b2*c1*c3*e8*y - 3*b2*c2*c3*e2*y - 3*b2*c3**2*e6*y + 3*b3**2*c1*e7*x + 3*b3**2*c2*e6*x + 3*b3*c1**2*e3*y - 3*b3*c1*c2*e4*y + 3*b3*c1*c3*e7*y + 3*b3*c2**2*e2*y + 3*b3*c2*c3*e6*y)/(8*A**3)
|
|
631
|
-
|
|
632
675
|
# New Nedelec-1 order 2 formulation
|
|
633
676
|
hx = (4*A*(2*c1*e12*(a2 + b2*x + c2*y) + 2*c1*e14*(a3 + b3*x + c3*y) + c1*e9*(a1 + b1*x + c1*y) - c1*e9*(A - a1 - b1*x - c1*y) + c2*e10*(a2 + b2*x + c2*y) - c2*e10*(A - a2 - b2*x - c2*y) + 2*c2*e12*(a1 + b1*x + c1*y) + 2*c2*e13*(a3 + b3*x + c3*y) + c3*e11*(a3 + b3*x + c3*y) - c3*e11*(A - a3 - b3*x - c3*y) + 2*c3*e13*(a2 + b2*x + c2*y) + 2*c3*e14*(a1 + b1*x + c1*y)) + jB*(2*A*(e1*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y)) + e2*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y)) + e3*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))) + e4*((c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + (c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a1 + b1*x + c1*y)) + e5*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a1 - a2 + b1*x - b2*x + c1*y - c2*y) + e6*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a2 - a3 + b2*x - b3*x + c2*y - c3*y) + e7*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a1 - a3 + b1*x - b3*x + c1*y - c3*y) - e8*((c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + (c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y))))/(8*A**3)
|
|
634
677
|
hy = (4*A*(-2*b1*e12*(a2 + b2*x + c2*y) - 2*b1*e14*(a3 + b3*x + c3*y) - b1*e9*(a1 + b1*x + c1*y) + b1*e9*(A - a1 - b1*x - c1*y) - b2*e10*(a2 + b2*x + c2*y) + b2*e10*(A - a2 - b2*x - c2*y) - 2*b2*e12*(a1 + b1*x + c1*y) - 2*b2*e13*(a3 + b3*x + c3*y) - b3*e11*(a3 + b3*x + c3*y) + b3*e11*(A - a3 - b3*x - c3*y) - 2*b3*e13*(a2 + b2*x + c2*y) - 2*b3*e14*(a1 + b1*x + c1*y)) - jB*(2*A*(e1*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y)) + e2*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y)) + e3*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))) + e4*((b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + (b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a1 + b1*x + c1*y)) + e5*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a1 - a2 + b1*x - b2*x + c1*y - c2*y) + e6*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a2 - a3 + b2*x - b3*x + c2*y - c3*y) + e7*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a1 - a3 + b1*x - b3*x + c1*y - c3*y) - e8*((b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + (b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y))))/(8*A**3)
|
|
@@ -637,4 +680,4 @@ def ned2_tri_interp_curl(coords: np.ndarray,
|
|
|
637
680
|
Ex[inside] = hx*dc[0,0]
|
|
638
681
|
Ey[inside] = hy*dc[1,1]
|
|
639
682
|
Ez[inside] = hz*dc[2,2]
|
|
640
|
-
return Ex, Ey, Ez
|
|
683
|
+
return Ex, Ey, Ez
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import sys
|
|
3
|
+
from importlib import import_module
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from loguru import logger
|
|
7
|
+
except ImportError:
|
|
8
|
+
# Fallback if loguru isn't installed
|
|
9
|
+
class _Logger:
|
|
10
|
+
def info(self, msg): print(f"[INFO] {msg}")
|
|
11
|
+
def warning(self, msg): print(f"[WARN] {msg}")
|
|
12
|
+
def error(self, msg): print(f"[ERROR] {msg}")
|
|
13
|
+
logger = _Logger()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def update_emerge(branch: str = "main", confirm: bool = True, _dryrun: bool = False) -> str | None:
|
|
17
|
+
"""
|
|
18
|
+
Update the EMerge library directly from GitHub.
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
branch : str, optional
|
|
23
|
+
The git branch or tag to install from. Default is "main".
|
|
24
|
+
confirm : bool, optional
|
|
25
|
+
If True, asks the user for confirmation before updating.
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
str | None
|
|
30
|
+
The updated version string if successful, otherwise None.
|
|
31
|
+
"""
|
|
32
|
+
logger.warning(
|
|
33
|
+
"You are about to update EMerge from GitHub. "
|
|
34
|
+
"This is an experimental feature and may overwrite your installed version."
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
if confirm:
|
|
38
|
+
ans = input("Do you wish to proceed? [y/N] ").strip().lower()
|
|
39
|
+
if ans != "y":
|
|
40
|
+
logger.info("Update aborted by user.")
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
url = f"git+https://github.com/FennisRobert/EMerge.git@{branch}"
|
|
44
|
+
logger.info(f"Updating EMerge from branch/tag '{branch}'...")
|
|
45
|
+
|
|
46
|
+
if not _dryrun:
|
|
47
|
+
try:
|
|
48
|
+
subprocess.check_call(
|
|
49
|
+
[sys.executable, "-m", "pip", "install", "--upgrade", "--force-reinstall", url]
|
|
50
|
+
)
|
|
51
|
+
except subprocess.CalledProcessError as e:
|
|
52
|
+
logger.error(f"Update failed: {e}")
|
|
53
|
+
return None
|
|
54
|
+
else:
|
|
55
|
+
logger.info('Dry run... No update executed!')
|
|
56
|
+
try:
|
|
57
|
+
emerge = import_module("emerge")
|
|
58
|
+
version = getattr(emerge, "__version__", "unknown")
|
|
59
|
+
logger.info(f"Successfully updated to EMerge version {version}.")
|
|
60
|
+
return version
|
|
61
|
+
except Exception as e:
|
|
62
|
+
logger.error(f"Update installed but could not retrieve version: {e}")
|
|
63
|
+
return None
|
emerge/_emerge/geo/operations.py
CHANGED
|
@@ -300,14 +300,15 @@ def unite(*objects: GeoObject) -> GeoObject:
|
|
|
300
300
|
GeoObject: The resultant object
|
|
301
301
|
"""
|
|
302
302
|
main, *rest = objects
|
|
303
|
+
|
|
303
304
|
if not rest:
|
|
304
305
|
return main
|
|
306
|
+
|
|
305
307
|
main._exists = False
|
|
306
308
|
dts = []
|
|
307
309
|
for other in rest:
|
|
308
310
|
dts.extend(other.dimtags)
|
|
309
311
|
other._exists = False
|
|
310
|
-
|
|
311
312
|
new_dimtags, mapping = gmsh.model.occ.fuse(main.dimtags, dts)
|
|
312
313
|
|
|
313
314
|
new_obj = GeoObject.from_dimtags(new_dimtags)._take_tools(*objects)
|
emerge/_emerge/geo/polybased.py
CHANGED
|
@@ -238,7 +238,8 @@ class XYPolygon:
|
|
|
238
238
|
def __init__(self,
|
|
239
239
|
xs: np.ndarray | list | tuple | None = None,
|
|
240
240
|
ys: np.ndarray | list | tuple | None = None,
|
|
241
|
-
cs: CoordinateSystem | None = None
|
|
241
|
+
cs: CoordinateSystem | None = None,
|
|
242
|
+
resolution: float = 1e-6):
|
|
242
243
|
"""Constructs an XY-plane placed polygon.
|
|
243
244
|
|
|
244
245
|
Args:
|
|
@@ -256,6 +257,7 @@ class XYPolygon:
|
|
|
256
257
|
self.fillets: list[tuple[float, int]] = []
|
|
257
258
|
|
|
258
259
|
self._cs: CoordinateSystem = cs
|
|
260
|
+
self.resolution: float = resolution
|
|
259
261
|
|
|
260
262
|
@property
|
|
261
263
|
def center(self) -> tuple[float, float]:
|
|
@@ -279,7 +281,7 @@ class XYPolygon:
|
|
|
279
281
|
The XYPolygon does not store redundant points p[0]==p[N] so if these are
|
|
280
282
|
the same, this function will remove the last point.
|
|
281
283
|
"""
|
|
282
|
-
if np.sqrt((self.x[-1]-self.x[0])**2 + (self.y[-1]-self.y[0])**2) < 1e-
|
|
284
|
+
if np.sqrt((self.x[-1]-self.x[0])**2 + (self.y[-1]-self.y[0])**2) < 1e-9:
|
|
283
285
|
self.x = self.x[:-1]
|
|
284
286
|
self.y = self.y[:-1]
|
|
285
287
|
|
|
@@ -329,6 +331,23 @@ class XYPolygon:
|
|
|
329
331
|
self.fillets.append((radius, i))
|
|
330
332
|
return self
|
|
331
333
|
|
|
334
|
+
def _cleanup(self, resolution: float | None = None) -> None:
|
|
335
|
+
# Compute differences between consecutive points
|
|
336
|
+
if resolution is None:
|
|
337
|
+
resolution = self.resolution
|
|
338
|
+
dx = np.diff(self.x)
|
|
339
|
+
dy = np.diff(self.y)
|
|
340
|
+
|
|
341
|
+
# Distances between consecutive points
|
|
342
|
+
dist = np.sqrt(dx**2 + dy**2)
|
|
343
|
+
|
|
344
|
+
# Keep the first point, then points where distance >= threshold
|
|
345
|
+
keep = np.insert(dist >= resolution, 1, True)
|
|
346
|
+
|
|
347
|
+
# Apply mask
|
|
348
|
+
self.x = self.x[keep]
|
|
349
|
+
self.y = self.y[keep]
|
|
350
|
+
|
|
332
351
|
def _make_wire(self, cs: CoordinateSystem) -> tuple[list[int], list[int], int]:
|
|
333
352
|
"""Turns the XYPolygon object into a GeoPolygon that is embedded in 3D space.
|
|
334
353
|
|
|
@@ -345,8 +364,11 @@ class XYPolygon:
|
|
|
345
364
|
ptags = []
|
|
346
365
|
xg, yg, zg = cs.in_global_cs(self.x, self.y, 0*self.x)
|
|
347
366
|
|
|
367
|
+
points = dict()
|
|
348
368
|
for x,y,z in zip(xg, yg, zg):
|
|
349
|
-
|
|
369
|
+
ptag = gmsh.model.occ.add_point(x,y,z)
|
|
370
|
+
points[ptag] = (x,y,z)
|
|
371
|
+
ptags.append(ptag)
|
|
350
372
|
|
|
351
373
|
lines = []
|
|
352
374
|
for i1, p1 in enumerate(ptags):
|
|
@@ -375,6 +397,7 @@ class XYPolygon:
|
|
|
375
397
|
Returns:
|
|
376
398
|
GeoPolygon: The resultant 3D GeoPolygon object.
|
|
377
399
|
"""
|
|
400
|
+
self._cleanup()
|
|
378
401
|
ptags, lines, wiretag = self._make_wire(cs)
|
|
379
402
|
surftag = gmsh.model.occ.add_plane_surface([wiretag,])
|
|
380
403
|
poly = GeoPolygon([surftag,], name=name)
|
|
@@ -635,8 +658,6 @@ class Curve(GeoEdge):
|
|
|
635
658
|
self.dstart: tuple[float, float, float] = (p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
|
|
636
659
|
|
|
637
660
|
|
|
638
|
-
|
|
639
|
-
|
|
640
661
|
@property
|
|
641
662
|
def p0(self) -> tuple[float, float, float]:
|
|
642
663
|
"""The start coordinate
|
emerge/_emerge/geometry.py
CHANGED
|
@@ -60,6 +60,11 @@ class _GeometryManager:
|
|
|
60
60
|
model = self.active
|
|
61
61
|
return [geo for geo in self.geometry_list[model].values() if geo._exists]
|
|
62
62
|
|
|
63
|
+
def set_geometries(self, geos: list[GeoObject], model: str | None = None):
|
|
64
|
+
if model is None:
|
|
65
|
+
model = self.active
|
|
66
|
+
self.geometry_list[model] = geos
|
|
67
|
+
|
|
63
68
|
def all_names(self, model: str | None = None) -> set[str]:
|
|
64
69
|
if model is None:
|
|
65
70
|
model = self.active
|
emerge/_emerge/logsettings.py
CHANGED
|
@@ -21,11 +21,25 @@ from typing import Literal
|
|
|
21
21
|
from pathlib import Path
|
|
22
22
|
import os
|
|
23
23
|
from collections import deque
|
|
24
|
-
|
|
24
|
+
import platform
|
|
25
|
+
import importlib
|
|
26
|
+
import multiprocessing
|
|
27
|
+
|
|
28
|
+
packages = ["numba", "numpy", "scipy", "gmsh", "joblib","matplotlib","pyvista","mkl","cloudpickle","scikit-umfpack","nvidia-cudss-cu12","nvmath-python[cu12]","cupy-cuda12x","ezdxf"]
|
|
29
|
+
|
|
30
|
+
def get_version(pkg_name):
|
|
31
|
+
try:
|
|
32
|
+
module = importlib.import_module(pkg_name)
|
|
33
|
+
return getattr(module, "__version__", "unknown")
|
|
34
|
+
except ImportError:
|
|
35
|
+
return "not installed"
|
|
36
|
+
|
|
25
37
|
_LOG_BUFFER = deque()
|
|
26
38
|
|
|
27
39
|
def _log_sink(message):
|
|
28
40
|
_LOG_BUFFER.append(message)
|
|
41
|
+
|
|
42
|
+
|
|
29
43
|
############################################################
|
|
30
44
|
# FORMATS #
|
|
31
45
|
############################################################
|
|
@@ -93,6 +107,17 @@ class LogController:
|
|
|
93
107
|
logger.opt(depth=6).log(msg.record["level"].name, msg.record["message"])
|
|
94
108
|
_LOG_BUFFER.clear()
|
|
95
109
|
|
|
110
|
+
def _sys_info(self) -> None:
|
|
111
|
+
for pkg in packages:
|
|
112
|
+
logger.trace(f" (!) {pkg} version: {get_version(pkg)}")
|
|
113
|
+
|
|
114
|
+
logger.trace(f" (!) OS: {platform.system()} {platform.release()} ({platform.version()})")
|
|
115
|
+
logger.trace(f" (!) Architecture: {platform.machine()} ({platform.architecture()[0]})")
|
|
116
|
+
logger.trace(f" (!) Processor: {platform.processor()}")
|
|
117
|
+
logger.trace(f" (!) Python build: {platform.python_build()}")
|
|
118
|
+
logger.trace(f" (!) Python version: {platform.python_version()} [{sys.version}]")
|
|
119
|
+
logger.trace(f" (!) CPU cores: {multiprocessing.cpu_count()}")
|
|
120
|
+
|
|
96
121
|
def set_std_loglevel(self, loglevel: str):
|
|
97
122
|
handler = {"sink": sys.stdout,
|
|
98
123
|
"level": loglevel,
|
emerge/_emerge/material.py
CHANGED
|
@@ -45,9 +45,10 @@ def _to_mat(value: float | complex | int | np.ndarray) -> np.ndarray:
|
|
|
45
45
|
class MatProperty:
|
|
46
46
|
_freq_dependent: bool = False
|
|
47
47
|
_coord_dependent: bool = False
|
|
48
|
+
_pickle_exclude = {"_func","_fmax"}
|
|
48
49
|
"""The MatProperty class is an interface for EMerge to deal with frequency and coordinate dependent material properties
|
|
49
50
|
"""
|
|
50
|
-
|
|
51
|
+
|
|
51
52
|
def __init__(self, value: float | complex | int | np.ndarray):
|
|
52
53
|
self.value: np.ndarray = _to_mat(value)
|
|
53
54
|
|
|
@@ -76,7 +77,19 @@ class MatProperty:
|
|
|
76
77
|
self._x: np.ndarray = np.array([], dtype=np.float64)
|
|
77
78
|
self._y: np.ndarray = np.array([], dtype=np.float64)
|
|
78
79
|
self._z: np.ndarray = np.array([], dtype=np.float64)
|
|
80
|
+
|
|
81
|
+
def __getstate__(self):
|
|
82
|
+
state = self.__dict__.copy()
|
|
83
|
+
for k in self._pickle_exclude:
|
|
84
|
+
state.pop(k, None)
|
|
79
85
|
|
|
86
|
+
return state
|
|
87
|
+
|
|
88
|
+
def __setstate__(self, state):
|
|
89
|
+
self.__dict__.update(state)
|
|
90
|
+
for k in self._pickle_exclude:
|
|
91
|
+
setattr(self, k, None)
|
|
92
|
+
|
|
80
93
|
class FreqDependent(MatProperty):
|
|
81
94
|
_freq_dependent: bool = True
|
|
82
95
|
_coord_dependent: bool = False
|
|
@@ -165,6 +178,7 @@ class CoordDependent(MatProperty):
|
|
|
165
178
|
if scalar is not None:
|
|
166
179
|
def _func(x, y, z) -> np.ndarray:
|
|
167
180
|
return np.eye(3)[:, :, None] * scalar(x,y,z)[None, None, :]
|
|
181
|
+
|
|
168
182
|
if vector is not None:
|
|
169
183
|
def _func(x, y, z) -> np.ndarray:
|
|
170
184
|
N = x.shape[0]
|
|
@@ -261,13 +275,6 @@ class FreqCoordDependent(MatProperty):
|
|
|
261
275
|
def scalar(self, f: float):
|
|
262
276
|
return self._func(f, 0,0,0)[0,0]
|
|
263
277
|
|
|
264
|
-
# To be finished once its clear how to deal with default values for functions
|
|
265
|
-
|
|
266
|
-
# def parse_material_property(value: complex | float | Callable):
|
|
267
|
-
# if not isinstance(value, Callable):
|
|
268
|
-
# return MatProperty(value)
|
|
269
|
-
# pass
|
|
270
|
-
|
|
271
278
|
class Material:
|
|
272
279
|
"""The Material class generalizes a material in the EMerge FEM environment.
|
|
273
280
|
|
|
@@ -282,6 +289,8 @@ class Material:
|
|
|
282
289
|
to supply a frequency and coordinate dependent property use: emerge.FreqCoordDependent()
|
|
283
290
|
|
|
284
291
|
"""
|
|
292
|
+
_pickle_exclude = {"_neff"}
|
|
293
|
+
|
|
285
294
|
def __init__(self,
|
|
286
295
|
er: float | complex | np.ndarray | MatProperty = 1.0,
|
|
287
296
|
ur: float | complex | np.ndarray | MatProperty = 1.0,
|
|
@@ -319,6 +328,18 @@ class Material:
|
|
|
319
328
|
hex_str = self.color.lstrip('#')
|
|
320
329
|
self._color_rgb = tuple(int(hex_str[i:i+2], 16)/255.0 for i in (0, 2, 4))
|
|
321
330
|
self._metal: bool = _metal
|
|
331
|
+
|
|
332
|
+
def __getstate__(self):
|
|
333
|
+
state = self.__dict__.copy()
|
|
334
|
+
for k in self._pickle_exclude:
|
|
335
|
+
state.pop(k, None)
|
|
336
|
+
|
|
337
|
+
return state
|
|
338
|
+
|
|
339
|
+
def __setstate__(self, state):
|
|
340
|
+
self.__dict__.update(state)
|
|
341
|
+
for k in self._pickle_exclude:
|
|
342
|
+
setattr(self, k, None)
|
|
322
343
|
|
|
323
344
|
def __hash__(self):
|
|
324
345
|
return self._hash_key
|
emerge/_emerge/mesh3d.py
CHANGED
|
@@ -26,6 +26,8 @@ from loguru import logger
|
|
|
26
26
|
from .bc import Periodic
|
|
27
27
|
from .material import Material
|
|
28
28
|
|
|
29
|
+
_MISSING_ID: int = -1234
|
|
30
|
+
|
|
29
31
|
def shortest_distance(point_cloud):
|
|
30
32
|
"""
|
|
31
33
|
Compute the shortest distance between any two points in a 3D point cloud.
|
|
@@ -128,7 +130,6 @@ class Mesh3D(Mesh):
|
|
|
128
130
|
## States
|
|
129
131
|
self.defined: bool = False
|
|
130
132
|
|
|
131
|
-
|
|
132
133
|
## Memory
|
|
133
134
|
self.ftag_to_tri: dict[int, list[int]] = dict()
|
|
134
135
|
self.ftag_to_node: dict[int, list[int]] = dict()
|
|
@@ -167,8 +168,8 @@ class Mesh3D(Mesh):
|
|
|
167
168
|
if i1==i2:
|
|
168
169
|
raise ValueError("Edge cannot be formed by the same node.")
|
|
169
170
|
search = (min(int(i1),int(i2)), max(int(i1),int(i2)))
|
|
170
|
-
result = self.inv_edges.get(search,
|
|
171
|
-
if result ==
|
|
171
|
+
result = self.inv_edges.get(search, _MISSING_ID)
|
|
172
|
+
if result == _MISSING_ID and not skip:
|
|
172
173
|
raise ValueError(f'There is no edge with indices {i1}, {i2}')
|
|
173
174
|
return result
|
|
174
175
|
|
|
@@ -182,9 +183,10 @@ class Mesh3D(Mesh):
|
|
|
182
183
|
|
|
183
184
|
def get_tri(self, i1, i2, i3) -> int:
|
|
184
185
|
'''Return the triangle index given the three node indices'''
|
|
186
|
+
i11, i21, i31 = tuple(sorted((int(i1), int(i2), int(i3))))
|
|
185
187
|
output = self.inv_tris.get(tuple(sorted((int(i1), int(i2), int(i3)))), None)
|
|
186
188
|
if output is None:
|
|
187
|
-
raise ValueError(f'There is no triangle with indices {
|
|
189
|
+
raise ValueError(f'There is no triangle with indices {i11}, {i21}, {i31}')
|
|
188
190
|
return output
|
|
189
191
|
|
|
190
192
|
def get_tet(self, i1, i2, i3, i4) -> int:
|
|
@@ -302,7 +304,7 @@ class Mesh3D(Mesh):
|
|
|
302
304
|
"""
|
|
303
305
|
from .mth.optimized import area
|
|
304
306
|
|
|
305
|
-
logger.trace('Generating mesh data.')
|
|
307
|
+
logger.trace('Generating internal mesh data.')
|
|
306
308
|
if periodic_bcs is None:
|
|
307
309
|
periodic_bcs = []
|
|
308
310
|
|
|
@@ -383,10 +385,10 @@ class Mesh3D(Mesh):
|
|
|
383
385
|
self.inv_tets = {_hash((self.tets[0,i], self.tets[1,i], self.tets[2,i], self.tets[3,i])): i for i in range(self.tets.shape[1])}
|
|
384
386
|
|
|
385
387
|
# Tet links
|
|
386
|
-
self.tet_to_edge = np.zeros((6, self.tets.shape[1]), dtype=int)
|
|
387
|
-
self.tet_to_edge_sign = np.zeros((6, self.tets.shape[1]), dtype=int)
|
|
388
|
-
self.tet_to_tri = np.zeros((4, self.tets.shape[1]), dtype=int)
|
|
389
|
-
self.tet_to_tri_sign = np.zeros((4, self.tets.shape[1]), dtype=int)
|
|
388
|
+
self.tet_to_edge = np.zeros((6, self.tets.shape[1]), dtype=int) + _MISSING_ID
|
|
389
|
+
self.tet_to_edge_sign = np.zeros((6, self.tets.shape[1]), dtype=int) + _MISSING_ID
|
|
390
|
+
self.tet_to_tri = np.zeros((4, self.tets.shape[1]), dtype=int) + _MISSING_ID
|
|
391
|
+
self.tet_to_tri_sign = np.zeros((4, self.tets.shape[1]), dtype=int) + _MISSING_ID
|
|
390
392
|
|
|
391
393
|
tri_to_tet = defaultdict(list)
|
|
392
394
|
for itet in range(self.tets.shape[1]):
|
|
@@ -408,7 +410,7 @@ class Mesh3D(Mesh):
|
|
|
408
410
|
tri_to_tet[self.tet_to_tri[3, itet]].append(itet)
|
|
409
411
|
|
|
410
412
|
# Tri links
|
|
411
|
-
self.tri_to_tet = np.zeros((2, self.tris.shape[1]), dtype=int)
|
|
413
|
+
self.tri_to_tet = np.zeros((2, self.tris.shape[1]), dtype=int)+_MISSING_ID
|
|
412
414
|
for itri in range(self.tris.shape[1]):
|
|
413
415
|
tets = tri_to_tet[itri]
|
|
414
416
|
self.tri_to_tet[:len(tets), itri] = tets
|
|
@@ -459,7 +461,7 @@ class Mesh3D(Mesh):
|
|
|
459
461
|
ent = np.array(edge_node_tags).reshape(-1,2).T
|
|
460
462
|
nET = ent.shape[1]
|
|
461
463
|
self.edge_t2i = {int(edge_tags[i]): self.get_edge(self.n_t2i[ent[0,i]], self.n_t2i[ent[1,i]], skip=True) for i in range(nET)}
|
|
462
|
-
self.edge_t2i = {key: value for key,value in self.edge_t2i.items() if value!=-
|
|
464
|
+
self.edge_t2i = {key: value for key,value in self.edge_t2i.items() if value!=-_MISSING_ID}
|
|
463
465
|
self.edge_i2t = {i: t for t, i in self.edge_t2i.items()}
|
|
464
466
|
|
|
465
467
|
edge_dimtags = gmsh.model.get_entities(1)
|
|
@@ -479,6 +481,7 @@ class Mesh3D(Mesh):
|
|
|
479
481
|
node_tags = [self.n_t2i[int(t)] for t in node_tags[0]]
|
|
480
482
|
self.ftag_to_node[t] = node_tags
|
|
481
483
|
node_tags = np.squeeze(np.array(node_tags)).reshape(-1,3).T
|
|
484
|
+
|
|
482
485
|
self.ftag_to_tri[t] = [self.get_tri(node_tags[0,i], node_tags[1,i], node_tags[2,i]) for i in range(node_tags.shape[1])]
|
|
483
486
|
self.ftag_to_edge[t] = sorted(list(np.unique(self.tri_to_edge[:,self.ftag_to_tri[t]].flatten())))
|
|
484
487
|
|
|
@@ -502,7 +505,7 @@ class Mesh3D(Mesh):
|
|
|
502
505
|
self.dimtag_to_center[dt] = gmsh.model.occ.get_center_of_mass(*dt)
|
|
503
506
|
self.dimtag_to_edges[dt] = self._domain_edge(dt)
|
|
504
507
|
|
|
505
|
-
logger.trace('
|
|
508
|
+
logger.trace('Finalized mesh data generation!')
|
|
506
509
|
|
|
507
510
|
|
|
508
511
|
## Higher order functions
|
|
@@ -548,7 +551,7 @@ class Mesh3D(Mesh):
|
|
|
548
551
|
node_ids_2_arry = np.array(node_ids_2)
|
|
549
552
|
dv = np.array(bc.dv)
|
|
550
553
|
|
|
551
|
-
nodemap = pair_coordinates(self.nodes, node_ids_1_arry, node_ids_2_arry, dv, dsmin/
|
|
554
|
+
nodemap = pair_coordinates(self.nodes, node_ids_1_arry, node_ids_2_arry, dv, dsmin/4)
|
|
552
555
|
node_ids_2_unsorted = [nodemap[i] for i in sorted(node_ids_1)]
|
|
553
556
|
node_ids_2_sorted = sorted(node_ids_2_unsorted)
|
|
554
557
|
conv_map = {i1: i2 for i1, i2 in zip(node_ids_2_unsorted, node_ids_2_sorted)}
|