emerge 0.4.7__py3-none-any.whl → 0.4.9__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 (78) hide show
  1. emerge/__init__.py +14 -14
  2. emerge/_emerge/__init__.py +42 -0
  3. emerge/_emerge/bc.py +197 -0
  4. emerge/_emerge/coord.py +119 -0
  5. emerge/_emerge/cs.py +523 -0
  6. emerge/_emerge/dataset.py +36 -0
  7. emerge/_emerge/elements/__init__.py +19 -0
  8. emerge/_emerge/elements/femdata.py +212 -0
  9. emerge/_emerge/elements/index_interp.py +64 -0
  10. emerge/_emerge/elements/legrange2.py +172 -0
  11. emerge/_emerge/elements/ned2_interp.py +645 -0
  12. emerge/_emerge/elements/nedelec2.py +140 -0
  13. emerge/_emerge/elements/nedleg2.py +217 -0
  14. emerge/_emerge/geo/__init__.py +24 -0
  15. emerge/_emerge/geo/horn.py +107 -0
  16. emerge/_emerge/geo/modeler.py +449 -0
  17. emerge/_emerge/geo/operations.py +254 -0
  18. emerge/_emerge/geo/pcb.py +1244 -0
  19. emerge/_emerge/geo/pcb_tools/calculator.py +28 -0
  20. emerge/_emerge/geo/pcb_tools/macro.py +79 -0
  21. emerge/_emerge/geo/pmlbox.py +204 -0
  22. emerge/_emerge/geo/polybased.py +529 -0
  23. emerge/_emerge/geo/shapes.py +427 -0
  24. emerge/_emerge/geo/step.py +77 -0
  25. emerge/_emerge/geo2d.py +86 -0
  26. emerge/_emerge/geometry.py +510 -0
  27. emerge/_emerge/howto.py +214 -0
  28. emerge/_emerge/logsettings.py +5 -0
  29. emerge/_emerge/material.py +118 -0
  30. emerge/_emerge/mesh3d.py +730 -0
  31. emerge/_emerge/mesher.py +339 -0
  32. emerge/_emerge/mth/common_functions.py +33 -0
  33. emerge/_emerge/mth/integrals.py +71 -0
  34. emerge/_emerge/mth/optimized.py +357 -0
  35. emerge/_emerge/periodic.py +263 -0
  36. emerge/_emerge/physics/__init__.py +0 -0
  37. emerge/_emerge/physics/microwave/__init__.py +1 -0
  38. emerge/_emerge/physics/microwave/adaptive_freq.py +279 -0
  39. emerge/_emerge/physics/microwave/assembly/assembler.py +569 -0
  40. emerge/_emerge/physics/microwave/assembly/curlcurl.py +448 -0
  41. emerge/_emerge/physics/microwave/assembly/generalized_eigen.py +426 -0
  42. emerge/_emerge/physics/microwave/assembly/robinbc.py +433 -0
  43. emerge/_emerge/physics/microwave/microwave_3d.py +1150 -0
  44. emerge/_emerge/physics/microwave/microwave_bc.py +915 -0
  45. emerge/_emerge/physics/microwave/microwave_data.py +1148 -0
  46. emerge/_emerge/physics/microwave/periodic.py +82 -0
  47. emerge/_emerge/physics/microwave/port_functions.py +53 -0
  48. emerge/_emerge/physics/microwave/sc.py +175 -0
  49. emerge/_emerge/physics/microwave/simjob.py +147 -0
  50. emerge/_emerge/physics/microwave/sparam.py +138 -0
  51. emerge/_emerge/physics/microwave/touchstone.py +140 -0
  52. emerge/_emerge/plot/__init__.py +0 -0
  53. emerge/_emerge/plot/display.py +394 -0
  54. emerge/_emerge/plot/grapher.py +93 -0
  55. emerge/_emerge/plot/matplotlib/mpldisplay.py +264 -0
  56. emerge/_emerge/plot/pyvista/__init__.py +1 -0
  57. emerge/_emerge/plot/pyvista/display.py +931 -0
  58. emerge/_emerge/plot/pyvista/display_settings.py +24 -0
  59. emerge/_emerge/plot/simple_plots.py +551 -0
  60. emerge/_emerge/plot.py +225 -0
  61. emerge/_emerge/projects/__init__.py +0 -0
  62. emerge/_emerge/projects/_gen_base.txt +32 -0
  63. emerge/_emerge/projects/_load_base.txt +24 -0
  64. emerge/_emerge/projects/generate_project.py +40 -0
  65. emerge/_emerge/selection.py +596 -0
  66. emerge/_emerge/simmodel.py +444 -0
  67. emerge/_emerge/simulation_data.py +411 -0
  68. emerge/_emerge/solver.py +993 -0
  69. emerge/_emerge/system.py +54 -0
  70. emerge/cli.py +19 -0
  71. emerge/lib.py +1 -1
  72. emerge/plot.py +1 -1
  73. {emerge-0.4.7.dist-info → emerge-0.4.9.dist-info}/METADATA +7 -6
  74. emerge-0.4.9.dist-info/RECORD +78 -0
  75. emerge-0.4.9.dist-info/entry_points.txt +2 -0
  76. emerge-0.4.7.dist-info/RECORD +0 -9
  77. emerge-0.4.7.dist-info/entry_points.txt +0 -2
  78. {emerge-0.4.7.dist-info → emerge-0.4.9.dist-info}/WHEEL +0 -0
