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.
- emerge/__init__.py +4 -1
- emerge/_emerge/cs.py +2 -2
- emerge/_emerge/elements/ned2_interp.py +21 -26
- emerge/_emerge/elements/nedleg2.py +27 -45
- emerge/_emerge/geo/__init__.py +1 -1
- emerge/_emerge/geo/modeler.py +2 -2
- emerge/_emerge/geo/pcb.py +4 -4
- emerge/_emerge/geo/shapes.py +37 -14
- emerge/_emerge/geometry.py +27 -1
- emerge/_emerge/howto.py +9 -9
- emerge/_emerge/material.py +1 -0
- emerge/_emerge/mesh3d.py +63 -14
- emerge/_emerge/mesher.py +7 -4
- emerge/_emerge/mth/optimized.py +30 -0
- emerge/_emerge/periodic.py +46 -16
- emerge/_emerge/physics/microwave/assembly/assembler.py +4 -21
- emerge/_emerge/physics/microwave/assembly/generalized_eigen.py +23 -19
- emerge/_emerge/physics/microwave/assembly/generalized_eigen_hb.py +465 -0
- emerge/_emerge/physics/microwave/assembly/robinbc.py +59 -18
- emerge/_emerge/physics/microwave/microwave_3d.py +38 -186
- emerge/_emerge/physics/microwave/microwave_bc.py +101 -35
- emerge/_emerge/physics/microwave/microwave_data.py +1 -1
- emerge/_emerge/plot/pyvista/display.py +40 -7
- emerge/_emerge/plot/pyvista/display_settings.py +1 -0
- emerge/_emerge/plot/simple_plots.py +159 -27
- emerge/_emerge/projects/_gen_base.txt +2 -2
- emerge/_emerge/projects/_load_base.txt +1 -1
- emerge/_emerge/simmodel.py +22 -7
- emerge/_emerge/solve_interfaces/cudss_interface.py +44 -2
- emerge/_emerge/solve_interfaces/pardiso_interface.py +1 -0
- emerge/_emerge/solver.py +26 -19
- emerge/ext.py +4 -0
- emerge/lib.py +1 -1
- {emerge-0.5.5.dist-info → emerge-0.6.0.dist-info}/METADATA +6 -4
- {emerge-0.5.5.dist-info → emerge-0.6.0.dist-info}/RECORD +38 -37
- emerge/_emerge/elements/legrange2.py +0 -172
- {emerge-0.5.5.dist-info → emerge-0.6.0.dist-info}/WHEEL +0 -0
- {emerge-0.5.5.dist-info → emerge-0.6.0.dist-info}/entry_points.txt +0 -0
- {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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
553
|
-
|
|
554
|
-
|
|
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
|
-
|
|
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
|
-
|
|
639
|
-
|
|
640
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,:] =
|
|
138
|
-
self.edge_to_field[
|
|
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)
|
emerge/_emerge/geo/__init__.py
CHANGED
|
@@ -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
|
|
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
|
emerge/_emerge/geo/modeler.py
CHANGED
|
@@ -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,
|
|
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 =
|
|
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,
|
|
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[
|
|
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[
|
|
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 =
|
|
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:
|
emerge/_emerge/geo/shapes.py
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
194
|
-
height (float): The height of the
|
|
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
|
|
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
|
|
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
|
|
253
|
-
height (float): The height of the
|
|
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 =
|
|
267
|
-
self.cyl_in =
|
|
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
|
-
|
|
308
|
+
|
|
301
309
|
sphere = Sphere(radius, position=position)
|
|
302
310
|
cx, cy, cz = position
|
|
303
311
|
|
|
304
|
-
|
|
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
|
-
|
|
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
|
|
emerge/_emerge/geometry.py
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
169
|
+
>>> model = emerge.Simulation(..., load_file=True)
|
|
170
170
|
|
|
171
171
|
The data from a simulation can be found in:
|
|
172
172
|
|