emerge 1.0.3__py3-none-any.whl → 1.0.5__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 +6 -3
- emerge/_emerge/geo/polybased.py +37 -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 +77 -21
- emerge/_emerge/simulation_data.py +22 -4
- emerge/_emerge/solver.py +67 -32
- {emerge-1.0.3.dist-info → emerge-1.0.5.dist-info}/METADATA +2 -3
- {emerge-1.0.3.dist-info → emerge-1.0.5.dist-info}/RECORD +30 -28
- {emerge-1.0.3.dist-info → emerge-1.0.5.dist-info}/WHEEL +0 -0
- {emerge-1.0.3.dist-info → emerge-1.0.5.dist-info}/entry_points.txt +0 -0
- {emerge-1.0.3.dist-info → emerge-1.0.5.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.5"
|
|
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
|
@@ -51,11 +51,13 @@ def add(main: T, tool: T,
|
|
|
51
51
|
GeoSurface | GeoVolume
|
|
52
52
|
A new object that is the union of the main and tool objects.
|
|
53
53
|
'''
|
|
54
|
+
|
|
54
55
|
out_dim_tags, out_dim_tags_map = gmsh.model.occ.fuse(main.dimtags, tool.dimtags, removeObject=remove_object, removeTool=remove_tool)
|
|
55
56
|
if out_dim_tags[0][0] == 3:
|
|
56
57
|
output = GeoVolume([dt[1] for dt in out_dim_tags])._take_tools(tool,main)
|
|
57
58
|
elif out_dim_tags[0][0] == 2:
|
|
58
59
|
output = GeoSurface([dt[1] for dt in out_dim_tags])._take_tools(tool,main)
|
|
60
|
+
|
|
59
61
|
if remove_object:
|
|
60
62
|
main._exists = False
|
|
61
63
|
if remove_tool:
|
|
@@ -300,15 +302,16 @@ def unite(*objects: GeoObject) -> GeoObject:
|
|
|
300
302
|
GeoObject: The resultant object
|
|
301
303
|
"""
|
|
302
304
|
main, *rest = objects
|
|
305
|
+
|
|
303
306
|
if not rest:
|
|
304
307
|
return main
|
|
308
|
+
|
|
305
309
|
main._exists = False
|
|
306
310
|
dts = []
|
|
307
|
-
for other in
|
|
311
|
+
for other in objects:
|
|
308
312
|
dts.extend(other.dimtags)
|
|
309
313
|
other._exists = False
|
|
310
|
-
|
|
311
|
-
new_dimtags, mapping = gmsh.model.occ.fuse(main.dimtags, dts)
|
|
314
|
+
new_dimtags, mapping = gmsh.model.occ.fuse(dts, main.dimtags)
|
|
312
315
|
|
|
313
316
|
new_obj = GeoObject.from_dimtags(new_dimtags)._take_tools(*objects)
|
|
314
317
|
new_obj.set_material(main.material)
|
emerge/_emerge/geo/polybased.py
CHANGED
|
@@ -24,6 +24,7 @@ from typing import Generator, Callable
|
|
|
24
24
|
from ..selection import FaceSelection
|
|
25
25
|
from typing import Literal
|
|
26
26
|
from functools import reduce
|
|
27
|
+
from loguru import logger
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
def _discretize_curve(xfunc: Callable, yfunc: Callable,
|
|
@@ -238,7 +239,8 @@ class XYPolygon:
|
|
|
238
239
|
def __init__(self,
|
|
239
240
|
xs: np.ndarray | list | tuple | None = None,
|
|
240
241
|
ys: np.ndarray | list | tuple | None = None,
|
|
241
|
-
cs: CoordinateSystem | None = None
|
|
242
|
+
cs: CoordinateSystem | None = None,
|
|
243
|
+
resolution: float = 1e-6):
|
|
242
244
|
"""Constructs an XY-plane placed polygon.
|
|
243
245
|
|
|
244
246
|
Args:
|
|
@@ -256,6 +258,7 @@ class XYPolygon:
|
|
|
256
258
|
self.fillets: list[tuple[float, int]] = []
|
|
257
259
|
|
|
258
260
|
self._cs: CoordinateSystem = cs
|
|
261
|
+
self.resolution: float = resolution
|
|
259
262
|
|
|
260
263
|
@property
|
|
261
264
|
def center(self) -> tuple[float, float]:
|
|
@@ -279,7 +282,7 @@ class XYPolygon:
|
|
|
279
282
|
The XYPolygon does not store redundant points p[0]==p[N] so if these are
|
|
280
283
|
the same, this function will remove the last point.
|
|
281
284
|
"""
|
|
282
|
-
if np.sqrt((self.x[-1]-self.x[0])**2 + (self.y[-1]-self.y[0])**2) < 1e-
|
|
285
|
+
if np.sqrt((self.x[-1]-self.x[0])**2 + (self.y[-1]-self.y[0])**2) < 1e-9:
|
|
283
286
|
self.x = self.x[:-1]
|
|
284
287
|
self.y = self.y[:-1]
|
|
285
288
|
|
|
@@ -329,6 +332,23 @@ class XYPolygon:
|
|
|
329
332
|
self.fillets.append((radius, i))
|
|
330
333
|
return self
|
|
331
334
|
|
|
335
|
+
def _cleanup(self, resolution: float | None = None) -> None:
|
|
336
|
+
# Compute differences between consecutive points
|
|
337
|
+
if resolution is None:
|
|
338
|
+
resolution = self.resolution
|
|
339
|
+
dx = np.diff(self.x)
|
|
340
|
+
dy = np.diff(self.y)
|
|
341
|
+
|
|
342
|
+
# Distances between consecutive points
|
|
343
|
+
dist = np.sqrt(dx**2 + dy**2)
|
|
344
|
+
|
|
345
|
+
# Keep the first point, then points where distance >= threshold
|
|
346
|
+
keep = np.insert(dist >= resolution, 1, True)
|
|
347
|
+
|
|
348
|
+
# Apply mask
|
|
349
|
+
self.x = self.x[keep]
|
|
350
|
+
self.y = self.y[keep]
|
|
351
|
+
|
|
332
352
|
def _make_wire(self, cs: CoordinateSystem) -> tuple[list[int], list[int], int]:
|
|
333
353
|
"""Turns the XYPolygon object into a GeoPolygon that is embedded in 3D space.
|
|
334
354
|
|
|
@@ -343,10 +363,23 @@ class XYPolygon:
|
|
|
343
363
|
self._check()
|
|
344
364
|
|
|
345
365
|
ptags = []
|
|
366
|
+
|
|
346
367
|
xg, yg, zg = cs.in_global_cs(self.x, self.y, 0*self.x)
|
|
347
368
|
|
|
369
|
+
points = dict()
|
|
348
370
|
for x,y,z in zip(xg, yg, zg):
|
|
349
|
-
|
|
371
|
+
reuse = False
|
|
372
|
+
for key, (px, py, pz) in points.items():
|
|
373
|
+
if ((x-px)**2 + (y-py)**2 + (z-pz)**2)**0.5 < 1e-12:
|
|
374
|
+
ptags.append(key)
|
|
375
|
+
reuse = True
|
|
376
|
+
break
|
|
377
|
+
if reuse:
|
|
378
|
+
logger.warning(f'Reusing {ptags[-1]}')
|
|
379
|
+
continue
|
|
380
|
+
ptag = gmsh.model.occ.add_point(x,y,z)
|
|
381
|
+
points[ptag] = (x,y,z)
|
|
382
|
+
ptags.append(ptag)
|
|
350
383
|
|
|
351
384
|
lines = []
|
|
352
385
|
for i1, p1 in enumerate(ptags):
|
|
@@ -375,6 +408,7 @@ class XYPolygon:
|
|
|
375
408
|
Returns:
|
|
376
409
|
GeoPolygon: The resultant 3D GeoPolygon object.
|
|
377
410
|
"""
|
|
411
|
+
self._cleanup()
|
|
378
412
|
ptags, lines, wiretag = self._make_wire(cs)
|
|
379
413
|
surftag = gmsh.model.occ.add_plane_surface([wiretag,])
|
|
380
414
|
poly = GeoPolygon([surftag,], name=name)
|
|
@@ -635,8 +669,6 @@ class Curve(GeoEdge):
|
|
|
635
669
|
self.dstart: tuple[float, float, float] = (p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
|
|
636
670
|
|
|
637
671
|
|
|
638
|
-
|
|
639
|
-
|
|
640
672
|
@property
|
|
641
673
|
def p0(self) -> tuple[float, float, float]:
|
|
642
674
|
"""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
|