@@ -0,0 +1,426 @@
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 coo_matrix
21
+ from numba_progress import ProgressBar, ProgressBarType
22
+ from ....mth.optimized import local_mapping, matinv, compute_distances
23
+ from numba import c16, types, f8, i8, njit, prange
24
+
25
+ @njit(i8[:,:](i8, i8[:,:], i8[:,:], i8[:,:]), cache=True, nogil=True)
26
+ def local_tri_to_edgeid(itri: int, tris, edges, tri_to_edge) -> np.ndarray:
27
+ global_edge_map = edges[:, tri_to_edge[:,itri]]
28
+ return local_mapping(tris[:, itri], global_edge_map)
29
+
30
+ def generelized_eigenvalue_matrix(field: NedelecLegrange2,
31
+ er: np.ndarray,
32
+ ur: np.ndarray,
33
+ basis: np.ndarray,
34
+ k0: float,) -> tuple[coo_matrix, coo_matrix]:
35
+
36
+ tris = field.mesh.tris
37
+ edges = field.mesh.edges
38
+ nodes = field.mesh.nodes
39
+
40
+ nT = tris.shape[1]
41
+ tri_to_field = field.tri_to_field
42
+
43
+ nodes = np.linalg.pinv(basis) @ nodes
44
+
45
+ with ProgressBar(total=nT, ncols=100, dynamic_ncols=False) as pgb:
46
+ dataE, dataB, rows, cols = _matrix_builder(nodes, tris, edges, tri_to_field, ur, er, k0, pgb)
47
+
48
+ nfield = field.n_field
49
+
50
+ E = coo_matrix((dataE, (rows, cols)), shape=(nfield, nfield)).tocsr()
51
+ B = coo_matrix((dataB, (rows, cols)), shape=(nfield, nfield)).tocsr()
52
+
53
+ return E, B
54
+
55
+ @njit(c16[:,:](c16[:,:], c16[:,:]), cache=True, nogil=True)
56
+ def matmul(a, b):
57
+ out = np.empty((2,b.shape[1]), dtype=np.complex128)
58
+ out[0,:] = a[0,0]*b[0,:] + a[0,1]*b[1,:]
59
+ out[1,:] = a[1,0]*b[0,:] + a[1,1]*b[1,:]
60
+ return out
61
+
62
+ ### GAUSS QUADRATURE IMPLEMENTATION
63
+
64
+ @njit(c16(c16[:], c16[:], types.Array(types.float64, 1, 'A', readonly=True)), cache=True, nogil=True)
65
+ def _gqi(v1, v2, W):
66
+ return np.sum(v1*v2*W)
67
+
68
+ @njit(c16(c16[:,:], c16[:,:], types.Array(types.float64, 1, 'A', readonly=True)), cache=True, nogil=True)
69
+ def _gqi2(v1, v2, W):
70
+ return np.sum(W*np.sum(v1*v2,axis=0))
71
+
72
+ @njit(c16[:,:](f8[:,:], f8[:,:]), cache=True, nogil=True)
73
+ def _ne1(coeff, coords):
74
+ a1, b1, c1 = coeff[:,0]
75
+ a2, b2, c2 = coeff[:,1]
76
+ xs = coords[0,:]
77
+ ys = coords[1,:]
78
+ out=np.empty((2,xs.shape[0]), dtype=np.complex128)
79
+ out[0,:] = (b1*(a2 + b2*xs + c2*ys) - b2*(a1 + b1*xs + c1*ys))*(a1 + b1*xs + c1*ys)
80
+ out[1,:] = (c1*(a2 + b2*xs + c2*ys) - c2*(a1 + b1*xs + c1*ys))*(a1 + b1*xs + c1*ys)
81
+ return out
82
+
83
+ @njit(c16[:,:](f8[:,:], f8[:,:]), cache=True, nogil=True)
84
+ def _ne2(coeff, coords):
85
+ a1, b1, c1 = coeff[:,0]
86
+ a2, b2, c2 = coeff[:,1]
87
+ xs = coords[0,:]
88
+ ys = coords[1,:]
89
+ out=np.empty((2,xs.shape[0]), dtype=np.complex128)
90
+ out[0,:] = (b1*(a2 + b2*xs + c2*ys) - b2*(a1 + b1*xs + c1*ys))*(a2 + b2*xs + c2*ys)
91
+ out[1,:] = (c1*(a2 + b2*xs + c2*ys) - c2*(a1 + b1*xs + c1*ys))*(a2 + b2*xs + c2*ys)
92
+ return out
93
+
94
+ @njit(c16[:,:](f8[:,:], f8[:,:]), cache=True, nogil=True)
95
+ def _nf1(coeff, coords):
96
+ a1, b1, c1 = coeff[:,0]
97
+ a2, b2, c2 = coeff[:,1]
98
+ a3, b3, c3 = coeff[:,2]
99
+ xs = coords[0,:]
100
+ ys = coords[1,:]
101
+ out=np.empty((2,xs.shape[0]), dtype=np.complex128)
102
+ out[0,:] = -(b1*(a3 + b3*xs + c3*ys) - b3*(a1 + b1*xs + c1*ys))*(a2 + b2*xs + c2*ys)
103
+ out[1,:] = -(c1*(a3 + b3*xs + c3*ys) - c3*(a1 + b1*xs + c1*ys))*(a2 + b2*xs + c2*ys)
104
+ return out
105
+
106
+ @njit(c16[:,:](f8[:,:], f8[:,:]), cache=True, nogil=True)
107
+ def _nf2(coeff, coords):
108
+ a1, b1, c1 = coeff[:,0]
109
+ a2, b2, c2 = coeff[:,1]
110
+ a3, b3, c3 = coeff[:,2]
111
+ xs = coords[0,:]
112
+ ys = coords[1,:]
113
+ out=np.empty((2,xs.shape[0]), dtype=np.complex128)
114
+ out[0,:] = (b1*(a2 + b2*xs + c2*ys) - b2*(a1 + b1*xs + c1*ys))*(a3 + b3*xs + c3*ys)
115
+ out[1,:] = (c1*(a2 + b2*xs + c2*ys) - c2*(a1 + b1*xs + c1*ys))*(a3 + b3*xs + c3*ys)
116
+ return out
117
+
118
+ @njit(c16[:](f8[:], f8[:,:]), cache=True, nogil=True)
119
+ def _lv(coeff, coords):
120
+ a1, b1, c1 = coeff
121
+ xs = coords[0,:]
122
+ ys = coords[1,:]
123
+ return -a1 - b1*xs - c1*ys + 2*(a1 + b1*xs + c1*ys)**2 + 0*1j
124
+
125
+ @njit(c16[:](f8[:,:], f8[:,:]), cache=True, nogil=True)
126
+ def _le(coeff, coords):
127
+ a1, b1, c1 = coeff[:,0]
128
+ a2, b2, c2 = coeff[:,1]
129
+ xs = coords[0,:]
130
+ ys = coords[1,:]
131
+ return 4*(a1 + b1*xs + c1*ys)*(a2 + b2*xs + c2*ys)+ 0*1j
132
+
133
+ @njit(c16[:,:](f8[:], f8[:,:]), cache=True, nogil=True)
134
+ def _lv_grad(coeff, coords):
135
+ a1, b1, c1 = coeff
136
+ xs = coords[0,:]
137
+ ys = coords[1,:]
138
+ out=np.empty((2,xs.shape[0]), dtype=np.complex128)
139
+ out[0,:] = b1*(4*a1 + 4*b1*xs + 4*c1*ys - 1)
140
+ out[1,:] = c1*(4*a1 + 4*b1*xs + 4*c1*ys - 1)
141
+ return out
142
+
143
+ @njit(c16[:,:](f8[:,:], f8[:,:]), cache=True, nogil=True)
144
+ def _le_grad(coeff, coords):
145
+ a1, b1, c1 = coeff[:,0]
146
+ a2, b2, c2 = coeff[:,1]
147
+ xs = coords[0,:]
148
+ ys = coords[1,:]
149
+ out=np.empty((2,xs.shape[0]), dtype=np.complex128)
150
+ out[0,:] = 4*b1*(a2 + b2*xs + c2*ys) + 4*b2*(a1 + b1*xs + c1*ys)
151
+ out[1,:] = 4*c1*(a2 + b2*xs + c2*ys) + 4*c2*(a1 + b1*xs + c1*ys)
152
+ return out
153
+
154
+ @njit(c16[:](f8[:,:], f8[:,:]), cache=True, nogil=True)
155
+ def _ne1_curl(coeff, coords):
156
+ a1, b1, c1 = coeff[:,0]
157
+ a2, b2, c2 = coeff[:,1]
158
+ xs = coords[0,:]
159
+ ys = coords[1,:]
160
+ return -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
161
+
162
+ @njit(c16[:](f8[:,:], f8[:,:]), cache=True, nogil=True)
163
+ def _ne2_curl(coeff, coords):
164
+ a1, b1, c1 = coeff[:,0]
165
+ a2, b2, c2 = coeff[:,1]
166
+ xs = coords[0,:]
167
+ ys = coords[1,:]
168
+ return -3*a2*b1*c2 + 3*a2*b2*c1 - 3*b1*b2*c2*xs - 3*b1*c2**2*ys + 3*b2**2*c1*xs + 3*b2*c1*c2*ys+ 0j
169
+
170
+ @njit(c16[:](f8[:,:], f8[:,:]), cache=True, nogil=True)
171
+ def _nf1_curl(coeff, coords):
172
+ a1, b1, c1 = coeff[:,0]
173
+ a2, b2, c2 = coeff[:,1]
174
+ a3, b3, c3 = coeff[:,2]
175
+ xs = coords[0,:]
176
+ ys = coords[1,:]
177
+ return -b2*(c1*(a3 + b3*xs + c3*ys) - c3*(a1 + b1*xs + c1*ys)) + c2*(b1*(a3 + b3*xs + c3*ys) - b3*(a1 + b1*xs + c1*ys)) + 2*(b1*c3 - b3*c1)*(a2 + b2*xs + c2*ys) + 0*1j
178
+
179
+ @njit(c16[:](f8[:,:], f8[:,:]), cache=True, nogil=True)
180
+ def _nf2_curl(coeff, coords):
181
+ a1, b1, c1 = coeff[:,0]
182
+ a2, b2, c2 = coeff[:,1]
183
+ a3, b3, c3 = coeff[:,2]
184
+ xs = coords[0,:]
185
+ ys = coords[1,:]
186
+ return b3*(c1*(a2 + b2*xs + c2*ys) - c2*(a1 + b1*xs + c1*ys)) - c3*(b1*(a2 + b2*xs + c2*ys) - b2*(a1 + b1*xs + c1*ys)) - 2*(b1*c2 - b2*c1)*(a3 + b3*xs + c3*ys) + 0*1j
187
+
188
+ ####
189
+ @njit(types.Tuple((f8[:], f8[:], f8[:], f8))(f8[:], f8[:]), cache = True, nogil=True)
190
+ def tri_coefficients(vxs, vys):
191
+
192
+ x1, x2, x3 = vxs
193
+ y1, y2, y3 = vys
194
+
195
+ a1 = x2*y3-y2*x3
196
+ a2 = x3*y1-y3*x1
197
+ a3 = x1*y2-y1*x2
198
+ b1 = y2-y3
199
+ b2 = y3-y1
200
+ b3 = y1-y2
201
+ c1 = x3-x2
202
+ c2 = x1-x3
203
+ c3 = x2-x1
204
+
205
+ #A = 0.5*(b1*c2 - b2*c1)
206
+ sA = 0.5*(((x1-x3)*(y2-y1) - (x1-x2)*(y3-y1)))
207
+ sign = np.sign(sA)
208
+ A = np.abs(sA)
209
+ As = np.array([a1, a2, a3])*sign
210
+ Bs = np.array([b1, b2, b3])*sign
211
+ Cs = np.array([c1, c2, c3])*sign
212
+ return As, Bs, Cs, A
213
+
214
+ #DPTS = gaus_quad_tri(4).astype(np.float64)
215
+
216
+ DPTS = np.array([[0.22338159, 0.22338159, 0.22338159, 0.10995174, 0.10995174, 0.10995174],
217
+ [0.10810302, 0.44594849, 0.44594849, 0.81684757, 0.09157621, 0.09157621],
218
+ [0.44594849, 0.44594849, 0.10810302, 0.09157621, 0.09157621, 0.81684757],
219
+ [0.44594849, 0.10810302, 0.44594849, 0.09157621, 0.81684757, 0.09157621]], dtype=np.float64)
220
+
221
+ @njit(types.Tuple((c16[:,:], c16[:,:]))(f8[:,:], i8[:,:], c16[:,:], c16[:,:], f8), cache=True, nogil=True)
222
+ def generalized_matrix_GQ(tri_vertices, local_edge_map, Ms, Mm, k0):
223
+ '''Nedelec-2 Triangle stiffness and mass submatrix'''
224
+ Att = np.zeros((8,8), dtype=np.complex128)
225
+ Btt = np.zeros((8,8), dtype=np.complex128)
226
+
227
+ Dtt = np.zeros((8,8), dtype=np.complex128)
228
+ Dzt = np.zeros((6,8), dtype=np.complex128)
229
+
230
+ Dzz1 = np.zeros((6,6), dtype=np.complex128)
231
+ Dzz2 = np.zeros((6,6), dtype=np.complex128)
232
+
233
+ Ls = np.ones((14,14), dtype=np.float64)
234
+ #Ls2 = np.ones((14,14), dtype=np.float64)
235
+
236
+ WEIGHTS = DPTS[0,:]
237
+ DPTS1 = DPTS[1,:]
238
+ DPTS2 = DPTS[2,:]
239
+ DPTS3 = DPTS[3,:]
240
+
241
+ txs = tri_vertices[0,:]
242
+ tys = tri_vertices[1,:]
243
+
244
+ Ds = compute_distances(txs, tys, 0*txs)
245
+
246
+ xs = txs[0]*DPTS1 + txs[1]*DPTS2 + txs[2]*DPTS3
247
+ ys = tys[0]*DPTS1 + tys[1]*DPTS2 + tys[2]*DPTS3
248
+
249
+ cs = np.empty((2,xs.shape[0]), dtype=np.float64)
250
+ cs[0,:] = xs
251
+ cs[1,:] = ys
252
+
253
+ aas, bbs, ccs, Area = tri_coefficients(txs, tys)
254
+
255
+ coeff = np.empty((3,3), dtype=np.float64)
256
+ coeff[0,:] = aas/(2*Area)
257
+ coeff[1,:] = bbs/(2*Area)
258
+ coeff[2,:] = ccs/(2*Area)
259
+
260
+ Msz = Ms[2,2]
261
+ Mmz = Mm[2,2]
262
+ Ms = Ms[:2,:2]
263
+ Mm = Mm[:2,:2]
264
+
265
+ fid = np.array([0,1,2], dtype=np.int64)
266
+
267
+ Ls[3,:] *= Ds[0,2]
268
+ Ls[7,:] *= Ds[0,1]
269
+ Ls[:,3] *= Ds[0,2]
270
+ Ls[:,7] *= Ds[0,1]
271
+
272
+ for iv1 in range(3):
273
+ ie1 = local_edge_map[:, iv1]
274
+
275
+ Le = Ds[ie1[0], ie1[1]]
276
+ Ls[iv1,:] *= Le
277
+ Ls[:,iv1] *= Le
278
+ Ls[iv1+4,:] *= Le
279
+ Ls[:,iv1+4] *= Le
280
+ F1 = _ne1_curl(coeff[:,ie1], cs)
281
+ F2 = _ne2_curl(coeff[:,ie1], cs)
282
+ F3 = _ne1(coeff[:,ie1], cs)
283
+ F4 = _ne2(coeff[:,ie1], cs)
284
+ F5 = _lv_grad(coeff[:,iv1],cs)
285
+ F6 = _le_grad(coeff[:,ie1],cs)
286
+ for iv2 in range(3):
287
+ ei2 = local_edge_map[:, iv2]
288
+
289
+
290
+ Att[iv1,iv2] = _gqi(F1, Msz * _ne1_curl(coeff[:,ei2],cs), WEIGHTS)
291
+ Att[iv1+4,iv2] = _gqi(F2, Msz * _ne1_curl(coeff[:,ei2],cs), WEIGHTS)
292
+ Att[iv1,iv2+4] = _gqi(F1, Msz * _ne2_curl(coeff[:,ei2],cs), WEIGHTS)
293
+ Att[iv1+4,iv2+4] = _gqi(F2, Msz * _ne2_curl(coeff[:,ei2],cs), WEIGHTS)
294
+
295
+ Btt[iv1,iv2] = _gqi2(F3, matmul(Mm,_ne1(coeff[:,ei2],cs)), WEIGHTS)
296
+ Btt[iv1+4,iv2] = _gqi2(F4, matmul(Mm,_ne1(coeff[:,ei2],cs)), WEIGHTS)
297
+ Btt[iv1,iv2+4] = _gqi2(F3, matmul(Mm,_ne2(coeff[:,ei2],cs)), WEIGHTS)
298
+ Btt[iv1+4,iv2+4] = _gqi2(F4, matmul(Mm,_ne2(coeff[:,ei2],cs)), WEIGHTS)
299
+
300
+ Dtt[iv1,iv2] = _gqi2(F3, matmul(Ms,_ne1(coeff[:,ei2],cs)), WEIGHTS)
301
+ Dtt[iv1+4,iv2] = _gqi2(F4, matmul(Ms,_ne1(coeff[:,ei2],cs)), WEIGHTS)
302
+ Dtt[iv1,iv2+4] = _gqi2(F3, matmul(Ms,_ne2(coeff[:,ei2],cs)), WEIGHTS)
303
+ Dtt[iv1+4,iv2+4] = _gqi2(F4, matmul(Ms,_ne2(coeff[:,ei2],cs)), WEIGHTS)
304
+
305
+ Dzt[iv1, iv2] = _gqi2(F5, matmul(Ms,_ne1(coeff[:,ei2],cs)), WEIGHTS)
306
+ Dzt[iv1+3, iv2] = _gqi2(F6, matmul(Ms,_ne1(coeff[:,ei2],cs)), WEIGHTS)
307
+ Dzt[iv1, iv2+4] = _gqi2(F5, matmul(Ms,_ne2(coeff[:,ei2],cs)), WEIGHTS)
308
+ Dzt[iv1+3, iv2+4] = _gqi2(F6, matmul(Ms,_ne2(coeff[:,ei2],cs)), WEIGHTS)
309
+
310
+ Dzz1[iv1, iv2] = _gqi2(_lv_grad(coeff[:,iv1], cs), matmul(Ms,_lv_grad(coeff[:,iv2],cs)), WEIGHTS)
311
+ Dzz1[iv1, iv2+3] = _gqi2(_lv_grad(coeff[:,iv1], cs), matmul(Ms,_le_grad(coeff[:,ei2],cs)), WEIGHTS)
312
+ Dzz1[iv1+3, iv2] = _gqi2(_le_grad(coeff[:,ie1], cs), matmul(Ms,_lv_grad(coeff[:,iv2],cs)), WEIGHTS)
313
+ Dzz1[iv1+3, iv2+3] = _gqi2(_le_grad(coeff[:,ie1], cs), matmul(Ms,_le_grad(coeff[:,ei2],cs)), WEIGHTS)
314
+
315
+ Dzz2[iv1, iv2] = _gqi(_lv(coeff[:,iv1], cs), Mmz * _lv(coeff[:,iv2],cs), WEIGHTS)
316
+ Dzz2[iv1, iv2+3] = _gqi(_lv(coeff[:,iv1], cs), Mmz * _le(coeff[:,ei2],cs), WEIGHTS)
317
+ Dzz2[iv1+3, iv2] = _gqi(_le(coeff[:,ie1], cs), Mmz * _lv(coeff[:,iv2],cs), WEIGHTS)
318
+ Dzz2[iv1+3, iv2+3] = _gqi(_le(coeff[:,ie1], cs), Mmz * _le(coeff[:,ei2],cs), WEIGHTS)
319
+
320
+
321
+ G1 = matmul(Mm,_nf1(coeff,cs))
322
+ G2 = matmul(Mm,_nf2(coeff,cs))
323
+ G3 = matmul(Ms,_nf1(coeff,cs))
324
+ G4 = matmul(Ms,_nf2(coeff,cs))
325
+ Att[iv1,3] = _gqi(F1, Msz * _nf1_curl(coeff,cs), WEIGHTS)
326
+ Att[iv1+4,3] = _gqi(_ne2_curl(coeff[:,ie1], cs), Msz * _nf1_curl(coeff,cs), WEIGHTS)
327
+ Att[iv1,7] = _gqi(F1, Msz * _nf2_curl(coeff,cs), WEIGHTS)
328
+ Att[iv1+4,7] = _gqi(_ne2_curl(coeff[:,ie1], cs), Msz * _nf2_curl(coeff,cs), WEIGHTS)
329
+
330
+ Att[3, iv1] = Att[iv1,3]
331
+ Att[7, iv1] = Att[iv1,7]
332
+ Att[3, iv1+4] = Att[iv1+4,3]
333
+ Att[7, iv1+4] = Att[iv1+4,7]
334
+
335
+ Btt[iv1,3] = _gqi2(F3, G1, WEIGHTS)
336
+ Btt[iv1+4,3] = _gqi2(F4, G1, WEIGHTS)
337
+ Btt[iv1,7] = _gqi2(F3, G2, WEIGHTS)
338
+ Btt[iv1+4,7] = _gqi2(F4, G2, WEIGHTS)
339
+
340
+ Btt[3, iv1] = Btt[iv1,3]
341
+ Btt[7, iv1] = Btt[iv1,7]
342
+ Btt[3, iv1+4] = Btt[iv1+4,3]
343
+ Btt[7, iv1+4] = Btt[iv1+4,7]
344
+
345
+ Dtt[iv1,3] = _gqi2(F3, G3, WEIGHTS)
346
+ Dtt[iv1+4,3] = _gqi2(F4, G3, WEIGHTS)
347
+ Dtt[iv1,7] = _gqi2(F3, G4, WEIGHTS)
348
+ Dtt[iv1+4,7] = _gqi2(F4, G4, WEIGHTS)
349
+
350
+ Dtt[3, iv1] = Dtt[iv1,3]
351
+ Dtt[7, iv1] = Dtt[iv1,7]
352
+ Dtt[3, iv1+4] = Dtt[iv1+4,3]
353
+ Dtt[7, iv1+4] = Dtt[iv1+4,7]
354
+
355
+ Dzt[iv1, 3] = _gqi2(F5, G3, WEIGHTS)
356
+ Dzt[iv1, 7] = _gqi2(F5, G4, WEIGHTS)
357
+ Dzt[iv1+3, 3] = _gqi2(F6, G3, WEIGHTS)
358
+ Dzt[iv1+3, 7] = _gqi2(F6, G4, WEIGHTS)
359
+
360
+ Att[3,3] = _gqi(_nf1_curl(coeff, cs), Msz * _nf1_curl(coeff,cs), WEIGHTS)
361
+ Att[7,3] = _gqi(_nf2_curl(coeff, cs), Msz * _nf1_curl(coeff,cs), WEIGHTS)
362
+ Att[3,7] = _gqi(_nf1_curl(coeff, cs), Msz * _nf2_curl(coeff,cs), WEIGHTS)
363
+ Att[7,7] = _gqi(_nf2_curl(coeff, cs), Msz * _nf2_curl(coeff,cs), WEIGHTS)
364
+
365
+ Btt[3,3] = _gqi2(_nf1(coeff, cs), G1, WEIGHTS)
366
+ Btt[7,3] = _gqi2(_nf2(coeff, cs), G1, WEIGHTS)
367
+ Btt[3,7] = _gqi2(_nf1(coeff, cs), G2, WEIGHTS)
368
+ Btt[7,7] = _gqi2(_nf2(coeff, cs), G2, WEIGHTS)
369
+
370
+ A = np.zeros((14, 14), dtype = np.complex128)
371
+ B = np.zeros((14, 14), dtype = np.complex128)
372
+
373
+ A[:8,:8] = (Att - k0**2 * Btt)
374
+
375
+ B[:8,:8] = Dtt
376
+ B[8:,:8] = Dzt
377
+ B[:8,8:] = Dzt.T
378
+ B[8:,8:] = Dzz1 - k0**2 * Dzz2
379
+
380
+ B = Ls*B*np.abs(Area)
381
+ A = Ls*A*np.abs(Area)
382
+ return A, B
383
+
384
+
385
+ @njit(types.Tuple((c16[:], c16[:], i8[:], i8[:]))(f8[:,:],
386
+ i8[:,:],
387
+ i8[:,:],
388
+ i8[:,:],
389
+ c16[:,:,:],
390
+ c16[:,:,:],
391
+ f8,
392
+ ProgressBarType), cache=True, nogil=True, parallel=True)
393
+ def _matrix_builder(nodes, tris, edges, tri_to_field, ur, er, k0, pgb: ProgressBar):
394
+
395
+ ntritot = tris.shape[1]
396
+ nnz = ntritot*196
397
+
398
+ rows = np.zeros(nnz, dtype=np.int64)
399
+ cols = np.zeros(nnz, dtype=np.int64)
400
+ dataE = np.zeros_like(rows, dtype=np.complex128)
401
+ dataB = np.zeros_like(rows, dtype=np.complex128)
402
+
403
+ tri_to_edge = tri_to_field[:3,:]
404
+
405
+ for itri in prange(ntritot):
406
+ p = itri*196
407
+ if np.mod(itri,10)==0:
408
+ pgb.update(10)
409
+ urt = ur[:,:,itri]
410
+ ert = er[:,:,itri]
411
+
412
+ # Construct a local mapping to global triangle orientations
413
+ local_tri_map = local_tri_to_edgeid(itri, tris, edges, tri_to_edge)
414
+
415
+ # Construct the local edge map
416
+ tri_nodes = nodes[:, tris[:,itri]]
417
+ Esub, Bsub = generalized_matrix_GQ(tri_nodes,local_tri_map, matinv(urt), ert, k0)
418
+
419
+ indices = tri_to_field[:, itri]
420
+ for ii in range(14):
421
+ rows[p+14*ii:p+14*(ii+1)] = indices[ii]
422
+ cols[p+ii:p+ii+196:14] = indices[ii]
423
+
424
+ dataE[p:p+196] = Esub.ravel()
425
+ dataB[p:p+196] = Bsub.ravel()
426
+ return dataE, dataB, rows, cols