basicemergesolverhelperpackage 0.0.3__tar.gz → 0.0.4__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.
Files changed (13) hide show
  1. {basicemergesolverhelperpackage-0.0.3 → basicemergesolverhelperpackage-0.0.4}/PKG-INFO +1 -1
  2. {basicemergesolverhelperpackage-0.0.3 → basicemergesolverhelperpackage-0.0.4}/setup.py +1 -1
  3. {basicemergesolverhelperpackage-0.0.3 → basicemergesolverhelperpackage-0.0.4}/src/basicemergesolverhelperpackage/EMergeHelperFunctions.py +256 -9
  4. {basicemergesolverhelperpackage-0.0.3 → basicemergesolverhelperpackage-0.0.4}/src/basicemergesolverhelperpackage.egg-info/PKG-INFO +1 -1
  5. {basicemergesolverhelperpackage-0.0.3 → basicemergesolverhelperpackage-0.0.4}/LICENSE +0 -0
  6. {basicemergesolverhelperpackage-0.0.3 → basicemergesolverhelperpackage-0.0.4}/README.md +0 -0
  7. {basicemergesolverhelperpackage-0.0.3 → basicemergesolverhelperpackage-0.0.4}/setup.cfg +0 -0
  8. {basicemergesolverhelperpackage-0.0.3 → basicemergesolverhelperpackage-0.0.4}/src/basicemergesolverhelperpackage/EMergeConstants.py +0 -0
  9. {basicemergesolverhelperpackage-0.0.3 → basicemergesolverhelperpackage-0.0.4}/src/basicemergesolverhelperpackage/__init__.py +0 -0
  10. {basicemergesolverhelperpackage-0.0.3 → basicemergesolverhelperpackage-0.0.4}/src/basicemergesolverhelperpackage.egg-info/SOURCES.txt +0 -0
  11. {basicemergesolverhelperpackage-0.0.3 → basicemergesolverhelperpackage-0.0.4}/src/basicemergesolverhelperpackage.egg-info/dependency_links.txt +0 -0
  12. {basicemergesolverhelperpackage-0.0.3 → basicemergesolverhelperpackage-0.0.4}/src/basicemergesolverhelperpackage.egg-info/requires.txt +0 -0
  13. {basicemergesolverhelperpackage-0.0.3 → basicemergesolverhelperpackage-0.0.4}/src/basicemergesolverhelperpackage.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basicemergesolverhelperpackage
3
- Version: 0.0.3
3
+ Version: 0.0.4
4
4
  Summary: Mesh creation and plot utilities for EMerge solver or other FEM solver.
5
5
  Home-page: https://github.com/LubomirJagos42/basic-emerge-solver-helper-package
