emerge 0.5.5__py3-none-any.whl → 0.6.0__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 (39) hide show
  1. emerge/__init__.py +4 -1
  2. emerge/_emerge/cs.py +2 -2
  3. emerge/_emerge/elements/ned2_interp.py +21 -26
  4. emerge/_emerge/elements/nedleg2.py +27 -45
  5. emerge/_emerge/geo/__init__.py +1 -1
  6. emerge/_emerge/geo/modeler.py +2 -2
  7. emerge/_emerge/geo/pcb.py +4 -4
  8. emerge/_emerge/geo/shapes.py +37 -14
  9. emerge/_emerge/geometry.py +27 -1
  10. emerge/_emerge/howto.py +9 -9
  11. emerge/_emerge/material.py +1 -0
  12. emerge/_emerge/mesh3d.py +63 -14
  13. emerge/_emerge/mesher.py +7 -4
  14. emerge/_emerge/mth/optimized.py +30 -0
  15. emerge/_emerge/periodic.py +46 -16
  16. emerge/_emerge/physics/microwave/assembly/assembler.py +4 -21
  17. emerge/_emerge/physics/microwave/assembly/generalized_eigen.py +23 -19
  18. emerge/_emerge/physics/microwave/assembly/generalized_eigen_hb.py +465 -0
  19. emerge/_emerge/physics/microwave/assembly/robinbc.py +59 -18
  20. emerge/_emerge/physics/microwave/microwave_3d.py +38 -186
  21. emerge/_emerge/physics/microwave/microwave_bc.py +101 -35
  22. emerge/_emerge/physics/microwave/microwave_data.py +1 -1
  23. emerge/_emerge/plot/pyvista/display.py +40 -7
  24. emerge/_emerge/plot/pyvista/display_settings.py +1 -0
  25. emerge/_emerge/plot/simple_plots.py +159 -27
  26. emerge/_emerge/projects/_gen_base.txt +2 -2
  27. emerge/_emerge/projects/_load_base.txt +1 -1
  28. emerge/_emerge/simmodel.py +22 -7
  29. emerge/_emerge/solve_interfaces/cudss_interface.py +44 -2
  30. emerge/_emerge/solve_interfaces/pardiso_interface.py +1 -0
  31. emerge/_emerge/solver.py +26 -19
  32. emerge/ext.py +4 -0
  33. emerge/lib.py +1 -1
  34. {emerge-0.5.5.dist-info → emerge-0.6.0.dist-info}/METADATA +6 -4
  35. {emerge-0.5.5.dist-info → emerge-0.6.0.dist-info}/RECORD +38 -37
  36. emerge/_emerge/elements/legrange2.py +0 -172
  37. {emerge-0.5.5.dist-info → emerge-0.6.0.dist-info}/WHEEL +0 -0
  38. {emerge-0.5.5.dist-info → emerge-0.6.0.dist-info}/entry_points.txt +0 -0
  39. {emerge-0.5.5.dist-info → emerge-0.6.0.dist-info}/licenses/LICENSE +0 -0
