emerge 0.5.1__py3-none-any.whl → 0.5.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of emerge might be problematic. Click here for more details.

Files changed (54) hide show
  1. emerge/_emerge/bc.py +14 -20
  2. emerge/_emerge/const.py +5 -0
  3. emerge/_emerge/cs.py +2 -2
  4. emerge/_emerge/elements/femdata.py +14 -14
  5. emerge/_emerge/elements/index_interp.py +1 -1
  6. emerge/_emerge/elements/ned2_interp.py +1 -1
  7. emerge/_emerge/elements/nedelec2.py +4 -4
  8. emerge/_emerge/elements/nedleg2.py +10 -10
  9. emerge/_emerge/geo/horn.py +1 -1
  10. emerge/_emerge/geo/modeler.py +18 -19
  11. emerge/_emerge/geo/operations.py +13 -10
  12. emerge/_emerge/geo/pcb.py +180 -82
  13. emerge/_emerge/geo/pcb_tools/calculator.py +2 -2
  14. emerge/_emerge/geo/pcb_tools/macro.py +14 -13
  15. emerge/_emerge/geo/pmlbox.py +1 -1
  16. emerge/_emerge/geometry.py +47 -33
  17. emerge/_emerge/logsettings.py +15 -16
  18. emerge/_emerge/material.py +15 -11
  19. emerge/_emerge/mesh3d.py +81 -59
  20. emerge/_emerge/mesher.py +26 -21
  21. emerge/_emerge/mth/integrals.py +1 -1
  22. emerge/_emerge/mth/pairing.py +2 -2
  23. emerge/_emerge/periodic.py +34 -31
  24. emerge/_emerge/physics/microwave/adaptive_freq.py +15 -16
  25. emerge/_emerge/physics/microwave/assembly/assembler.py +120 -93
  26. emerge/_emerge/physics/microwave/assembly/curlcurl.py +1 -8
  27. emerge/_emerge/physics/microwave/assembly/generalized_eigen.py +43 -8
  28. emerge/_emerge/physics/microwave/assembly/robinbc.py +5 -5
  29. emerge/_emerge/physics/microwave/microwave_3d.py +71 -44
  30. emerge/_emerge/physics/microwave/microwave_bc.py +206 -117
  31. emerge/_emerge/physics/microwave/microwave_data.py +36 -38
  32. emerge/_emerge/physics/microwave/sc.py +26 -26
  33. emerge/_emerge/physics/microwave/simjob.py +20 -15
  34. emerge/_emerge/physics/microwave/sparam.py +12 -12
  35. emerge/_emerge/physics/microwave/touchstone.py +1 -1
  36. emerge/_emerge/plot/display.py +12 -6
  37. emerge/_emerge/plot/pyvista/display.py +44 -39
  38. emerge/_emerge/plot/pyvista/display_settings.py +1 -1
  39. emerge/_emerge/plot/simple_plots.py +15 -15
  40. emerge/_emerge/selection.py +35 -39
  41. emerge/_emerge/simmodel.py +41 -47
  42. emerge/_emerge/simulation_data.py +24 -15
  43. emerge/_emerge/solve_interfaces/cudss_interface.py +238 -0
  44. emerge/_emerge/solve_interfaces/pardiso_interface.py +24 -18
  45. emerge/_emerge/solver.py +314 -136
  46. emerge/cli.py +1 -1
  47. emerge/lib.py +245 -248
  48. {emerge-0.5.1.dist-info → emerge-0.5.3.dist-info}/METADATA +5 -1
  49. emerge-0.5.3.dist-info/RECORD +83 -0
  50. emerge/_emerge/plot/grapher.py +0 -93
  51. emerge-0.5.1.dist-info/RECORD +0 -82
  52. {emerge-0.5.1.dist-info → emerge-0.5.3.dist-info}/WHEEL +0 -0
  53. {emerge-0.5.1.dist-info → emerge-0.5.3.dist-info}/entry_points.txt +0 -0
  54. {emerge-0.5.1.dist-info → emerge-0.5.3.dist-info}/licenses/LICENSE +0 -0
