emerge 0.6.7__tar.gz → 0.6.9__tar.gz
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-0.6.7 → emerge-0.6.9}/.bumpversion.toml +1 -1
- {emerge-0.6.7 → emerge-0.6.9}/.gitignore +3 -2
- {emerge-0.6.7 → emerge-0.6.9}/LICENSE +2 -2
- {emerge-0.6.7 → emerge-0.6.9}/PKG-INFO +2 -1
- {emerge-0.6.7 → emerge-0.6.9}/emerge/__init__.py +2 -2
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/_cache_check.py +1 -1
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/elements/femdata.py +3 -2
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/elements/index_interp.py +1 -2
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/elements/ned2_interp.py +16 -16
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/elements/nedelec2.py +17 -6
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/elements/nedleg2.py +21 -9
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/geo/__init__.py +1 -1
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/geo/horn.py +0 -1
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/geo/modeler.py +1 -1
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/geo/operations.py +13 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/geo/pcb_tools/calculator.py +2 -3
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/geo/pmlbox.py +35 -11
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/geometry.py +13 -6
- emerge-0.6.9/emerge/_emerge/material.py +375 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/mesh3d.py +14 -8
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/assembly/assembler.py +43 -20
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/microwave_3d.py +57 -44
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/microwave_bc.py +26 -24
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/microwave_data.py +90 -7
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/plot/pyvista/display.py +53 -15
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/plot/pyvista/display_settings.py +4 -1
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/plot/simple_plots.py +42 -26
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/projects/_load_base.txt +1 -2
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/selection.py +4 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/simmodel.py +21 -9
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/solver.py +45 -18
- emerge-0.6.9/emerge/lib.py +313 -0
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo10_sgh.py +12 -10
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo11_lumped_element_filter.py +3 -1
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo12_mode_alignment.py +2 -2
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo13_helix_antenna.py +4 -12
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo14_boundary_selection.py +7 -12
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo1_stepped_imp_filter.py +4 -4
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo2_combline_filter.py +6 -6
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo3_coupled_line_filter.py +3 -3
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo4_patch_antenna.py +40 -34
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo5_revolve.py +1 -1
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo6_striplines_with_vias.py +13 -13
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo7_periodic_cells.py +22 -19
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo8_waveguide_bpf_synthesis.py +4 -4
- {emerge-0.6.7 → emerge-0.6.9}/examples/demo9_dielectric_resonator.py +4 -3
- {emerge-0.6.7 → emerge-0.6.9}/pyproject.toml +2 -1
- {emerge-0.6.7 → emerge-0.6.9}/uv.lock +12 -1
- emerge-0.6.7/emerge/_emerge/material.py +0 -123
- emerge-0.6.7/emerge/lib.py +0 -307
- emerge-0.6.7/src/_img/logo.jpeg +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/.opt +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/.python-version +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/README.md +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/THIRD_PARTY_LICENSES.md +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/UMFPACK_Install_windows.md +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/UMFPACK_installer_windows.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/__main__.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/__init__.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/bc.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/const.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/coord.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/cs.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/dataset.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/elements/__init__.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/geo/pcb.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/geo/pcb_tools/macro.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/geo/polybased.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/geo/shapes.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/geo/step.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/geo2d.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/howto.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/logsettings.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/mesher.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/mth/common_functions.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/mth/integrals.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/mth/optimized.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/mth/pairing.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/periodic.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/__init__.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/__init__.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/adaptive_freq.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/assembly/curlcurl.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/assembly/generalized_eigen.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/assembly/generalized_eigen_hb.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/assembly/periodicbc.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/assembly/robinbc.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/periodic.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/port_functions.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/sc.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/simjob.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/sparam.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/physics/microwave/touchstone.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/plot/__init__.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/plot/display.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/plot/matplotlib/mpldisplay.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/plot/pyvista/__init__.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/plot.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/projects/__init__.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/projects/_gen_base.txt +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/projects/generate_project.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/simulation_data.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/solve_interfaces/cudss_interface.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/solve_interfaces/pardiso_interface.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/_emerge/system.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/cli.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/ext.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/plot.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/emerge/pyvista.py +0 -0
- {emerge-0.6.7 → emerge-0.6.9}/src/__init__.py +0 -0
|
@@ -8,8 +8,8 @@ wheels/
|
|
|
8
8
|
|
|
9
9
|
# Virtual environments
|
|
10
10
|
.venv
|
|
11
|
-
.vscode
|
|
12
11
|
.mypy_cache
|
|
12
|
+
environment.yml
|
|
13
13
|
|
|
14
14
|
# paths
|
|
15
15
|
meshes/
|
|
@@ -42,8 +42,9 @@ manual_scripts/
|
|
|
42
42
|
tests/
|
|
43
43
|
trial_scripts/
|
|
44
44
|
wheelhouse/
|
|
45
|
-
|
|
45
|
+
benchmarks/
|
|
46
46
|
.pytest_cache/
|
|
47
47
|
|
|
48
48
|
.vscode/
|
|
49
|
+
.idea/
|
|
49
50
|
pytest.ini
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
──────────────────────────────────────────────────────────────────────────────
|
|
2
|
-
PREAMBLE
|
|
2
|
+
PREAMBLE - Licence map and disclaimers (not part of the GNU GPL text)
|
|
3
3
|
──────────────────────────────────────────────────────────────────────────────
|
|
4
4
|
This repository is distributed under two distinct licences:
|
|
5
5
|
|
|
@@ -11,7 +11,7 @@ This repository is distributed under two distinct licences:
|
|
|
11
11
|
When you distribute binaries containing these components, the complete
|
|
12
12
|
corresponding source code must be offered under GPL-2.0+.
|
|
13
13
|
|
|
14
|
-
• **`lib.py`
|
|
14
|
+
• **`lib.py` - materials-property database**
|
|
15
15
|
This single file is dedicated to the public domain under **CC0 1.0**.
|
|
16
16
|
You may copy, modify, merge, publish, distribute, sublicense and/or sell
|
|
17
17
|
copies of `lib.py` without restriction. The data it contains are
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: emerge
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.9
|
|
4
4
|
Summary: An open source EM FEM simulator in Python
|
|
5
5
|
Project-URL: Homepage, https://github.com/FennisRobert/EMerge
|
|
6
6
|
Project-URL: Issues, https://github.com/FennisRobert/EMerge/issues
|
|
7
7
|
License-File: LICENSE
|
|
8
8
|
Requires-Python: <4.0,>=3.10
|
|
9
|
+
Requires-Dist: cloudpickle>=3.1.1
|
|
9
10
|
Requires-Dist: gmsh<4.14.0,>=4.13.0
|
|
10
11
|
Requires-Dist: joblib>=1.5.1
|
|
11
12
|
Requires-Dist: loguru>=0.7.3
|
|
@@ -18,7 +18,7 @@ along with this program; if not, see
|
|
|
18
18
|
"""
|
|
19
19
|
import os
|
|
20
20
|
|
|
21
|
-
__version__ = "0.6.
|
|
21
|
+
__version__ = "0.6.9"
|
|
22
22
|
|
|
23
23
|
############################################################
|
|
24
24
|
# HANDLE ENVIRONMENT VARIABLES #
|
|
@@ -45,7 +45,7 @@ LOG_CONTROLLER.set_default()
|
|
|
45
45
|
logger.debug('Importing modules')
|
|
46
46
|
|
|
47
47
|
from ._emerge.simmodel import Simulation
|
|
48
|
-
from ._emerge.material import Material
|
|
48
|
+
from ._emerge.material import Material, FreqCoordDependent, FreqDependent, CoordDependent
|
|
49
49
|
from ._emerge import bc
|
|
50
50
|
from ._emerge.solver import SolverBicgstab, SolverGMRES, SolveRoutine, ReverseCuthillMckee, Sorter, SolverPardiso, SolverUMFPACK, SolverSuperLU, EMSolver
|
|
51
51
|
from ._emerge.cs import CoordinateSystem, CS, GCS, Plane, Axis, XAX, YAX, ZAX, XYPLANE, XZPLANE, YZPLANE, YXPLANE, ZXPLANE, ZYPLANE
|
|
@@ -22,7 +22,7 @@ _COMPILE_MESSAGE = """
|
|
|
22
22
|
[ EMERGE ]
|
|
23
23
|
⚠ Numba is compiling optimized code; this may take a few minutes.
|
|
24
24
|
• Additional functions may be compiled on-the-fly.
|
|
25
|
-
• Compilation happens only once
|
|
25
|
+
• Compilation happens only once-subsequent runs load from cache.
|
|
26
26
|
Please wait…"""
|
|
27
27
|
|
|
28
28
|
@njit(cache=True)
|
|
@@ -64,7 +64,7 @@ class FEMBasis:
|
|
|
64
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]:
|
|
65
65
|
raise NotImplementedError()
|
|
66
66
|
|
|
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) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
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]:
|
|
68
68
|
"""
|
|
69
69
|
Interpolates the curl of the field at the given points.
|
|
70
70
|
"""
|
|
@@ -151,7 +151,8 @@ class FEMBasis:
|
|
|
151
151
|
def interpolate_index(self, xs: np.ndarray,
|
|
152
152
|
ys: np.ndarray,
|
|
153
153
|
zs: np.ndarray,
|
|
154
|
-
tetids: np.ndarray | None = None
|
|
154
|
+
tetids: np.ndarray | None = None,
|
|
155
|
+
usenan: bool = True) -> np.ndarray:
|
|
155
156
|
raise NotImplementedError()
|
|
156
157
|
|
|
157
158
|
def map_edge_to_field(self, edge_ids: np.ndarray) -> np.ndarray:
|
|
@@ -27,9 +27,8 @@ def index_interp(coords: np.ndarray,
|
|
|
27
27
|
# Solution has shape (nEdges, nsols)
|
|
28
28
|
nNodes = coords.shape[1]
|
|
29
29
|
|
|
30
|
-
prop = np.
|
|
30
|
+
prop = np.full((nNodes, ), -1, dtype=np.int64)
|
|
31
31
|
|
|
32
|
-
|
|
33
32
|
for i_iter in range(tetids.shape[0]):
|
|
34
33
|
itet = tetids[i_iter]
|
|
35
34
|
|
|
@@ -130,10 +130,10 @@ def ned2_tet_interp(coords: np.ndarray,
|
|
|
130
130
|
ys = coords[1,:]
|
|
131
131
|
zs = coords[2,:]
|
|
132
132
|
|
|
133
|
-
Ex = np.
|
|
134
|
-
Ey = np.
|
|
135
|
-
Ez = np.
|
|
136
|
-
|
|
133
|
+
Ex = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
134
|
+
Ey = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
135
|
+
Ez = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
136
|
+
|
|
137
137
|
for i_iter in range(tetids.shape[0]):
|
|
138
138
|
itet = tetids[i_iter]
|
|
139
139
|
|
|
@@ -259,9 +259,9 @@ def ned2_tet_interp_curl(coords: np.ndarray,
|
|
|
259
259
|
ys = coords[1,:]
|
|
260
260
|
zs = coords[2,:]
|
|
261
261
|
|
|
262
|
-
Ex = np.
|
|
263
|
-
Ey = np.
|
|
264
|
-
Ez = np.
|
|
262
|
+
Ex = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
263
|
+
Ey = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
264
|
+
Ez = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
265
265
|
|
|
266
266
|
for i_iter in range(tetids.shape[0]):
|
|
267
267
|
itet = tetids[i_iter]
|
|
@@ -382,9 +382,9 @@ def ned2_tri_interp(coords: np.ndarray,
|
|
|
382
382
|
xs = coords[0,:]
|
|
383
383
|
ys = coords[1,:]
|
|
384
384
|
|
|
385
|
-
Ex = np.
|
|
386
|
-
Ey = np.
|
|
387
|
-
Ez = np.
|
|
385
|
+
Ex = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
386
|
+
Ey = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
387
|
+
Ez = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
388
388
|
|
|
389
389
|
nodes = nodes[:2,:]
|
|
390
390
|
|
|
@@ -491,9 +491,9 @@ def ned2_tri_interp_full(coords: np.ndarray,
|
|
|
491
491
|
xs = coords[0,:]
|
|
492
492
|
ys = coords[1,:]
|
|
493
493
|
|
|
494
|
-
Ex = np.
|
|
495
|
-
Ey = np.
|
|
496
|
-
Ez = np.
|
|
494
|
+
Ex = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
495
|
+
Ey = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
496
|
+
Ez = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
497
497
|
|
|
498
498
|
nodes = nodes[:2,:]
|
|
499
499
|
|
|
@@ -572,9 +572,9 @@ def ned2_tri_interp_curl(coords: np.ndarray,
|
|
|
572
572
|
xs = coords[0,:]
|
|
573
573
|
ys = coords[1,:]
|
|
574
574
|
jB = 1j*beta
|
|
575
|
-
Ex = np.
|
|
576
|
-
Ey = np.
|
|
577
|
-
Ez = np.
|
|
575
|
+
Ex = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
576
|
+
Ey = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
577
|
+
Ez = np.full((nNodes, ), np.nan, dtype=np.complex128)
|
|
578
578
|
|
|
579
579
|
nodes = nodes[:2,:]
|
|
580
580
|
|
|
@@ -68,30 +68,41 @@ class Nedelec2(FEMBasis):
|
|
|
68
68
|
|
|
69
69
|
self.empty_tri_rowcol()
|
|
70
70
|
|
|
71
|
-
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]:
|
|
71
|
+
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]:
|
|
72
72
|
'''
|
|
73
73
|
Interpolate the provided field data array at the given xs, ys and zs coordinates
|
|
74
74
|
'''
|
|
75
75
|
if tetids is None:
|
|
76
76
|
tetids = self._all_tet_ids
|
|
77
|
-
|
|
77
|
+
vals = ned2_tet_interp(np.array([xs, ys, zs]), field, self.mesh.tets, self.mesh.tris, self.mesh.edges, self.mesh.nodes, self.tet_to_field, tetids)
|
|
78
|
+
if not usenan:
|
|
79
|
+
vals = np.nan_to_num(vals)
|
|
80
|
+
return vals
|
|
78
81
|
|
|
79
|
-
def interpolate_curl(self, field: np.ndarray, xs: np.ndarray, ys: np.ndarray, zs:np.ndarray, c: np.ndarray, tetids: np.ndarray | None = None) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
82
|
+
def interpolate_curl(self, field: np.ndarray, xs: np.ndarray, ys: np.ndarray, zs:np.ndarray, c: np.ndarray, tetids: np.ndarray | None = None, usenan: bool = True) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
80
83
|
"""
|
|
81
84
|
Interpolates the curl of the field at the given points.
|
|
82
85
|
"""
|
|
83
86
|
if tetids is None:
|
|
84
87
|
tetids = self._all_tet_ids
|
|
85
|
-
|
|
88
|
+
vals = ned2_tet_interp_curl(np.array([xs, ys, zs]), field, self.mesh.tets, self.mesh.tris, self.mesh.edges, self.mesh.nodes, self.tet_to_field, c, tetids)
|
|
89
|
+
if not usenan:
|
|
90
|
+
vals = np.nan_to_num(vals)
|
|
91
|
+
return vals
|
|
86
92
|
|
|
87
93
|
def interpolate_index(self, xs: np.ndarray,
|
|
88
94
|
ys: np.ndarray,
|
|
89
95
|
zs: np.ndarray,
|
|
90
|
-
tetids: np.ndarray | None = None
|
|
96
|
+
tetids: np.ndarray | None = None,
|
|
97
|
+
usenan: bool = True) -> np.ndarray:
|
|
91
98
|
if tetids is None:
|
|
92
99
|
tetids = self._all_tet_ids
|
|
93
100
|
|
|
94
|
-
|
|
101
|
+
vals = index_interp(np.array([xs, ys, zs]), self.mesh.tets, self.mesh.nodes, tetids)
|
|
102
|
+
if not usenan:
|
|
103
|
+
vals[vals==-1]==0
|
|
104
|
+
return vals
|
|
105
|
+
|
|
95
106
|
###### INDEX MAPPINGS
|
|
96
107
|
|
|
97
108
|
def local_tet_to_triid(self, itet: int) -> np.ndarray:
|
|
@@ -73,24 +73,30 @@ class FieldFunctionClass:
|
|
|
73
73
|
Fx, Fy, Fz = self.cs.in_global_basis(Fxl, Fyl, Fzl)
|
|
74
74
|
return np.array([Fx, Fy, Fz])*self.constant
|
|
75
75
|
|
|
76
|
-
def calcE(self, xs: np.ndarray, ys: np.ndarray) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
76
|
+
def calcE(self, xs: np.ndarray, ys: np.ndarray, usenan: bool = False) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
77
77
|
coordinates = np.array([xs, ys])
|
|
78
|
-
|
|
78
|
+
vals = ned2_tri_interp_full(coordinates,
|
|
79
79
|
self.field,
|
|
80
80
|
self.tris,
|
|
81
81
|
self.nodes,
|
|
82
82
|
self.tri_to_field)
|
|
83
|
+
if not usenan:
|
|
84
|
+
vals = np.nan_to_num(vals)
|
|
85
|
+
return vals
|
|
83
86
|
|
|
84
|
-
def calcH(self, xs: np.ndarray, ys: np.ndarray) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
87
|
+
def calcH(self, xs: np.ndarray, ys: np.ndarray, usenan: bool = False) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
85
88
|
coordinates = np.array([xs, ys])
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
vals = ned2_tri_interp_curl(coordinates,
|
|
88
91
|
self.field,
|
|
89
92
|
self.tris,
|
|
90
93
|
self.nodes,
|
|
91
94
|
self.tri_to_field,
|
|
92
95
|
self.diadic,
|
|
93
96
|
self.beta)
|
|
97
|
+
if not usenan:
|
|
98
|
+
vals = np.nan_to_num(vals)
|
|
99
|
+
return vals
|
|
94
100
|
|
|
95
101
|
############### Nedelec2 Class
|
|
96
102
|
|
|
@@ -178,22 +184,28 @@ class NedelecLegrange2(FEMBasis):
|
|
|
178
184
|
|
|
179
185
|
return FieldFunctionClass(field, self.cs, self.local_nodes, self.mesh.tris, self.tri_to_field, 'H', urinv, beta, constant)
|
|
180
186
|
|
|
181
|
-
def tri_interpolate(self, field, xs: np.ndarray, ys: np.ndarray) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
187
|
+
def tri_interpolate(self, field, xs: np.ndarray, ys: np.ndarray, usenan: bool = False) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
182
188
|
coordinates = np.array([xs, ys])
|
|
183
|
-
|
|
189
|
+
vals = ned2_tri_interp_full(coordinates,
|
|
184
190
|
field,
|
|
185
191
|
self.mesh.tris,
|
|
186
192
|
self.local_nodes,
|
|
187
193
|
self.tri_to_field)
|
|
194
|
+
if not usenan:
|
|
195
|
+
vals = np.nan_to_num(vals)
|
|
196
|
+
return vals
|
|
188
197
|
|
|
189
|
-
def tri_interpolate_curl(self, field, xs: np.ndarray, ys: np.ndarray, diadic: np.ndarray | None = None, beta: float = 0.0) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
198
|
+
def tri_interpolate_curl(self, field, xs: np.ndarray, ys: np.ndarray, diadic: np.ndarray | None = None, beta: float = 0.0, usenan: bool = False) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
190
199
|
coordinates = np.array([xs, ys])
|
|
191
200
|
if diadic is None:
|
|
192
201
|
diadic = np.eye(3)[:,:,np.newaxis()] * np.ones((self.mesh.n_tris)) # type: ignore
|
|
193
|
-
|
|
202
|
+
vals = ned2_tri_interp_curl(coordinates,
|
|
194
203
|
field,
|
|
195
204
|
self.mesh.tris,
|
|
196
205
|
self.local_nodes,
|
|
197
206
|
self.tri_to_field,
|
|
198
207
|
diadic,
|
|
199
|
-
beta)
|
|
208
|
+
beta)
|
|
209
|
+
if not usenan:
|
|
210
|
+
vals = np.nan_to_num(vals)
|
|
211
|
+
return vals
|
|
@@ -19,6 +19,6 @@ from .pcb import PCB
|
|
|
19
19
|
from .pmlbox import pmlbox
|
|
20
20
|
from .horn import Horn
|
|
21
21
|
from .shapes import Cylinder, CoaxCylinder, Box, XYPlate, HalfSphere, Sphere, Plate, OldBox, Alignment, Cone
|
|
22
|
-
from .operations import subtract, add, embed, remove, rotate, mirror, change_coordinate_system, translate, intersect, unite, expand_surface
|
|
22
|
+
from .operations import subtract, add, embed, remove, rotate, mirror, change_coordinate_system, translate, intersect, unite, expand_surface, stretch
|
|
23
23
|
from .polybased import XYPolygon, GeoPrism, Disc, Curve
|
|
24
24
|
from .step import STEPItems
|
|
@@ -268,6 +268,19 @@ def change_coordinate_system(main: GeoObject,
|
|
|
268
268
|
fp.affine_transform(M2)
|
|
269
269
|
return main
|
|
270
270
|
|
|
271
|
+
def stretch(main: GeoObject, fx: float = 1, fy: float = 1, fz: float = 1, origin: tuple[float, float, float] = (0.0, 0.0, 0.0)) -> GeoObject:
|
|
272
|
+
"""Stretches a geometry with a factor fx, fy and fz along the x, y and Z axes respectively
|
|
273
|
+
|
|
274
|
+
The stretch origin is centered at the provided origin.
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
_type_: _description_
|
|
278
|
+
"""
|
|
279
|
+
gmsh.model.occ.dilate(main.dimtags, *origin, fx, fy, fz)
|
|
280
|
+
|
|
281
|
+
return main
|
|
282
|
+
|
|
283
|
+
|
|
271
284
|
@overload
|
|
272
285
|
def unite(*objects: GeoVolume) -> GeoVolume: ...
|
|
273
286
|
|
|
@@ -20,9 +20,8 @@ class PCBCalculator:
|
|
|
20
20
|
self.mat = material
|
|
21
21
|
self.unit = unit
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
def z0(self, Z0: float, layer: int = -1, ground_layer: int = 0):
|
|
23
|
+
def z0(self, Z0: float, layer: int = -1, ground_layer: int = 0, f0: float = 1e9):
|
|
25
24
|
th = abs(self.layers[layer] - self.layers[ground_layer])*self.unit
|
|
26
25
|
ws = np.geomspace(1e-6,1e-1,101)
|
|
27
|
-
Z0ms = microstrip_z0(ws, th, self.mat.er)
|
|
26
|
+
Z0ms = microstrip_z0(ws, th, self.mat.er.scalar(f0))
|
|
28
27
|
return np.interp(Z0, Z0ms[::-1], ws[::-1])/self.unit
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
from ..geometry import GeoVolume
|
|
19
19
|
from .shapes import Box, Alignment, Plate
|
|
20
|
-
from ..material import Material, AIR
|
|
20
|
+
from ..material import Material, AIR, CoordDependent
|
|
21
21
|
import numpy as np
|
|
22
22
|
from functools import partial
|
|
23
23
|
|
|
@@ -31,6 +31,15 @@ def _add_pml_layer(center: tuple[float, float, float],
|
|
|
31
31
|
exponent: float,
|
|
32
32
|
deltamax: float,
|
|
33
33
|
material: Material) -> GeoVolume:
|
|
34
|
+
|
|
35
|
+
if material.frequency_dependent:
|
|
36
|
+
raise ValueError('EMerge cannot handle frequency dependent material properties for PML layers at this point.')
|
|
37
|
+
if material.coordinate_dependent:
|
|
38
|
+
raise ValueError('Its not possible to define PML regions for materials that are coordinate dependent.')
|
|
39
|
+
|
|
40
|
+
mater = material.er.scalar(1e9)
|
|
41
|
+
matur = material.ur.scalar(1e9)
|
|
42
|
+
|
|
34
43
|
px, py, pz = center
|
|
35
44
|
W,D,H = dims
|
|
36
45
|
dx, dy, dz = direction
|
|
@@ -69,15 +78,16 @@ def _add_pml_layer(center: tuple[float, float, float],
|
|
|
69
78
|
|
|
70
79
|
def ermat(x, y, z):
|
|
71
80
|
ers = np.zeros((3,3,x.shape[0]), dtype=np.complex128)
|
|
72
|
-
ers[0,0,:] =
|
|
73
|
-
ers[1,1,:] =
|
|
74
|
-
ers[2,2,:] =
|
|
81
|
+
ers[0,0,:] = mater * syf(x,y,z)*szf(x,y,z)/sxf(x,y,z)
|
|
82
|
+
ers[1,1,:] = mater * szf(x,y,z)*sxf(x,y,z)/syf(x,y,z)
|
|
83
|
+
ers[2,2,:] = mater * sxf(x,y,z)*syf(x,y,z)/szf(x,y,z)
|
|
75
84
|
return ers
|
|
85
|
+
|
|
76
86
|
def urmat(x, y, z):
|
|
77
87
|
urs = np.zeros((3,3,x.shape[0]), dtype=np.complex128)
|
|
78
|
-
urs[0,0,:] =
|
|
79
|
-
urs[1,1,:] =
|
|
80
|
-
urs[2,2,:] =
|
|
88
|
+
urs[0,0,:] = matur * syf(x,y,z)*szf(x,y,z)/sxf(x,y,z)
|
|
89
|
+
urs[1,1,:] = matur * szf(x,y,z)*sxf(x,y,z)/syf(x,y,z)
|
|
90
|
+
urs[2,2,:] = matur * sxf(x,y,z)*syf(x,y,z)/szf(x,y,z)
|
|
81
91
|
return urs
|
|
82
92
|
|
|
83
93
|
pml_box = Box(*pml_block_size, new_center, alignment=Alignment.CENTER)
|
|
@@ -106,7 +116,9 @@ def _add_pml_layer(center: tuple[float, float, float],
|
|
|
106
116
|
plate = Plate(np.array([p0x-tW/2, p0y-tD/2, p0z-dz*thickness/2 + dz*(n+1)*thl]), ax1, ax2)
|
|
107
117
|
planes.append(plate)
|
|
108
118
|
|
|
109
|
-
|
|
119
|
+
erfunc = CoordDependent(max_value=mater, matrix=ermat)
|
|
120
|
+
urfunc = CoordDependent(max_value=matur, matrix=urmat)
|
|
121
|
+
pml_box.material = Material(er=erfunc, ur=urfunc,_neff=np.sqrt(mater*matur), color='#bbbbff', opacity=0.1)
|
|
110
122
|
pml_box.max_meshsize = thickness/N_mesh_layers
|
|
111
123
|
pml_box._embeddings = planes
|
|
112
124
|
|
|
@@ -121,9 +133,10 @@ def pmlbox(width: float,
|
|
|
121
133
|
material: Material = AIR,
|
|
122
134
|
thickness: float = 0.1,
|
|
123
135
|
Nlayers: int = 1,
|
|
124
|
-
N_mesh_layers: int =
|
|
136
|
+
N_mesh_layers: int = 5,
|
|
125
137
|
exponent: float = 1.5,
|
|
126
138
|
deltamax: float = 8.0,
|
|
139
|
+
sides: str = '',
|
|
127
140
|
top: bool = False,
|
|
128
141
|
bottom: bool = False,
|
|
129
142
|
left: bool = False,
|
|
@@ -145,10 +158,11 @@ def pmlbox(width: float,
|
|
|
145
158
|
alignment (Alignment, optional): Which point of the box is placed at the given coordinate. Defaults to Alignment.CORNER.
|
|
146
159
|
material (Material, optional): The material of the box. Defaults to AIR.
|
|
147
160
|
thickness (float, optional): The thickness of the PML Layer. Defaults to 0.1.
|
|
148
|
-
Nlayers (int, optional): The number of PML layers
|
|
149
|
-
N_mesh_layers (int, optional): The number of mesh layers. Sets the discretization size accordingly. Defaults to
|
|
161
|
+
Nlayers (int, optional): The number of geometrical PML layers. Defaults to 1.
|
|
162
|
+
N_mesh_layers (int, optional): The number of mesh layers. Sets the discretization size accordingly. Defaults to 5
|
|
150
163
|
exponent (float, optional): The PML gradient growth function. Defaults to 1.5.
|
|
151
164
|
deltamax (float, optional): A PML matching coefficient. Defaults to 8.0.
|
|
165
|
+
sides (str, optional): A string of pml sides as characters ([T]op, [B]ottom, [L]eft, [R]ight, [F]ront, b[A]ck)
|
|
152
166
|
top (bool, optional): Add a top PML layer. Defaults to True.
|
|
153
167
|
bottom (bool, optional): Add a bottom PML layer. Defaults to False.
|
|
154
168
|
left (bool, optional): Add a left PML layer. Defaults to False.
|
|
@@ -159,6 +173,16 @@ def pmlbox(width: float,
|
|
|
159
173
|
Returns:
|
|
160
174
|
list[GeoVolume]: A list of objects [main box, *pml boxes]
|
|
161
175
|
"""
|
|
176
|
+
|
|
177
|
+
sides = sides.lower()
|
|
178
|
+
|
|
179
|
+
top = "t" in sides or top
|
|
180
|
+
bottom = "b" in sides or bottom
|
|
181
|
+
left = "l" in sides or left
|
|
182
|
+
right = "r" in sides or right
|
|
183
|
+
front = "f" in sides or front
|
|
184
|
+
back = "a" in sides or back
|
|
185
|
+
|
|
162
186
|
px, py, pz = position
|
|
163
187
|
if alignment == Alignment.CORNER:
|
|
164
188
|
px = px + width / 2
|
|
@@ -61,8 +61,11 @@ class _GeometryManager:
|
|
|
61
61
|
self.geometry_list[model].append(geo)
|
|
62
62
|
|
|
63
63
|
def sign_in(self, modelname: str) -> None:
|
|
64
|
-
if modelname not in self.geometry_list:
|
|
65
|
-
|
|
64
|
+
# if modelname not in self.geometry_list:
|
|
65
|
+
# self.geometry_list[modelname] = []
|
|
66
|
+
if modelname is self.geometry_list:
|
|
67
|
+
logger.warning(f'{modelname} already exist, Geometries will be reset.')
|
|
68
|
+
self.geometry_list[modelname] = []
|
|
66
69
|
self.active = modelname
|
|
67
70
|
|
|
68
71
|
def reset(self, modelname: str) -> None:
|
|
@@ -242,6 +245,10 @@ class GeoObject:
|
|
|
242
245
|
def opacity(self) -> float:
|
|
243
246
|
return self.material.opacity
|
|
244
247
|
|
|
248
|
+
@property
|
|
249
|
+
def _metal(self) -> bool:
|
|
250
|
+
return self.material._metal
|
|
251
|
+
|
|
245
252
|
@property
|
|
246
253
|
def select(self) -> Selection:
|
|
247
254
|
'''Returns a corresponding Face/Domain or Edge Selection object'''
|
|
@@ -376,7 +383,7 @@ class GeoObject:
|
|
|
376
383
|
return self
|
|
377
384
|
|
|
378
385
|
def prio_up(self) -> GeoObject:
|
|
379
|
-
"""
|
|
386
|
+
"""Increases the material selection priority by 1
|
|
380
387
|
|
|
381
388
|
Returns:
|
|
382
389
|
GeoObject: _description_
|
|
@@ -385,7 +392,7 @@ class GeoObject:
|
|
|
385
392
|
return self
|
|
386
393
|
|
|
387
394
|
def prio_down(self) -> GeoObject:
|
|
388
|
-
"""
|
|
395
|
+
"""Decreases the material selection priority by 1
|
|
389
396
|
|
|
390
397
|
Returns:
|
|
391
398
|
GeoObject: _description_
|
|
@@ -394,7 +401,7 @@ class GeoObject:
|
|
|
394
401
|
return self
|
|
395
402
|
|
|
396
403
|
def background(self) -> GeoObject:
|
|
397
|
-
"""Set the priority to be on the background.
|
|
404
|
+
"""Set the material selection priority to be on the background.
|
|
398
405
|
|
|
399
406
|
Returns:
|
|
400
407
|
GeoObject: _description_
|
|
@@ -403,7 +410,7 @@ class GeoObject:
|
|
|
403
410
|
return self
|
|
404
411
|
|
|
405
412
|
def foreground(self) -> GeoObject:
|
|
406
|
-
"""Set the priority to be on top.
|
|
413
|
+
"""Set the material selection priority to be on top.
|
|
407
414
|
|
|
408
415
|
Returns:
|
|
409
416
|
GeoObject: _description_
|