emerge/__init__.py CHANGED
@@ -18,6 +18,7 @@ along with this program; if not, see
18
18
  """
19
19
  import os
20
20
 
21
+ __version__ = "0.6.0"
21
22
 
22
23
  ############################################################
23
24
  # HANDLE ENVIRONMENT VARIABLES #
@@ -43,7 +44,7 @@ from loguru import logger
43
44
  LOG_CONTROLLER.set_default()
44
45
  logger.debug('Importing modules')
45
46
 
46
- from ._emerge.simmodel import Simulation3D
47
+ from ._emerge.simmodel import Simulation
47
48
  from ._emerge.material import Material
48
49
  from ._emerge import bc
49
50
  from ._emerge.solver import SolverBicgstab, SolverGMRES, SolveRoutine, ReverseCuthillMckee, Sorter, SolverPardiso, SolverUMFPACK, SolverSuperLU, EMSolver
@@ -57,5 +58,7 @@ from ._emerge.periodic import RectCell, HexCell
57
58
  from ._emerge.mesher import Algorithm2D, Algorithm3D
58
59
  from . import lib
59
60
  from ._emerge.howto import _HowtoClass
61
+
60
62
  howto = _HowtoClass()
63
+
61
64
  logger.debug('Importing complete!')
emerge/_emerge/cs.py CHANGED
@@ -128,7 +128,7 @@ def _parse_vector(vec: np.ndarray | tuple[float, float, float] | list[float] | A
128
128
  return np.array(vec)
129
129
  elif isinstance(vec, Axis):
130
130
  return vec.vector
131
- return None
131
+ return np.array(vec)
132
132
 
133
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.
@@ -145,7 +145,7 @@ def _parse_axis(vec: np.ndarray | tuple[float, float, float] | list[float] | Axi
145
145
  return Axis(np.array(vec))
146
146
  elif isinstance(vec, Axis):
147
147
  return vec
148
- return None
148
+ return Axis(np.array(vec))
149
149
 
150
150
  @dataclass
151
151
  class Plane:
@@ -525,7 +525,7 @@ def ned2_tri_interp_full(coords: np.ndarray,
525
525
  if inside.sum() == 0:
526
526
  continue
527
527
 
528
- ######### INSIDE THE TETRAHEDRON #########
528
+ ######### INSIDE THE TRIANGLE #########
529
529
 
530
530
  x = xs[inside==1]
531
531
  y = ys[inside==1]
@@ -533,26 +533,23 @@ def ned2_tri_interp_full(coords: np.ndarray,
533
533
  xvs = nodes[0, tris[:,itri]]
534
534
  yvs = nodes[1, tris[:,itri]]
535
535
 
536
- Ds = compute_distances(xvs, yvs, 0*xvs)
537
-
538
- L1 = Ds[0,1]
539
- L2 = Ds[1,2]
540
- L3 = Ds[0,2]
541
-
542
- mult = np.array([L1,L2,L3,L3,L1,L2,L3,L1,1,1,1,1,1,1])
543
-
544
536
  a_s, b_s, c_s, A = tri_coefficients(xvs, yvs)
545
537
 
546
- e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14 = Etri*mult
538
+ e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14 = Etri
547
539
 
548
540
  a1, a2, a3 = a_s
549
541
  b1, b2, b3 = b_s
550
542
  c1, c2, c3 = c_s
551
543
 
552
- ex = (e1*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) + e2*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a2 + b2*x + c2*y) + e3*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) - e4*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e5*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e6*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a3 + b3*x + c3*y) + e7*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + e8*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y))/(8*A**3)
553
- ey = (e1*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) + e2*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a2 + b2*x + c2*y) + e3*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) - e4*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e5*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e6*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a3 + b3*x + c3*y) + e7*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + e8*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y))/(8*A**3)
554
- ez = (a1 + b1*x + c1*y)*(e10*(-A + a1 + b1*x + c1*y) + e11*(-A + a1 + b1*x + c1*y) + e12*(a2 + b2*x + c2*y) + e13*(a2 + b2*x + c2*y) + e14*(a2 + b2*x + c2*y) + e9*(-A + a1 + b1*x + c1*y))/(2*A**2)
544
+ # original Nedelec-1 order 2 formulation
545
+ # ex = (e1*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) + e2*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a2 + b2*x + c2*y) + e3*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) - e4*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e5*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e6*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a3 + b3*x + c3*y) + e7*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + e8*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y))/(8*A**3)
546
+ # ey = (e1*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) + e2*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a2 + b2*x + c2*y) + e3*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) - e4*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e5*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e6*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a3 + b3*x + c3*y) + e7*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + e8*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y))/(8*A**3)
547
+ # ez = (a1 + b1*x + c1*y)*(e10*(-A + a1 + b1*x + c1*y) + e11*(-A + a1 + b1*x + c1*y) + e12*(a2 + b2*x + c2*y) + e13*(a2 + b2*x + c2*y) + e14*(a2 + b2*x + c2*y) + e9*(-A + a1 + b1*x + c1*y))/(2*A**2)
555
548
 
549
+ # New Nedelec-1 order 2 formulation
550
+ ex = (-2*A*(e1*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y)) + e2*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y)) + e3*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))) - e4*((b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + (b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a1 + b1*x + c1*y)) - e5*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a1 - a2 + b1*x - b2*x + c1*y - c2*y) - e6*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a2 - a3 + b2*x - b3*x + c2*y - c3*y) - e7*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a1 - a3 + b1*x - b3*x + c1*y - c3*y) + e8*((b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + (b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y)))/(8*A**3)
551
+ ey = (-2*A*(e1*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y)) + e2*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y)) + e3*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))) - e4*((c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + (c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a1 + b1*x + c1*y)) - e5*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a1 - a2 + b1*x - b2*x + c1*y - c2*y) - e6*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a2 - a3 + b2*x - b3*x + c2*y - c3*y) - e7*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a1 - a3 + b1*x - b3*x + c1*y - c3*y) + e8*((c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + (c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y)))/(8*A**3)
552
+ ez = (-e10*(a2 + b2*x + c2*y)*(A - a2 - b2*x - c2*y)/2 - e11*(a3 + b3*x + c3*y)*(A - a3 - b3*x - c3*y)/2 + e12*(a1 + b1*x + c1*y)*(a2 + b2*x + c2*y) + e13*(a2 + b2*x + c2*y)*(a3 + b3*x + c3*y) + e14*(a1 + b1*x + c1*y)*(a3 + b3*x + c3*y) - e9*(a1 + b1*x + c1*y)*(A - a1 - b1*x - c1*y)/2)/A**2
556
553
  Ex[inside] = ex
557
554
  Ey[inside] = ey
558
555
  Ez[inside] = ez
@@ -621,23 +618,21 @@ def ned2_tri_interp_curl(coords: np.ndarray,
621
618
 
622
619
  a_s, b_s, c_s, A = tri_coefficients(xvs, yvs)
623
620
 
624
- Ds = compute_distances(xvs, yvs, 0*xvs)
625
-
626
- L1 = Ds[0,1]
627
- L2 = Ds[1,2]
628
- L3 = Ds[0,2]
629
-
630
- mult = np.array([L1,L2,L3,L3,L1,L2,L3,L1,1,1,1,1,1,1])
631
-
632
- e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14 = Etri*mult
621
+ e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14 = Etri
633
622
 
634
623
  a1, a2, a3 = a_s
635
624
  b1, b2, b3 = b_s
636
625
  c1, c2, c3 = c_s
637
-
638
- hx = (4*A*(c1*(e10*(-A + a1 + b1*x + c1*y) + e11*(-A + a1 + b1*x + c1*y) + e12*(a2 + b2*x + c2*y) + e13*(a2 + b2*x + c2*y) + e14*(a2 + b2*x + c2*y) + e9*(-A + a1 + b1*x + c1*y)) + (a1 + b1*x + c1*y)*(c1*e10 + c1*e11 + c1*e9 + c2*e12 + c2*e13 + c2*e14)) + jB*(e1*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) + e2*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a2 + b2*x + c2*y) + e3*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) - e4*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e5*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e6*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a3 + b3*x + c3*y) + e7*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + e8*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y)))/(8*A**3)
639
- hy = (4*A*(b1*(e10*(-A + a1 + b1*x + c1*y) + e11*(-A + a1 + b1*x + c1*y) + e12*(a2 + b2*x + c2*y) + e13*(a2 + b2*x + c2*y) + e14*(a2 + b2*x + c2*y) + e9*(-A + a1 + b1*x + c1*y)) + (a1 + b1*x + c1*y)*(b1*e10 + b1*e11 + b1*e9 + b2*e12 + b2*e13 + b2*e14)) - jB*(e1*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) + e2*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a2 + b2*x + c2*y) + e3*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) - e4*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e5*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e6*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a3 + b3*x + c3*y) + e7*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + e8*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y)))/(8*A**3)
640
- hz = (-3*a1*b1*c2*e1 - 3*a1*b1*c3*e3 + 3*a1*b2*c1*e1 + a1*b2*c3*e4 + a1*b2*c3*e8 + 3*a1*b3*c1*e3 - a1*b3*c2*e4 - a1*b3*c2*e8 - 3*a2*b1*c2*e5 + 2*a2*b1*c3*e4 - a2*b1*c3*e8 + 3*a2*b2*c1*e5 - 3*a2*b2*c3*e2 - 2*a2*b3*c1*e4 + a2*b3*c1*e8 + 3*a2*b3*c2*e2 + a3*b1*c2*e4 - 2*a3*b1*c2*e8 - 3*a3*b1*c3*e7 - a3*b2*c1*e4 + 2*a3*b2*c1*e8 - 3*a3*b2*c3*e6 + 3*a3*b3*c1*e7 + 3*a3*b3*c2*e6 - 3*b1**2*c2*e1*x - 3*b1**2*c3*e3*x + 3*b1*b2*c1*e1*x - 3*b1*b2*c2*e5*x + 3*b1*b2*c3*e4*x + 3*b1*b3*c1*e3*x - 3*b1*b3*c2*e8*x - 3*b1*b3*c3*e7*x - 3*b1*c1*c2*e1*y - 3*b1*c1*c3*e3*y - 3*b1*c2**2*e5*y + 3*b1*c2*c3*e4*y - 3*b1*c2*c3*e8*y - 3*b1*c3**2*e7*y + 3*b2**2*c1*e5*x - 3*b2**2*c3*e2*x - 3*b2*b3*c1*e4*x + 3*b2*b3*c1*e8*x + 3*b2*b3*c2*e2*x - 3*b2*b3*c3*e6*x + 3*b2*c1**2*e1*y + 3*b2*c1*c2*e5*y + 3*b2*c1*c3*e8*y - 3*b2*c2*c3*e2*y - 3*b2*c3**2*e6*y + 3*b3**2*c1*e7*x + 3*b3**2*c2*e6*x + 3*b3*c1**2*e3*y - 3*b3*c1*c2*e4*y + 3*b3*c1*c3*e7*y + 3*b3*c2**2*e2*y + 3*b3*c2*c3*e6*y)/(8*A**3)
626
+
627
+ # original Nedelec-1 order 2 formulation
628
+ #hx = (4*A*(c1*(e10*(-A + a1 + b1*x + c1*y) + e11*(-A + a1 + b1*x + c1*y) + e12*(a2 + b2*x + c2*y) + e13*(a2 + b2*x + c2*y) + e14*(a2 + b2*x + c2*y) + e9*(-A + a1 + b1*x + c1*y)) + (a1 + b1*x + c1*y)*(c1*e10 + c1*e11 + c1*e9 + c2*e12 + c2*e13 + c2*e14)) + jB*(e1*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) + e2*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a2 + b2*x + c2*y) + e3*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) - e4*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e5*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e6*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a3 + b3*x + c3*y) + e7*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + e8*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y)))/(8*A**3)
629
+ # hy = (4*A*(b1*(e10*(-A + a1 + b1*x + c1*y) + e11*(-A + a1 + b1*x + c1*y) + e12*(a2 + b2*x + c2*y) + e13*(a2 + b2*x + c2*y) + e14*(a2 + b2*x + c2*y) + e9*(-A + a1 + b1*x + c1*y)) + (a1 + b1*x + c1*y)*(b1*e10 + b1*e11 + b1*e9 + b2*e12 + b2*e13 + b2*e14)) - jB*(e1*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) + e2*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a2 + b2*x + c2*y) + e3*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a1 + b1*x + c1*y) - e4*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e5*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + e6*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a3 + b3*x + c3*y) + e7*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + e8*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y)))/(8*A**3)
630
+ # hz = (-3*a1*b1*c2*e1 - 3*a1*b1*c3*e3 + 3*a1*b2*c1*e1 + a1*b2*c3*e4 + a1*b2*c3*e8 + 3*a1*b3*c1*e3 - a1*b3*c2*e4 - a1*b3*c2*e8 - 3*a2*b1*c2*e5 + 2*a2*b1*c3*e4 - a2*b1*c3*e8 + 3*a2*b2*c1*e5 - 3*a2*b2*c3*e2 - 2*a2*b3*c1*e4 + a2*b3*c1*e8 + 3*a2*b3*c2*e2 + a3*b1*c2*e4 - 2*a3*b1*c2*e8 - 3*a3*b1*c3*e7 - a3*b2*c1*e4 + 2*a3*b2*c1*e8 - 3*a3*b2*c3*e6 + 3*a3*b3*c1*e7 + 3*a3*b3*c2*e6 - 3*b1**2*c2*e1*x - 3*b1**2*c3*e3*x + 3*b1*b2*c1*e1*x - 3*b1*b2*c2*e5*x + 3*b1*b2*c3*e4*x + 3*b1*b3*c1*e3*x - 3*b1*b3*c2*e8*x - 3*b1*b3*c3*e7*x - 3*b1*c1*c2*e1*y - 3*b1*c1*c3*e3*y - 3*b1*c2**2*e5*y + 3*b1*c2*c3*e4*y - 3*b1*c2*c3*e8*y - 3*b1*c3**2*e7*y + 3*b2**2*c1*e5*x - 3*b2**2*c3*e2*x - 3*b2*b3*c1*e4*x + 3*b2*b3*c1*e8*x + 3*b2*b3*c2*e2*x - 3*b2*b3*c3*e6*x + 3*b2*c1**2*e1*y + 3*b2*c1*c2*e5*y + 3*b2*c1*c3*e8*y - 3*b2*c2*c3*e2*y - 3*b2*c3**2*e6*y + 3*b3**2*c1*e7*x + 3*b3**2*c2*e6*x + 3*b3*c1**2*e3*y - 3*b3*c1*c2*e4*y + 3*b3*c1*c3*e7*y + 3*b3*c2**2*e2*y + 3*b3*c2*c3*e6*y)/(8*A**3)
631
+
632
+ # New Nedelec-1 order 2 formulation
633
+ hx = (4*A*(2*c1*e12*(a2 + b2*x + c2*y) + 2*c1*e14*(a3 + b3*x + c3*y) + c1*e9*(a1 + b1*x + c1*y) - c1*e9*(A - a1 - b1*x - c1*y) + c2*e10*(a2 + b2*x + c2*y) - c2*e10*(A - a2 - b2*x - c2*y) + 2*c2*e12*(a1 + b1*x + c1*y) + 2*c2*e13*(a3 + b3*x + c3*y) + c3*e11*(a3 + b3*x + c3*y) - c3*e11*(A - a3 - b3*x - c3*y) + 2*c3*e13*(a2 + b2*x + c2*y) + 2*c3*e14*(a1 + b1*x + c1*y)) + jB*(2*A*(e1*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y)) + e2*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y)) + e3*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))) + e4*((c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + (c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a1 + b1*x + c1*y)) + e5*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a1 - a2 + b1*x - b2*x + c1*y - c2*y) + e6*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y))*(a2 - a3 + b2*x - b3*x + c2*y - c3*y) + e7*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a1 - a3 + b1*x - b3*x + c1*y - c3*y) - e8*((c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + (c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y))))/(8*A**3)
634
+ hy = (4*A*(-2*b1*e12*(a2 + b2*x + c2*y) - 2*b1*e14*(a3 + b3*x + c3*y) - b1*e9*(a1 + b1*x + c1*y) + b1*e9*(A - a1 - b1*x - c1*y) - b2*e10*(a2 + b2*x + c2*y) + b2*e10*(A - a2 - b2*x - c2*y) - 2*b2*e12*(a1 + b1*x + c1*y) - 2*b2*e13*(a3 + b3*x + c3*y) - b3*e11*(a3 + b3*x + c3*y) + b3*e11*(A - a3 - b3*x - c3*y) - 2*b3*e13*(a2 + b2*x + c2*y) - 2*b3*e14*(a1 + b1*x + c1*y)) - jB*(2*A*(e1*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y)) + e2*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y)) + e3*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))) + e4*((b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y) + (b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a1 + b1*x + c1*y)) + e5*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a1 - a2 + b1*x - b2*x + c1*y - c2*y) + e6*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y))*(a2 - a3 + b2*x - b3*x + c2*y - c3*y) + e7*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a1 - a3 + b1*x - b3*x + c1*y - c3*y) - e8*((b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y))*(a3 + b3*x + c3*y) + (b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y))*(a2 + b2*x + c2*y))))/(8*A**3)
635
+ hz = (4*A*(e1*(b1*c2 - b2*c1) + e2*(b2*c3 - b3*c2) + e3*(b1*c3 - b3*c1)) - e4*(b1*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y)) + b2*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y)) - (b1*c3 - b3*c1)*(a2 + b2*x + c2*y) - (b2*c3 - b3*c2)*(a1 + b1*x + c1*y)) + e4*(c1*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y)) + c2*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y)) + (b1*c3 - b3*c1)*(a2 + b2*x + c2*y) + (b2*c3 - b3*c2)*(a1 + b1*x + c1*y)) - e5*(b1 - b2)*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y)) + e5*(c1 - c2)*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y)) + 2*e5*(b1*c2 - b2*c1)*(a1 - a2 + b1*x - b2*x + c1*y - c2*y) - e6*(b2 - b3)*(c2*(a3 + b3*x + c3*y) - c3*(a2 + b2*x + c2*y)) + e6*(c2 - c3)*(b2*(a3 + b3*x + c3*y) - b3*(a2 + b2*x + c2*y)) + 2*e6*(b2*c3 - b3*c2)*(a2 - a3 + b2*x - b3*x + c2*y - c3*y) - e7*(b1 - b3)*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y)) + e7*(c1 - c3)*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y)) + 2*e7*(b1*c3 - b3*c1)*(a1 - a3 + b1*x - b3*x + c1*y - c3*y) + e8*(b2*(c1*(a3 + b3*x + c3*y) - c3*(a1 + b1*x + c1*y)) + b3*(c1*(a2 + b2*x + c2*y) - c2*(a1 + b1*x + c1*y)) - (b1*c2 - b2*c1)*(a3 + b3*x + c3*y) - (b1*c3 - b3*c1)*(a2 + b2*x + c2*y)) - e8*(c2*(b1*(a3 + b3*x + c3*y) - b3*(a1 + b1*x + c1*y)) + c3*(b1*(a2 + b2*x + c2*y) - b2*(a1 + b1*x + c1*y)) + (b1*c2 - b2*c1)*(a3 + b3*x + c3*y) + (b1*c3 - b3*c1)*(a2 + b2*x + c2*y)))/(8*A**3)
641
636
 
642
637
  Ex[inside] = hx*dc[0,0]
643
638
  Ey[inside] = hy*dc[1,1]
@@ -28,13 +28,13 @@ from ..const import MU0, C0
28
28
 
29
29
  class FieldFunctionClass:
30
30
  """ This Class serves as a picklable class so that ModalPort boundary conditions
