emerge 0.5.5__py3-none-any.whl → 0.5.6__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 +3 -0
- emerge/_emerge/cs.py +2 -2
- emerge/_emerge/elements/ned2_interp.py +21 -26
- emerge/_emerge/elements/nedleg2.py +25 -43
- emerge/_emerge/geo/shapes.py +26 -3
- emerge/_emerge/geometry.py +27 -1
- 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 +22 -4
- 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/simmodel.py +15 -1
- 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.5.6.dist-info}/METADATA +5 -3
- {emerge-0.5.5.dist-info → emerge-0.5.6.dist-info}/RECORD +31 -30
- emerge/_emerge/elements/legrange2.py +0 -172
- {emerge-0.5.5.dist-info → emerge-0.5.6.dist-info}/WHEEL +0 -0
- {emerge-0.5.5.dist-info → emerge-0.5.6.dist-info}/entry_points.txt +0 -0
- {emerge-0.5.5.dist-info → emerge-0.5.6.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
# EMerge is an open source Python based FEM EM simulation module.
|
|
2
|
+
# Copyright (C) 2025 Robert Fennis.
|
|
3
|
+
|
|
4
|
+
# This program is free software; you can redistribute it and/or
|
|
5
|
+
# modify it under the terms of the GNU General Public License
|
|
6
|
+
# as published by the Free Software Foundation; either version 2
|
|
7
|
+
# of the License, or (at your option) any later version.
|
|
8
|
+
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program; if not, see
|
|
16
|
+
# <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import numpy as np
|
|
19
|
+
from ....elements.nedleg2 import NedelecLegrange2
|
|
20
|
+
from scipy.sparse import csr_matrix
|
|
21
|
+
from numba_progress import ProgressBar, ProgressBarType
|
|
22
|
+
from ....mth.optimized import local_mapping, matinv, compute_distances, gaus_quad_tri
|
|
23
|
+
from numba import c16, types, f8, i8, njit, prange
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
############################################################
|
|
28
|
+
# FIELD MAPPING #
|
|
29
|
+
############################################################
|
|
30
|
+
|
|
31
|
+
@njit(i8[:,:](i8, i8[:,:], i8[:,:], i8[:,:]), cache=True, nogil=True)
|
|
32
|
+
def local_tri_to_edgeid(itri: int, tris, edges, tri_to_edge) -> np.ndarray:
|
|
33
|
+
global_edge_map = edges[:, tri_to_edge[:,itri]]
|
|
34
|
+
return local_mapping(tris[:, itri], global_edge_map)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
############################################################
|
|
39
|
+
# PYTHON INTERFACE #
|
|
40
|
+
############################################################
|
|
41
|
+
|
|
42
|
+
def generelized_eigenvalue_matrix(field: NedelecLegrange2,
|
|
43
|
+
er: np.ndarray,
|
|
44
|
+
ur: np.ndarray,
|
|
45
|
+
basis: np.ndarray,
|
|
46
|
+
k0: float,) -> tuple[csr_matrix, csr_matrix]:
|
|
47
|
+
|
|
48
|
+
tris = field.mesh.tris
|
|
49
|
+
edges = field.mesh.edges
|
|
50
|
+
nodes = field.mesh.nodes
|
|
51
|
+
|
|
52
|
+
nT = tris.shape[1]
|
|
53
|
+
tri_to_field = field.tri_to_field
|
|
54
|
+
|
|
55
|
+
nodes = field.local_nodes
|
|
56
|
+
|
|
57
|
+
with ProgressBar(total=nT, ncols=100, dynamic_ncols=False) as pgb:
|
|
58
|
+
dataE, dataB, rows, cols = _matrix_builder(nodes, tris, edges, tri_to_field, ur, er, k0, pgb)
|
|
59
|
+
|
|
60
|
+
nfield = field.n_field
|
|
61
|
+
|
|
62
|
+
E = csr_matrix((dataE, (rows, cols)), shape=(nfield, nfield))
|
|
63
|
+
B = csr_matrix((dataB, (rows, cols)), shape=(nfield, nfield))
|
|
64
|
+
|
|
65
|
+
return E, B
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
############################################################
|
|
69
|
+
# MATRIX MULTIPLICATION #
|
|
70
|
+
############################################################
|
|
71
|
+
|
|
72
|
+
@njit(c16[:,:](c16[:,:], c16[:,:]), cache=True, nogil=True)
|
|
73
|
+
def matmul(a, b):
|
|
74
|
+
out = np.empty((2,b.shape[1]), dtype=np.complex128)
|
|
75
|
+
out[0,:] = a[0,0]*b[0,:] + a[0,1]*b[1,:]
|
|
76
|
+
out[1,:] = a[1,0]*b[0,:] + a[1,1]*b[1,:]
|
|
77
|
+
return out
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
############################################################
|
|
81
|
+
# GAUSS QUADRATURE IMPLEMENTATION #
|
|
82
|
+
############################################################
|
|
83
|
+
|
|
84
|
+
@njit(c16(c16[:], c16[:], types.Array(types.float64, 1, 'A', readonly=True)), cache=True, nogil=True)
|
|
85
|
+
def _gqi(v1, v2, W):
|
|
86
|
+
return np.sum(v1*v2*W)
|
|
87
|
+
|
|
88
|
+
@njit(c16(c16[:,:], c16[:,:], types.Array(types.float64, 1, 'A', readonly=True)), cache=True, nogil=True)
|
|
89
|
+
def _gqi2(v1, v2, W):
|
|
90
|
+
return np.sum(W*np.sum(v1*v2,axis=0))
|
|
91
|
+
|
|
92
|
+
@njit(c16[:,:](f8[:,:], f8[:,:]), cache=True, nogil=True)
|
|
93
|
+
def _ne1(coeff, coords):
|
|
94
|
+
a1, b1, c1 = coeff[:,0]
|
|
95
|
+
a2, b2, c2 = coeff[:,1]
|
|
96
|
+
xs = coords[0,:]
|
|
97
|
+
ys = coords[1,:]
|
|
98
|
+
out=np.empty((2,xs.shape[0]), dtype=np.complex128)
|
|
99
|
+
out[0,:] = (-b1*(a2 + b2*xs + c2*ys) + b2*(a1 + b1*xs + c1*ys))
|
|
100
|
+
out[1,:] = (-c1*(a2 + b2*xs + c2*ys) + c2*(a1 + b1*xs + c1*ys))
|
|
101
|
+
return out
|
|
102
|
+
|
|
103
|
+
@njit(c16[:,:](f8[:,:], f8[:,:]), cache=True, nogil=True)
|
|
104
|
+
def _ne2(coeff, coords):
|
|
105
|
+
a1, b1, c1 = coeff[:,0]
|
|
106
|
+
a2, b2, c2 = coeff[:,1]
|
|
107
|
+
xs = coords[0,:]
|
|
108
|
+
ys = coords[1,:]
|
|
109
|
+
out=np.empty((2,xs.shape[0]), dtype=np.complex128)
|
|
110
|
+
out[0,:] = (-b1*(a2 + b2*xs + c2*ys) + b2*(a1 + b1*xs + c1*ys))*(a1 - a2 + b1*xs - b2*xs + c1*ys - c2*ys)
|
|
111
|
+
out[1,:] = (-c1*(a2 + b2*xs + c2*ys) + c2*(a1 + b1*xs + c1*ys))*(a1 - a2 + b1*xs - b2*xs + c1*ys - c2*ys)
|
|
112
|
+
return out
|
|
113
|
+
|
|
114
|
+
@njit(c16[:,:](f8[:,:], f8[:,:]), cache=True, nogil=True)
|
|
115
|
+
def _nf1(coeff, coords):
|
|
116
|
+
a1, b1, c1 = coeff[:,0]
|
|
117
|
+
a2, b2, c2 = coeff[:,1]
|
|
118
|
+
a3, b3, c3 = coeff[:,2]
|
|
119
|
+
xs = coords[0,:]
|
|
120
|
+
ys = coords[1,:]
|
|
121
|
+
out=np.empty((2,xs.shape[0]), dtype=np.complex128)
|
|
122
|
+
out[0,:] = -(b1*(a3 + b3*xs + c3*ys) - b3*(a1 + b1*xs + c1*ys))*(a2 + b2*xs + c2*ys) - (b2*(a3 + b3*xs + c3*ys) - b3*(a2 + b2*xs + c2*ys))*(a1 + b1*xs + c1*ys)
|
|
123
|
+
out[1,:] = -(c1*(a3 + b3*xs + c3*ys) - c3*(a1 + b1*xs + c1*ys))*(a2 + b2*xs + c2*ys) + (-c2*(a3 + b3*xs + c3*ys) + c3*(a2 + b2*xs + c2*ys))*(a1 + b1*xs + c1*ys)
|
|
124
|
+
return out
|
|
125
|
+
|
|
126
|
+
@njit(c16[:,:](f8[:,:], f8[:,:]), cache=True, nogil=True)
|
|
127
|
+
def _nf2(coeff, coords):
|
|
128
|
+
a1, b1, c1 = coeff[:,0]
|
|
129
|
+
a2, b2, c2 = coeff[:,1]
|
|
130
|
+
a3, b3, c3 = coeff[:,2]
|
|
131
|
+
xs = coords[0,:]
|
|
132
|
+
ys = coords[1,:]
|
|
133
|
+
out=np.empty((2,xs.shape[0]), dtype=np.complex128)
|
|
134
|
+
out[0,:] = (b1*(a2 + b2*xs + c2*ys) - b2*(a1 + b1*xs + c1*ys))*(a3 + b3*xs + c3*ys) + (b1*(a3 + b3*xs + c3*ys) - b3*(a1 + b1*xs + c1*ys))*(a2 + b2*xs + c2*ys)
|
|
135
|
+
out[1,:] = -(-c1*(a2 + b2*xs + c2*ys) + c2*(a1 + b1*xs + c1*ys))*(a3 + b3*xs + c3*ys) + (c1*(a3 + b3*xs + c3*ys) - c3*(a1 + b1*xs + c1*ys))*(a2 + b2*xs + c2*ys)
|
|
136
|
+
return out
|
|
137
|
+
|
|
138
|
+
@njit(c16[:](f8[:], f8[:,:]), cache=True, nogil=True)
|
|
139
|
+
def _lv(coeff, coords):
|
|
140
|
+
a1, b1, c1 = coeff
|
|
141
|
+
xs = coords[0,:]
|
|
142
|
+
ys = coords[1,:]
|
|
143
|
+
return -a1 - b1*xs - c1*ys + 2*(a1 + b1*xs + c1*ys)**2 + 0*1j
|
|
144
|
+
|
|
145
|
+
@njit(c16[:](f8[:,:], f8[:,:]), cache=True, nogil=True)
|
|
146
|
+
def _le(coeff, coords):
|
|
147
|
+
a1, b1, c1 = coeff[:,0]
|
|
148
|
+
a2, b2, c2 = coeff[:,1]
|
|
149
|
+
xs = coords[0,:]
|
|
150
|
+
ys = coords[1,:]
|
|
151
|
+
return 4*(a1 + b1*xs + c1*ys)*(a2 + b2*xs + c2*ys)+ 0*1j
|
|
152
|
+
|
|
153
|
+
@njit(c16[:,:](f8[:], f8[:,:]), cache=True, nogil=True)
|
|
154
|
+
def _lv_grad(coeff, coords):
|
|
155
|
+
a1, b1, c1 = coeff
|
|
156
|
+
xs = coords[0,:]
|
|
157
|
+
ys = coords[1,:]
|
|
158
|
+
out=np.empty((2,xs.shape[0]), dtype=np.complex128)
|
|
159
|
+
out[0,:] = b1*(4*a1 + 4*b1*xs + 4*c1*ys - 1)
|
|
160
|
+
out[1,:] = c1*(4*a1 + 4*b1*xs + 4*c1*ys - 1)
|
|
161
|
+
return out
|
|
162
|
+
|
|
163
|
+
@njit(c16[:,:](f8[:,:], f8[:,:]), cache=True, nogil=True)
|
|
164
|
+
def _le_grad(coeff, coords):
|
|
165
|
+
a1, b1, c1 = coeff[:,0]
|
|
166
|
+
a2, b2, c2 = coeff[:,1]
|
|
167
|
+
xs = coords[0,:]
|
|
168
|
+
ys = coords[1,:]
|
|
169
|
+
out=np.empty((2,xs.shape[0]), dtype=np.complex128)
|
|
170
|
+
out[0,:] = 4*b1*(a2 + b2*xs + c2*ys) + 4*b2*(a1 + b1*xs + c1*ys)
|
|
171
|
+
out[1,:] = 4*c1*(a2 + b2*xs + c2*ys) + 4*c2*(a1 + b1*xs + c1*ys)
|
|
172
|
+
return out
|
|
173
|
+
|
|
174
|
+
@njit(c16[:](f8[:,:], f8[:,:]), cache=True, nogil=True)
|
|
175
|
+
def _ne1_curl(coeff, coords):
|
|
176
|
+
a1, b1, c1 = coeff[:,0]
|
|
177
|
+
a2, b2, c2 = coeff[:,1]
|
|
178
|
+
xs = coords[0,:]
|
|
179
|
+
ys = coords[1,:]
|
|
180
|
+
return (2*b1*c2 - 2*b2*c1)*np.ones_like(xs) + 0j#-3*a1*b1*c2 + 3*a1*b2*c1 - 3*b1**2*c2*xs + 3*b1*b2*c1*xs - 3*b1*c1*c2*ys + 3*b2*c1**2*ys + 0j
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@njit(c16[:](f8[:,:], f8[:,:]), cache=True, nogil=True)
|
|
184
|
+
def _ne2_curl(coeff, coords):
|
|
185
|
+
a1, b1, c1 = coeff[:,0]
|
|
186
|
+
a2, b2, c2 = coeff[:,1]
|
|
187
|
+
xs = coords[0,:]
|
|
188
|
+
ys = coords[1,:]
|
|
189
|
+
return (-(b1 - b2)*(c1*(a2 + b2*xs + c2*ys) - c2*(a1 + b1*xs + c1*ys)) + (c1 - c2)*(b1*(a2 + b2*xs + c2*ys) - b2*(a1 + b1*xs + c1*ys)) + 2*(b1*c2 - b2*c1)*(a1 - a2 + b1*xs - b2*xs + c1*ys - c2*ys)) + 0j
|
|
190
|
+
|
|
191
|
+
@njit(c16[:](f8[:,:], f8[:,:]), cache=True, nogil=True)
|
|
192
|
+
def _nf1_curl(coeff, coords):
|
|
193
|
+
a1, b1, c1 = coeff[:,0]
|
|
194
|
+
a2, b2, c2 = coeff[:,1]
|
|
195
|
+
a3, b3, c3 = coeff[:,2]
|
|
196
|
+
xs = coords[0,:]
|
|
197
|
+
ys = coords[1,:]
|
|
198
|
+
return 3*a1*b2*c3 - 3*a1*b3*c2 + 3*a2*b1*c3 - 3*a2*b3*c1 + 6*b1*b2*c3*xs - 3*b1*b3*c2*xs + 3*b1*c2*c3*ys - 3*b2*b3*c1*xs + 3*b2*c1*c3*ys - 6*b3*c1*c2*ys + 0*1j
|
|
199
|
+
|
|
200
|
+
@njit(c16[:](f8[:,:], f8[:,:]), cache=True, nogil=True)
|
|
201
|
+
def _nf2_curl(coeff, coords):
|
|
202
|
+
a1, b1, c1 = coeff[:,0]
|
|
203
|
+
a2, b2, c2 = coeff[:,1]
|
|
204
|
+
a3, b3, c3 = coeff[:,2]
|
|
205
|
+
xs = coords[0,:]
|
|
206
|
+
ys = coords[1,:]
|
|
207
|
+
return -3*a2*b1*c3 + 3*a2*b3*c1 - 3*a3*b1*c2 + 3*a3*b2*c1 - 3*b1*b2*c3*xs - 3*b1*b3*c2*xs - 6*b1*c2*c3*ys + 6*b2*b3*c1*xs + 3*b2*c1*c3*ys + 3*b3*c1*c2*ys + 0*1j
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
############################################################
|
|
211
|
+
# TRIANGLE BARYCENTRIC COORDINATE LIN. COEFFICIENTS #
|
|
212
|
+
############################################################
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
@njit(types.Tuple((f8[:], f8[:], f8[:], f8))(f8[:], f8[:]), cache = True, nogil=True)
|
|
216
|
+
def tri_coefficients(vxs, vys):
|
|
217
|
+
|
|
218
|
+
x1, x2, x3 = vxs
|
|
219
|
+
y1, y2, y3 = vys
|
|
220
|
+
|
|
221
|
+
a1 = x2*y3-y2*x3
|
|
222
|
+
a2 = x3*y1-y3*x1
|
|
223
|
+
a3 = x1*y2-y1*x2
|
|
224
|
+
b1 = y2-y3
|
|
225
|
+
b2 = y3-y1
|
|
226
|
+
b3 = y1-y2
|
|
227
|
+
c1 = x3-x2
|
|
228
|
+
c2 = x1-x3
|
|
229
|
+
c3 = x2-x1
|
|
230
|
+
|
|
231
|
+
#A = 0.5*(b1*c2 - b2*c1)
|
|
232
|
+
sA = 0.5*(((x1-x3)*(y2-y1) - (x1-x2)*(y3-y1)))
|
|
233
|
+
sign = np.sign(sA)
|
|
234
|
+
A = np.abs(sA)
|
|
235
|
+
As = np.array([a1, a2, a3])*sign
|
|
236
|
+
Bs = np.array([b1, b2, b3])*sign
|
|
237
|
+
Cs = np.array([c1, c2, c3])*sign
|
|
238
|
+
return As, Bs, Cs, A
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
############################################################
|
|
242
|
+
# CONSTANT DEFINITION #
|
|
243
|
+
############################################################
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
DPTS = np.array([[0.22338159, 0.22338159, 0.22338159, 0.10995174, 0.10995174, 0.10995174],
|
|
247
|
+
[0.10810302, 0.44594849, 0.44594849, 0.81684757, 0.09157621, 0.09157621],
|
|
248
|
+
[0.44594849, 0.44594849, 0.10810302, 0.09157621, 0.09157621, 0.81684757],
|
|
249
|
+
[0.44594849, 0.10810302, 0.44594849, 0.09157621, 0.81684757, 0.09157621]], dtype=np.float64)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
############################################################
|
|
253
|
+
# NUMBA OPTIMIZED ASSEMBLER #
|
|
254
|
+
############################################################
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
@njit(types.Tuple((c16[:,:], c16[:,:]))(f8[:,:], i8[:,:], c16[:,:], c16[:,:], f8), cache=True, nogil=True)
|
|
258
|
+
def generalized_matrix_GQ(tri_vertices, local_edge_map, Ms, Mm, k0):
|
|
259
|
+
'''Nedelec-2 Triangle stiffness and mass submatrix'''
|
|
260
|
+
Att = np.zeros((8,8), dtype=np.complex128)
|
|
261
|
+
Btt = np.zeros((8,8), dtype=np.complex128)
|
|
262
|
+
|
|
263
|
+
Dtt = np.zeros((8,8), dtype=np.complex128)
|
|
264
|
+
Dzt = np.zeros((6,8), dtype=np.complex128)
|
|
265
|
+
|
|
266
|
+
Dzz1 = np.zeros((6,6), dtype=np.complex128)
|
|
267
|
+
Dzz2 = np.zeros((6,6), dtype=np.complex128)
|
|
268
|
+
|
|
269
|
+
Ls = np.ones((14,14), dtype=np.float64)
|
|
270
|
+
|
|
271
|
+
WEIGHTS = DPTS[0,:]
|
|
272
|
+
DPTS1 = DPTS[1,:]
|
|
273
|
+
DPTS2 = DPTS[2,:]
|
|
274
|
+
DPTS3 = DPTS[3,:]
|
|
275
|
+
|
|
276
|
+
txs = tri_vertices[0,:]
|
|
277
|
+
tys = tri_vertices[1,:]
|
|
278
|
+
|
|
279
|
+
Ds = compute_distances(txs, tys, 0*txs)
|
|
280
|
+
|
|
281
|
+
xs = txs[0]*DPTS1 + txs[1]*DPTS2 + txs[2]*DPTS3
|
|
282
|
+
ys = tys[0]*DPTS1 + tys[1]*DPTS2 + tys[2]*DPTS3
|
|
283
|
+
|
|
284
|
+
cs = np.empty((2,xs.shape[0]), dtype=np.float64)
|
|
285
|
+
cs[0,:] = xs
|
|
286
|
+
cs[1,:] = ys
|
|
287
|
+
|
|
288
|
+
aas, bbs, ccs, Area = tri_coefficients(txs, tys)
|
|
289
|
+
|
|
290
|
+
coeff = np.empty((3,3), dtype=np.float64)
|
|
291
|
+
coeff[0,:] = aas/(2*Area)
|
|
292
|
+
coeff[1,:] = bbs/(2*Area)
|
|
293
|
+
coeff[2,:] = ccs/(2*Area)
|
|
294
|
+
|
|
295
|
+
Msz = Ms[2,2]
|
|
296
|
+
Mmz = Mm[2,2]
|
|
297
|
+
Ms = Ms[:2,:2]
|
|
298
|
+
Mm = Mm[:2,:2]
|
|
299
|
+
|
|
300
|
+
Ls[3,:] *= Ds[0,2]
|
|
301
|
+
Ls[7,:] *= Ds[0,1]
|
|
302
|
+
Ls[:,3] *= Ds[0,2]
|
|
303
|
+
Ls[:,7] *= Ds[0,1]
|
|
304
|
+
|
|
305
|
+
for iv1 in range(3):
|
|
306
|
+
ie1 = local_edge_map[:, iv1]
|
|
307
|
+
|
|
308
|
+
Le = Ds[ie1[0], ie1[1]]
|
|
309
|
+
Ls[iv1,:] *= Le
|
|
310
|
+
Ls[:,iv1] *= Le
|
|
311
|
+
Ls[iv1+4,:] *= Le
|
|
312
|
+
Ls[:,iv1+4] *= Le
|
|
313
|
+
F1 = _ne1_curl(coeff[:,ie1], cs)
|
|
314
|
+
F2 = _ne2_curl(coeff[:,ie1], cs)
|
|
315
|
+
F3 = _ne1(coeff[:,ie1], cs)
|
|
316
|
+
F4 = _ne2(coeff[:,ie1], cs)
|
|
317
|
+
F5 = _lv_grad(coeff[:,iv1],cs)
|
|
318
|
+
F6 = _le_grad(coeff[:,ie1],cs)
|
|
319
|
+
|
|
320
|
+
for iv2 in range(3):
|
|
321
|
+
ei2 = local_edge_map[:, iv2]
|
|
322
|
+
|
|
323
|
+
H1 = matmul(Ms,_ne1(coeff[:,ei2],cs))
|
|
324
|
+
H2 = matmul(Ms,_ne2(coeff[:,ei2],cs))
|
|
325
|
+
|
|
326
|
+
Att[iv1,iv2] = _gqi(F1, Msz * _ne1_curl(coeff[:,ei2],cs), WEIGHTS)
|
|
327
|
+
Att[iv1+4,iv2] = _gqi(F2, Msz * _ne1_curl(coeff[:,ei2],cs), WEIGHTS)
|
|
328
|
+
Att[iv1,iv2+4] = _gqi(F1, Msz * _ne2_curl(coeff[:,ei2],cs), WEIGHTS)
|
|
329
|
+
Att[iv1+4,iv2+4] = _gqi(F2, Msz * _ne2_curl(coeff[:,ei2],cs), WEIGHTS)
|
|
330
|
+
|
|
331
|
+
Btt[iv1,iv2] = _gqi2(F3, matmul(Mm,_ne1(coeff[:,ei2],cs)), WEIGHTS)
|
|
332
|
+
Btt[iv1+4,iv2] = _gqi2(F4, matmul(Mm,_ne1(coeff[:,ei2],cs)), WEIGHTS)
|
|
333
|
+
Btt[iv1,iv2+4] = _gqi2(F3, matmul(Mm,_ne2(coeff[:,ei2],cs)), WEIGHTS)
|
|
334
|
+
Btt[iv1+4,iv2+4] = _gqi2(F4, matmul(Mm,_ne2(coeff[:,ei2],cs)), WEIGHTS)
|
|
335
|
+
|
|
336
|
+
Dtt[iv1,iv2] = _gqi2(F3, H1, WEIGHTS)
|
|
337
|
+
Dtt[iv1+4,iv2] = _gqi2(F4, H1, WEIGHTS)
|
|
338
|
+
Dtt[iv1,iv2+4] = _gqi2(F3, H2, WEIGHTS)
|
|
339
|
+
Dtt[iv1+4,iv2+4] = _gqi2(F4, H2, WEIGHTS)
|
|
340
|
+
|
|
341
|
+
Dzt[iv1, iv2] = _gqi2(F5, H1, WEIGHTS)
|
|
342
|
+
Dzt[iv1+3, iv2] = _gqi2(F6, H1, WEIGHTS)
|
|
343
|
+
Dzt[iv1, iv2+4] = _gqi2(F5, H2, WEIGHTS)
|
|
344
|
+
Dzt[iv1+3, iv2+4] = _gqi2(F6, H2, WEIGHTS)
|
|
345
|
+
|
|
346
|
+
Dzz1[iv1, iv2] = _gqi2(_lv_grad(coeff[:,iv1], cs), matmul(Ms,_lv_grad(coeff[:,iv2],cs)), WEIGHTS)
|
|
347
|
+
Dzz1[iv1, iv2+3] = _gqi2(_lv_grad(coeff[:,iv1], cs), matmul(Ms,_le_grad(coeff[:,ei2],cs)), WEIGHTS)
|
|
348
|
+
Dzz1[iv1+3, iv2] = _gqi2(_le_grad(coeff[:,ie1], cs), matmul(Ms,_lv_grad(coeff[:,iv2],cs)), WEIGHTS)
|
|
349
|
+
Dzz1[iv1+3, iv2+3] = _gqi2(_le_grad(coeff[:,ie1], cs), matmul(Ms,_le_grad(coeff[:,ei2],cs)), WEIGHTS)
|
|
350
|
+
|
|
351
|
+
Dzz2[iv1, iv2] = _gqi(_lv(coeff[:,iv1], cs), Mmz * _lv(coeff[:,iv2],cs), WEIGHTS)
|
|
352
|
+
Dzz2[iv1, iv2+3] = _gqi(_lv(coeff[:,iv1], cs), Mmz * _le(coeff[:,ei2],cs), WEIGHTS)
|
|
353
|
+
Dzz2[iv1+3, iv2] = _gqi(_le(coeff[:,ie1], cs), Mmz * _lv(coeff[:,iv2],cs), WEIGHTS)
|
|
354
|
+
Dzz2[iv1+3, iv2+3] = _gqi(_le(coeff[:,ie1], cs), Mmz * _le(coeff[:,ei2],cs), WEIGHTS)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
G1 = matmul(Mm,_nf1(coeff,cs))
|
|
358
|
+
G2 = matmul(Mm,_nf2(coeff,cs))
|
|
359
|
+
G3 = matmul(Ms,_nf1(coeff,cs))
|
|
360
|
+
G4 = matmul(Ms,_nf2(coeff,cs))
|
|
361
|
+
|
|
362
|
+
Att[iv1,3] = _gqi(F1, Msz * _nf1_curl(coeff,cs), WEIGHTS)
|
|
363
|
+
Att[iv1+4,3] = _gqi(_ne2_curl(coeff[:,ie1], cs), Msz * _nf1_curl(coeff,cs), WEIGHTS)
|
|
364
|
+
Att[iv1,7] = _gqi(F1, Msz * _nf2_curl(coeff,cs), WEIGHTS)
|
|
365
|
+
Att[iv1+4,7] = _gqi(_ne2_curl(coeff[:,ie1], cs), Msz * _nf2_curl(coeff,cs), WEIGHTS)
|
|
366
|
+
|
|
367
|
+
Att[3, iv1] = Att[iv1,3]
|
|
368
|
+
Att[7, iv1] = Att[iv1,7]
|
|
369
|
+
Att[3, iv1+4] = Att[iv1+4,3]
|
|
370
|
+
Att[7, iv1+4] = Att[iv1+4,7]
|
|
371
|
+
|
|
372
|
+
Btt[iv1,3] = _gqi2(F3, G1, WEIGHTS)
|
|
373
|
+
Btt[iv1+4,3] = _gqi2(F4, G1, WEIGHTS)
|
|
374
|
+
Btt[iv1,7] = _gqi2(F3, G2, WEIGHTS)
|
|
375
|
+
Btt[iv1+4,7] = _gqi2(F4, G2, WEIGHTS)
|
|
376
|
+
|
|
377
|
+
Btt[3, iv1] = Btt[iv1,3]
|
|
378
|
+
Btt[7, iv1] = Btt[iv1,7]
|
|
379
|
+
Btt[3, iv1+4] = Btt[iv1+4,3]
|
|
380
|
+
Btt[7, iv1+4] = Btt[iv1+4,7]
|
|
381
|
+
|
|
382
|
+
Dtt[iv1,3] = _gqi2(F3, G3, WEIGHTS)
|
|
383
|
+
Dtt[iv1+4,3] = _gqi2(F4, G3, WEIGHTS)
|
|
384
|
+
Dtt[iv1,7] = _gqi2(F3, G4, WEIGHTS)
|
|
385
|
+
Dtt[iv1+4,7] = _gqi2(F4, G4, WEIGHTS)
|
|
386
|
+
|
|
387
|
+
Dtt[3, iv1] = Dtt[iv1,3]
|
|
388
|
+
Dtt[7, iv1] = Dtt[iv1,7]
|
|
389
|
+
Dtt[3, iv1+4] = Dtt[iv1+4,3]
|
|
390
|
+
Dtt[7, iv1+4] = Dtt[iv1+4,7]
|
|
391
|
+
|
|
392
|
+
Dzt[iv1, 3] = _gqi2(F5, G3, WEIGHTS)
|
|
393
|
+
Dzt[iv1, 7] = _gqi2(F5, G4, WEIGHTS)
|
|
394
|
+
Dzt[iv1+3, 3] = _gqi2(F6, G3, WEIGHTS)
|
|
395
|
+
Dzt[iv1+3, 7] = _gqi2(F6, G4, WEIGHTS)
|
|
396
|
+
|
|
397
|
+
Att[3,3] = _gqi(_nf1_curl(coeff, cs), Msz * _nf1_curl(coeff,cs), WEIGHTS)
|
|
398
|
+
Att[7,3] = _gqi(_nf2_curl(coeff, cs), Msz * _nf1_curl(coeff,cs), WEIGHTS)
|
|
399
|
+
Att[3,7] = _gqi(_nf1_curl(coeff, cs), Msz * _nf2_curl(coeff,cs), WEIGHTS)
|
|
400
|
+
Att[7,7] = _gqi(_nf2_curl(coeff, cs), Msz * _nf2_curl(coeff,cs), WEIGHTS)
|
|
401
|
+
|
|
402
|
+
Btt[3,3] = _gqi2(_nf1(coeff, cs), G1, WEIGHTS)
|
|
403
|
+
Btt[7,3] = _gqi2(_nf2(coeff, cs), G1, WEIGHTS)
|
|
404
|
+
Btt[3,7] = _gqi2(_nf1(coeff, cs), G2, WEIGHTS)
|
|
405
|
+
Btt[7,7] = _gqi2(_nf2(coeff, cs), G2, WEIGHTS)
|
|
406
|
+
|
|
407
|
+
A = np.zeros((14, 14), dtype = np.complex128)
|
|
408
|
+
B = np.zeros((14, 14), dtype = np.complex128)
|
|
409
|
+
|
|
410
|
+
A[:8,:8] = (Att - k0**2 * Btt)
|
|
411
|
+
|
|
412
|
+
B[:8,:8] = Dtt
|
|
413
|
+
B[8:,:8] = Dzt
|
|
414
|
+
B[:8,8:] = Dzt.T
|
|
415
|
+
B[8:,8:] = Dzz1 - k0**2 * Dzz2
|
|
416
|
+
|
|
417
|
+
Ls = np.ones((14,14), dtype=np.float64)
|
|
418
|
+
|
|
419
|
+
B = Ls*B*np.abs(Area)
|
|
420
|
+
A = Ls*A*np.abs(Area)
|
|
421
|
+
return A, B
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
@njit(types.Tuple((c16[:], c16[:], i8[:], i8[:]))(f8[:,:],
|
|
425
|
+
i8[:,:],
|
|
426
|
+
i8[:,:],
|
|
427
|
+
i8[:,:],
|
|
428
|
+
c16[:,:,:],
|
|
429
|
+
c16[:,:,:],
|
|
430
|
+
f8,
|
|
431
|
+
ProgressBarType), cache=True, nogil=True, parallel=True)
|
|
432
|
+
def _matrix_builder(nodes, tris, edges, tri_to_field, ur, er, k0, pgb: ProgressBar):
|
|
433
|
+
|
|
434
|
+
ntritot = tris.shape[1]
|
|
435
|
+
nnz = ntritot*196
|
|
436
|
+
|
|
437
|
+
rows = np.zeros(nnz, dtype=np.int64)
|
|
438
|
+
cols = np.zeros(nnz, dtype=np.int64)
|
|
439
|
+
dataE = np.zeros_like(rows, dtype=np.complex128)
|
|
440
|
+
dataB = np.zeros_like(rows, dtype=np.complex128)
|
|
441
|
+
|
|
442
|
+
tri_to_edge = tri_to_field[:3,:]
|
|
443
|
+
|
|
444
|
+
for itri in prange(ntritot): # type: ignore
|
|
445
|
+
p = itri*196
|
|
446
|
+
if np.mod(itri,10)==0:
|
|
447
|
+
pgb.update(10)
|
|
448
|
+
urt = ur[:,:,itri]
|
|
449
|
+
ert = er[:,:,itri]
|
|
450
|
+
|
|
451
|
+
# Construct a local mapping to global triangle orientations
|
|
452
|
+
local_tri_map = local_tri_to_edgeid(itri, tris, edges, tri_to_edge)
|
|
453
|
+
|
|
454
|
+
# Construct the local edge map
|
|
455
|
+
tri_nodes = nodes[:, tris[:,itri]]
|
|
456
|
+
Esub, Bsub = generalized_matrix_GQ(tri_nodes,local_tri_map, matinv(urt), ert, k0)
|
|
457
|
+
|
|
458
|
+
indices = tri_to_field[:, itri]
|
|
459
|
+
for ii in range(14):
|
|
460
|
+
rows[p+14*ii:p+14*(ii+1)] = indices[ii]
|
|
461
|
+
cols[p+ii:p+ii+196:14] = indices[ii]
|
|
462
|
+
|
|
463
|
+
dataE[p:p+196] = Esub.ravel()
|
|
464
|
+
dataB[p:p+196] = Bsub.ravel()
|
|
465
|
+
return dataE, dataB, rows, cols
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
import numpy as np
|
|
20
20
|
from numba import njit, f8, c16, i8, types, prange
|
|
21
|
+
from ....mth.optimized import cross, matinv_r
|
|
21
22
|
from ....elements import Nedelec2
|
|
22
23
|
from typing import Callable
|
|
23
24
|
from loguru import logger
|
|
@@ -86,6 +87,28 @@ def generate_points(vertices_local, tris, DPTs, surf_triangle_indices):
|
|
|
86
87
|
yflat = yall.flatten()
|
|
87
88
|
return xflat, yflat
|
|
88
89
|
|
|
90
|
+
@njit(types.Tuple((f8[:],f8[:], f8[:]))(f8[:,:], i8[:,:], f8[:,:], i8[:]), cache=True, nogil=True)
|
|
91
|
+
def generate_points_3d(vertices, tris, DPTs, surf_triangle_indices):
|
|
92
|
+
NS = surf_triangle_indices.shape[0]
|
|
93
|
+
xall = np.zeros((DPTs.shape[1], NS))
|
|
94
|
+
yall = np.zeros((DPTs.shape[1], NS))
|
|
95
|
+
zall = np.zeros((DPTs.shape[1], NS))
|
|
96
|
+
for i in range(NS):
|
|
97
|
+
itri = surf_triangle_indices[i]
|
|
98
|
+
vertex_ids = tris[:, itri]
|
|
99
|
+
|
|
100
|
+
x1, x2, x3 = vertices[0, vertex_ids]
|
|
101
|
+
y1, y2, y3 = vertices[1, vertex_ids]
|
|
102
|
+
z1, z2, z3 = vertices[2, vertex_ids]
|
|
103
|
+
|
|
104
|
+
xall[:,i] = x1*DPTs[1,:] + x2*DPTs[2,:] + x3*DPTs[3,:]
|
|
105
|
+
yall[:,i] = y1*DPTs[1,:] + y2*DPTs[2,:] + y3*DPTs[3,:]
|
|
106
|
+
zall[:,i] = z1*DPTs[1,:] + z2*DPTs[2,:] + z3*DPTs[3,:]
|
|
107
|
+
xflat = xall.flatten()
|
|
108
|
+
yflat = yall.flatten()
|
|
109
|
+
zflat = zall.flatten()
|
|
110
|
+
return xflat, yflat, zflat
|
|
111
|
+
|
|
89
112
|
@njit(f8[:,:](f8[:], f8[:], f8[:]), cache=True, nogil=True, fastmath=True)
|
|
90
113
|
def compute_distances(xs: np.ndarray, ys: np.ndarray, zs: np.ndarray) -> np.ndarray:
|
|
91
114
|
N = xs.shape[0]
|
|
@@ -96,8 +119,12 @@ def compute_distances(xs: np.ndarray, ys: np.ndarray, zs: np.ndarray) -> np.ndar
|
|
|
96
119
|
Ds[j,i] = Ds[i,j]
|
|
97
120
|
return Ds
|
|
98
121
|
|
|
122
|
+
@njit(cache=True, nogil=True)
|
|
123
|
+
def normalize(a: np.ndarray):
|
|
124
|
+
return a/((a[0]**2 + a[1]**2 + a[2]**2)**0.5)
|
|
125
|
+
|
|
99
126
|
@njit(types.Tuple((c16[:,:],c16[:]))(f8[:,:], c16, c16[:,:], f8[:,:]), cache=True, nogil=True, parallel=False)
|
|
100
|
-
def ned2_tri_stiff_force(
|
|
127
|
+
def ned2_tri_stiff_force(glob_vertices, gamma, glob_Uinc, DPTs):
|
|
101
128
|
''' Nedelec-2 Triangle Stiffness matrix and forcing vector (For Boundary Condition of the Third Kind)
|
|
102
129
|
|
|
103
130
|
'''
|
|
@@ -105,9 +132,25 @@ def ned2_tri_stiff_force(lcs_vertices, gamma, lcs_Uinc, DPTs):
|
|
|
105
132
|
Bmat = np.zeros((8,8), dtype=np.complex128)
|
|
106
133
|
bvec = np.zeros((8,), dtype=np.complex128)
|
|
107
134
|
|
|
135
|
+
orig = glob_vertices[:,0]
|
|
136
|
+
v2 = glob_vertices[:,1]
|
|
137
|
+
v3 = glob_vertices[:,2]
|
|
138
|
+
|
|
139
|
+
e1 = v2-orig
|
|
140
|
+
e2 = v3-orig
|
|
141
|
+
zhat = normalize(cross(e1, e2))
|
|
142
|
+
xhat = normalize(e1)
|
|
143
|
+
yhat = normalize(cross(zhat, xhat))
|
|
144
|
+
basis = np.zeros((3,3), dtype=np.float64)
|
|
145
|
+
basis[0,:] = xhat
|
|
146
|
+
basis[1,:] = yhat
|
|
147
|
+
basis[2,:] = zhat
|
|
148
|
+
lcs_vertices = optim_matmul(basis, glob_vertices - orig[:,np.newaxis])
|
|
149
|
+
lcs_Uinc = optim_matmul(basis, glob_Uinc)
|
|
150
|
+
|
|
108
151
|
xs = lcs_vertices[0,:]
|
|
109
152
|
ys = lcs_vertices[1,:]
|
|
110
|
-
|
|
153
|
+
|
|
111
154
|
x1, x2, x3 = xs
|
|
112
155
|
y1, y2, y3 = ys
|
|
113
156
|
|
|
@@ -249,7 +292,7 @@ def ned2_tri_stiff_force(lcs_vertices, gamma, lcs_Uinc, DPTs):
|
|
|
249
292
|
return Bmat, bvec
|
|
250
293
|
|
|
251
294
|
@njit(types.Tuple((c16[:], c16[:]))(f8[:,:], i8[:,:], c16[:], c16[:], i8[:], c16, c16[:,:,:], f8[:,:], i8[:,:]), cache=True, nogil=True, parallel=False)
|
|
252
|
-
def compute_bc_entries_excited(
|
|
295
|
+
def compute_bc_entries_excited(vertices_global, tris, Bmat, Bvec, surf_triangle_indices, gamma, Uglobal_all, DPTs, tri_to_field):
|
|
253
296
|
N = 64
|
|
254
297
|
Niter = surf_triangle_indices.shape[0]
|
|
255
298
|
for i in prange(Niter): # type: ignore
|
|
@@ -257,9 +300,9 @@ def compute_bc_entries_excited(vertices_local, tris, Bmat, Bvec, surf_triangle_i
|
|
|
257
300
|
|
|
258
301
|
vertex_ids = tris[:, itri]
|
|
259
302
|
|
|
260
|
-
Ulocal =
|
|
303
|
+
Ulocal = Uglobal_all[:,:, i]
|
|
261
304
|
|
|
262
|
-
Bsub, bvec = ned2_tri_stiff_force(
|
|
305
|
+
Bsub, bvec = ned2_tri_stiff_force(vertices_global[:,vertex_ids], gamma, Ulocal, DPTs)
|
|
263
306
|
|
|
264
307
|
indices = tri_to_field[:, itri]
|
|
265
308
|
|
|
@@ -402,30 +445,28 @@ def compute_bc_entries(vertices, tris, Bmat, all_edge_lengths, surf_triangle_ind
|
|
|
402
445
|
|
|
403
446
|
def assemble_robin_bc_excited(field: Nedelec2,
|
|
404
447
|
Bmat: np.ndarray,
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
origin: np.ndarray,
|
|
410
|
-
DPTs: np.ndarray):
|
|
448
|
+
surf_triangle_indices: np.ndarray,
|
|
449
|
+
Ufunc: Callable,
|
|
450
|
+
gamma: complex,
|
|
451
|
+
DPTs: np.ndarray):
|
|
411
452
|
|
|
412
453
|
Bvec = np.zeros((field.n_field,), dtype=np.complex128)
|
|
413
454
|
|
|
414
|
-
|
|
455
|
+
vertices = field.mesh.nodes
|
|
415
456
|
|
|
416
|
-
xflat, yflat =
|
|
457
|
+
xflat, yflat, zflat = generate_points_3d(vertices, field.mesh.tris, DPTs, surf_triangle_indices)
|
|
417
458
|
|
|
418
|
-
|
|
459
|
+
U_global = Ufunc(xflat, yflat, zflat)
|
|
419
460
|
|
|
420
|
-
|
|
461
|
+
U_global_all = U_global.reshape((3, DPTs.shape[1], surf_triangle_indices.shape[0]))
|
|
421
462
|
|
|
422
|
-
Bmat, Bvec = compute_bc_entries_excited(
|
|
463
|
+
Bmat, Bvec = compute_bc_entries_excited(vertices, field.mesh.tris, Bmat, Bvec, surf_triangle_indices, gamma, U_global_all, DPTs, field.tri_to_field)
|
|
423
464
|
return Bmat, Bvec
|
|
424
465
|
|
|
425
466
|
def assemble_robin_bc(field: Nedelec2,
|
|
426
467
|
Bmat: np.ndarray,
|
|
427
|
-
|
|
428
|
-
|
|
468
|
+
surf_triangle_indices: np.ndarray,
|
|
469
|
+
gamma: np.ndarray):
|
|
429
470
|
vertices = field.mesh.nodes
|
|
430
471
|
all_edge_lengths = field.mesh.edge_lengths[field.mesh.tri_to_edge]
|
|
431
472
|
Bmat = compute_bc_entries(vertices, field.mesh.tris, Bmat, all_edge_lengths, surf_triangle_indices, gamma)
|
|
@@ -24,6 +24,7 @@ from ...elements.nedelec2 import Nedelec2
|
|
|
24
24
|
from ...solver import DEFAULT_ROUTINE, SolveRoutine
|
|
25
25
|
from ...system import called_from_main_function
|
|
26
26
|
from ...selection import FaceSelection
|
|
27
|
+
from ...mth.optimized import compute_distances
|
|
27
28
|
from .microwave_bc import MWBoundaryConditionSet, PEC, ModalPort, LumpedPort, PortBC
|
|
28
29
|
from .microwave_data import MWData
|
|
29
30
|
from .assembly.assembler import Assembler
|
|
@@ -60,7 +61,7 @@ def run_job_multi(job: SimJob) -> SimJob:
|
|
|
60
61
|
return job
|
|
61
62
|
|
|
62
63
|
|
|
63
|
-
def _dimstring(data: list[float]) -> str:
|
|
64
|
+
def _dimstring(data: list[float] | np.ndarray) -> str:
|
|
64
65
|
"""A String formatter for dimensions in millimeters
|
|
65
66
|
|
|
66
67
|
Args:
|
|
@@ -99,6 +100,21 @@ def shortest_path(xyz1: np.ndarray, xyz2: np.ndarray, Npts: int) -> np.ndarray:
|
|
|
99
100
|
|
|
100
101
|
return path
|
|
101
102
|
|
|
103
|
+
def _pick_central(vertices: np.ndarray) -> np.ndarray:
|
|
104
|
+
"""Computes the coordinate in the vertex set that has the shortest square distance to all other points.
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
vertices (np.ndarray): The set of coordinates [3,:]
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
np.ndarray: The most central point
|
|
112
|
+
"""
|
|
113
|
+
Ds = compute_distances(vertices[0,:], vertices[1,:], vertices[2,:])
|
|
114
|
+
sumDs = np.sum(Ds**2, axis=1)
|
|
115
|
+
id_central = np.argwhere(sumDs==np.min(sumDs)).flatten()[0]
|
|
116
|
+
return vertices[:, id_central].squeeze()
|
|
117
|
+
|
|
102
118
|
class Microwave3D:
|
|
103
119
|
"""The Electrodynamics time harmonic physics class.
|
|
104
120
|
|
|
@@ -302,8 +318,8 @@ class Microwave3D:
|
|
|
302
318
|
dotprod = xs*field_axis[0] + ys*field_axis[1] + zs*field_axis[2]
|
|
303
319
|
|
|
304
320
|
start_id = points[np.argwhere(dotprod == np.min(dotprod))]
|
|
305
|
-
|
|
306
|
-
start =
|
|
321
|
+
|
|
322
|
+
start = _pick_central(self.mesh.nodes[:,start_id.flatten()])
|
|
307
323
|
logger.info(f'Starting node = {_dimstring(start)}')
|
|
308
324
|
end = start + port.Vdirection.np*port.height
|
|
309
325
|
|
|
@@ -493,6 +509,7 @@ class Microwave3D:
|
|
|
493
509
|
if TEM:
|
|
494
510
|
target_kz = ermean*urmean*1.1*k0
|
|
495
511
|
else:
|
|
512
|
+
|
|
496
513
|
target_kz = ermean*urmean*0.7*k0
|
|
497
514
|
|
|
498
515
|
|
|
@@ -514,7 +531,8 @@ class Microwave3D:
|
|
|
514
531
|
Emode[solve_ids] = np.squeeze(eigenmode)
|
|
515
532
|
Emode = Emode * np.exp(-1j*np.angle(np.max(Emode)))
|
|
516
533
|
|
|
517
|
-
|
|
534
|
+
beta_base = np.emath.sqrt(-eigen_values[i])
|
|
535
|
+
beta = min(k0*np.sqrt(ermax*urmax), beta_base)
|
|
518
536
|
|
|
519
537
|
residuals = -1
|
|
520
538
|
|