emerge/_emerge/bc.py CHANGED
@@ -21,6 +21,9 @@ from loguru import logger
21
21
  from .selection import Selection, FaceSelection
22
22
  import numpy as np
23
23
  from .geometry import GeoObject
24
+ from typing import TypeVar, Type
25
+
26
+ T = TypeVar('T')
24
27
 
25
28
  class BCDimension(Enum):
26
29
  ANY = -1
@@ -61,17 +64,8 @@ class BoundaryCondition:
61
64
  return self.dimension.value
62
65
 
63
66
  def __repr__(self) -> str:
64
- if self.dimension is BCDimension.ANY:
65
- return f'{type(self).__name__}{self.tags}'
66
- elif self.dimension is BCDimension.EDGE:
67
- return f'{type(self).__name__}{self.tags}'
68
- elif self.dimension is BCDimension.NODE:
69
- return f'{type(self).__name__}{self.tags}'
70
- elif self.dimension is BCDimension.FACE:
71
- return f'{type(self).__name__}{self.tags}'
72
- elif self.dimension is BCDimension.DOMAIN:
73
- return f'{type(self).__name__}{self.tags}'
74
-
67
+ return f'{type(self).__name__}{self.tags}'
68
+
75
69
  def __str__(self) -> str:
76
70
  return self.__repr__()
77
71
 
@@ -94,14 +88,14 @@ class BoundaryCondition:
94
88
  elif self.dimension != BCDimension(dimension):
95
89
  raise ValueError(f'Current boundary condition has dimension {self.dimension}, but tags have dimension {BCDimension(dimension)}')
96
90
 
97
- def add_tags(self, tags: list[tuple[int,int]]) -> None:
91
+ def add_tags(self, dimtags: list[tuple[int,int]]) -> None:
98
92
  """Adds the given taggs to this boundary condition.
99
93
 
100
94
  Args:
101
95
  tags (list[tuple[int,int]]): The tags to include
102
96
  """
103
- self.check_dimension(tags)
104
- tags = [x[1] for x in tags]
97
+ self.check_dimension(dimtags)
98
+ tags = [x[1] for x in dimtags]
105
99
  self.tags = _unique(self.tags + tags)
106
100
 
107
101
  def remove_tags(self, tags: list[int]) -> list[int]:
@@ -137,12 +131,12 @@ class BoundaryConditionSet:
137
131
  self.boundary_conditions: list[BoundaryCondition] = []
138
132
  self._initialized: bool = False
139
133
 
140
- def _construct_bc(self, constructor: type):
134
+ def _construct_bc(self, constructor: type) -> type:
141
135
  def constr(*args, **kwargs):
142
136
  obj = constructor(*args, **kwargs)
143
137
  self.assign(obj)
144
138
  return obj
145
- return constr
139
+ return constr # type: ignore
146
140
 
147
141
  def assigned(self, dim: int = 2) -> list[int]:
148
142
  """Returns all boundary tags that have a boundary condition assigned to them
@@ -171,7 +165,7 @@ class BoundaryConditionSet:
171
165
  """
172
166
  return len(self.oftype(bctype))
173
167
 
174
- def oftype(self, bctype: type) -> list[BoundaryCondition]:
168
+ def oftype(self, bctype: Type[T]) -> list[T]:
175
169
  """Returns a list of all boundary conditions of a certain type.
176
170
 
177
171
  Args:
@@ -180,7 +174,7 @@ class BoundaryConditionSet:
180
174
  Returns:
181
175
  list[BoundaryCondition]: The list of boundary conditions
182
176
  """
183
- return [item for item in self. boundary_conditions if isinstance(item, bctype)]
177
+ return [item for item in self.boundary_conditions if isinstance(item, bctype)]
184
178
 
185
179
  def reset(self) -> None:
186
180
  """Resets the boundary conditions that are defined
@@ -218,8 +212,8 @@ class BoundaryConditionSet:
218
212
  class Periodic(BoundaryCondition):
219
213
 
220
214
  def __init__(self,
221
- selection1: FaceSelection,
222
- selection2: FaceSelection,
215
+ selection1: Selection,
216
+ selection2: Selection,
223
217
  dv: tuple[float,float,float],
224
218
  ):
225
219
  self.face1: BoundaryCondition = BoundaryCondition(selection1)
@@ -0,0 +1,5 @@
1
+ C0 = 299792458
2
+ Z0 = 376.73031366857
3
+ PI = 3.14159265358979323846
4
+ EPS0 = 8.854187818814e-12
5
+ MU0 = 1/(C0*C0*EPS0)#1.2566370612720e-6
emerge/_emerge/cs.py CHANGED
@@ -120,7 +120,7 @@ XAX: Axis = Axis(np.array([1, 0, 0]))
120
120
  YAX: Axis = Axis(np.array([0, 1, 0]))
121
121
  ZAX: Axis = Axis(np.array([0, 0, 1]))
122
122
 
123
- def _parse_vector(vec: np.ndarray | tuple | list | Axis) -> np.ndarray:
123
+ def _parse_vector(vec: np.ndarray | tuple[float, float, float] | list[float] | Axis) -> np.ndarray:
124
124
  """ Takes an array, tuple, list or Axis and alwasys returns an array."""
125
125
  if isinstance(vec, np.ndarray):
126
126
  return vec
@@ -130,7 +130,7 @@ def _parse_vector(vec: np.ndarray | tuple | list | Axis) -> np.ndarray:
130
130
  return vec.vector
131
131
  return None
132
132
 
133
- def _parse_axis(vec: np.ndarray | tuple | list | Axis) -> Axis:
133
+ def _parse_axis(vec: np.ndarray | tuple[float, float, float] | list[float] | Axis) -> Axis:
134
134
  """Takes an array, tuple, list or Axis and always returns an Axis.
135
135
 
136
136
  Args:
@@ -19,7 +19,7 @@ from __future__ import annotations
19
19
  from ..mesh3d import Mesh3D
20
20
  import numpy as np
21
21
  from typing import Callable
22
- from scipy.sparse import coo_matrix, csr_matrix
22
+ from scipy.sparse import csr_matrix # type: ignore
23
23
 
24
24
  from ..mth.optimized import matmul
25
25
 
@@ -31,22 +31,22 @@ class FEMBasis:
31
31
  self.n_tris: int = self.mesh.n_tris
32
32
  self.n_tets: int = self.mesh.n_tets
33
33
 
34
- self.n_tet_dofs: int = None
35
- self.n_tri_dofs: int = None
34
+ self.n_tet_dofs: int = -1
35
+ self.n_tri_dofs: int = -1
36
36
 
37
37
  self.n_field: int = 2*self.n_edges + 2*self.n_tris
38
38
 
39
- self.tet_to_field: np.ndarray = None
39
+ self.tet_to_field: np.ndarray = np.array([])
40
40
 
41
- self.edge_to_field: np.ndarray = None
41
+ self.edge_to_field: np.ndarray = np.array([])
42
42
 
43
- self.tri_to_field: np.ndarray = None
43
+ self.tri_to_field: np.ndarray = np.array([])
44
44
 
45
- self._rows: np.ndarray = None
46
- self._cols: np.ndarray = None
45
+ self._rows: np.ndarray = np.array([])
46
+ self._cols: np.ndarray = np.array([])
47
47
 
48
48
 
49
- def interpolate_Ef(self, field: np.ndarray, basis: np.ndarray = None, origin: np.ndarray = None, tetids: np.ndarray = None) -> Callable:
49
+ def interpolate_Ef(self, field: np.ndarray, basis: np.ndarray | None = None, origin: np.ndarray | None = None, tetids: np.ndarray | None = None) -> Callable:
50
50
  '''Generates the Interpolation function as a function object for a given coordiante basis and origin.'''
51
51
  if basis is None:
52
52
  basis = np.eye(3)
@@ -61,14 +61,14 @@ class FEMBasis:
61
61
  return matmul(ibasis, np.array(self.interpolate(field, xyzg[0,:], xyzg[1,:], xyzg[2,:], tetids)))
62
62
  return func
63
63
 
64
- def interpolate(self, field: np.ndarray, xs: np.ndarray, ys: np.ndarray, zs: np.ndarray, tetids: np.ndarray = None) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
65
- pass
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
+ 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) -> 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) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
68
68
  """
69
69
  Interpolates the curl of the field at the given points.
70
70
  """