31
- can actually be stored with the Simulation3D class. Functions aren't picklable in
31
+ can actually be stored with the Simulation class. Functions aren't picklable in
32
32
  Python.
33
33
 
34
34
  I am not happy with the existence of this class, it feels too ad-hoc but for now it
35
35
  is the simplest way. It stores all actually required information needed to do a
36
36
  surface field interpolation without needing to store the Mesh3D and SurfaceMesh class
37
- objects plus the NedelecLegrange2 classes with the Simulation3D.
37
+ objects plus the NedelecLegrange2 classes with the Simulation.
38
38
 
39
39
  As it stands currently, only the GMSH mesh is stored plus the geometry objects. The
40
40
  mesh is reconstructed as it is deterministic.
@@ -103,6 +103,8 @@ class NedelecLegrange2(FEMBasis):
103
103
 
104
104
  self.cs: CoordinateSystem = cs
105
105
 
106
+ LGORDER = 2
107
+
106
108
  ##
107
109
  nodes = self.mesh.nodes
108
110
  self.local_nodes: np.ndarray = np.array(self.cs.in_local_cs(nodes[0,:], nodes[1,:], nodes[2,:]))
@@ -113,15 +115,23 @@ class NedelecLegrange2(FEMBasis):
113
115
  self.n_tris: int = self.mesh.n_tris
