emerge 0.6.10__tar.gz → 1.0.0__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.10 → emerge-1.0.0}/.bumpversion.toml +1 -1
- {emerge-0.6.10 → emerge-1.0.0}/PKG-INFO +4 -8
- {emerge-0.6.10 → emerge-1.0.0}/README.md +3 -7
- {emerge-0.6.10 → emerge-1.0.0}/emerge/__init__.py +1 -1
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/bc.py +9 -4
- emerge-1.0.0/emerge/_emerge/cacherun.py +79 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/geo/pcb.py +17 -7
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/geometry.py +32 -5
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/material.py +2 -1
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/assembly/assembler.py +12 -12
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/microwave_3d.py +42 -15
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/microwave_bc.py +6 -6
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/plot/matplotlib/mpldisplay.py +1 -1
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/plot/pyvista/display.py +25 -18
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/plot/pyvista/display_settings.py +2 -1
- emerge-1.0.0/emerge/_emerge/settings.py +12 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/simmodel.py +118 -18
- {emerge-0.6.10 → emerge-1.0.0}/emerge/lib.py +1 -1
- {emerge-0.6.10 → emerge-1.0.0}/examples/demo10_sgh.py +12 -8
- {emerge-0.6.10 → emerge-1.0.0}/examples/demo11_lumped_element_filter.py +2 -6
- {emerge-0.6.10 → emerge-1.0.0}/examples/demo12_mode_alignment.py +3 -3
- {emerge-0.6.10 → emerge-1.0.0}/examples/demo13_helix_antenna.py +1 -1
- {emerge-0.6.10 → emerge-1.0.0}/examples/demo14_boundary_selection.py +1 -1
- {emerge-0.6.10 → emerge-1.0.0}/examples/demo1_stepped_imp_filter.py +2 -3
- {emerge-0.6.10 → emerge-1.0.0}/examples/demo2_combline_filter.py +1 -1
- {emerge-0.6.10 → emerge-1.0.0}/examples/demo3_coupled_line_filter.py +20 -20
- {emerge-0.6.10 → emerge-1.0.0}/examples/demo4_patch_antenna.py +4 -6
- emerge-1.0.0/examples/demo5_revolve.py +98 -0
- {emerge-0.6.10 → emerge-1.0.0}/examples/demo6_striplines_with_vias.py +3 -5
- {emerge-0.6.10 → emerge-1.0.0}/examples/demo7_periodic_cells.py +3 -3
- {emerge-0.6.10 → emerge-1.0.0}/examples/demo8_waveguide_bpf_synthesis.py +1 -1
- {emerge-0.6.10 → emerge-1.0.0}/examples/demo9_dielectric_resonator.py +9 -10
- {emerge-0.6.10 → emerge-1.0.0}/pyproject.toml +1 -1
- {emerge-0.6.10 → emerge-1.0.0}/uv.lock +1 -1
- emerge-0.6.10/.opt +0 -714
- emerge-0.6.10/examples/demo5_revolve.py +0 -15
- {emerge-0.6.10 → emerge-1.0.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/.gitignore +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/.python-version +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/LICENSE +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/THIRD_PARTY_LICENSES.md +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/UMFPACK_Install_windows.md +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/UMFPACK_installer_windows.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/__main__.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/__init__.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/_cache_check.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/const.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/coord.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/cs.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/dataset.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/elements/__init__.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/elements/femdata.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/elements/index_interp.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/elements/ned2_interp.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/elements/nedelec2.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/elements/nedleg2.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/geo/__init__.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/geo/horn.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/geo/modeler.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/geo/operations.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/geo/pcb_tools/calculator.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/geo/pcb_tools/macro.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/geo/pmlbox.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/geo/polybased.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/geo/shapes.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/geo/step.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/geo2d.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/howto.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/logsettings.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/mesh3d.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/mesher.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/mth/common_functions.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/mth/integrals.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/mth/optimized.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/mth/pairing.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/periodic.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/__init__.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/__init__.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/adaptive_freq.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/assembly/curlcurl.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/assembly/generalized_eigen.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/assembly/generalized_eigen_hb.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/assembly/periodicbc.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/assembly/robinbc.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/microwave_data.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/periodic.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/port_functions.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/sc.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/simjob.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/sparam.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/physics/microwave/touchstone.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/plot/__init__.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/plot/display.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/plot/pyvista/__init__.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/plot/simple_plots.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/plot.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/projects/__init__.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/projects/_gen_base.txt +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/projects/_load_base.txt +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/projects/generate_project.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/selection.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/simulation_data.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/solve_interfaces/cudss_interface.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/solve_interfaces/pardiso_interface.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/solver.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/_emerge/system.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/cli.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/ext.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/plot.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/emerge/pyvista.py +0 -0
- {emerge-0.6.10 → emerge-1.0.0}/src/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: emerge
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
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
|
|
@@ -82,17 +82,13 @@ To run this FEM library you need the following libraries
|
|
|
82
82
|
- numba
|
|
83
83
|
- matplotlib (for the matplotlib base display)
|
|
84
84
|
- pyvista (for the PyVista base display)
|
|
85
|
-
-
|
|
85
|
+
- cloudpickle
|
|
86
86
|
- mkl (x86 devices only)
|
|
87
87
|
|
|
88
88
|
Optional:
|
|
89
89
|
- scikit-umfpack
|
|
90
90
|
- cudss
|
|
91
91
|
|
|
92
|
-
##
|
|
92
|
+
## Resources / Manual
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
## Third Party License Notice
|
|
97
|
-
|
|
98
|
-
“This package depends on Intel® Math Kernel Library (MKL), which is licensed separately under the Intel Simplified Software License (October 2022). Installing with pip will fetch the MKL wheel and prompt you to accept that licence.”
|
|
94
|
+
You can find the latest versions of the manual on: **https://www.emerge-software.com/resources/**
|
|
@@ -56,17 +56,13 @@ To run this FEM library you need the following libraries
|
|
|
56
56
|
- numba
|
|
57
57
|
- matplotlib (for the matplotlib base display)
|
|
58
58
|
- pyvista (for the PyVista base display)
|
|
59
|
-
-
|
|
59
|
+
- cloudpickle
|
|
60
60
|
- mkl (x86 devices only)
|
|
61
61
|
|
|
62
62
|
Optional:
|
|
63
63
|
- scikit-umfpack
|
|
64
64
|
- cudss
|
|
65
65
|
|
|
66
|
-
##
|
|
66
|
+
## Resources / Manual
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
## Third Party License Notice
|
|
71
|
-
|
|
72
|
-
“This package depends on Intel® Math Kernel Library (MKL), which is licensed separately under the Intel Simplified Software License (October 2022). Installing with pip will fetch the MKL wheel and prompt you to accept that licence.”
|
|
68
|
+
You can find the latest versions of the manual on: **https://www.emerge-software.com/resources/**
|
|
@@ -53,7 +53,7 @@ class BoundaryCondition:
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
if isinstance(assignment, GeoObject):
|
|
56
|
-
assignment = assignment.
|
|
56
|
+
assignment = assignment.selection
|
|
57
57
|
|
|
58
58
|
self.selection: Selection = assignment
|
|
59
59
|
self.tags: list[int] = self.selection.tags
|
|
@@ -83,7 +83,7 @@ class BoundaryCondition:
|
|
|
83
83
|
raise ValueError(f'All tags must have the same dimension, instead its {tags}')
|
|
84
84
|
dimension = tags[0][0]
|
|
85
85
|
if self.dimension is BCDimension.ANY:
|
|
86
|
-
logger.info(f'Assigning dimension
|
|
86
|
+
logger.info(f'Assigning {self} to dimension{BCDimension(dimension)}')
|
|
87
87
|
self.dimension = BCDimension(dimension)
|
|
88
88
|
elif self.dimension != BCDimension(dimension):
|
|
89
89
|
raise ValueError(f'Current boundary condition has dimension {self.dimension}, but tags have dimension {BCDimension(dimension)}')
|
|
@@ -131,6 +131,13 @@ class BoundaryConditionSet:
|
|
|
131
131
|
self.boundary_conditions: list[BoundaryCondition] = []
|
|
132
132
|
self._initialized: bool = False
|
|
133
133
|
|
|
134
|
+
def cleanup(self) -> None:
|
|
135
|
+
""" Removes non assigned boundary conditions"""
|
|
136
|
+
logger.trace("Cleaning up boundary conditions.")
|
|
137
|
+
toremove = [bc for bc in self.boundary_conditions if len(bc.tags)==0]
|
|
138
|
+
logger.trace(f"Removing: {toremove}")
|
|
139
|
+
self.boundary_conditions = [bc for bc in self.boundary_conditions if len(bc.tags)>0]
|
|
140
|
+
|
|
134
141
|
def _construct_bc(self, constructor: type) -> type:
|
|
135
142
|
def constr(*args, **kwargs):
|
|
136
143
|
obj = constructor(*args, **kwargs)
|
|
@@ -201,8 +208,6 @@ class BoundaryConditionSet:
|
|
|
201
208
|
|
|
202
209
|
bc.add_tags(bc.selection.dimtags)
|
|
203
210
|
|
|
204
|
-
logger.info('Excluding other possible boundary conditions')
|
|
205
|
-
|
|
206
211
|
for existing_bc in self.boundary_conditions:
|
|
207
212
|
excluded = existing_bc.exclude_bc(bc)
|
|
208
213
|
if excluded:
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# inside your module, e.g. utils.py
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
import ast
|
|
6
|
+
import textwrap
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _is_plain_check_run(test: ast.AST) -> bool:
|
|
11
|
+
"""True only for a bare call to check_run() as the entire if-test."""
|
|
12
|
+
if not isinstance(test, ast.Call) or test.args or test.keywords:
|
|
13
|
+
return False
|
|
14
|
+
f = test.func
|
|
15
|
+
return (
|
|
16
|
+
isinstance(f, ast.Attribute) and f.attr == "cache_run"
|
|
17
|
+
) or (
|
|
18
|
+
isinstance(f, ast.Name) and f.id == "cache_run"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
def get_run_block_str(source: str) -> str:
|
|
22
|
+
"""
|
|
23
|
+
Return all source text before the first `if check_run():` / `if *.check_run():`.
|
|
24
|
+
Returns None if no matching if-statement exists.
|
|
25
|
+
"""
|
|
26
|
+
tree = ast.parse(source)
|
|
27
|
+
candidates = [n for n in ast.walk(tree) if isinstance(n, ast.If) and _is_plain_check_run(n.test)]
|
|
28
|
+
if not candidates:
|
|
29
|
+
return None
|
|
30
|
+
first = min(candidates, key=lambda n: n.lineno)
|
|
31
|
+
lines = source.splitlines(keepends=True)
|
|
32
|
+
return "".join(lines[: first.lineno - 1])
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_build_block_str(source: str) -> str | None:
|
|
36
|
+
"""Return the code string inside the first `if *.checkrun(...):` block, or None."""
|
|
37
|
+
tree = ast.parse(source)
|
|
38
|
+
for node in ast.walk(tree):
|
|
39
|
+
if isinstance(node, ast.If) and isinstance(node.test, ast.Call):
|
|
40
|
+
f = node.test.func
|
|
41
|
+
called = (isinstance(f, ast.Attribute) and f.attr == "cache_build") or \
|
|
42
|
+
(isinstance(f, ast.Name) and f.id == "cache_build")
|
|
43
|
+
if called and node.body:
|
|
44
|
+
start = node.body[0].lineno - 1 # 0-based start line
|
|
45
|
+
end = node.body[-1].end_lineno # 1-based end line (inclusive)
|
|
46
|
+
lines = source.splitlines()
|
|
47
|
+
block = "\n".join(lines[start:end])
|
|
48
|
+
return textwrap.dedent(block)
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
def entry_script_path():
|
|
52
|
+
main = sys.modules.get("__main__")
|
|
53
|
+
# Most normal runs: python path/to/app.py
|
|
54
|
+
if main and hasattr(main, "__file__"):
|
|
55
|
+
return os.path.abspath(main.__file__)
|
|
56
|
+
# Fallbacks (e.g. python -m pkg.mod)
|
|
57
|
+
if sys.argv and sys.argv[0] not in ("", "-c"):
|
|
58
|
+
return os.path.abspath(sys.argv[0])
|
|
59
|
+
# Interactive sessions, notebooks, or embedded interpreters
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_build_section() -> str:
|
|
64
|
+
""" Returns the string section inside the check_build() if statement"""
|
|
65
|
+
name = entry_script_path()
|
|
66
|
+
|
|
67
|
+
lines = get_build_block_str(Path(name).read_text())
|
|
68
|
+
return lines
|
|
69
|
+
|
|
70
|
+
def get_run_section() -> str:
|
|
71
|
+
"""Return sthe string section before the check_run() if statement
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
str: _description_
|
|
75
|
+
"""
|
|
76
|
+
name = entry_script_path()
|
|
77
|
+
|
|
78
|
+
lines = get_run_block_str(Path(name).read_text())
|
|
79
|
+
return lines
|
|
@@ -19,7 +19,7 @@ from __future__ import annotations
|
|
|
19
19
|
|
|
20
20
|
from ..cs import CoordinateSystem, GCS, Axis
|
|
21
21
|
from ..geometry import GeoPolygon, GeoVolume, GeoSurface
|
|
22
|
-
from ..material import Material, AIR, COPPER
|
|
22
|
+
from ..material import Material, AIR, COPPER, PEC
|
|
23
23
|
from .shapes import Box, Plate, Cylinder
|
|
24
24
|
from .polybased import XYPolygon
|
|
25
25
|
from .operations import change_coordinate_system, unite
|
|
@@ -86,7 +86,7 @@ class PCBPoly:
|
|
|
86
86
|
xs: list[float],
|
|
87
87
|
ys: list[float],
|
|
88
88
|
z: float = 0,
|
|
89
|
-
material: Material =
|
|
89
|
+
material: Material = PEC):
|
|
90
90
|
self.xs: list[float] = xs
|
|
91
91
|
self.ys: list[float] = ys
|
|
92
92
|
self.z: float = z
|
|
@@ -906,12 +906,14 @@ class PCB:
|
|
|
906
906
|
unit: float = 0.001,
|
|
907
907
|
cs: CoordinateSystem | None = None,
|
|
908
908
|
material: Material = AIR,
|
|
909
|
+
trace_material: Material = PEC,
|
|
909
910
|
layers: int = 2,
|
|
910
911
|
):
|
|
911
912
|
|
|
912
913
|
self.thickness: float = thickness
|
|
913
914
|
self._zs: np.ndarray = np.linspace(-self.thickness, 0, layers)
|
|
914
915
|
self.material: Material = material
|
|
916
|
+
self.trace_material: Material = trace_material
|
|
915
917
|
self.width: float | None = None
|
|
916
918
|
self.length: float | None = None
|
|
917
919
|
self.origin: np.ndarray = np.array([0.,0.,0.])
|
|
@@ -926,6 +928,9 @@ class PCB:
|
|
|
926
928
|
self.cs: CoordinateSystem = cs
|
|
927
929
|
if self.cs is None:
|
|
928
930
|
self.cs = GCS
|
|
931
|
+
|
|
932
|
+
self.dielectric_priority: int = 11
|
|
933
|
+
self.via_priority: int = 12
|
|
929
934
|
|
|
930
935
|
self.traces: list[GeoPolygon] = []
|
|
931
936
|
self.ports: list[GeoPolygon] = []
|
|
@@ -1110,7 +1115,7 @@ class PCB:
|
|
|
1110
1115
|
|
|
1111
1116
|
plane = Plate(origin, (width*self.unit, 0, 0), (0, height*self.unit, 0)) # type: ignore
|
|
1112
1117
|
plane = change_coordinate_system(plane, self.cs) # type: ignore
|
|
1113
|
-
plane.set_material(
|
|
1118
|
+
plane.set_material(self.trace_material)
|
|
1114
1119
|
return plane # type: ignore
|
|
1115
1120
|
|
|
1116
1121
|
def generate_pcb(self,
|
|
@@ -1140,9 +1145,10 @@ class PCB:
|
|
|
1140
1145
|
position=(x0, y0, z0+z1*self.unit))
|
|
1141
1146
|
box.material = self.material
|
|
1142
1147
|
box = change_coordinate_system(box, self.cs)
|
|
1148
|
+
box.prio_set(self.dielectric_priority)
|
|
1143
1149
|
boxes.append(box)
|
|
1144
1150
|
if merge:
|
|
1145
|
-
return GeoVolume.merged(boxes) # type: ignore
|
|
1151
|
+
return GeoVolume.merged(boxes).prio_set(self.dielectric_priority) # type: ignore
|
|
1146
1152
|
return boxes # type: ignore
|
|
1147
1153
|
|
|
1148
1154
|
box = Box(self.width*self.unit,
|
|
@@ -1150,6 +1156,7 @@ class PCB:
|
|
|
1150
1156
|
self.thickness*self.unit,
|
|
1151
1157
|
position=(x0,y0,z0-self.thickness*self.unit))
|
|
1152
1158
|
box.material = self.material
|
|
1159
|
+
box.prio_set(self.dielectric_priority)
|
|
1153
1160
|
box = change_coordinate_system(box, self.cs)
|
|
1154
1161
|
return box # type: ignore
|
|
1155
1162
|
|
|
@@ -1304,7 +1311,8 @@ class PCB:
|
|
|
1304
1311
|
xg, yg, zg = self.cs.in_global_cs(x0, y0, z0)
|
|
1305
1312
|
cs = CoordinateSystem(self.cs.xax, self.cs.yax, self.cs.zax, np.array([xg, yg, zg]))
|
|
1306
1313
|
cyl = Cylinder(via.radius*self.unit, (via.z2-via.z1)*self.unit, cs, via.segments)
|
|
1307
|
-
cyl.material =
|
|
1314
|
+
cyl.material = self.trace_material
|
|
1315
|
+
cyl.prio_set(self.via_priority)
|
|
1308
1316
|
vias.append(cyl)
|
|
1309
1317
|
if merge:
|
|
1310
1318
|
|
|
@@ -1315,7 +1323,7 @@ class PCB:
|
|
|
1315
1323
|
xs: list[float],
|
|
1316
1324
|
ys: list[float],
|
|
1317
1325
|
z: float = 0,
|
|
1318
|
-
material: Material =
|
|
1326
|
+
material: Material = None) -> None:
|
|
1319
1327
|
"""Add a custom polygon to the PCB
|
|
1320
1328
|
|
|
1321
1329
|
Args:
|
|
@@ -1324,6 +1332,8 @@ class PCB:
|
|
|
1324
1332
|
z (float, optional): The z-height. Defaults to 0.
|
|
1325
1333
|
material (Material, optional): The material. Defaults to COPPER.
|
|
1326
1334
|
"""
|
|
1335
|
+
if material is None:
|
|
1336
|
+
material = self.trace_material
|
|
1327
1337
|
self.polies.append(PCBPoly(xs, ys, z, material))
|
|
1328
1338
|
|
|
1329
1339
|
def _gen_poly(self, xys: list[tuple[float, float]], z: float) -> GeoPolygon:
|
|
@@ -1385,7 +1395,7 @@ class PCB:
|
|
|
1385
1395
|
ally.append(y)
|
|
1386
1396
|
|
|
1387
1397
|
poly = self._gen_poly(xys2, z)
|
|
1388
|
-
poly.material =
|
|
1398
|
+
poly.material = self.trace_material
|
|
1389
1399
|
polys.append(poly)
|
|
1390
1400
|
|
|
1391
1401
|
for pcbpoly in self.polies:
|
|
@@ -50,6 +50,9 @@ class _GeometryManager:
|
|
|
50
50
|
self.geometry_list: dict[str, list[GeoObject]] = dict()
|
|
51
51
|
self.active: str = ''
|
|
52
52
|
|
|
53
|
+
def get_surfaces(self) -> list[GeoSurface]:
|
|
54
|
+
return [geo for geo in self.all_geometries() if geo.dim==2]
|
|
55
|
+
|
|
53
56
|
def all_geometries(self, model: str | None = None) -> list[GeoObject]:
|
|
54
57
|
if model is None:
|
|
55
58
|
model = self.active
|
|
@@ -250,7 +253,7 @@ class GeoObject:
|
|
|
250
253
|
return self.material._metal
|
|
251
254
|
|
|
252
255
|
@property
|
|
253
|
-
def
|
|
256
|
+
def selection(self) -> Selection:
|
|
254
257
|
'''Returns a corresponding Face/Domain or Edge Selection object'''
|
|
255
258
|
if self.dim==1:
|
|
256
259
|
return EdgeSelection(self.tags)
|
|
@@ -391,6 +394,30 @@ class GeoObject:
|
|
|
391
394
|
self._priority = level
|
|
392
395
|
return self
|
|
393
396
|
|
|
397
|
+
def above(self, other: GeoObject) -> GeoObject:
|
|
398
|
+
"""Puts the priority of this object one higher than the other, then returns this object
|
|
399
|
+
|
|
400
|
+
Args:
|
|
401
|
+
other (GeoObject): The other object to put below this object
|
|
402
|
+
|
|
403
|
+
Returns:
|
|
404
|
+
GeoObject: This object
|
|
405
|
+
"""
|
|
406
|
+
self._priority = other._priority + 1
|
|
407
|
+
return self
|
|
408
|
+
|
|
409
|
+
def below(self, other: GeoObject) -> GeoObject:
|
|
410
|
+
"""Puts the priority of this object one lower than the other, then returns this object
|
|
411
|
+
|
|
412
|
+
Args:
|
|
413
|
+
other (GeoObject): The other object to put above this object
|
|
414
|
+
|
|
415
|
+
Returns:
|
|
416
|
+
GeoObject: This object
|
|
417
|
+
"""
|
|
418
|
+
self._priority = other._priority -1
|
|
419
|
+
return self
|
|
420
|
+
|
|
394
421
|
def prio_up(self) -> GeoObject:
|
|
395
422
|
"""Increases the material selection priority by 1
|
|
396
423
|
|
|
@@ -517,14 +544,14 @@ class GeoVolume(GeoObject):
|
|
|
517
544
|
self.tags = [tag,]
|
|
518
545
|
|
|
519
546
|
@property
|
|
520
|
-
def
|
|
547
|
+
def selection(self) -> DomainSelection:
|
|
521
548
|
return DomainSelection(self.tags)
|
|
522
549
|
|
|
523
550
|
class GeoPoint(GeoObject):
|
|
524
551
|
dim = 0
|
|
525
552
|
|
|
526
553
|
@property
|
|
527
|
-
def
|
|
554
|
+
def selection(self) -> PointSelection:
|
|
528
555
|
return PointSelection(self.tags)
|
|
529
556
|
|
|
530
557
|
def __init__(self, tag: int | list[int]):
|
|
@@ -540,7 +567,7 @@ class GeoEdge(GeoObject):
|
|
|
540
567
|
dim = 1
|
|
541
568
|
|
|
542
569
|
@property
|
|
543
|
-
def
|
|
570
|
+
def selection(self) -> EdgeSelection:
|
|
544
571
|
return EdgeSelection(self.tags)
|
|
545
572
|
|
|
546
573
|
def __init__(self, tag: int | list[int]):
|
|
@@ -558,7 +585,7 @@ class GeoSurface(GeoObject):
|
|
|
558
585
|
dim = 2
|
|
559
586
|
|
|
560
587
|
@property
|
|
561
|
-
def
|
|
588
|
+
def selection(self) -> FaceSelection:
|
|
562
589
|
return FaceSelection(self.tags)
|
|
563
590
|
|
|
564
591
|
def __init__(self, tag: int | list[int]):
|
|
@@ -381,4 +381,5 @@ class Material:
|
|
|
381
381
|
return self._color_rgb
|
|
382
382
|
|
|
383
383
|
AIR = Material(color="#4496f3", opacity=0.05, name='Air')
|
|
384
|
-
COPPER = Material(cond=5.8e7, color="#62290c", _metal=True, name='Copper')
|
|
384
|
+
COPPER = Material(cond=5.8e7, color="#62290c", _metal=True, name='Copper')
|
|
385
|
+
PEC = Material(color="#ff78aa", opacity=1.0, cond=1e30, _metal=True, name="PEC")
|
|
@@ -22,6 +22,7 @@ from ....elements.nedleg2 import NedelecLegrange2
|
|
|
22
22
|
from ....mth.optimized import gaus_quad_tri
|
|
23
23
|
from ....mth.pairing import pair_coordinates
|
|
24
24
|
from ....material import Material
|
|
25
|
+
from ....settings import Settings
|
|
25
26
|
from scipy.sparse import csr_matrix
|
|
26
27
|
from loguru import logger
|
|
27
28
|
from ..simjob import SimJob
|
|
@@ -102,13 +103,10 @@ class Assembler:
|
|
|
102
103
|
|
|
103
104
|
It stores some cached properties to accellerate preformance.
|
|
104
105
|
"""
|
|
105
|
-
def __init__(self):
|
|
106
|
+
def __init__(self, settings: Settings):
|
|
106
107
|
|
|
107
108
|
self.cached_matrices = None
|
|
108
|
-
self.
|
|
109
|
-
# Currently not used.
|
|
110
|
-
#self._Pmat_cache: dict[tuple[int,int], csr_matrix] = dict()
|
|
111
|
-
#self._remove_cache: list[int] = []
|
|
109
|
+
self.settings = settings
|
|
112
110
|
|
|
113
111
|
def assemble_bma_matrices(self,
|
|
114
112
|
field: Nedelec2,
|
|
@@ -155,20 +153,22 @@ class Assembler:
|
|
|
155
153
|
E, B = generelized_eigenvalue_matrix(nedlegfield, ermesh, urmesh, port.cs._basis, k0)
|
|
156
154
|
|
|
157
155
|
# TODO: Simplified to all "conductors" loosely defined. Must change to implementing line robin boundary conditions.
|
|
158
|
-
pecs: list[BoundaryCondition] = bc_set.get_conductors()
|
|
156
|
+
pecs: list[BoundaryCondition] = bc_set.get_conductors()
|
|
159
157
|
if len(pecs) > 0:
|
|
160
|
-
logger.debug(f'.total of equiv. {len(pecs)} PEC BCs implemented')
|
|
158
|
+
logger.debug(f'.total of equiv. {len(pecs)} PEC BCs implemented for BMA')
|
|
161
159
|
|
|
162
160
|
pec_ids = []
|
|
163
161
|
|
|
164
162
|
# Process all concutors. Everything above the conductivity limit is considered pec.
|
|
165
163
|
for it in range(boundary_surface.n_tris):
|
|
166
|
-
if sigmesh[it] > self.
|
|
164
|
+
if sigmesh[it] > self.settings.mw_3d_peclim:
|
|
167
165
|
pec_ids.extend(list(nedlegfield.tri_to_field[:,it]))
|
|
168
166
|
|
|
169
167
|
# Process all PEC Boundary Conditions
|
|
170
168
|
for pec in pecs:
|
|
171
169
|
logger.trace(f'.implementing {pec}')
|
|
170
|
+
if len(pec.tags)==0:
|
|
171
|
+
continue
|
|
172
172
|
face_tags = pec.tags
|
|
173
173
|
tri_ids = mesh.get_triangles(face_tags)
|
|
174
174
|
edge_ids = list(mesh.tri_to_edge[:,tri_ids].flatten())
|
|
@@ -235,7 +235,7 @@ class Assembler:
|
|
|
235
235
|
|
|
236
236
|
er = er*(1-1j*tand) - 1j*cond/(W0*EPS0)
|
|
237
237
|
|
|
238
|
-
is_frequency_dependent = is_frequency_dependent or np.any((cond > 0) & (cond < self.
|
|
238
|
+
is_frequency_dependent = is_frequency_dependent or np.any((cond > 0) & (cond < self.settings.mw_3d_peclim)) # type: ignore
|
|
239
239
|
|
|
240
240
|
if cache_matrices and not is_frequency_dependent and self.cached_matrices is not None:
|
|
241
241
|
# IF CACHED AND AVAILABLE PULL E AND B FROM CACHE
|
|
@@ -273,11 +273,11 @@ class Assembler:
|
|
|
273
273
|
# Conductivity above al imit, consider it all PEC
|
|
274
274
|
ipec = 0
|
|
275
275
|
for itet in range(field.n_tets):
|
|
276
|
-
if cond[0,0,itet] > self.
|
|
276
|
+
if cond[0,0,itet] > self.settings.mw_3d_peclim:
|
|
277
277
|
ipec+=1
|
|
278
278
|
pec_ids.extend(field.tet_to_field[:,itet])
|
|
279
279
|
if ipec>0:
|
|
280
|
-
logger.trace(f'Extended PEC with {ipec} tets with a conductivity > {self.
|
|
280
|
+
logger.trace(f'Extended PEC with {ipec} tets with a conductivity > {self.settings.mw_3d_peclim}.')
|
|
281
281
|
|
|
282
282
|
for pec in pec_bcs:
|
|
283
283
|
logger.trace(f'Implementing: {pec}')
|
|
@@ -466,7 +466,7 @@ class Assembler:
|
|
|
466
466
|
|
|
467
467
|
# Conductivity above a limit, consider it all PEC
|
|
468
468
|
for itet in range(field.n_tets):
|
|
469
|
-
if cond[0,0,itet] > self.
|
|
469
|
+
if cond[0,0,itet] > self.settings.mw_3d_peclim:
|
|
470
470
|
pec_ids.extend(field.tet_to_field[:,itet])
|
|
471
471
|
|
|
472
472
|
# PEC Boundary conditions
|
|
@@ -19,12 +19,14 @@ from ...mesher import Mesher
|
|
|
19
19
|
from ...material import Material
|
|
20
20
|
from ...mesh3d import Mesh3D
|
|
21
21
|
from ...coord import Line
|
|
22
|
+
from ...geometry import GeoSurface
|
|
22
23
|
from ...elements.femdata import FEMBasis
|
|
23
24
|
from ...elements.nedelec2 import Nedelec2
|
|
24
25
|
from ...solver import DEFAULT_ROUTINE, SolveRoutine
|
|
25
26
|
from ...system import called_from_main_function
|
|
26
27
|
from ...selection import FaceSelection
|
|
27
28
|
from ...mth.optimized import compute_distances
|
|
29
|
+
from ...settings import Settings
|
|
28
30
|
from .microwave_bc import MWBoundaryConditionSet, PEC, ModalPort, LumpedPort, PortBC
|
|
29
31
|
from .microwave_data import MWData
|
|
30
32
|
from .assembly.assembler import Assembler
|
|
@@ -122,16 +124,16 @@ class Microwave3D:
|
|
|
122
124
|
formulation.
|
|
123
125
|
|
|
124
126
|
"""
|
|
125
|
-
def __init__(self, mesher: Mesher, mwdata: MWData, order: int = 2):
|
|
127
|
+
def __init__(self, mesher: Mesher, settings: Settings, mwdata: MWData, order: int = 2):
|
|
126
128
|
self.frequencies: list[float] = []
|
|
127
129
|
self.current_frequency = 0
|
|
128
130
|
self.order: int = order
|
|
129
131
|
self.resolution: float = 1
|
|
130
|
-
|
|
132
|
+
self._settings: Settings = settings
|
|
131
133
|
self.mesher: Mesher = mesher
|
|
132
134
|
self.mesh: Mesh3D = Mesh3D(self.mesher)
|
|
133
135
|
|
|
134
|
-
self.assembler: Assembler = Assembler()
|
|
136
|
+
self.assembler: Assembler = Assembler(self._settings)
|
|
135
137
|
self.bc: MWBoundaryConditionSet = MWBoundaryConditionSet(None)
|
|
136
138
|
self.basis: Nedelec2 | None = None
|
|
137
139
|
self.solveroutine: SolveRoutine = DEFAULT_ROUTINE
|
|
@@ -190,14 +192,28 @@ class Microwave3D:
|
|
|
190
192
|
return sorted(self.bc.oftype(PortBC), key=lambda x: x.number) # type: ignore
|
|
191
193
|
|
|
192
194
|
|
|
193
|
-
def _initialize_bcs(self) -> None:
|
|
195
|
+
def _initialize_bcs(self, surfaces: list[GeoSurface]) -> None:
|
|
194
196
|
"""Initializes the boundary conditions to set PEC as all exterior boundaries.
|
|
195
197
|
"""
|
|
196
198
|
logger.debug('Initializing boundary conditions.')
|
|
197
199
|
|
|
198
200
|
tags = self.mesher.domain_boundary_face_tags
|
|
201
|
+
|
|
202
|
+
# Assigning surface impedance boundary condition
|
|
203
|
+
if self._settings.mw_2dbc:
|
|
204
|
+
for surf in surfaces:
|
|
205
|
+
if surf.material.cond.scalar(1e9) > self._settings.mw_2dbc_peclim:
|
|
206
|
+
logger.debug(f'Assinging PEC to {surf}')
|
|
207
|
+
self.bc.PEC(surf)
|
|
208
|
+
elif surf.material.cond.scalar(1e9) > self._settings.mw_2dbc_lim:
|
|
209
|
+
logger.debug(f'Assigning SurfaceImpedance to {surf}')
|
|
210
|
+
self.bc.SurfaceImpedance(surf, surf.material)
|
|
211
|
+
|
|
212
|
+
|
|
199
213
|
tags = [tag for tag in tags if tag not in self.bc.assigned(2)]
|
|
214
|
+
|
|
200
215
|
self.bc.PEC(FaceSelection(tags))
|
|
216
|
+
|
|
201
217
|
logger.info(f'Adding PEC boundary condition with tags {tags}.')
|
|
202
218
|
if self.mesher.periodic_cell is not None:
|
|
203
219
|
self.mesher.periodic_cell.generate_bcs()
|
|
@@ -247,6 +263,12 @@ class Microwave3D:
|
|
|
247
263
|
resolution (float): The desired wavelength fraction.
|
|
248
264
|
|
|
249
265
|
"""
|
|
266
|
+
if resolution > 0.5:
|
|
267
|
+
logger.warning('Resolutions greater than 0.5 cannot yield accurate results, capping resolution to 0.4')
|
|
268
|
+
resolution = 0.4
|
|
269
|
+
elif resolution > 0.334:
|
|
270
|
+
logger.warning('A resolution greater than 0.33 may cause accuracy issues.')
|
|
271
|
+
|
|
250
272
|
self.resolution = resolution
|
|
251
273
|
|
|
252
274
|
def set_conductivity_limit(self, condutivity: float) -> None:
|
|
@@ -292,6 +314,7 @@ class Microwave3D:
|
|
|
292
314
|
''' Initializes auxilliary required boundary condition information before running simulations.
|
|
293
315
|
'''
|
|
294
316
|
logger.debug('Initializing boundary conditions')
|
|
317
|
+
self.bc.cleanup()
|
|
295
318
|
for port in self.bc.oftype(LumpedPort):
|
|
296
319
|
self.define_lumped_port_integration_points(port)
|
|
297
320
|
|
|
@@ -311,22 +334,25 @@ class Microwave3D:
|
|
|
311
334
|
|
|
312
335
|
if points.size==0:
|
|
313
336
|
raise SimulationError(f'The lumped port {port} has no nodes associated with it')
|
|
337
|
+
|
|
314
338
|
xs = self.mesh.nodes[0,points]
|
|
315
339
|
ys = self.mesh.nodes[1,points]
|
|
316
340
|
zs = self.mesh.nodes[2,points]
|
|
317
341
|
|
|
318
342
|
dotprod = xs*field_axis[0] + ys*field_axis[1] + zs*field_axis[2]
|
|
319
343
|
|
|
320
|
-
start_id =
|
|
344
|
+
start_id = np.argwhere(dotprod == np.min(dotprod)).flatten()
|
|
345
|
+
|
|
346
|
+
xs = xs[start_id]
|
|
347
|
+
ys = ys[start_id]
|
|
348
|
+
zs = zs[start_id]
|
|
321
349
|
|
|
322
|
-
start = _pick_central(self.mesh.nodes[:,start_id.flatten()])
|
|
323
|
-
logger.info(f'Starting node = {_dimstring(start)}')
|
|
324
|
-
end = start + port.Vdirection.np*port.height
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
port.vintline = Line.from_points(start, end, 21)
|
|
328
350
|
|
|
329
|
-
|
|
351
|
+
for x,y,z in zip(xs, ys, zs):
|
|
352
|
+
start = np.array([x,y,z])
|
|
353
|
+
end = start + port.Vdirection.np*port.height
|
|
354
|
+
port.vintline.append(Line.from_points(start, end, 21))
|
|
355
|
+
logger.trace(f'Port[{port.port_number}] integration line {start} -> {end}.')
|
|
330
356
|
|
|
331
357
|
port.v_integration = True
|
|
332
358
|
|
|
@@ -569,10 +595,10 @@ class Microwave3D:
|
|
|
569
595
|
elif TEM:
|
|
570
596
|
G1, G2 = self._find_tem_conductors(port, sigtri=cond)
|
|
571
597
|
cs, dls = self._compute_integration_line(G1,G2)
|
|
572
|
-
mode.modetype='TEM'
|
|
598
|
+
mode.modetype = 'TEM'
|
|
573
599
|
Ex, Ey, Ez = portfE(cs[0,:], cs[1,:], cs[2,:])
|
|
574
600
|
voltage = np.sum(Ex*dls[0,:] + Ey*dls[1,:] + Ez*dls[2,:])
|
|
575
|
-
mode.Z0 = voltage**2/(2*P)
|
|
601
|
+
mode.Z0 = abs(voltage**2/(2*P))
|
|
576
602
|
logger.debug(f'Port Z0 = {mode.Z0}')
|
|
577
603
|
|
|
578
604
|
mode.set_power(P*port._qmode(k0)**2)
|
|
@@ -1003,7 +1029,8 @@ class Microwave3D:
|
|
|
1003
1029
|
if bc.Z0 is None:
|
|
1004
1030
|
raise SimulationError('Trying to compute the impedance of a boundary condition with no characteristic impedance.')
|
|
1005
1031
|
|
|
1006
|
-
|
|
1032
|
+
Voltages = [line.line_integral(fieldfunction) for line in bc.vintline]
|
|
1033
|
+
V = sum(Voltages)/len(Voltages)
|
|
1007
1034
|
|
|
1008
1035
|
if bc.active:
|
|
1009
1036
|
if bc.voltage is None:
|
|
@@ -73,11 +73,11 @@ class MWBoundaryConditionSet(BoundaryConditionSet):
|
|
|
73
73
|
"""
|
|
74
74
|
bcs = self.oftype(PEC)
|
|
75
75
|
for bc in self.oftype(SurfaceImpedance):
|
|
76
|
-
if bc.sigma >
|
|
76
|
+
if bc.sigma > 10.0:
|
|
77
77
|
bcs.append(bc)
|
|
78
78
|
|
|
79
79
|
return bcs
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
def get_type(self, bctype: Literal['PEC','ModalPort','LumpedPort','PMC','LumpedElement','RectangularWaveguide','Periodic','FloquetPort','SurfaceImpedance']) -> FaceSelection:
|
|
82
82
|
tags = []
|
|
83
83
|
for bc in self.boundary_conditions:
|
|
@@ -545,7 +545,7 @@ class ModalPort(PortBC):
|
|
|
545
545
|
self.modes[k0] = new_modes
|
|
546
546
|
return
|
|
547
547
|
for k0, modes in self.modes.items():
|
|
548
|
-
self.modes[k0] = sorted(modes, key=lambda m: m.
|
|
548
|
+
self.modes[k0] = sorted(modes, key=lambda m: m.beta, reverse=True)
|
|
549
549
|
|
|
550
550
|
def get_mode(self, k0: float, i=None) -> PortMode:
|
|
551
551
|
"""Returns a given mode solution in the form of a PortMode object.
|
|
@@ -834,7 +834,7 @@ class LumpedPort(PortBC):
|
|
|
834
834
|
# logger.info('Constructing coordinate system from normal port')
|
|
835
835
|
# self.cs = Axis(self.selection.normal).construct_cs() # type: ignore
|
|
836
836
|
self.cs = GCS
|
|
837
|
-
self.vintline: Line
|
|
837
|
+
self.vintline: list[Line] = []
|
|
838
838
|
self.v_integration = True
|
|
839
839
|
|
|
840
840
|
@property
|
|
@@ -1031,7 +1031,7 @@ class SurfaceImpedance(RobinBC):
|
|
|
1031
1031
|
self.sigma: float = 0.0
|
|
1032
1032
|
|
|
1033
1033
|
if material is not None:
|
|
1034
|
-
self.sigma = material.cond
|
|
1034
|
+
self.sigma = material.cond.scalar(1e9)
|
|
1035
1035
|
self._mur = material.ur
|
|
1036
1036
|
self._epsr = material.er
|
|
1037
1037
|
|
|
@@ -1064,7 +1064,7 @@ class SurfaceImpedance(RobinBC):
|
|
|
1064
1064
|
|
|
1065
1065
|
w0 = k0*C0
|
|
1066
1066
|
f0 = w0/(2*np.pi)
|
|
1067
|
-
sigma = self.sigma
|
|
1067
|
+
sigma = self.sigma
|
|
1068
1068
|
mur = self._material.ur.scalar(f0)
|
|
1069
1069
|
er = self._material.er.scalar(f0)
|
|
1070
1070
|
|