71
- pass
71
+ raise NotImplementedError()
72
72
 
73
73
  def empty_tet_matrix(self) -> np.ndarray:
74
74
  nnz = self.n_tets*self.n_tet_dofs**2
@@ -151,7 +151,7 @@ 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) -> np.ndarray:
154
+ tetids: np.ndarray | None = None) -> np.ndarray:
155
155
  raise NotImplementedError()
156
156
 
157
157
  def map_edge_to_field(self, edge_ids: np.ndarray) -> np.ndarray:
@@ -14,7 +14,7 @@
14
14
  # You should have received a copy of the GNU General Public License
15
15
  # along with this program; if not, see
16
16
  # <https://www.gnu.org/licenses/>.
17
- from numba import njit, f8, c16, i8, types
17
+ from numba import njit, f8, c16, i8, types # type: ignore
18
18
  import numpy as np
19
19
 
20
20
 
@@ -14,7 +14,7 @@
14
14
  # You should have received a copy of the GNU General Public License
15
15
  # along with this program; if not, see
16
16
  # <https://www.gnu.org/licenses/>.
17
- from numba import njit, f8, c16, i8, types
17
+ from numba import njit, f8, c16, i8, types # type: ignore
18
18
  import numpy as np
19
19
  from ..mth.optimized import compute_distances
20
20
 
@@ -61,14 +61,14 @@ class Nedelec2(FEMBasis):
61
61
  self.tri_to_field[7,:] = np.arange(ntris) + 2*nedges + ntris
62
62
 
63
63
  ##
64
- self._field: np.ndarray = None
64
+ self._field: np.ndarray | None = None
65
65
  self.n_tet_dofs = 20
66
66
  self.n_tri_dofs = 8