114
116
  self.n_tri_dofs: int = None
115
117
 
116
- self.n_field: int = 2*self.n_edges + 2*self.n_tris + self.n_nodes + self.n_edges
118
+ if LGORDER == 2:
119
+ self.n_field: int = 2*self.n_edges + 2*self.n_tris + self.n_nodes + self.n_edges
120
+ else:
121
+ self.n_field: int = 2*self.n_edges + 2*self.n_tris + self.n_nodes + self.n_edges*2 + self.n_tris
122
+
117
123
  self.n_xy: int = 2*self.n_edges + 2*self.n_tris
118
-
119
124
  ######## MESH Derived
120
125
  Nn = self.mesh.n_nodes
121
126
  Ne = self.mesh.n_edges
122
127
  Nt = self.mesh.n_tris
123
128
 
124
- self.tri_to_field: np.ndarray = np.zeros((8 + 6, self.n_tris), dtype=int)
129
+
130
+
131
+ if LGORDER==3:
132
+ self.tri_to_field: np.ndarray = np.zeros((8 + 10, self.n_tris), dtype=int)
133
+ else:
134
+ self.tri_to_field: np.ndarray = np.zeros((8 + 6, self.n_tris), dtype=int)
125
135
 
126
136
  self.tri_to_field[:3,:] = self.mesh.tri_to_edge
