emerge 0.6.3__tar.gz → 0.6.5__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.5/.bumpversion.toml +72 -0
- {emerge-0.6.3 → emerge-0.6.5}/PKG-INFO +1 -1
- {emerge-0.6.3 → emerge-0.6.5}/emerge/__init__.py +1 -1
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/geo/polybased.py +118 -24
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/microwave_3d.py +1 -1
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/microwave_data.py +24 -7
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/simmodel.py +26 -1
- {emerge-0.6.3 → emerge-0.6.5}/examples/demo10_sgh.py +2 -2
- {emerge-0.6.3 → emerge-0.6.5}/examples/demo11_lumped_element_filter.py +3 -1
- {emerge-0.6.3 → emerge-0.6.5}/examples/demo12_mode_alignment.py +2 -1
- {emerge-0.6.3 → emerge-0.6.5}/examples/demo13_helix_antenna.py +10 -4
- emerge-0.6.3/examples/demo4_boundary_selection.py → emerge-0.6.5/examples/demo14_boundary_selection.py +1 -0
- {emerge-0.6.3 → emerge-0.6.5}/examples/demo1_stepped_imp_filter.py +1 -1
- {emerge-0.6.3 → emerge-0.6.5}/examples/demo2_combline_filter.py +2 -2
- {emerge-0.6.3 → emerge-0.6.5}/examples/demo3_coupled_line_filter.py +2 -2
- emerge-0.6.3/examples/demo3_patch_antenna.py → emerge-0.6.5/examples/demo4_patch_antenna.py +2 -2
- {emerge-0.6.3 → emerge-0.6.5}/examples/demo5_revolve.py +1 -0
- {emerge-0.6.3 → emerge-0.6.5}/examples/demo6_striplines_with_vias.py +3 -1
- {emerge-0.6.3 → emerge-0.6.5}/examples/demo7_periodic_cells.py +2 -1
- {emerge-0.6.3 → emerge-0.6.5}/examples/demo8_waveguide_bpf_synthesis.py +4 -3
- {emerge-0.6.3 → emerge-0.6.5}/examples/demo9_dielectric_resonator.py +2 -1
- {emerge-0.6.3 → emerge-0.6.5}/pyproject.toml +1 -1
- {emerge-0.6.3 → emerge-0.6.5}/uv.lock +1 -1
- emerge-0.6.3/.bumpversion.toml +0 -30
- emerge-0.6.3/emerge/_emerge/geo/pipes.py +0 -62
- {emerge-0.6.3 → emerge-0.6.5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/.gitignore +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/.opt +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/.python-version +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/LICENSE +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/README.md +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/THIRD_PARTY_LICENSES.md +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/UMFPACK_Install_windows.md +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/UMFPACK_installer_windows.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/__main__.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/__init__.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/_cache_check.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/bc.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/const.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/coord.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/cs.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/dataset.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/elements/__init__.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/elements/femdata.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/elements/index_interp.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/elements/ned2_interp.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/elements/nedelec2.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/elements/nedleg2.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/geo/__init__.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/geo/horn.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/geo/modeler.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/geo/operations.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/geo/pcb.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/geo/pcb_tools/calculator.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/geo/pcb_tools/macro.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/geo/pmlbox.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/geo/shapes.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/geo/step.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/geo2d.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/geometry.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/howto.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/logsettings.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/material.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/mesh3d.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/mesher.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/mth/common_functions.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/mth/integrals.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/mth/optimized.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/mth/pairing.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/periodic.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/__init__.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/__init__.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/adaptive_freq.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/assembly/assembler.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/assembly/curlcurl.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/assembly/generalized_eigen.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/assembly/generalized_eigen_hb.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/assembly/periodicbc.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/assembly/robinbc.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/microwave_bc.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/periodic.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/port_functions.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/sc.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/simjob.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/sparam.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/touchstone.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/plot/__init__.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/plot/display.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/plot/matplotlib/mpldisplay.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/plot/pyvista/__init__.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/plot/pyvista/display.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/plot/pyvista/display_settings.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/plot/simple_plots.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/plot.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/projects/__init__.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/projects/_gen_base.txt +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/projects/_load_base.txt +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/projects/generate_project.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/selection.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/simulation_data.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/solve_interfaces/cudss_interface.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/solve_interfaces/pardiso_interface.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/solver.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/system.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/cli.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/ext.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/lib.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/plot.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/emerge/pyvista.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/src/__init__.py +0 -0
- {emerge-0.6.3 → emerge-0.6.5}/src/_img/logo.jpeg +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
[tool.bumpversion]
|
|
2
|
+
current_version = "0.6.5"
|
|
3
|
+
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
|
4
|
+
serialize = ["{major}.{minor}.{patch}"]
|
|
5
|
+
search = "{current_version}"
|
|
6
|
+
replace = "{new_version}"
|
|
7
|
+
regex = false
|
|
8
|
+
ignore_missing_version = false
|
|
9
|
+
ignore_missing_files = false
|
|
10
|
+
tag = true
|
|
11
|
+
sign_tags= false
|
|
12
|
+
tag_name = "v{new_version}"
|
|
13
|
+
tag_message = "Bump version: {current_version} → {new_version}"
|
|
14
|
+
allow_dirty = false
|
|
15
|
+
commit = true
|
|
16
|
+
message = "Bump version: {current_version} → {new_version}"
|
|
17
|
+
moveable_tags = []
|
|
18
|
+
commit_args = ""
|
|
19
|
+
setup_hooks = []
|
|
20
|
+
pre_commit_hooks = []
|
|
21
|
+
post_commit_hooks = []
|
|
22
|
+
|
|
23
|
+
[[tool.bumpversion.files]]
|
|
24
|
+
filename = "uv.lock"
|
|
25
|
+
|
|
26
|
+
[[tool.bumpversion.files]]
|
|
27
|
+
filename = "pyproject.toml"
|
|
28
|
+
|
|
29
|
+
[[tool.bumpversion.files]]
|
|
30
|
+
filename = "src/emerge/__init__.py"
|
|
31
|
+
|
|
32
|
+
[[tool.bumpversion.files]]
|
|
33
|
+
filename = "examples/demo1_stepped_imp_filter.py"
|
|
34
|
+
|
|
35
|
+
[[tool.bumpversion.files]]
|
|
36
|
+
filename = "examples/demo2_combline_filter.py"
|
|
37
|
+
|
|
38
|
+
[[tool.bumpversion.files]]
|
|
39
|
+
filename = "examples/demo3_coupled_line_filter.py"
|
|
40
|
+
|
|
41
|
+
[[tool.bumpversion.files]]
|
|
42
|
+
filename = "examples/demo4_patch_antenna.py"
|
|
43
|
+
|
|
44
|
+
[[tool.bumpversion.files]]
|
|
45
|
+
filename = "examples/demo5_revolve.py"
|
|
46
|
+
|
|
47
|
+
[[tool.bumpversion.files]]
|
|
48
|
+
filename = "examples/demo6_striplines_with_vias.py"
|
|
49
|
+
|
|
50
|
+
[[tool.bumpversion.files]]
|
|
51
|
+
filename = "examples/demo7_periodic_cells.py"
|
|
52
|
+
|
|
53
|
+
[[tool.bumpversion.files]]
|
|
54
|
+
filename = "examples/demo8_waveguide_bpf_synthesis.py"
|
|
55
|
+
|
|
56
|
+
[[tool.bumpversion.files]]
|
|
57
|
+
filename = "examples/demo9_dielectric_resonator.py"
|
|
58
|
+
|
|
59
|
+
[[tool.bumpversion.files]]
|
|
60
|
+
filename = "examples/demo10_sgh.py"
|
|
61
|
+
|
|
62
|
+
[[tool.bumpversion.files]]
|
|
63
|
+
filename = "examples/demo11_lumped_element_filter.py"
|
|
64
|
+
|
|
65
|
+
[[tool.bumpversion.files]]
|
|
66
|
+
filename = "examples/demo12_mode_alignment.py"
|
|
67
|
+
|
|
68
|
+
[[tool.bumpversion.files]]
|
|
69
|
+
filename = "examples/demo13_helix_antenna.py"
|
|
70
|
+
|
|
71
|
+
[[tool.bumpversion.files]]
|
|
72
|
+
filename = "examples/demo14_boundary_selection.py"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
# <https://www.gnu.org/licenses/>.
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
import numpy as np
|
|
19
|
-
from ..cs import CoordinateSystem, GCS, Axis
|
|
19
|
+
from ..cs import CoordinateSystem, GCS, Axis, _parse_axis
|
|
20
20
|
from ..geometry import GeoVolume, GeoPolygon, GeoEdge, GeoSurface
|
|
21
21
|
from .shapes import Alignment
|
|
22
22
|
import gmsh
|
|
@@ -158,7 +158,35 @@ def rotate_point(point: tuple[float, float, float],
|
|
|
158
158
|
rotated += o
|
|
159
159
|
return tuple(rotated)
|
|
160
160
|
|
|
161
|
+
def _dist(p1: tuple[float, float], p2: tuple[float, float]) -> float:
|
|
162
|
+
return ((p2[0]-p1[0])**2 + (p2[1]-p1[1])**2)**(0.5)
|
|
161
163
|
|
|
164
|
+
def _pair_points(x1: np.ndarray,
|
|
165
|
+
y1: np.ndarray,
|
|
166
|
+
x2: np.ndarray,
|
|
167
|
+
y2: np.ndarray) -> list[tuple[int,int]]:
|
|
168
|
+
if x1.shape[0]==x2.shape[0]:
|
|
169
|
+
return [(i,i) for i in range(x1.shape[0])]
|
|
170
|
+
|
|
171
|
+
#create point tuples
|
|
172
|
+
p1s = [(x,y) for x,y in zip(x1, y1)]
|
|
173
|
+
p2s = [(x,y) for x,y in zip(x2, y2)]
|
|
174
|
+
|
|
175
|
+
pairs = []
|
|
176
|
+
for i, p1 in enumerate(p1s):
|
|
177
|
+
d1 = _dist(p1, p2s[i-1])
|
|
178
|
+
d2 = _dist(p1, p2s[i])
|
|
179
|
+
d3 = _dist(p1, p2s[i+1])
|
|
180
|
+
mind = min([d1, d2, d3])
|
|
181
|
+
if mind==d1:
|
|
182
|
+
pairs.append((i,i-1))
|
|
183
|
+
continue
|
|
184
|
+
elif mind==d2:
|
|
185
|
+
pairs.append((i,i))
|
|
186
|
+
else:
|
|
187
|
+
pairs.append((i,i+1))
|
|
188
|
+
return pairs
|
|
189
|
+
|
|
162
190
|
def orthonormalize(axis: np.ndarray) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
163
191
|
"""Generates a set of orthonormal vectors given an input vector X
|
|
164
192
|
|
|
@@ -233,8 +261,9 @@ class XYPolygon:
|
|
|
233
261
|
"""This class generalizes a polygon in an un-embedded XY space that can be embedded in 3D space.
|
|
234
262
|
"""
|
|
235
263
|
def __init__(self,
|
|
236
|
-
xs: np.ndarray | list | tuple = None,
|
|
237
|
-
ys: np.ndarray | list | tuple = None
|
|
264
|
+
xs: np.ndarray | list | tuple | None = None,
|
|
265
|
+
ys: np.ndarray | list | tuple | None = None,
|
|
266
|
+
cs: CoordinateSystem | None = None):
|
|
238
267
|
"""Constructs an XY-plane placed polygon.
|
|
239
268
|
|
|
240
269
|
Args:
|
|
@@ -250,7 +279,13 @@ class XYPolygon:
|
|
|
250
279
|
self.y: np.ndarray = np.asarray(ys)
|
|
251
280
|
|
|
252
281
|
self.fillets: list[tuple[float, int]] = []
|
|
282
|
+
|
|
283
|
+
self._cs: CoordinateSystem = cs
|
|
253
284
|
|
|
285
|
+
@property
|
|
286
|
+
def center(self) -> tuple[float, float]:
|
|
287
|
+
return np.mean(self.x), np.mean(self.y)
|
|
288
|
+
|
|
254
289
|
@property
|
|
255
290
|
def length(self):
|
|
256
291
|
return sum([((self.x[i2]-self.x[i1])**2 + (self.y[i2]-self.y[i1])**2)**0.5 for i1, i2 in zip(range(self.N-1),range(1, self.N))])
|
|
@@ -282,6 +317,10 @@ class XYPolygon:
|
|
|
282
317
|
"""
|
|
283
318
|
return 0.5*np.abs(np.dot(self.x,np.roll(self.y,1))-np.dot(self.y,np.roll(self.x,1)))
|
|
284
319
|
|
|
320
|
+
def incs(self, cs: CoordinateSystem) -> XYPolygon:
|
|
321
|
+
self._cs = cs
|
|
322
|
+
return self
|
|
323
|
+
|
|
285
324
|
def extend(self, xpts: list[float], ypts: list[float]) -> XYPolygon:
|
|
286
325
|
"""Adds a series for x and y coordinates to the existing polygon.
|
|
287
326
|
|
|
@@ -301,7 +340,7 @@ class XYPolygon:
|
|
|
301
340
|
for i in range(self.N):
|
|
302
341
|
yield (self.x[i], self.y[i])
|
|
303
342
|
|
|
304
|
-
def fillet(self, radius: float, *indices: int) ->
|
|
343
|
+
def fillet(self, radius: float, *indices: int) -> XYPolygon:
|
|
305
344
|
"""Add a fillet rounding with a given radius to the provided nodes.
|
|
306
345
|
|
|
307
346
|
Example:
|
|
@@ -313,8 +352,9 @@ class XYPolygon:
|
|
|
313
352
|
"""
|
|
314
353
|
for i in indices:
|
|
315
354
|
self.fillets.append((radius, i))
|
|
355
|
+
return self
|
|
316
356
|
|
|
317
|
-
def
|
|
357
|
+
def _make_wire(self, cs: CoordinateSystem) -> tuple[list[int], list[int], int]:
|
|
318
358
|
"""Turns the XYPolygon object into a GeoPolygon that is embedded in 3D space.
|
|
319
359
|
|
|
320
360
|
The polygon will be placed in the XY-plane of the provided coordinate center.
|
|
@@ -340,13 +380,27 @@ class XYPolygon:
|
|
|
340
380
|
|
|
341
381
|
add = 0
|
|
342
382
|
for radius, index in self.fillets:
|
|
343
|
-
t1 = lines[index + add]
|
|
344
|
-
t2 = lines[
|
|
383
|
+
t1 = lines[(index + add-1) % len(lines)]
|
|
384
|
+
t2 = lines[index + add]
|
|
345
385
|
tag = gmsh.model.occ.fillet2_d(t1, t2, radius)
|
|
346
386
|
lines.insert(index, tag)
|
|
347
387
|
add += 1
|
|
348
388
|
|
|
349
389
|
wiretag = gmsh.model.occ.add_wire(lines)
|
|
390
|
+
return ptags, lines, wiretag
|
|
391
|
+
|
|
392
|
+
def _finalize(self, cs: CoordinateSystem) -> GeoPolygon:
|
|
393
|
+
"""Turns the XYPolygon object into a GeoPolygon that is embedded in 3D space.
|
|
394
|
+
|
|
395
|
+
The polygon will be placed in the XY-plane of the provided coordinate center.
|
|
396
|
+
|
|
397
|
+
Args:
|
|
398
|
+
cs (CoordinateSystem, optional): The coordinate system in which to put the polygon. Defaults to None.
|
|
399
|
+
|
|
400
|
+
Returns:
|
|
401
|
+
GeoPolygon: The resultant 3D GeoPolygon object.
|
|
402
|
+
"""
|
|
403
|
+
ptags, lines, wiretag = self._make_wire(cs)
|
|
350
404
|
surftag = gmsh.model.occ.add_plane_surface([wiretag,])
|
|
351
405
|
poly = GeoPolygon([surftag,])
|
|
352
406
|
poly.points = ptags
|
|
@@ -384,6 +438,8 @@ class XYPolygon:
|
|
|
384
438
|
Returns:
|
|
385
439
|
GeoPolygon: The resultant object.
|
|
386
440
|
"""
|
|
441
|
+
if self._cs is not None:
|
|
442
|
+
return self._finalize(self._cs)
|
|
387
443
|
if cs is None:
|
|
388
444
|
cs = GCS
|
|
389
445
|
return self._finalize(cs)
|
|
@@ -500,7 +556,34 @@ class XYPolygon:
|
|
|
500
556
|
self.extend(xs, ys)
|
|
501
557
|
return self
|
|
502
558
|
|
|
559
|
+
def connect(self, other: XYPolygon) -> GeoVolume:
|
|
560
|
+
"""Connect two XYPolygons with a defined coordinate system
|
|
503
561
|
|
|
562
|
+
The coordinate system must be defined before this function can be used. To add a coordinate systme without
|
|
563
|
+
rendering the Polygon to a GeoVolume, use:
|
|
564
|
+
>>> polygon.incs(my_cs_obj)
|
|
565
|
+
|
|
566
|
+
Args:
|
|
567
|
+
other (XYPolygon): _descrThe otheiption_
|
|
568
|
+
|
|
569
|
+
Returns:
|
|
570
|
+
GeoVolume: The resultant volume object
|
|
571
|
+
"""
|
|
572
|
+
if self._cs is None:
|
|
573
|
+
raise RuntimeError('Cannot connect XYPolygons without a defined coordinate system. Set this first using .incs()')
|
|
574
|
+
if other._cs is None:
|
|
575
|
+
raise RuntimeError('Cannot connect XYPolygons without a defined coordinate system. Set this first using .incs()')
|
|
576
|
+
p1, l1, w1 = self._make_wire(self._cs)
|
|
577
|
+
p2, l2, w2 = other._make_wire(other._cs)
|
|
578
|
+
o1 = np.array(self._cs.in_global_cs(*self.center, 0)).flatten()
|
|
579
|
+
o2 = np.array(other._cs.in_global_cs(*other.center, 0)).flatten()
|
|
580
|
+
dts = gmsh.model.occ.addThruSections([w1, w2], True, parametrization="IsoParametric")
|
|
581
|
+
vol = GeoVolume([t for d,t in dts if d==3])
|
|
582
|
+
|
|
583
|
+
vol._add_face_pointer('front',o1, self._cs.zax.np)
|
|
584
|
+
vol._add_face_pointer('back', o2, other._cs.zax.np)
|
|
585
|
+
return vol
|
|
586
|
+
|
|
504
587
|
class Disc(GeoSurface):
|
|
505
588
|
|
|
506
589
|
def __init__(self, origin: tuple[float, float, float],
|
|
@@ -525,8 +608,7 @@ class Curve(GeoEdge):
|
|
|
525
608
|
degree: int = 3,
|
|
526
609
|
weights: list[float] | None = None,
|
|
527
610
|
knots: list[float] | None = None,
|
|
528
|
-
ctype: Literal['Spline','BSpline','Bezier'] = '
|
|
529
|
-
dstart: tuple[float, float, float] | None = None):
|
|
611
|
+
ctype: Literal['Spline','BSpline','Bezier'] = 'Spline'):
|
|
530
612
|
"""Generate a Spline/Bspline or Bezier curve based on a series of points
|
|
531
613
|
|
|
532
614
|
This calls the different curve features in OpenCASCADE.
|
|
@@ -547,11 +629,6 @@ class Curve(GeoEdge):
|
|
|
547
629
|
self.xpts: np.ndarray = xpts
|
|
548
630
|
self.ypts: np.ndarray = ypts
|
|
549
631
|
self.zpts: np.ndarray = zpts
|
|
550
|
-
|
|
551
|
-
if dstart is None:
|
|
552
|
-
dstart = (xpts[1]-xpts[0], ypts[1]-ypts[0], zpts[1]-zpts[0])
|
|
553
|
-
|
|
554
|
-
self.dstart: tuple[float, float, float] = dstart
|
|
555
632
|
|
|
556
633
|
points = [gmsh.model.occ.add_point(x,y,z) for x,y,z in zip(xpts, ypts, zpts)]
|
|
557
634
|
|
|
@@ -571,6 +648,14 @@ class Curve(GeoEdge):
|
|
|
571
648
|
gmsh.model.occ.remove([(0,tag) for tag in points])
|
|
572
649
|
super().__init__(tags)
|
|
573
650
|
|
|
651
|
+
gmsh.model.occ.synchronize()
|
|
652
|
+
p1 = gmsh.model.getValue(self.dim, self.tags[0], [0,])
|
|
653
|
+
p2 = gmsh.model.getValue(self.dim, self.tags[0], [1e-6])
|
|
654
|
+
self.dstart: tuple[float, float, float] = (p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
|
|
574
659
|
@property
|
|
575
660
|
def p0(self) -> tuple[float, float, float]:
|
|
576
661
|
"""The start coordinate
|
|
@@ -653,7 +738,7 @@ class Curve(GeoEdge):
|
|
|
653
738
|
zp[2] += d/2*dz
|
|
654
739
|
dp = tuple(Z)
|
|
655
740
|
|
|
656
|
-
return Curve(xp, yp, zp, ctype='Spline'
|
|
741
|
+
return Curve(xp, yp, zp, ctype='Spline')
|
|
657
742
|
|
|
658
743
|
@staticmethod
|
|
659
744
|
def helix_lh(pstart: tuple[float, float, float],
|
|
@@ -731,9 +816,12 @@ class Curve(GeoEdge):
|
|
|
731
816
|
zp[2] += d/2*dz
|
|
732
817
|
dp = tuple(Z)
|
|
733
818
|
|
|
734
|
-
return Curve(xp, yp, zp, ctype='Spline'
|
|
819
|
+
return Curve(xp, yp, zp, ctype='Spline')
|
|
735
820
|
|
|
736
|
-
def pipe(self, crossection: GeoSurface | XYPolygon,
|
|
821
|
+
def pipe(self, crossection: GeoSurface | XYPolygon,
|
|
822
|
+
max_mesh_size: float | None = None,
|
|
823
|
+
start_tangent: Axis | tuple[float, float, float] | np.ndarray | None = None,
|
|
824
|
+
x_axis: Axis | tuple[float, float, float] | np.ndarray | None = None) -> GeoVolume:
|
|
737
825
|
"""Extrudes a surface or XYPolygon object along the given curve
|
|
738
826
|
|
|
739
827
|
If a GeoSurface object is used, make sure it starts at the center of the curve. This property
|
|
@@ -744,25 +832,31 @@ class Curve(GeoEdge):
|
|
|
744
832
|
Args:
|
|
745
833
|
crossection (GeoSurface | XYPolygon): The cross section definition to be used
|
|
746
834
|
max_mesh_size (float, optional): The maximum mesh size. Defaults to None
|
|
835
|
+
start_tangent (Axis, tuple, ndarray, optional): The input polygon plane normal direction. Defaults to None
|
|
836
|
+
x_axis (Axis, tuple, ndarray optional): The reference X-axis to align the input polygon. Defaults to None
|
|
747
837
|
Returns:
|
|
748
838
|
GeoVolume: The resultant volume object
|
|
749
839
|
"""
|
|
750
840
|
if isinstance(crossection, XYPolygon):
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
841
|
+
if start_tangent is None:
|
|
842
|
+
start_tangent = self.dstart
|
|
843
|
+
if x_axis is not None:
|
|
844
|
+
xax = _parse_axis(x_axis)
|
|
845
|
+
zax = _parse_axis(self.dstart)
|
|
846
|
+
yax = zax.cross(xax)
|
|
847
|
+
cs = CoordinateSystem(xax, yax, zax, self.p0)
|
|
848
|
+
else:
|
|
849
|
+
zax = self.dstart
|
|
850
|
+
cs = Axis(np.array(zax)).construct_cs(self.p0)
|
|
851
|
+
surf = crossection.geo(cs)
|
|
754
852
|
else:
|
|
755
853
|
surf = crossection
|
|
756
854
|
x1, y1, z1, x2, y2, z2 = gmsh.model.occ.getBoundingBox(*surf.dimtags[0])
|
|
757
855
|
diag = ((x2-x1)**2 + (y2-y1)**2 + (z2-z1)**2)**(0.5)
|
|
758
|
-
|
|
759
856
|
pipetag = gmsh.model.occ.addPipe(surf.dimtags, self.tags[0], 'GuidePlan')
|
|
760
|
-
|
|
761
857
|
self.remove()
|
|
762
858
|
surf.remove()
|
|
763
|
-
|
|
764
859
|
volume = GeoVolume(pipetag[0][1])
|
|
765
|
-
|
|
766
860
|
volume.max_meshsize = diag/2
|
|
767
861
|
return volume
|
|
768
862
|
|
|
@@ -249,7 +249,7 @@ class MWData:
|
|
|
249
249
|
self.sim.new(**vars)['report'] = report
|
|
250
250
|
|
|
251
251
|
@dataclass
|
|
252
|
-
class
|
|
252
|
+
class FarFieldData:
|
|
253
253
|
E: np.ndarray
|
|
254
254
|
H: np.ndarray
|
|
255
255
|
theta: np.ndarray
|
|
@@ -816,7 +816,7 @@ class MWField:
|
|
|
816
816
|
ang_range: tuple[float, float] = (-180, 180),
|
|
817
817
|
Npoints: int = 201,
|
|
818
818
|
origin: tuple[float, float, float] | None = None,
|
|
819
|
-
syms: list[Literal['Ex','Ey','Ez', 'Hx','Hy','Hz']] | None = None) ->
|
|
819
|
+
syms: list[Literal['Ex','Ey','Ez', 'Hx','Hy','Hz']] | None = None) -> FarFieldData:#tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
820
820
|
"""Compute the farfield electric and magnetic field defined by a circle.
|
|
821
821
|
|
|
822
822
|
Args:
|
|
@@ -836,14 +836,14 @@ class MWField:
|
|
|
836
836
|
theta, phi = arc_on_plane(refdir, plane_normal_parsed, ang_range, Npoints)
|
|
837
837
|
E,H = self.farfield(theta, phi, faces, origin, syms = syms)
|
|
838
838
|
angs = np.linspace(*ang_range, Npoints)*np.pi/180
|
|
839
|
-
return
|
|
839
|
+
return FarFieldData(E, H, theta, phi, ang=angs)
|
|
840
840
|
|
|
841
841
|
def farfield_3d(self,
|
|
842
842
|
faces: FaceSelection | GeoSurface,
|
|
843
843
|
thetas: np.ndarray | None = None,
|
|
844
844
|
phis: np.ndarray | None = None,
|
|
845
845
|
origin: tuple[float, float, float] | None = None,
|
|
846
|
-
syms: list[Literal['Ex','Ey','Ez', 'Hx','Hy','Hz']] | None = None) ->
|
|
846
|
+
syms: list[Literal['Ex','Ey','Ez', 'Hx','Hy','Hz']] | None = None) -> FarFieldData:
|
|
847
847
|
"""Compute the farfield in a 3D angular grid
|
|
848
848
|
|
|
849
849
|
If thetas and phis are not provided, they default to a sample space of 2 degrees.
|
|
@@ -868,7 +868,7 @@ class MWField:
|
|
|
868
868
|
E = E.reshape((3, ) + T.shape)
|
|
869
869
|
H = H.reshape((3, ) + T.shape)
|
|
870
870
|
|
|
871
|
-
return
|
|
871
|
+
return FarFieldData(E, H, T, P)
|
|
872
872
|
|
|
873
873
|
def farfield(self, theta: np.ndarray,
|
|
874
874
|
phi: np.ndarray,
|
|
@@ -924,7 +924,7 @@ class MWField:
|
|
|
924
924
|
|
|
925
925
|
return Eff, Hff
|
|
926
926
|
|
|
927
|
-
def
|
|
927
|
+
def optycal_surface(self, faces: FaceSelection | GeoSurface | None = None) -> tuple:
|
|
928
928
|
"""Export this models exterior to an Optical acceptable dataset
|
|
929
929
|
|
|
930
930
|
Args:
|
|
@@ -948,7 +948,24 @@ class MWField:
|
|
|
948
948
|
H = field.H
|
|
949
949
|
k0 = self.k0
|
|
950
950
|
return vertices, triangles, E, H, origin, k0
|
|
951
|
-
|
|
951
|
+
|
|
952
|
+
def optycal_antenna(self, faces: FaceSelection | GeoSurface | None = None,
|
|
953
|
+
origin: tuple[float, float, float] | None = None,
|
|
954
|
+
syms: list[Literal['Ex','Ey','Ez', 'Hx','Hy','Hz']] | None = None) -> dict:
|
|
955
|
+
"""Export this models exterior to an Optical acceptable dataset
|
|
956
|
+
|
|
957
|
+
Args:
|
|
958
|
+
faces (FaceSelection | GeoSurface): The faces to export. Defaults to None
|
|
959
|
+
|
|
960
|
+
Returns:
|
|
961
|
+
tuple: _description_
|
|
962
|
+
"""
|
|
963
|
+
freq = self.freq
|
|
964
|
+
def function(theta: np.ndarray, phi: np.ndarray, k0: float):
|
|
965
|
+
E, H = self.farfield(theta, phi, faces, origin, syms)
|
|
966
|
+
return E[0,:], E[1,:], E[2,:], H[0,:], H[1,:], H[2,:]
|
|
967
|
+
|
|
968
|
+
return dict(freq=freq, ff_function=function)
|
|
952
969
|
|
|
953
970
|
class MWScalar:
|
|
954
971
|
"""The MWDataSet class stores solution data of FEM Time Harmonic simulations.
|
|
@@ -37,7 +37,7 @@ import inspect
|
|
|
37
37
|
from pathlib import Path
|
|
38
38
|
from atexit import register
|
|
39
39
|
import signal
|
|
40
|
-
|
|
40
|
+
from .. import __version__
|
|
41
41
|
|
|
42
42
|
############################################################
|
|
43
43
|
# EXCEPTION DEFINITIONS #
|
|
@@ -54,6 +54,9 @@ Known problems/solutions:
|
|
|
54
54
|
class SimulationError(Exception):
|
|
55
55
|
pass
|
|
56
56
|
|
|
57
|
+
class VersionError(Exception):
|
|
58
|
+
pass
|
|
59
|
+
|
|
57
60
|
############################################################
|
|
58
61
|
# BASE 3D SIMULATION MODEL #
|
|
59
62
|
############################################################
|
|
@@ -228,6 +231,28 @@ class Simulation:
|
|
|
228
231
|
# PUBLIC FUNCTIONS #
|
|
229
232
|
############################################################
|
|
230
233
|
|
|
234
|
+
def check_version(self, version: str) -> None:
|
|
235
|
+
"""Compares the provided version number with the version number of EMerge that is running the script.
|
|
236
|
+
|
|
237
|
+
You may remove any call to check_version to suppress VersionErrors and warnings.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
version (str): The EMerge version you intend to write this code for.
|
|
241
|
+
|
|
242
|
+
Raises:
|
|
243
|
+
VersionError: A potential version error if incompatibility is possible
|
|
244
|
+
"""
|
|
245
|
+
vM, vm, vp = [float(x) for x in version.split('.')]
|
|
246
|
+
cM, cm, cp = [float(x) for x in __version__.split('.')]
|
|
247
|
+
if vM != cM:
|
|
248
|
+
raise VersionError(f"You are running a script designed for version {version} with a possibly incompatible version of EMerge {__version__}")
|
|
249
|
+
if vm != cm:
|
|
250
|
+
raise VersionError(f"You are running a script designed for version {version} with a possibly incompatible version of EMerge {__version__}")
|
|
251
|
+
if vp != cp:
|
|
252
|
+
logger.warning(f"You are running a script designed for version {version} with a possibly incompatible version of EMerge {__version__}")
|
|
253
|
+
logger.warning("You may suppress this error by removing the call to .check_version().")
|
|
254
|
+
input('Press enter to proceed...')
|
|
255
|
+
|
|
231
256
|
def save(self) -> None:
|
|
232
257
|
"""Saves the current model in the provided project directory."""
|
|
233
258
|
# Ensure directory exists
|
|
@@ -28,8 +28,8 @@ th = 1 * mm # PML thickness
|
|
|
28
28
|
dx = 2 * mm # distance from horn exit to PML start
|
|
29
29
|
|
|
30
30
|
# Create simulation object
|
|
31
|
-
m = em.Simulation('HornAntenna'
|
|
32
|
-
|
|
31
|
+
m = em.Simulation('HornAntenna')
|
|
32
|
+
m.check_version("0.6.5") # Checks version compatibility.
|
|
33
33
|
# --- Coordinate system for horn geometry -------------------------------
|
|
34
34
|
hornCS = em.CS(em.YAX, em.ZAX, em.XAX)
|
|
35
35
|
|
|
@@ -28,7 +28,9 @@ def Cf(C):
|
|
|
28
28
|
# --- PCB and lumped-component parameters ---------------------------------
|
|
29
29
|
pack = '0603' # package footprint for lumped components
|
|
30
30
|
# Create simulation and PCB layouter with substrate thickness and material
|
|
31
|
-
m = em.Simulation('LumpedFilter'
|
|
31
|
+
m = em.Simulation('LumpedFilter')
|
|
32
|
+
m.check_version("0.6.5") # Checks version compatibility.
|
|
33
|
+
|
|
32
34
|
th = 0.5 # substrate thickness (meters)
|
|
33
35
|
Hair = 2.0
|
|
34
36
|
pcb = em.geo.PCB(th, unit=mm, cs=em.GCS,
|
|
@@ -11,7 +11,8 @@ direction (+Z vs -Z). In EMerge we can alignm modes using the .align_mode() meth
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
# First we define our simulation
|
|
14
|
-
m = em.Simulation('aligntest'
|
|
14
|
+
m = em.Simulation('aligntest')
|
|
15
|
+
m.check_version("0.6.5") # Checks version compatibility.
|
|
15
16
|
|
|
16
17
|
# We create a cyllindrical waveguide in the Y-axis.
|
|
17
18
|
cyl = em.geo.Cylinder(0.012, 0.05, em.CS(em.XAX, em.ZAX, em.YAX))
|
|
@@ -24,8 +24,10 @@ L = 4*rad0 # helix axial length
|
|
|
24
24
|
porth = 2*mm # vertical height of the feed extrusion
|
|
25
25
|
|
|
26
26
|
# --- Simulation object -------------------------------------------------------
|
|
27
|
-
model = em.Simulation('helix'
|
|
28
|
-
|
|
27
|
+
model = em.Simulation('helix')
|
|
28
|
+
model.check_version("0.6.5") # Checks version compatibility.
|
|
29
|
+
|
|
30
|
+
dfeed = 3*mm # straight feed length before the helix starts
|
|
29
31
|
|
|
30
32
|
# --- Geometry: helix curve and metal pipe -----------------------------------
|
|
31
33
|
# Helix curve from (0,0,porth+dfeed/2) to (0,0,porth+dfeed/2+L)
|
|
@@ -44,11 +46,15 @@ dfeed = 5*mm # straight feed length before the helix starts
|
|
|
44
46
|
# (x0,y1)
|
|
45
47
|
|
|
46
48
|
# We add the porth height + half of the startfeed distance to the total height to put the helix in the right spot.
|
|
47
|
-
h_curve = em.geo.Curve.helix_lh((0,0,porth+dfeed/2), (0,0,porth+dfeed/2+L), rad0, 13, r_end=0.8*rad0
|
|
49
|
+
h_curve = em.geo.Curve.helix_lh((0,0,porth+dfeed/2), (0,0,porth+dfeed/2+L), rad0, 13, r_end=0.8*rad0)
|
|
50
|
+
|
|
51
|
+
cross_section = em.geo.XYPolygon.circle(radw, Nsections=6)
|
|
48
52
|
|
|
49
53
|
# Sweep a circular cross-section along the curve to make a metallic pipe
|
|
50
|
-
helix = h_curve.pipe(
|
|
54
|
+
helix = h_curve.pipe(cross_section).set_material(em.lib.MET_COPPER)
|
|
51
55
|
|
|
56
|
+
# We add a block to make attachment of ports easier.
|
|
57
|
+
block = em.geo.Box(dfeed, dfeed, dfeed, position=h_curve.p0, alignment=em.geo.Alignment.CENTER).set_material(em.lib.MET_COPPER)
|
|
52
58
|
# Optional preview of current scene (geometry only at this point)
|
|
53
59
|
model.view()
|
|
54
60
|
|
|
@@ -28,7 +28,7 @@ pcbmat = em.Material(er=2.2, tand=0.00, color="#217627", opacity=0.2)
|
|
|
28
28
|
# We start by creating our simulation object.
|
|
29
29
|
|
|
30
30
|
m = em.Simulation('Demo1_SIF', loglevel='INFO')
|
|
31
|
-
|
|
31
|
+
m.check_version("0.6.5") # Checks version compatibility.
|
|
32
32
|
# To accomodate PCB routing we make use of the PCBLayouter class. To use it we need to
|
|
33
33
|
# supply it with a thickness, the desired air-box height, the units at which we supply
|
|
34
34
|
# the dimensions and the PCB material.
|
|
@@ -42,8 +42,8 @@ rin = 12.5*mil
|
|
|
42
42
|
lfeed = 100*mil
|
|
43
43
|
|
|
44
44
|
# A usual we start our simulation file
|
|
45
|
-
model = em.Simulation('Combline_DEMO'
|
|
46
|
-
|
|
45
|
+
model = em.Simulation('Combline_DEMO')
|
|
46
|
+
model.check_version("0.6.5") # Checks version compatibility.
|
|
47
47
|
|
|
48
48
|
# The filter consists of quarter lamba cylindrical pins inside an airbox.
|
|
49
49
|
# First we create the airbox
|
|
@@ -37,8 +37,8 @@ Dtot = 750 # total clearance (mil)
|
|
|
37
37
|
extra = 100 # extra margin (mil)
|
|
38
38
|
|
|
39
39
|
# --- Simulation setup ----------------------------------------------------
|
|
40
|
-
model = em.Simulation('Demo3'
|
|
41
|
-
|
|
40
|
+
model = em.Simulation('Demo3')
|
|
41
|
+
model.check_version("0.6.5") # Checks version compatibility.
|
|
42
42
|
# --- Material and layouter -----------------------------------------------
|
|
43
43
|
mat = em.Material(er=3.55, color="#488343", opacity=0.1)
|
|
44
44
|
# Create PCB layouter with given substrate thickness and units
|
|
@@ -35,8 +35,8 @@ f2 = 1.6e9 # stop frequency
|
|
|
35
35
|
|
|
36
36
|
# --- Create simulation object -------------------------------------------
|
|
37
37
|
# Using PVDisplay backend for 3D visualization
|
|
38
|
-
model = em.Simulation('MyPatchAntenna'
|
|
39
|
-
|
|
38
|
+
model = em.Simulation('MyPatchAntenna')
|
|
39
|
+
model.check_version("0.6.5") # Checks version compatibility.
|
|
40
40
|
# --- Define geometry primitives -----------------------------------------
|
|
41
41
|
# Substrate block centered at origin in XY, thickness in Z (negative down)
|
|
42
42
|
dielectric = em.geo.Box(wsub, hsub, th,
|
|
@@ -11,7 +11,9 @@ PCB related demos (demo1 and demo3) to get more information on the PCBLayouter.
|
|
|
11
11
|
mm = 0.001
|
|
12
12
|
th = 1
|
|
13
13
|
|
|
14
|
-
model = em.Simulation('Stripline_test'
|
|
14
|
+
model = em.Simulation('Stripline_test')
|
|
15
|
+
model.check_version("0.6.5") # Checks version compatibility.
|
|
16
|
+
|
|
15
17
|
# As usual we start by creating our layouter
|
|
16
18
|
ly = em.geo.PCB(th, mm, em.GCS, em.lib.DIEL_RO4350B)
|
|
17
19
|
|
|
@@ -28,7 +28,8 @@ wgb = 18*mm
|
|
|
28
28
|
fl = 25*mm
|
|
29
29
|
|
|
30
30
|
# We start again by defining our simulation model
|
|
31
|
-
model = em.Simulation('Periodic'
|
|
31
|
+
model = em.Simulation('Periodic')
|
|
32
|
+
model.check_version("0.6.5") # Checks version compatibility.
|
|
32
33
|
|
|
33
34
|
# Next we will create a PeriodicCell class (in our case a hexagonal cell). This class
|
|
34
35
|
# is simply meant to simplify our lives and improve the simulation setup flow.
|
|
@@ -79,7 +79,8 @@ def KZ0(S11, S12, S21, S22):
|
|
|
79
79
|
wgaps = np.linspace(1*mm, 20*mm, 21)
|
|
80
80
|
Ks = []
|
|
81
81
|
hphis = []
|
|
82
|
-
with em.Simulation('IrisSim'
|
|
82
|
+
with em.Simulation('IrisSim') as sim:
|
|
83
|
+
sim.check_version("0.6.5") # Checks version compatibility.
|
|
83
84
|
for (wgap,) in sim.parameter_sweep(True, wgap=wgaps):
|
|
84
85
|
# Define two short waveguide sections separated by iris plate
|
|
85
86
|
wg1 = em.geo.Box(wga, Lfeed, wgb, (-wga/2, -Lfeed - t_thickness/2, 0))
|
|
@@ -128,7 +129,7 @@ cavity_lengths = (1/beta0 * np.array([
|
|
|
128
129
|
])).real
|
|
129
130
|
|
|
130
131
|
# --- Build and simulate full filter -------------------------------------
|
|
131
|
-
with em.Simulation('FullFilter'
|
|
132
|
+
with em.Simulation('FullFilter') as mf:
|
|
132
133
|
# Input feed section
|
|
133
134
|
feed1 = em.geo.Box(wga, Lfeed, wgb, (-wga/2, -Lfeed, 0))
|
|
134
135
|
# Create cavities and irises sequentially
|
|
@@ -149,7 +150,7 @@ with em.Simulation('FullFilter', loglevel='DEBUG') as mf:
|
|
|
149
150
|
mf.commit_geometry(feed1, feed2, last_iris, *(cavities + irises))
|
|
150
151
|
|
|
151
152
|
# Simulation settings and mesh
|
|
152
|
-
mf.mw.set_frequency_range(f1 - 0.2e9, f2 + 0.2e9,
|
|
153
|
+
mf.mw.set_frequency_range(f1 - 0.2e9, f2 + 0.2e9, 51)
|
|
153
154
|
mf.mw.set_resolution(0.10)
|
|
154
155
|
for ir in irises:
|
|
155
156
|
mf.mesher.set_domain_size(ir, 2*mm)
|
|
@@ -32,7 +32,8 @@ mat_resonator = em.lib.Material(er=34, color="#ededed")
|
|
|
32
32
|
Nmodes = 5
|
|
33
33
|
|
|
34
34
|
# --- Create simulation ---------------------------------------------------
|
|
35
|
-
model = em.Simulation('DielectricResonatorFilter'
|
|
35
|
+
model = em.Simulation('DielectricResonatorFilter')
|
|
36
|
+
model.check_version("0.6.5") # Checks version compatibility.
|
|
36
37
|
|
|
37
38
|
# --- Build geometry ------------------------------------------------------
|
|
38
39
|
# Metal enclosure box (PEC by default)
|
emerge-0.6.3/.bumpversion.toml
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
[tool.bumpversion]
|
|
2
|
-
current_version = "0.6.3"
|
|
3
|
-
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
|
4
|
-
serialize = ["{major}.{minor}.{patch}"]
|
|
5
|
-
search = "{current_version}"
|
|
6
|
-
replace = "{new_version}"
|
|
7
|
-
regex = false
|
|
8
|
-
ignore_missing_version = false
|
|
9
|
-
ignore_missing_files = false
|
|
10
|
-
tag = true
|
|
11
|
-
sign_tags= false
|
|
12
|
-
tag_name = "v{new_version}"
|
|
13
|
-
tag_message = "Bump version: {current_version} → {new_version}"
|
|
14
|
-
allow_dirty = false
|
|
15
|
-
commit = true
|
|
16
|
-
message = "Bump version: {current_version} → {new_version}"
|
|
17
|
-
moveable_tags = []
|
|
18
|
-
commit_args = ""
|
|
19
|
-
setup_hooks = []
|
|
20
|
-
pre_commit_hooks = []
|
|
21
|
-
post_commit_hooks = []
|
|
22
|
-
|
|
23
|
-
[[tool.bumpversion.files]]
|
|
24
|
-
filename = "uv.lock"
|
|
25
|
-
|
|
26
|
-
[[tool.bumpversion.files]]
|
|
27
|
-
filename = "pyproject.toml"
|
|
28
|
-
|
|
29
|
-
[[tool.bumpversion.files]]
|
|
30
|
-
filename = "src/emerge/__init__.py"
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# EMerge is an open source Python based FEM EM simulation module.
|
|
2
|
-
# Copyright (C) 2025 Robert Fennis.
|
|
3
|
-
|
|
4
|
-
# This program is free software; you can redistribute it and/or
|
|
5
|
-
# modify it under the terms of the GNU General Public License
|
|
6
|
-
# as published by the Free Software Foundation; either version 2
|
|
7
|
-
# of the License, or (at your option) any later version.
|
|
8
|
-
|
|
9
|
-
# This program is distributed in the hope that it will be useful,
|
|
10
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
-
# GNU General Public License for more details.
|
|
13
|
-
|
|
14
|
-
# You should have received a copy of the GNU General Public License
|
|
15
|
-
# along with this program; if not, see
|
|
16
|
-
# <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
from __future__ import annotations
|
|
19
|
-
import gmsh
|
|
20
|
-
import numpy as np
|
|
21
|
-
from typing import Literal, Callable
|
|
22
|
-
from ..geometry import GeoEdge, GeoSurface, GeoVolume
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class Curve(GeoEdge):
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def __init__(self, xpts: np.ndarray, ypts: np.ndarray, zpts: np.ndarray,
|
|
30
|
-
degree: int = 3,
|
|
31
|
-
weights: list[float] | None = None,
|
|
32
|
-
knots: list[float] | None = None,
|
|
33
|
-
ctype: Literal['Spline','BSpline','Bezier'] = 'Bezier'):
|
|
34
|
-
self.xpts: np.ndarray = xpts
|
|
35
|
-
self.ypts: np.ndarray = ypts
|
|
36
|
-
self.zpts: np.ndarray = zpts
|
|
37
|
-
|
|
38
|
-
points = [gmsh.model.occ.add_point(x,y,z) for x,y,z in zip(xpts, ypts, zpts)]
|
|
39
|
-
|
|
40
|
-
if ctype.lower()=='spline':
|
|
41
|
-
tags = gmsh.model.occ.addSpline(points)
|
|
42
|
-
|
|
43
|
-
elif ctype.lower()=='bspline':
|
|
44
|
-
if weights is None:
|
|
45
|
-
weights = []
|
|
46
|
-
if knots is None:
|
|
47
|
-
knots = []
|
|
48
|
-
tags = gmsh.model.occ.addBSpline(points, degree=degree, weights=weights, knots=knots)
|
|
49
|
-
else:
|
|
50
|
-
tags = gmsh.model.occ.addBezier(points)
|
|
51
|
-
|
|
52
|
-
tags = gmsh.model.occ.addWire([tags,])
|
|
53
|
-
gmsh.model.occ.remove([(0,tag) for tag in points])
|
|
54
|
-
super().__init__(tags)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class Helix(GeoVolume):
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/assembly/generalized_eigen.py
RENAMED
|
File without changes
|
{emerge-0.6.3 → emerge-0.6.5}/emerge/_emerge/physics/microwave/assembly/generalized_eigen_hb.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|