67
67
  self._all_tet_ids = np.arange(self.ntets)
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) -> 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) -> 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
  '''
@@ -76,7 +76,7 @@ class Nedelec2(FEMBasis):
76
76
  tetids = self._all_tet_ids
77
77
  return 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
78
 
79
- def interpolate_curl(self, field: np.ndarray, xs: np.ndarray, ys: np.ndarray, zs:np.ndarray, c: np.ndarray, tetids: np.ndarray = None) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
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]:
80
80
  """
81
81
  Interpolates the curl of the field at the given points.
82
82
  """
@@ -87,7 +87,7 @@ class Nedelec2(FEMBasis):
87
87
  def interpolate_index(self, xs: np.ndarray,
88
88
  ys: np.ndarray,
89
89
  zs: np.ndarray,
90
- tetids: np.ndarray = None) -> np.ndarray:
90
+ tetids: np.ndarray | None = None) -> np.ndarray:
91
91
  if tetids is None:
92
92
  tetids = self._all_tet_ids
93
93
 
@@ -22,7 +22,7 @@ from .femdata import FEMBasis
22
22
  from .ned2_interp import ned2_tri_interp_full, ned2_tri_interp_curl
23
23
  from ..mth.optimized import matinv
24
24
  from ..cs import CoordinateSystem
25
-
25
+ from ..const import MU0, C0
26
26
 
27
27
  ## TODO: TEMPORARY SOLUTION FIX THIS
28
28
 
@@ -46,21 +46,21 @@ class FieldFunctionClass:
46
46
  tris: np.ndarray,
47
47
  tri_to_field: np.ndarray,
48
48
  EH: str = 'E',
49
- diadic: np.ndarray = None,
50
- beta: float = None,
51
- constant: float = 1.0):
49
+ diadic: np.ndarray | None = None,
50
+ beta: float | None = None,
51
+ constant: float | int | complex = 1.0):
52
52
  self.field: np.ndarray = field
53
53
  self.cs: CoordinateSystem = cs
54
54
  self.nodes: np.ndarray = nodes
55
55
  self.tris: np.ndarray = tris
56
56
  self.tri_to_field: np.ndarray = tri_to_field
57
57
  self.eh: str = EH
58
- self.diadic: np.ndarray = diadic
59
- self.beta: float = beta
58
+ self.diadic: np.ndarray | None = diadic
59
+ self.beta: float | None = beta
60
60
  self.constant: float = constant
61
61
  if EH == 'H':
62
62
  if diadic is None:
63
- self.diadic = np.eye(3)[:,:,np.newaxis()] * np.ones((self.tris.shape[1]))
63
+ self.diadic = np.eye(3)[:,:,np.newaxis()] * np.ones((self.tris.shape[1])) # type: ignore
64
64
 
65
65
  def __call__(self, xs: np.ndarray,
66
66
  ys: np.ndarray,
@@ -158,7 +158,7 @@ class NedelecLegrange2(FEMBasis):
158
158
 
159
159
  def interpolate_Hf(self, field: np.ndarray, k0: float, ur: np.ndarray, beta: float) -> FieldFunctionClass:
160
160
  '''Generates the Interpolation function as a function object for a given coordiante basis and origin.'''
161
- constant = 1j/ ((k0*299792458)*(4*np.pi*1e-7))
161
+ constant = 1j / ((k0*C0)*MU0)
162
162
  urinv = np.zeros_like(ur)
163
163
 
164
164
  for i in range(ur.shape[2]):
@@ -179,10 +179,10 @@ class NedelecLegrange2(FEMBasis):
179
179
  self.local_nodes,
180
180
  self.tri_to_field)
181
181
 
182
- def tri_interpolate_curl(self, field, xs: np.ndarray, ys: np.ndarray, diadic: np.ndarray = None, beta: float = 0) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
182
+ 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]:
183
183
  coordinates = np.array([xs, ys])
184
184
  if diadic is None:
185
- diadic = np.eye(3)[:,:,np.newaxis()] * np.ones((self.mesh.n_tris))
185
+ diadic = np.eye(3)[:,:,np.newaxis()] * np.ones((self.mesh.n_tris)) # type: ignore
186
186
  return ned2_tri_interp_curl(coordinates,
187
187
  field,
188
188
  self.mesh.tris,
@@ -19,7 +19,7 @@ from ..geometry import GeoVolume
19
19
  from ..cs import CoordinateSystem
20
20
  from ..selection import FaceSelection
21
21
 
22
- import gmsh
22
+ import gmsh # type: ignore
23
23
 
24
24
  class Horn(GeoVolume):
25
25
 
@@ -17,9 +17,9 @@
17
17
 
18
18
  from __future__ import annotations
19
19
  import numpy as np
20
- from typing import Callable, Iterable, Any
21
- from .shapes import Box, Sphere, Cyllinder, CoaxCyllinder, Alignment
22
- from ..geometry import GeoVolume, GeoObject, GeoSurface
20
+ from typing import Callable, Iterable
21
+ from .shapes import Box, Cyllinder, Alignment
22
+ from ..geometry import GeoVolume, GeoObject
23
23
  from .operations import rotate, mirror, translate, add, subtract, embed
24
24
  from numbers import Number
25
25
  from functools import reduce
@@ -57,18 +57,16 @@ def get_count(args) -> int:
57
57
  return get_count(arg)
58
58
  return 1
59
59
 
60
- def get_item(value, n: int):
60
+ def get_item(value: Number | Series | list, n: int) -> Number | Series | Iterable | None:
61
61
  if isinstance(value, Number):
62
62
  return value
63
63
  elif isinstance(value, Series):
64
64
  return value[n]
65
65
  elif isinstance(value, Iterable):
66
- typ = type(value)
67
- return typ([get_item(v,n) for v in value])
66
+ return type(value)([get_item(v, n) for v in value])
68
67
  return None
69
68
 
70
69
  def unpack(*args):
71
- output = []
72
70
  N = get_count(args)
73
71
  return tuple(zip(*[[get_item(a,n) for a in args] for n in range(N)]))
74
72
 
@@ -86,7 +84,7 @@ class PartialFunction:
86
84
  self.identity: bool = identity
87
85
  self.permute: bool = permute
88
86
  self.N: int = 1
89
- self.kwargset: list[dict] = None
87
+ self.kwargset: list[dict] | None = None
90
88
 
91
89
  for key, value in self.kwargs.items():
92
90
  if not isinstance(value, Series):
@@ -98,7 +96,7 @@ class PartialFunction:
98
96
  self.N = self.N + 1
99
97
 
100
98
  def _compile(self) -> None:
101
- kwargset = []
99
+ kwargset: list = []
102
100
  N = self.N
103
101
 
104
102
  if self.identity:
@@ -116,7 +114,8 @@ class PartialFunction:
116
114
  self.kwargset = kwargset
117
115
 
118
116
  def __call__(self, objects: list[GeoObject], index: int) -> list[GeoObject]:
119
-
117
+ if self.kwargset is None:
118
+ raise ValueError('self.kwargset is not yet defined.')
120
119
  kwargs = self.kwargset[index]
121
120
  if kwargs is None:
122
121
  return objects
@@ -159,7 +158,7 @@ class NDimContainer:
159
158
  return n
160
159
 
161
160
  @property
162
- def dimtup(self) -> tuple[int]:
161
+ def dimtup(self) -> tuple[int, ...]:
163
162
  """A dimension tuple containing the dimensions of the NDimContainer
164
163
 
165
164
  Returns:
@@ -179,7 +178,7 @@ class NDimContainer:
179
178
  self.expanded_dims.append((i,n,N))
180
179
 
181
180
  if self.Ncopies > 1:
182
- self.expanded_dims.append((i+1, (1, self.Ncopies)))
181
+ self.expanded_dims.append((i+1, 1, self.Ncopies))
183
182
 
184
183
  self.map = np.arange(self.Ntot).reshape(self.dimtup)
185
184
 
@@ -215,7 +214,7 @@ class NDimContainer:
215
214
  number: int) -> list:
216
215
  dimindex, niter, Nvariations = self.expanded_dims[dim_ex_dim]
217
216
  slclist = [slice(None) for _ in self.dimensions]
218
- slclist[dimindex] = number
217
+ slclist[dimindex] = number # type: ignore
219
218
  return list(self.map[tuple(slclist)].flatten())
220
219
 
221
220
 
@@ -286,7 +285,7 @@ class Modeler:
286
285
  tags = []
287
286
  for obj in objs:
288
287
  tags.extend(obj.tags)
289
- gmshobj = GeoObject.from_dimtags(objs[0].dim, tags)
288
+ gmshobj = GeoObject.from_dimtags([(objs[0].dim, tag) for tag in tags])
290
289
  for obj in objs:
291
290
  gmshobj._take_tools(obj)
292
291
  return gmshobj
@@ -388,12 +387,12 @@ class Modeler:
388
387
  position: tuple[float | Series, float | Series, float | Series],
389
388
  cs: CoordinateSystem = GCS,
390
389
  merge: bool = False,
391
- NPoly: int = False):
390
+ NPoly: int = False) -> GeoVolume | list[GeoVolume]:
392
391
 
393
392
  N_objects = self.nvars()
394
393
  Rs, Hs, Ps = unpack(radius, height, position)
395
394
  N = len(Rs)
396
- cyls = []
395
+ cyls: list[GeoObject] = []
397
396
 
398
397
  for _ in range(N_objects):
399
398
  for r,h,p in zip(Rs, Hs, Ps):
@@ -408,7 +407,7 @@ class Modeler:
408
407
  self._apply_presteps(cyls)
409
408
 
410
409
  if merge:
411
- cyls = self._merge_object(cyls)
410
+ return self._merge_object(cyls)
412
411
 
413
412
  return cyls
414
413
 
@@ -434,7 +433,7 @@ class Modeler:
434
433
  N_objects = self.nvars()
435
434
  Ws, Ds, Hs, Ps = unpack(width, depth, height, position)
436
435
  N = len(Ws)
437
- boxes = []
436
+ boxes: list[GeoVolume] = []
438
437
 
439
438
  for _ in range(N_objects):
440
439
  for w, d, h, p in zip(Ws, Ds, Hs, Ps):
@@ -444,6 +443,6 @@ class Modeler:
444
443
  self._apply_presteps(boxes)
445
444
 
446
445
  if merge:
447
- boxes = self._merge_object(boxes)
446
+ return self._merge_object(boxes)
448
447
 
449
448
  return boxes
@@ -16,12 +16,12 @@
16
16
  # <https://www.gnu.org/licenses/>.
17
17
 
18
18
  from typing import TypeVar
19
- from ..geometry import GeoSurface, GeoVolume
19
+ from ..geometry import GeoSurface, GeoVolume, GeoObject, GeoPoint, GeoEdge
20
20
  from ..cs import CoordinateSystem, GCS
21
21
  import gmsh
22
22
  import numpy as np
23
23
 
24
- T = TypeVar('T', GeoSurface, GeoVolume)
24
+ T = TypeVar('T', GeoSurface, GeoVolume, GeoObject, GeoPoint, GeoEdge)
25
25
 
26
26
  def _gen_mapping(obj_in, obj_out) -> dict:
27
27
  tag_mapping: dict[int, dict] = {0: dict(),
@@ -60,7 +60,7 @@ def add(main: T, tool: T,
60
60
  main._exists = False
61
61
  if remove_tool:
62
62
  tool._exists = False
63
- return output
63
+ return output # type: ignore
64
64
 
65
65
  def remove(main: T, tool: T,
66
66
  remove_object: bool = True,
@@ -90,7 +90,7 @@ def remove(main: T, tool: T,
90
90
  main._exists = False
91
91
  if remove_tool:
92
92
  tool._exists = False
93
- return output
93
+ return output # type: ignore
94
94
 
95
95
  subtract = remove
96
96
 
@@ -122,7 +122,7 @@ def intersect(main: T, tool: T,
122
122
  main._exists = False
123
123
  if remove_tool:
124
124
  tool._exists = False
125
- return output
125
+ return output #type:ignore
126
126
 
127
127
  def embed(main: GeoVolume, other: GeoSurface) -> None:
128
128
  ''' Embeds a surface into a volume in the GMSH model.