127
137
  self.tri_to_field[3,:] = np.arange(Nt) + Ne
@@ -129,13 +139,21 @@ class NedelecLegrange2(FEMBasis):
129
139
  self.tri_to_field[7,:] = np.arange(Nt) + 2*Ne + Nt
130
140
  self.tri_to_field[8:11,:] = self.mesh.tris + (2*Ne + 2*Nt) # + E + T + E + T
131
141
  self.tri_to_field[11:14,:] = self.mesh.tri_to_edge + (2*Ne + 2*Nt + Nn)
132
-
142
+
143
+ if LGORDER==3:
144
+ # Legrange 3
145
+ self.tri_to_field[14:17,:] = self.mesh.tri_to_edge + (2*Ne + 2*Nt + Nn + Ne)
146
+ self.tri_to_field[17,:] = np.arange(Nt) + (2*Ne + 2*Nt + Nn + Ne + Ne)
147
+
133
148
  self.edge_to_field: np.ndarray = np.zeros((5,Ne), dtype=int) #edge mode 1, edge mode 2, edge legrande mode, edge vertex mode 1, edge vertex mode 2
134
149
 
135
150
  self.edge_to_field[0,:] = np.arange(Ne)
136
151
  self.edge_to_field[1,:] = np.arange(Ne) + Nt + Ne
137
- self.edge_to_field[2,:] = np.arange(Ne) + Ne*2 + Nt*2 + Nn
138
- self.edge_to_field[3:,:] = self.mesh.edges + Ne*2 + Nt*2
152
+ self.edge_to_field[2:4,:] = self.mesh.edges + Ne*2 + Nt*2
153
+ self.edge_to_field[4,:] = np.arange(Ne) + Ne*2 + Nt*2 + Nn
154
+
155
+ if LGORDER==3:
156
+ self.edge_to_field[5:,:] = np.arange(Ne) + Ne*2 + Nt*2 + Nn + Ne
139
157
 
140
158
  ##
141
159
  self._field: np.ndarray = None
@@ -148,12 +166,6 @@ class NedelecLegrange2(FEMBasis):
148
166
 
149
167
  def interpolate_Ef(self, field: np.ndarray) -> FieldFunctionClass:
150
168
  '''Generates the Interpolation function as a function object for a given coordiante basis and origin.'''
151
-
152
- # def func(xs: np.ndarray, ys: np.ndarray, zs: np.ndarray) -> np.ndarray:
153
- # xl, yl, zl = self.cs.in_local_cs(xs, ys, zs)
154
- # Exl, Eyl, Ezl = self.tri_interpolate(field, xl, yl)
155
- # Ex, Ey, Ez = self.cs.in_global_basis(Exl, Eyl, Ezl)
156
- # return np.array([Ex, Ey, Ez])
157
169
  return FieldFunctionClass(field, self.cs, self.local_nodes, self.mesh.tris, self.tri_to_field, 'E')
158
170
 
159
171
  def interpolate_Hf(self, field: np.ndarray, k0: float, ur: np.ndarray, beta: float) -> FieldFunctionClass:
@@ -164,11 +176,6 @@ class NedelecLegrange2(FEMBasis):
164
176
  for i in range(ur.shape[2]):
165
177
  urinv[:,:,i] = matinv(ur[:,:,i])
166
178
 
167
- # def func(xs: np.ndarray, ys: np.ndarray, zs: np.ndarray) -> np.ndarray:
168
- # xl, yl, _ = self.cs.in_local_cs(xs, ys, zs)
169
- # Exl, Eyl, Ezl = self.tri_interpolate_curl(field, xl, yl, urinv, beta)
170
- # Ex, Ey, Ez = self.cs.in_global_basis(Exl, Eyl, Ezl)
171
- # return np.array([Ex, Ey, Ez])*constant
172
179
  return FieldFunctionClass(field, self.cs, self.local_nodes, self.mesh.tris, self.tri_to_field, 'H', urinv, beta, constant)