6
6
  Author: Lubomir Jagos
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setup(
7
7
  name="basicemergesolverhelperpackage",
8
- version="0.0.3",
8
+ version="0.0.4",
9
9
  author="Lubomir Jagos",
10
10
  author_email="lubomir.jagos.42@gmail.com",
11
11
  description="Mesh creation and plot utilities for EMerge solver or other FEM solver.",
@@ -1,6 +1,7 @@
1
1
  import emerge as em
2
2
  import emerge._emerge.geometry as emergeGeo
3
- from typing import Callable
3
+ import emerge._emerge.physics.microwave.microwave_bc as emergeMicrowaveBC
4
+ from typing import Callable, Literal
4
5
  import gmsh
5
6
  import os
6
7
 
@@ -129,12 +130,29 @@ class EMergeHelperFunctions:
129
130
  gmsh.model.addPhysicalGroup(2, objectTag2DList, name=groupName)
130
131
  gmsh.model.addPhysicalGroup(3, objectTag3DList, name=groupName)
131
132
 
132
- def addMaterial(self, name, materialObj, color="#000000", opacity: float = -89.0):
133
+ def addMaterial(self, name, materialObj, color="#000000", opacity: float = 1.0):
133
134
  self.materialList[name] = materialObj
134
135
  self.materialList[name].color = color
135
136
  self.materialList[name].opacity = opacity
136
137
 
137
- def setMaterialColor(self, name, color="#000000", opacity: float = -89.0):
138
+ def getMaterial(self, name):
139
+ #
140
+ # Get material from internal material list
141
+ #
142
+ materialObj = self.materialList[name] if name in self.materialList.keys() else None
143
+
144
+ #
145
+ # If material not found try to scan all geometries and their assigned materials if it will be found
146
+ #
147
+ if materialObj == None:
148
+ for geometryObj in self.simulationObj.state.manager.geometry_list[self.simulationObj.modelname].values():
149
+ if geometryObj.material.name == name:
150
+ materialObj = geometryObj.material
151
+ break
152
+
153
+ return materialObj
154
+
155
+ def setMaterialColor(self, name, color="#000000", opacity: float = 1.0):
138
156
  """Setter for color and opacity
139
157
  :param name: Name of material
140
158
  :param color: Color string in html for like #FF0000 (red)
@@ -143,7 +161,29 @@ class EMergeHelperFunctions:
143
161
  self.materialList[name].color = color
144
162
  self.materialList[name].opacity = opacity
145
163
 
146
- def addPort(self, name="", portStart=[0.0, 0.0, 0.0], width=0.0, height=0.0, R=50.0, direction=em.ZAX, excitationAmplitude:float=0.0, geometryObject:em._emerge.geometry.GeoObject=None, portNumber:int=-1):
164
+ def addPort(
165
+ self,
166
+ name="",
167
+ portStart=[0.0, 0.0, 0.0],
168
+ width=0.0,
169
+ height=0.0,
170
+ R=50.0,
171
+ direction=em.ZAX,
172
+ excitationAmplitude:float=0.0,
173
+ geometryObject:em._emerge.geometry.GeoObject=None,
174
+ portNumber:int=-1,
175
+
176
+ modalModeType: Literal['TE','TM','TEM'] | None = None,
177
+ modalMixedMaterials: bool = False,
178
+ modalImpedanceDefinition: Literal['PV','PI','VI'] = 'PV',
179
+
180
+ rectangularWaveguideMode: tuple[int, int] = (0, 0),
181
+ rectangularWaveguidePermittivity: float = 1.0,
182
+
183
+ coaxPortInnerRadius: float = 0.0,
184
+ coaxPortOuterRadius: float = 0.0,
185
+ coaxPortPermittivity: float = 1.0,
186
+ ):
147
187
  self.portList[name] = {}
148
188
  self.portList[name]['portStart'] = portStart
149
189
  self.portList[name]['width'] = width
@@ -154,9 +194,103 @@ class EMergeHelperFunctions:
154
194
  self.portList[name]['object'] = geometryObject
155
195
  self.portList[name]['portNumber'] = self._generatedPortIndex if portNumber == -1 else portNumber
156
196
 
197
+ self.portList[name]["modalModeType"] = modalModeType
198
+ self.portList[name]["modalMixedMaterials"] = modalMixedMaterials
199
+ self.portList[name]["modalImpedanceDefinition"] = modalImpedanceDefinition
200
+
201
+ self.portList[name]["rectangularWaveguideMode"] = rectangularWaveguideMode
202
+ self.portList[name]["rectangularWaveguidePermittivity"] = rectangularWaveguidePermittivity
203
+
204
+ self.portList[name]["coaxPortInnerRadius"] = coaxPortInnerRadius
205
+ self.portList[name]["coaxPortOuterRadius"] = coaxPortOuterRadius
206
+ self.portList[name]["coaxPortPermittivity"] = coaxPortPermittivity
207
+
157
208
  if portNumber == -1:
158
209
  self._generatedPortIndex += 1
159
210
 
211
+ def addLumpedPort(
212
+ self,
213
+ name = "",
214
+ portStart = [0.0, 0.0, 0.0],
215
+ width = 0.0,
216
+ height = 0.0,
217
+ R = 50.0,
218
+ direction = em.ZAX,
219
+ power:float = 0.0,
220
+ geometryObject:em._emerge.geometry.GeoObject = None,
221
+ portNumber:int = -1
222
+ ):
223
+ self.addPort(
224
+ name=name,
225
+ portStart=portStart,
226
+ width=width,
227
+ height=height,
228
+ R=R,
229
+ direction=direction,
230
+ excitationAmplitude=power,
231
+ geometryObject=geometryObject,
232
+ portNumber=portNumber
233
+ )
234
+
235
+ def addModalPort(
236
+ self,
237
+ name = "",
238
+ mode: Literal["TE", "TM", "TEM"] = "TE",
239
+ mixedMaterials: bool = False,
240
+ impedanceDefinition: Literal["PV", "PI", "VI"] = "PV",
241
+ power:float = 0.0,
242
+ geometryObject:em._emerge.geometry.GeoObject = None,
243
+ portNumber:int = -1
244
+ ):
245
+ self.addPort(
246
+ name=name,
247
+ modalModeType=mode,
248
+ modalMixedMaterials=mixedMaterials,
249
+ modalImpedanceDefinition=impedanceDefinition,
250
+ excitationAmplitude=power,
251
+ geometryObject=geometryObject,
252
+ portNumber=portNumber
253
+ )
254
+
255
+ def addRectangularWaveguidePort(
256
+ self,
257
+ name = "",
258
+ mode: tuple[int, int] = (0,0),
259
+ er: float = 1.0,
260
+ power:float = 1.0,
261
+ geometryObject:em._emerge.geometry.GeoObject = None,
262
+ portNumber:int = -1
263
+ ):
264
+ self.addPort(
265
+ name=name,
266
+ rectangularWaveguideMode = mode,
267
+ rectangularWaveguidePermittivity = er,
268
+ excitationAmplitude=power,
269
+ geometryObject=geometryObject,
270
+ portNumber=portNumber
271
+ )
272
+
273
+ def addCoaxPort(
274
+ self,
275
+ name = "",
276
+ inner_radius: float = 0.0,
277
+ outer_radius: float = 0.0,
278
+ er: float = 1.0,
279
+ power:float = 1.0,
280
+ geometryObject:em._emerge.geometry.GeoObject = None,
281
+ portNumber:int = -1
282
+ ):
283
+ self.addPort(
284
+ name=name,
285
+ coaxPortInnerRadius = inner_radius,
286
+ coaxPortOuterRadius = outer_radius,
287
+ coaxPortPermittivity = er,
288
+ excitationAmplitude=power,
289
+ geometryObject=geometryObject,
290
+ portNumber=portNumber
291
+ )
292
+
293
+
160
294
  def getPort(self, name):
161
295
  return self.portList[name]
162
296
 
@@ -172,8 +306,9 @@ class EMergeHelperFunctions:
172
306
  if portObj['portNumber'] == name:
173
307
  return portObj['portNumber']
174
308
 
175
- def setPortAsLumpedPort(self, name, searchObjectName=""):
309
+ def setPortAsLumpedPort(self, name, searchObjectName="") -> list[emergeMicrowaveBC.LumpedPort]:
176
310
  portObj = self.getPort(name)
311
+ resultBoundaryConditionList = []
177
312
 
178
313
  #
179
314
  # Port object can be splitted since there was fragmentation operation in EMerge
@@ -181,8 +316,8 @@ class EMergeHelperFunctions:
181
316
  portGeometryObjectList = self.getAllObjectByName(name if searchObjectName == "" else searchObjectName)
182
317
  for geometryObj in portGeometryObjectList:
183
318
  if portObj['excitationAmplitude'] > 0.0:
184
- self.simulationObj.mw.bc.LumpedPort(
185
- geometryObj,
319
+ resultObj = self.simulationObj.mw.bc.LumpedPort(
320
+ face=geometryObj,
186
321
  port_number=portObj['portNumber'],
187
322
  width=portObj['width'],
188
323
  height=portObj['height'],
@@ -191,17 +326,82 @@ class EMergeHelperFunctions:
191
326
  power=portObj['excitationAmplitude']
192
327
  )
193
328
  else:
194
- self.simulationObj.mw.bc.LumpedPort(
195
- geometryObj,
329
+ resultObj = self.simulationObj.mw.bc.LumpedPort(
330
+ face=geometryObj,
196
331
  port_number=portObj['portNumber'],
197
332
  width=portObj['width'],
198
333
  height=portObj['height'],
199
334
  direction=portObj['direction'],
200
335
  Z0=portObj['R']
201
336
  )
337
+ resultBoundaryConditionList.append(resultObj)
202
338
 
203
339
  self._temporaryInternalPortIndex += 1
204
340
 
341
+ return resultBoundaryConditionList
342
+
343
+ def setPortAsModalPort(self, name, searchObjectName="") -> list[emergeMicrowaveBC.ModalPort]:
344
+ """Experimental implementation not tested on real world example!!!"""
345
+
346
+ resultBoundaryConditionList = []
347
+
348
+ portObj = self.getPort(name)
349
+ portGeometryObjectList = self.getAllObjectByName(name if searchObjectName == "" else searchObjectName)
350
+
351
+ for geometryObj in portGeometryObjectList:
352
+ resultObj = self.simulationObj.mw.bc.ModalPort(
353
+ face = geometryObj,
354
+ port_number=portObj['portNumber'],
355
+ power = portObj['excitationAmplitude'],
356
+ modetype = portObj["modalModeType"],
357
+ number_of_modes = 1,
358
+ mixed_materials = portObj["modalMixedMaterials"],
359
+ impedance_definition = portObj["modalImpedanceDefinition"]
360
+ )
361
+ resultBoundaryConditionList.append(resultObj)
362
+
363
+ return resultBoundaryConditionList
364
+
365
+ def setPortAsRectangularWaveguidePort(self, name, searchObjectName="") -> list[emergeMicrowaveBC.RectangularWaveguide]:
366
+ """Experimental implementation not tested on real world example!!!"""
367
+
368
+ resultBoundaryConditionList = []
369
+
370
+ portObj = self.getPort(name)
371
+ portGeometryObjectList = self.getAllObjectByName(name if searchObjectName == "" else searchObjectName)
372
+
373
+ for geometryObj in portGeometryObjectList:
374
+ resultObj = self.simulationObj.mw.bc.RectangularWaveguide(
375
+ face = geometryObj,
376
+ port_number=portObj['portNumber'],
377
+ power = portObj['excitationAmplitude'],
378
+ mode = portObj["rectangularWaveguideMode"],
379
+ er = portObj["rectangularWaveguidePermittivity"]
380
+ )
381
+ resultBoundaryConditionList.append(resultObj)
382
+
383
+ return resultBoundaryConditionList
384
+
385
+ def setPortAsCoaxPort(self, name, searchObjectName="") -> list[emergeMicrowaveBC.CoaxPort]:
386
+ """Experimental implementation not tested on real world example!!!"""
387
+
388
+ resultBoundaryConditionList = []
389
+
390
+ portObj = self.getPort(name)
391
+ portGeometryObjectList = self.getAllObjectByName(name if searchObjectName == "" else searchObjectName)
392
+
393
+ for geometryObj in portGeometryObjectList:
394
+ resultObj = self.simulationObj.mw.bc.CoaxPort(
395
+ face = geometryObj,
396
+ port_number=portObj['portNumber'],
397
+ power = portObj['excitationAmplitude'],
398
+ rad_in_out = (portObj["coaxPortInnerRadius"], portObj["coaxPortInnerRadius"]),
399
+ er = portObj["coaxPortPermittivity"]
400
+ )
401
+ resultBoundaryConditionList.append(resultObj)
402
+
403
+ return resultBoundaryConditionList
404
+
205
405
  def plotSParamUsingPortName(self, sourcePortName, targetPortName, dblim=[-40, 0], plotSmithChart=False):
206
406
  sourcePortNumber = self.getPortNumber(sourcePortName)
207
407
  targetPortNumber = self.getPortNumber(targetPortName)
@@ -246,3 +446,50 @@ class EMergeHelperFunctions:
246
446
 
247
447
  for geoObject in objectList:
248
448
  self.simulationObj.display.add_object(geoObject, opacity=opacity)
449
+
450
+ def create_emerge_plane_data(self, port_start, port_stop, normal):
451
+ """
452
+ Computes origin, u, and v vectors for an EMerge Plane using
453
+ start/stop diagonal points and a surface normal vector.
454
+
455
+ Inputs can be FreeCAD vectors or standard (x, y, z) tuples.
456
+ """
457
+ # 1. Convert everything to numpy arrays for clean math
458
+ p1 = np.array([port_start[0], port_start[1], port_start[2]])
459
+ p4 = np.array([port_stop[0], port_stop[1], port_stop[2]])
460
+ n = np.array([normal[0], normal[1], normal[2]])
461
+
462
+ # Normalize the normal vector to ensure it is a unit vector
463
+ n = n / np.linalg.norm(n)
464
+
465
+ # 2. Calculate the full diagonal vector across the port
466
+ diag = p4 - p1
467
+
468
+ # 3. Project the diagonal vector to eliminate any component pointing
469
+ # along the normal (ensures the math stays strictly flat on the 2D plane)
470
+ diag_planar = diag - np.dot(diag, n) * n
471
+
472
+ # 4. Determine the primary coordinate alignment for the 'u' axis.
473
+ # We choose an axis that isn't parallel to our normal vector.
474
+ if abs(n[0]) < 0.9:
475
+ ref_dir = np.array([1.0, 0.0, 0.0]) # Fallback to X axis alignment
476
+ else:
477
+ ref_dir = np.array([0.0, 1.0, 0.0]) # Fallback to Y axis alignment
478
+
479
+ # Generate an orthogonal direction for 'u' using a cross product
480
+ u_direction = np.cross(n, ref_dir)
481
+ u_axis = u_direction / np.linalg.norm(u_direction)
482
+
483
+ # Generate the perpendicular 'v' direction
484
+ v_axis = np.cross(n, u_axis)
485
+
486
+ # 5. Project the planar diagonal onto our newly established u and v axes
487
+ u_magnitude = np.dot(diag_planar, u_axis)
488
+ v_magnitude = np.dot(diag_planar, v_axis)
489
+
490
+ # 6. Reconstruct the final u and v vectors as clean 3D tuples
491
+ u = tuple(u_axis * u_magnitude)
492
+ v = tuple(v_axis * v_magnitude)
493
+ origin = tuple(p1)
494
+
495
+ return origin, u, v
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basicemergesolverhelperpackage
3
- Version: 0.0.3
3
+ Version: 0.0.4
4
4
  Summary: Mesh creation and plot utilities for EMerge solver or other FEM solver.
5
5
  Home-page: https://github.com/LubomirJagos42/basic-emerge-solver-helper-package
6
6
  Author: Lubomir Jagos