@@ -138,7 +138,7 @@ def embed(main: GeoVolume, other: GeoSurface) -> None:
138
138
  None
139
139
  '''
140
140
  gmsh.model.geo.synchronize()
141
- gmsh.model.mesh.embed(other.dim, [other.tag,], main.dim, main.tags)
141
+ gmsh.model.mesh.embed(other.dim, other.tags, main.dim, main.tags)
142
142
 
143
143
  def rotate(main: GeoVolume,
144
144
  c0: tuple[float, float, float],
@@ -189,10 +189,10 @@ def translate(main: GeoVolume,
189
189
 
190
190
  return main
191
191
 
192
- def mirror(main: GeoVolume,
192
+ def mirror(main: GeoObject,
193
193
  origin: tuple[float, float, float] = (0.0, 0.0, 0.0),
194
194
  direction: tuple[float, float, float] = (1.0, 0.0, 0.0),
195
- make_copy: bool = True) -> GeoVolume:
195
+ make_copy: bool = True) -> GeoObject:
196
196
  """Mirrors a GeoVolume object along a miror plane defined by a direction originating at a point
197
197
 
198
198
  Args:
@@ -203,6 +203,9 @@ def mirror(main: GeoVolume,
203
203
  Returns:
204
204
  GeoVolume: The mirrored GeoVolume object
205
205
  """
206
+ origin = np.array(origin)
207
+ direction = np.array(direction)
208
+
206
209
  a, b, c = direction
207
210
  x0, y0, z0 = origin
208
211
  d = -(a*x0 + b*y0 + c*z0)
@@ -220,9 +223,9 @@ def mirror(main: GeoVolume,
220
223
  fp.mirror(origin, direction)
221
224
  return mirror_obj
222
225
 
223
- def change_coordinate_system(main: GeoVolume,
226
+ def change_coordinate_system(main: GeoObject,
224
227
  new_cs: CoordinateSystem = GCS,
225
- old_cs: CoordinateSystem = GCS):
228
+ old_cs: CoordinateSystem = GCS) -> GeoObject:
226
229
  """Moves the GeoVolume object from a current coordinate system to a new one.
227
230
 
228
231
  The old and new coordinate system by default are the global coordinate system.