173
180
 
174
181
  def tri_interpolate(self, field, xs: np.ndarray, ys: np.ndarray) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
@@ -189,29 +196,4 @@ class NedelecLegrange2(FEMBasis):
189
196
  self.local_nodes,
190
197
  self.tri_to_field,
191
198
  diadic,
192
- beta)
193
-
194
-
195
- # def interpolate_curl(self, field: np.ndarray, xs: np.ndarray, ys: np.ndarray, zs:np.ndarray, c: np.ndarray) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
196
- # """
197
- # Interpolates the curl of the field at the given points.
198
- # """
199
- # return ned2_tet_interp_curl(np.array([xs, ys,zs]), field, self.mesh.tets, self.mesh.tris, self.mesh.edges, self.mesh.nodes, self.tet_to_field, c)
200
-
201
- # def fieldf(self, field: np.ndarray, basis: np.ndarray = None, origin: np.ndarray = None) -> Callable:
202
- # if basis is None:
203
- # basis = np.eye(3)
204
-
205
- # if origin is None:
206
- # origin = np.zeros(3)
207
-
208
- # ibasis = np.linalg.pinv(basis)
209
- # def func(xs: np.ndarray, ys: np.ndarray, zs: np.ndarray) -> np.ndarray:
210
- # xyz = np.array([xs, ys, zs]) + origin[:, np.newaxis]
211
- # xyzg = basis @ xyz
212
- # return ibasis @ np.array(self.interpolate(field, xyzg[0,:], xyzg[1,:], xyzg[2,:]))
213
- # return func
214
-
215
- ###### INDEX MAPPINGS
216
-
217
-
199
+ beta)
@@ -18,7 +18,7 @@
18
18
  from .pcb import PCB
19
19
  from .pmlbox import pmlbox
20
20
  from .horn import Horn
21
- from .shapes import Cyllinder, CoaxCyllinder, Box, XYPlate, HalfSphere, Sphere, Plate, OldBox, Alignment
21
+ from .shapes import Cylinder, CoaxCylinder, Box, XYPlate, HalfSphere, Sphere, Plate, OldBox, Alignment
22
22
  from .operations import subtract, add, embed, remove, rotate, mirror, change_coordinate_system, translate, intersect
23
23
  from .polybased import XYPolygon, GeoPrism
24
24
  from .step import STEPItems
@@ -18,7 +18,7 @@
18
18
  from __future__ import annotations
19
19
  import numpy as np
20
20
  from typing import Callable, Iterable
21
- from .shapes import Box, Cyllinder, Alignment
21
+ from .shapes import Box, Cylinder, Alignment
22
22
  from ..geometry import GeoVolume, GeoObject
23
23
  from .operations import rotate, mirror, translate, add, subtract, embed
24
24
  from numbers import Number
@@ -400,7 +400,7 @@ class Modeler:
400
400
  if NPoly:
401
401
  cyl = XYPolygon.circle(r, Nsections=NPoly).extrude(h, cs2)
402
402
  else:
403
- cyl = Cyllinder(r,h, cs2)
403
+ cyl = Cylinder(r,h, cs2)
404
404
  cyls.append(cyl)
405
405
 
406
406
  self.ndimcont.set_copies(N)
emerge/_emerge/geo/pcb.py CHANGED
@@ -20,7 +20,7 @@ from __future__ import annotations
20
20
  from ..cs import CoordinateSystem, GCS, Axis
21
21
  from ..geometry import GeoPolygon, GeoVolume, GeoSurface
22
22
  from ..material import Material, AIR, COPPER
23
- from .shapes import Box, Plate, Cyllinder
23
+ from .shapes import Box, Plate, Cylinder
24
24
  from .polybased import XYPolygon
25
25
  from .operations import change_coordinate_system
26
26
  from .pcb_tools.macro import parse_macro
@@ -1247,14 +1247,14 @@ class PCB:
1247
1247
  plate = change_coordinate_system(plate, self.cs)
1248
1248
  return plate # type: ignore
1249
1249
 
1250
- def generate_vias(self, merge=False) -> list[Cyllinder] | Cyllinder:
1250
+ def generate_vias(self, merge=False) -> list[Cylinder] | Cylinder:
1251
1251
  """Generates the via objects.
1252
1252
 
1253
1253
  Args:
1254
1254
  merge (bool, optional): Whether to merge the result into a final object. Defaults to False.
1255
1255
 
1256
1256
  Returns:
1257
- list[Cyllinder] | Cyllinder: Either al ist of cylllinders or a single one (merge=True)
1257
+ list[Cylinder] | Cylinder: Either al ist of cylllinders or a single one (merge=True)
1258
1258
  """
1259
1259
  vias = []
1260
1260
  for via in self.vias:
@@ -1263,7 +1263,7 @@ class PCB:
1263
1263
  z0 = via.z1*self.unit
1264
1264
  xg, yg, zg = self.cs.in_global_cs(x0, y0, z0)
1265
1265
  cs = CoordinateSystem(self.cs.xax, self.cs.yax, self.cs.zax, np.array([xg, yg, zg]))
1266
- cyl = Cyllinder(via.radius*self.unit, (via.z2-via.z1)*self.unit, cs, via.segments)
1266
+ cyl = Cylinder(via.radius*self.unit, (via.z2-via.z1)*self.unit, cs, via.segments)
1267
1267
  cyl.material = COPPER
1268
1268
  vias.append(cyl)
1269
1269
  if merge:
@@ -172,26 +172,26 @@ class Plate(GeoSurface):
172
172
  tags: list[int] = [gmsh.model.occ.addPlaneSurface([tag_wire,]),]
173
173
  super().__init__(tags)
174
174
 
175
- class Cyllinder(GeoVolume):
175
+ class Cylinder(GeoVolume):
176
176
 
177
177
  def __init__(self,
178
178
  radius: float,
179
179
  height: float,
180
180
  cs: CoordinateSystem = None,
181
181
  Nsections: int = None):
182
- """Generates a Cyllinder object in 3D space.
182
+ """Generates a Cylinder object in 3D space.
183
183
  The cyllinder will always be placed in the origin of the provided CoordinateSystem.
184
184
  The bottom cyllinder plane is always placed in the XY-plane. The lenth of the cyllinder is
185
185
  oriented along the Z-axis.
186
186
 
187
187
  By default the cyllinder uses the Open Cascade modeling for a cyllinder. In this representation
188
188
  the surface of the cyllinder is approximated with a tolerance thay may be irregular.
189
- As an alternative, the argument Nsections may be provided in which case the Cyllinder is replaced
189
+ As an alternative, the argument Nsections may be provided in which case the Cylinder is replaced
190
190
  by an extrusion of a regular N-sided polygon.
191
191
 
192
192
  Args:
193
- radius (float): The radius of the Cyllinder
194
- height (float): The height of the Cyllinder
193
+ radius (float): The radius of the Cylinder
194
+ height (float): The height of the Cylinder
195
195
  cs (CoordinateSystem, optional): The coordinate system. Defaults to None.
196
196
  Nsections (int, optional): The number of sections. Defaults to None.
197
197
  """
@@ -210,6 +210,10 @@ class Cyllinder(GeoVolume):
210
210
  super().__init__(cyl)
211
211
  self._add_face_pointer('front', cs.origin, -cs.zax.np)
212
212
  self._add_face_pointer('back', cs.origin+height*cs.zax.np, cs.zax.np)
213
+ self._add_face_pointer('bottom', cs.origin, -cs.zax.np)
214
+ self._add_face_pointer('top', cs.origin+height*cs.zax.np, cs.zax.np)
215
+ self._add_face_pointer('left', cs.origin, -cs.zax.np)
216
+ self._add_face_pointer('right', cs.origin+height*cs.zax.np, cs.zax.np)
213
217
 
214
218
  self.cs: CoordinateSystem = cs
215
219
  self.radius = radius
@@ -229,7 +233,7 @@ class Cyllinder(GeoVolume):
229
233
  xo, yo, zo = self.cs.in_global_cs(x.flatten(), y.flatten(), z.flatten())
230
234
  return xo, yo, zo
231
235
 
232
- class CoaxCyllinder(GeoVolume):
236
+ class CoaxCylinder(GeoVolume):
233
237
  """A coaxial cylinder with an inner and outer radius."""
234
238
 
235
239
  def __init__(self,
@@ -245,12 +249,12 @@ class CoaxCyllinder(GeoVolume):
245
249
 
246
250
  By default the coax uses the Open Cascade modeling for a cyllinder. In this representation
247
251
  the surface of the cyllinder is approximated with a tolerance thay may be irregular.
248
- As an alternative, the argument Nsections may be provided in which case the Cyllinder is replaced
252
+ As an alternative, the argument Nsections may be provided in which case the Cylinder is replaced
249
253
  by an extrusion of a regular N-sided polygon.
250
254
 
251
255
  Args:
252
- radius (float): The radius of the Cyllinder
253
- height (float): The height of the Cyllinder
256
+ radius (float): The radius of the Cylinder
257
+ height (float): The height of the Cylinder
254
258
  cs (CoordinateSystem, optional): The coordinate system. Defaults to None.
255
259
  Nsections (int, optional): The number of sections. Defaults to None.
256
260
  """
@@ -263,8 +267,8 @@ class CoaxCyllinder(GeoVolume):
263
267
  self.rin = rin
264
268
  self.height = height
265
269
 
266
- self.cyl_out = Cyllinder(rout, height, cs, Nsections=Nsections)
267
- self.cyl_in = Cyllinder(rin, height, cs, Nsections=Nsections)
270
+ self.cyl_out = Cylinder(rout, height, cs, Nsections=Nsections)
271
+ self.cyl_in = Cylinder(rin, height, cs, Nsections=Nsections)
268
272
  self.cyl_in._exists = False
269
273
  self.cyl_out._exists = False
270
274
  cyltags, _ = gmsh.model.occ.cut(self.cyl_out.dimtags, self.cyl_in.dimtags)
@@ -273,6 +277,10 @@ class CoaxCyllinder(GeoVolume):
273
277
 
274
278
  self._add_face_pointer('front', cs.origin, -cs.zax.np)
275
279
  self._add_face_pointer('back', cs.origin+height*cs.zax.np, cs.zax.np)
280
+ self._add_face_pointer('bottom', cs.origin, -cs.zax.np)
281
+ self._add_face_pointer('top', cs.origin+height*cs.zax.np, cs.zax.np)
282
+ self._add_face_pointer('left', cs.origin, -cs.zax.np)
283
+ self._add_face_pointer('right', cs.origin+height*cs.zax.np, cs.zax.np)
276
284
 
277
285
  self.cs = cs
278
286
 
@@ -297,13 +305,28 @@ class HalfSphere(GeoVolume):
297
305
  radius: float,
298
306
  position: tuple = (0,0,0),
299
307
  direction: tuple = (1,0,0)):
300
- super().__init__([])
308
+
301
309
  sphere = Sphere(radius, position=position)
302
310
  cx, cy, cz = position
303
311
 
304
- box = Box(1.1*radius, 2.2*radius, 2.2*radius, position=(cx-radius*1.1,cy-radius*1.1, cz-radius*1.1))
312
+ dx, dy, dz = direction
313
+ fx = 0.5**dx
314
+ fy = 0.5**dy
315
+ fz = 0.5**dz
316
+ box = Box(2.2*radius*fx, 2.2*radius*fy, 2.2*radius*fz, position=(cx-radius*1.1*dx*0.5,cy-radius*1.1*dy*0.5, cz-radius*1.1*dz*0.5), alignment=Alignment.CENTER)
317
+
318
+ dimtags, _ = gmsh.model.occ.cut(sphere.dimtags, box.dimtags)
319
+
320
+ sphere._exists = False
321
+ box._exists = False
305
322
 
306
- self.tag = subtract(sphere, box)[0].tag
323
+ super().__init__([dt[1] for dt in dimtags])
324
+
325
+ self._add_face_pointer('front',np.array(position), np.array(direction))
326
+ self._add_face_pointer('back',np.array(position), np.array(direction))
327
+ self._add_face_pointer('bottom',np.array(position), np.array(direction))
328
+ self._add_face_pointer('face',np.array(position), np.array(direction))
329
+
307
330
 
308
331
 
309
332
 
@@ -67,7 +67,13 @@ class _GeometryManager:
67
67
 
68
68
  def reset(self, modelname: str) -> None:
69
69
  self.geometry_list[modelname] = []
70
-
70
+
71
+ def lowest_priority(self) -> int:
72
+ return min([geo._priority for geo in self.all_geometries()])
73
+
74
+ def highest_priority(self) -> int:
75
+ return min([geo._priority for geo in self.all_geometries()])
76
+
71
77
  class _FacePointer:
72
78
  """The FacePointer class defines a face to be selectable as a
73
79
  face normal vector plus an origin. All faces of an object
@@ -387,6 +393,24 @@ class GeoObject:
387
393
  self._priority -= 1
388
394
  return self
389
395
 
396
+ def background(self) -> GeoObject:
397
+ """Set the priority to be on the background.
398
+
399
+ Returns:
400
+ GeoObject: _description_
401
+ """
402
+ self._priority = _GEOMANAGER.lowest_priority()-10
403
+ return self
404
+
405
+ def foreground(self) -> GeoObject:
406
+ """Set the priority to be on top.
407
+
408
+ Returns:
409
+ GeoObject: _description_
410
+ """
411
+ self._priority = _GEOMANAGER.highest_priority()+10
412
+ return self
413
+
390
414
  def outside(self, *exclude: FaceNames, tags: list[int] | None = None) -> FaceSelection:
391
415
  """Returns the complete set of outside faces.
392
416
 
@@ -398,6 +422,8 @@ class GeoObject:
398
422
  """
399
423
  if tags is None:
400
424
  tags = []
425
+ for name in exclude:
426
+ tags.extend(self.face(name).tags)
401
427
  dimtags = gmsh.model.get_boundary(self.dimtags, True, False)
402
428
  return FaceSelection([t for d,t in dimtags if t not in tags])
403
429
 
emerge/_emerge/howto.py CHANGED
@@ -27,11 +27,11 @@ class _HowtoClass:
27
27
  """
28
28
  To start a simulation simply create a model object through:
29
29
 
30
- >>> model = emerge.Simulation3D('MyProjectName')
30
+ >>> model = emerge.Simulation('MyProjectName')
31
31
 
32
32
  Optionally, you can use a context manager for a more explicit handling of exiting the GMSH api and storing data after simulations.
33
33
 
34
- >>> with emerge.Simulation3D('MyProjectName') as model:
34
+ >>> with emerge.Simulation('MyProjectName') as model:
35
35
 
36
36
  """
37
37
  pass
@@ -45,7 +45,7 @@ class _HowtoClass:
45
45
  >>> sphere = emerge.geo.Sphere(...)
46
46
  >>> pcb_layouter = emerge.geo.PCBLayout(...)
47
47
  >>> plate = emerge.geo.Plate(...)
48
- >>> cyl = emerge.geo.Cyllinder(...)
48
+ >>> cyl = emerge.geo.Cylinder(...)
49
49
 
50
50
  After making geometries, you should pass all of them to
51
51
  the simulation object
@@ -77,7 +77,7 @@ class _HowtoClass:
77
77
  >>> face = cutout.face('front', tool=box)
78
78
 
79
79
  Exclusions or specific isolations can be added with optional arguments.
80
- There is also a select object in your Simulation3D class that has various convenient selection options
80
+ There is also a select object in your Simulation class that has various convenient selection options
81
81
  >>> faces = model.select.face.inlayer()
82
82
  >>> faces = model.select.inplane()
83
83
  >>> faces = model.select.face.near(x,y,z)
@@ -99,15 +99,15 @@ class _HowtoClass:
99
99
 
100
100
  """
101
101
 
102
- def run_frequency_domain(self):
102
+ def run_sweep(self):
103
103
  """
104
104
  You can run a frequency domain study by simply calling:\
105
105
 
106
- >>> results = model.mw.frequency_domain(...)
106
+ >>> results = model.mw.run_sweep(...)
107
107
 
108
108
  You can distribute your frequency sweep across multiple threads using
109
109
 
110
- >>> results = model.mw.frequency_domain(parallel=True, njobs=3)
110
+ >>> results = model.mw.run_sweep(parallel=True, njobs=3)
111
111
 
112
112
  The frequency domain study will return an MWSimData object that contains all data.
113
113
  """
@@ -154,7 +154,7 @@ class _HowtoClass:
154
154
  def save_and_load(self):
155
155
  """
156
156
  You can save your project data by setting save_file to True:
157
- >>> model = emerge.Simulation3D(..., save_file=True)
157
+ >>> model = emerge.Simulation(..., save_file=True)
158
158
 
159
159
  Whenever you want, you can save all data by calling the .save() method
160
160
 
@@ -166,7 +166,7 @@ class _HowtoClass:
166
166
 
167
167
  You can load the data from a simulation using:
168
168
 
169
- >>> model = emerge.Simulation3D(..., load_file=True)
169
+ >>> model = emerge.Simulation(..., load_file=True)
170
170
 
171
171
  The data from a simulation can be found in:
172
172
 
@@ -18,6 +18,7 @@
18
18
  import numpy as np
19
19
  from dataclasses import dataclass
20
20
  from typing import Callable
21
+
21
22
  @dataclass
22
23
  class Material:
23
24
  """The Material class generalizes a material in the EMerge FEM environment.