emerge 0.5.2__py3-none-any.whl → 0.5.4__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 +2 -2
- emerge/_emerge/__init__.py +1 -26
- emerge/_emerge/_cache_check.py +46 -0
- emerge/_emerge/bc.py +3 -12
- emerge/_emerge/const.py +5 -0
- emerge/_emerge/elements/nedleg2.py +2 -2
- emerge/_emerge/geo/pcb.py +110 -13
- emerge/_emerge/geo/pcb_tools/calculator.py +2 -2
- emerge/_emerge/geometry.py +1 -1
- emerge/_emerge/logsettings.py +29 -13
- emerge/_emerge/material.py +4 -0
- emerge/_emerge/mesh3d.py +9 -9
- emerge/_emerge/mth/integrals.py +1 -1
- emerge/_emerge/mth/pairing.py +1 -2
- emerge/_emerge/periodic.py +1 -1
- emerge/_emerge/physics/microwave/adaptive_freq.py +1 -5
- emerge/_emerge/physics/microwave/assembly/assembler.py +62 -39
- emerge/_emerge/physics/microwave/assembly/curlcurl.py +1 -8
- emerge/_emerge/physics/microwave/microwave_3d.py +33 -26
- emerge/_emerge/physics/microwave/microwave_bc.py +97 -27
- emerge/_emerge/physics/microwave/microwave_data.py +3 -5
- emerge/_emerge/physics/microwave/sc.py +26 -26
- emerge/_emerge/physics/microwave/simjob.py +8 -3
- emerge/_emerge/selection.py +1 -1
- emerge/_emerge/simmodel.py +12 -9
- emerge/_emerge/simulation_data.py +5 -1
- emerge/_emerge/solve_interfaces/cudss_interface.py +238 -0
- emerge/_emerge/solver.py +285 -107
- emerge/cli.py +1 -1
- emerge/lib.py +54 -40
- {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/METADATA +15 -8
- {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/RECORD +35 -32
- {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/licenses/LICENSE +39 -0
- {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/WHEEL +0 -0
- {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/entry_points.txt +0 -0
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
# <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
18
|
import numpy as np
|
|
19
|
-
from ..microwave_bc import PEC, BoundaryCondition, RectangularWaveguide, RobinBC, PortBC, Periodic
|
|
19
|
+
from ..microwave_bc import PEC, BoundaryCondition, RectangularWaveguide, RobinBC, PortBC, Periodic, MWBoundaryConditionSet
|
|
20
20
|
from ....elements.nedelec2 import Nedelec2
|
|
21
21
|
from ....elements.nedleg2 import NedelecLegrange2
|
|
22
22
|
from ....mth.optimized import gaus_quad_tri
|
|
@@ -26,14 +26,7 @@ from scipy.sparse import csr_matrix
|
|
|
26
26
|
from loguru import logger
|
|
27
27
|
from ..simjob import SimJob
|
|
28
28
|
from .periodicbc import gen_periodic_matrix
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
############################################################
|
|
32
|
-
# CONSTANTS #
|
|
33
|
-
############################################################
|
|
34
|
-
|
|
35
|
-
C0 = 299792458
|
|
36
|
-
EPS0 = 8.854187818814e-12
|
|
29
|
+
from ....const import MU0, EPS0, C0
|
|
37
30
|
|
|
38
31
|
|
|
39
32
|
############################################################
|
|
@@ -124,7 +117,7 @@ class Assembler:
|
|
|
124
117
|
sig: np.ndarray,
|
|
125
118
|
k0: float,
|
|
126
119
|
port: PortBC,
|
|
127
|
-
|
|
120
|
+
bc_set: MWBoundaryConditionSet) -> tuple[csr_matrix, csr_matrix, np.ndarray, NedelecLegrange2]:
|
|
128
121
|
"""Computes the boundary mode analysis matrices
|
|
129
122
|
|
|
130
123
|
Args:
|
|
@@ -134,32 +127,37 @@ class Assembler:
|
|
|
134
127
|
sig (np.ndarray): The conductivity scalar of shape (N,)
|
|
135
128
|
k0 (float): The simulation phase constant
|
|
136
129
|
port (PortBC): The port boundary condition object
|
|
137
|
-
bcs (
|
|
130
|
+
bcs (MWBoundaryConditionSet): The other boundary conditions
|
|
138
131
|
|
|
139
132
|
Returns:
|
|
140
133
|
tuple[np.ndarray, np.ndarray, np.ndarray, NedelecLegrange2]: The E, B, solve ids and Mixed order field object.
|
|
141
134
|
"""
|
|
142
135
|
from .generalized_eigen import generelized_eigenvalue_matrix
|
|
143
|
-
|
|
136
|
+
logger.debug('Assembling Boundary Mode Matrices')
|
|
137
|
+
|
|
138
|
+
bcs = bc_set.boundary_conditions
|
|
144
139
|
mesh = field.mesh
|
|
145
140
|
tri_ids = mesh.get_triangles(port.tags)
|
|
141
|
+
logger.trace(f'.boundary face has {len(tri_ids)} triangles.')
|
|
146
142
|
|
|
147
143
|
origin = tuple([c-n for c,n in zip(port.cs.origin, port.cs.gzhat)])
|
|
148
|
-
|
|
144
|
+
logger.trace(f'.boundary origin {origin}')
|
|
145
|
+
|
|
149
146
|
boundary_surface = mesh.boundary_surface(port.tags, origin)
|
|
150
147
|
nedlegfield = NedelecLegrange2(boundary_surface, port.cs)
|
|
151
148
|
|
|
152
149
|
ermesh = er[:,:,tri_ids]
|
|
153
150
|
urmesh = ur[:,:,tri_ids]
|
|
154
151
|
sigmesh = sig[tri_ids]
|
|
155
|
-
|
|
156
152
|
ermesh = ermesh - 1j * sigmesh/(k0*C0*EPS0)
|
|
157
153
|
|
|
154
|
+
logger.trace(f'.assembling matrices for {nedlegfield} at k0={k0:.2f}')
|
|
158
155
|
E, B = generelized_eigenvalue_matrix(nedlegfield, ermesh, urmesh, port.cs._basis, k0)
|
|
159
156
|
|
|
160
|
-
|
|
157
|
+
# TODO: Simplified to all "conductors" loosely defined. Must change to implementing line robin boundary conditions.
|
|
158
|
+
pecs: list[BoundaryCondition] = bc_set.get_conductors()#[bc for bc in bcs if isinstance(bc,PEC)]
|
|
161
159
|
if len(pecs) > 0:
|
|
162
|
-
logger.debug('
|
|
160
|
+
logger.debug(f'.total of equiv. {len(pecs)} PEC BCs implemented')
|
|
163
161
|
|
|
164
162
|
pec_ids = []
|
|
165
163
|
|
|
@@ -172,8 +170,8 @@ class Assembler:
|
|
|
172
170
|
pec_edges = []
|
|
173
171
|
pec_vertices = []
|
|
174
172
|
for pec in pecs:
|
|
173
|
+
logger.trace(f'.implementing {pec}')
|
|
175
174
|
face_tags = pec.tags
|
|
176
|
-
|
|
177
175
|
tri_ids = mesh.get_triangles(face_tags)
|
|
178
176
|
edge_ids = list(mesh.tri_to_edge[:,tri_ids].flatten())
|
|
179
177
|
for ii in edge_ids:
|
|
@@ -186,7 +184,6 @@ class Assembler:
|
|
|
186
184
|
pec_vertices.append(eids[3]-nedlegfield.n_xy)
|
|
187
185
|
pec_vertices.append(eids[4]-nedlegfield.n_xy)
|
|
188
186
|
|
|
189
|
-
|
|
190
187
|
for ii in tri_ids:
|
|
191
188
|
i2 = nedlegfield.mesh.from_source_tri(ii)
|
|
192
189
|
if i2 is None:
|
|
@@ -196,6 +193,8 @@ class Assembler:
|
|
|
196
193
|
|
|
197
194
|
# Process all port boundary Conditions
|
|
198
195
|
pec_ids_set: set[int] = set(pec_ids)
|
|
196
|
+
|
|
197
|
+
logger.trace(f'.total of {len(pec_ids_set)} pec DoF to remove.')
|
|
199
198
|
solve_ids = [i for i in range(nedlegfield.n_field) if i not in pec_ids_set]
|
|
200
199
|
|
|
201
200
|
return E, B, np.array(solve_ids), nedlegfield
|
|
@@ -236,11 +235,11 @@ class Assembler:
|
|
|
236
235
|
|
|
237
236
|
if cache_matrices and not is_frequency_dependent and self.cached_matrices is not None:
|
|
238
237
|
# IF CACHED AND AVAILABLE PULL E AND B FROM CACHE
|
|
239
|
-
logger.debug('
|
|
238
|
+
logger.debug('Using cached matricies.')
|
|
240
239
|
E, B = self.cached_matrices
|
|
241
240
|
else:
|
|
242
241
|
# OTHERWISE, COMPUTE
|
|
243
|
-
logger.debug('
|
|
242
|
+
logger.debug('Assembling matrices')
|
|
244
243
|
E, B = tet_mass_stiffness_matrices(field, er, ur)
|
|
245
244
|
self.cached_matrices = (E, B)
|
|
246
245
|
|
|
@@ -259,15 +258,24 @@ class Assembler:
|
|
|
259
258
|
b = np.zeros((E.shape[0],)).astype(np.complex128)
|
|
260
259
|
port_vectors = {port.port_number: np.zeros((E.shape[0],)).astype(np.complex128) for port in port_bcs}
|
|
261
260
|
|
|
262
|
-
|
|
263
|
-
|
|
261
|
+
|
|
262
|
+
############################################################
|
|
263
|
+
# PEC BOUNDARY CONDITIONS #
|
|
264
|
+
############################################################
|
|
265
|
+
|
|
266
|
+
logger.debug('Implementing PEC Boundary Conditions.')
|
|
264
267
|
pec_ids: list[int] = []
|
|
265
268
|
# Conductivity above al imit, consider it all PEC
|
|
269
|
+
ipec = 0
|
|
266
270
|
for itet in range(field.n_tets):
|
|
267
271
|
if sig[itet] > self.conductivity_limit:
|
|
272
|
+
ipec+=1
|
|
268
273
|
pec_ids.extend(field.tet_to_field[:,itet])
|
|
269
|
-
|
|
274
|
+
if ipec>0:
|
|
275
|
+
logger.trace(f'Extended PEC with {ipec} tets with a conductivity > {self.conductivity_limit}.')
|
|
276
|
+
|
|
270
277
|
for pec in pec_bcs:
|
|
278
|
+
logger.trace(f'Implementing: {pec}')
|
|
271
279
|
if len(pec.tags)==0:
|
|
272
280
|
continue
|
|
273
281
|
face_tags = pec.tags
|
|
@@ -282,14 +290,18 @@ class Assembler:
|
|
|
282
290
|
tids = field.tri_to_field[:, ii]
|
|
283
291
|
pec_ids.extend(list(tids))
|
|
284
292
|
|
|
285
|
-
|
|
293
|
+
|
|
294
|
+
############################################################
|
|
295
|
+
# ROBIN BOUNDARY CONDITIONS #
|
|
296
|
+
############################################################
|
|
297
|
+
|
|
286
298
|
if len(robin_bcs) > 0:
|
|
287
|
-
logger.debug('
|
|
299
|
+
logger.debug('Implementing Robin Boundary Conditions.')
|
|
288
300
|
|
|
289
301
|
gauss_points = gaus_quad_tri(4)
|
|
290
302
|
Bempty = field.empty_tri_matrix()
|
|
291
303
|
for bc in robin_bcs:
|
|
292
|
-
|
|
304
|
+
logger.trace(f'.Implementing {bc}')
|
|
293
305
|
for tag in bc.tags:
|
|
294
306
|
face_tags = [tag,]
|
|
295
307
|
|
|
@@ -298,6 +310,7 @@ class Assembler:
|
|
|
298
310
|
edge_ids = list(mesh.tri_to_edge[:,tri_ids].flatten())
|
|
299
311
|
|
|
300
312
|
gamma = bc.get_gamma(K0)
|
|
313
|
+
logger.trace(f'..robin bc γ={gamma:.3f}')
|
|
301
314
|
|
|
302
315
|
def Ufunc(x,y):
|
|
303
316
|
return bc.get_Uinc(x,y,K0)
|
|
@@ -306,38 +319,42 @@ class Assembler:
|
|
|
306
319
|
if ibasis is None:
|
|
307
320
|
basis = plane_basis_from_points(mesh.nodes[:,nodes]) + 1e-16
|
|
308
321
|
ibasis = np.linalg.pinv(basis)
|
|
322
|
+
logger.trace(f'..Using computed basis: {ibasis.flatten()}')
|
|
309
323
|
if bc._include_force:
|
|
310
|
-
|
|
311
324
|
Bempty, b_p = assemble_robin_bc_excited(field, Bempty, tri_ids, Ufunc, gamma, ibasis, bc.cs.origin, gauss_points) # type: ignore
|
|
312
|
-
|
|
313
325
|
port_vectors[bc.port_number] += b_p # type: ignore
|
|
314
|
-
|
|
326
|
+
logger.trace(f'..included force vector term with norm {np.linalg.norm(b_p):.3f}')
|
|
315
327
|
else:
|
|
316
328
|
Bempty = assemble_robin_bc(field, Bempty, tri_ids, gamma) # type: ignore
|
|
317
329
|
B_p = field.generate_csr(Bempty)
|
|
318
330
|
K = K + B_p
|
|
319
331
|
|
|
320
332
|
if len(periodic_bcs) > 0:
|
|
321
|
-
logger.debug('
|
|
333
|
+
logger.debug('Implementing Periodic Boundary Conditions.')
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
############################################################
|
|
337
|
+
# PERIODIC BOUNDARY CONDITIONS #
|
|
338
|
+
############################################################
|
|
322
339
|
|
|
323
|
-
|
|
324
|
-
# Periodic BCs
|
|
325
340
|
Pmats = []
|
|
326
341
|
remove: set[int] = set()
|
|
327
342
|
has_periodic = False
|
|
328
343
|
|
|
329
344
|
for pbc in periodic_bcs:
|
|
345
|
+
logger.trace(f'.Implementing {pbc}')
|
|
330
346
|
has_periodic = True
|
|
331
347
|
tri_ids_1 = mesh.get_triangles(pbc.face1.tags)
|
|
332
348
|
edge_ids_1 = mesh.get_edges(pbc.face1.tags)
|
|
333
349
|
tri_ids_2 = mesh.get_triangles(pbc.face2.tags)
|
|
334
350
|
edge_ids_2 = mesh.get_edges(pbc.face2.tags)
|
|
335
351
|
dv = np.array(pbc.dv)
|
|
352
|
+
logger.trace(f'..displacement vector {dv}')
|
|
336
353
|
linked_tris = pair_coordinates(mesh.tri_centers, tri_ids_1, tri_ids_2, dv, 1e-9)
|
|
337
354
|
linked_edges = pair_coordinates(mesh.edge_centers, edge_ids_1, edge_ids_2, dv, 1e-9)
|
|
338
355
|
dv = np.array(pbc.dv)
|
|
339
356
|
phi = pbc.phi(K0)
|
|
340
|
-
|
|
357
|
+
logger.trace(f'..ϕ={phi} rad/m')
|
|
341
358
|
Pmat, rows = gen_periodic_matrix(tri_ids_1,
|
|
342
359
|
edge_ids_1,
|
|
343
360
|
field.tri_to_field,
|
|
@@ -348,8 +365,9 @@ class Assembler:
|
|
|
348
365
|
phi)
|
|
349
366
|
remove.update(rows)
|
|
350
367
|
Pmats.append(Pmat)
|
|
351
|
-
|
|
368
|
+
|
|
352
369
|
if Pmats:
|
|
370
|
+
logger.trace(f'.periodic bc removes {len(remove)} boundary DoF')
|
|
353
371
|
Pmat = Pmats[0]
|
|
354
372
|
for P2 in Pmats[1:]:
|
|
355
373
|
Pmat = Pmat @ P2
|
|
@@ -360,6 +378,11 @@ class Assembler:
|
|
|
360
378
|
else:
|
|
361
379
|
Pmat = None
|
|
362
380
|
|
|
381
|
+
|
|
382
|
+
############################################################
|
|
383
|
+
# FINALIZE #
|
|
384
|
+
############################################################
|
|
385
|
+
|
|
363
386
|
pec_ids_set = set(pec_ids)
|
|
364
387
|
solve_ids = np.array([i for i in range(E.shape[0]) if i not in pec_ids_set])
|
|
365
388
|
|
|
@@ -416,7 +439,7 @@ class Assembler:
|
|
|
416
439
|
|
|
417
440
|
er = er - 1j*sig/(w0*EPS0)*np.repeat(np.eye(3)[:, :, np.newaxis], er.shape[2], axis=2)
|
|
418
441
|
|
|
419
|
-
logger.debug('
|
|
442
|
+
logger.debug('Assembling matrices')
|
|
420
443
|
E, B = tet_mass_stiffness_matrices(field, er, ur)
|
|
421
444
|
self.cached_matrices = (E, B)
|
|
422
445
|
|
|
@@ -429,7 +452,7 @@ class Assembler:
|
|
|
429
452
|
# Process all PEC Boundary Conditions
|
|
430
453
|
pec_ids: list = []
|
|
431
454
|
|
|
432
|
-
logger.debug('
|
|
455
|
+
logger.debug('Implementing PEC Boundary Conditions.')
|
|
433
456
|
|
|
434
457
|
# Conductivity above a limit, consider it all PEC
|
|
435
458
|
for itet in range(field.n_tets):
|
|
@@ -454,10 +477,10 @@ class Assembler:
|
|
|
454
477
|
|
|
455
478
|
# Robin BCs
|
|
456
479
|
if len(robin_bcs) > 0:
|
|
457
|
-
logger.debug('
|
|
480
|
+
logger.debug('Implementing Robin Boundary Conditions.')
|
|
458
481
|
|
|
459
482
|
if len(robin_bcs) > 0:
|
|
460
|
-
logger.debug('
|
|
483
|
+
logger.debug('Implementing Robin Boundary Conditions.')
|
|
461
484
|
|
|
462
485
|
gauss_points = gaus_quad_tri(4)
|
|
463
486
|
Bempty = field.empty_tri_matrix()
|
|
@@ -482,7 +505,7 @@ class Assembler:
|
|
|
482
505
|
B = B + B_p
|
|
483
506
|
|
|
484
507
|
if len(periodic) > 0:
|
|
485
|
-
logger.debug('
|
|
508
|
+
logger.debug('Implementing Periodic Boundary Conditions.')
|
|
486
509
|
|
|
487
510
|
# Periodic BCs
|
|
488
511
|
Pmats = []
|
|
@@ -22,16 +22,12 @@ from numba_progress import ProgressBar, ProgressBarType
|
|
|
22
22
|
from ....mth.optimized import local_mapping, matinv, dot_c, cross_c, compute_distances
|
|
23
23
|
from numba import c16, types, f8, i8, njit, prange
|
|
24
24
|
|
|
25
|
-
|
|
26
25
|
############################################################
|
|
27
26
|
# CACHED FACTORIAL VALUES #
|
|
28
27
|
############################################################
|
|
29
28
|
|
|
30
|
-
|
|
31
29
|
_FACTORIALS = np.array([1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880], dtype=np.int64)
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
35
31
|
############################################################
|
|
36
32
|
# INDEX MAPPING FUNCTIONS #
|
|
37
33
|
############################################################
|
|
@@ -264,7 +260,6 @@ def ned2_tet_stiff_mass(tet_vertices, edge_lengths, local_edge_map, local_tri_ma
|
|
|
264
260
|
Dmat[ei+0,ej+10] = Q*VAD
|
|
265
261
|
Dmat[ei+10,ej+0] = Q*VBC
|
|
266
262
|
Dmat[ei+10,ej+10] = Q*VBD
|
|
267
|
-
|
|
268
263
|
|
|
269
264
|
Fmat[ei+0,ej+0] = Q2*(VABCD*BD1-VABCC*BE1-VAACD*BF1+VAACC*BG1)
|
|
270
265
|
Fmat[ei+0,ej+10] = Q2*(VABDD*BD1-VABCD*BE1-VAADD*BF1+VAACD*BG1)
|
|
@@ -313,7 +308,6 @@ def ned2_tet_stiff_mass(tet_vertices, edge_lengths, local_edge_map, local_tri_ma
|
|
|
313
308
|
BH1 = dot_c(GB,BC1)
|
|
314
309
|
BI1 = dot_c(GA,BD1)
|
|
315
310
|
BJ1 = dot_c(GB,BD1)
|
|
316
|
-
|
|
317
311
|
|
|
318
312
|
Dmat[ei+0,ej+6] = L1*Lac2*(-6*VAD*AI1-3*VAC*AJ1-3*VAF*AK1)
|
|
319
313
|
Dmat[ei+0,ej+16] = L1*Lab2*(6*VAF*AK1+3*VAD*AI1-3*VAC*AJ1)
|
|
@@ -372,7 +366,6 @@ def ned2_tet_stiff_mass(tet_vertices, edge_lengths, local_edge_map, local_tri_ma
|
|
|
372
366
|
VBCEF = VOLUME_COEFF_CACHE[B,E,F,C]
|
|
373
367
|
VADEF = VOLUME_COEFF_CACHE[E,A,D,F]
|
|
374
368
|
|
|
375
|
-
|
|
376
369
|
Lac2 = Ds[ej1, fj]
|
|
377
370
|
Lab2 = Ds[ej1, ej2]
|
|
378
371
|
|
|
@@ -447,7 +440,7 @@ def _matrix_builder(nodes, tets, tris, edges, all_edge_lengths, tet_to_field, te
|
|
|
447
440
|
dataB = np.empty_like(rows, dtype=np.complex128)
|
|
448
441
|
|
|
449
442
|
|
|
450
|
-
for itet in prange(nT):
|
|
443
|
+
for itet in prange(nT): # ty: ignore
|
|
451
444
|
p = itet*400
|
|
452
445
|
if np.mod(itet,10)==0:
|
|
453
446
|
pgb.update(10)
|
|
@@ -24,21 +24,22 @@ 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 scipy.sparse.linalg import inv as sparse_inverse # type: ignore
|
|
28
27
|
from .microwave_bc import MWBoundaryConditionSet, PEC, ModalPort, LumpedPort, PortBC
|
|
29
28
|
from .microwave_data import MWData
|
|
30
29
|
from .assembly.assembler import Assembler
|
|
31
30
|
from .port_functions import compute_avg_power_flux
|
|
32
31
|
from .simjob import SimJob
|
|
32
|
+
|
|
33
33
|
from concurrent.futures import ThreadPoolExecutor
|
|
34
|
-
import numpy as np
|
|
35
34
|
from loguru import logger
|
|
36
35
|
from typing import Callable, Literal
|
|
37
|
-
import time
|
|
38
|
-
import threading
|
|
39
36
|
import multiprocessing as mp
|
|
40
37
|
from cmath import sqrt as csqrt
|
|
41
38
|
|
|
39
|
+
import numpy as np
|
|
40
|
+
import threading
|
|
41
|
+
import time
|
|
42
|
+
|
|
42
43
|
class SimulationError(Exception):
|
|
43
44
|
pass
|
|
44
45
|
|
|
@@ -51,9 +52,10 @@ def run_job_multi(job: SimJob) -> SimJob:
|
|
|
51
52
|
Returns:
|
|
52
53
|
SimJob: The solved SimJob
|
|
53
54
|
"""
|
|
54
|
-
routine = DEFAULT_ROUTINE.duplicate().
|
|
55
|
-
for A, b, ids, reuse in job.iter_Ab():
|
|
55
|
+
routine = DEFAULT_ROUTINE.duplicate()._configure_routine('MP')
|
|
56
|
+
for A, b, ids, reuse, aux in job.iter_Ab():
|
|
56
57
|
solution, report = routine.solve(A, b, ids, reuse, id=job.id)
|
|
58
|
+
report.add(**aux)
|
|
57
59
|
job.submit_solution(solution, report)
|
|
58
60
|
return job
|
|
59
61
|
|
|
@@ -117,7 +119,6 @@ class Microwave3D:
|
|
|
117
119
|
self.bc: MWBoundaryConditionSet = MWBoundaryConditionSet(None)
|
|
118
120
|
self.basis: Nedelec2 | None = None
|
|
119
121
|
self.solveroutine: SolveRoutine = DEFAULT_ROUTINE
|
|
120
|
-
self.set_order(order)
|
|
121
122
|
self.cache_matrices: bool = True
|
|
122
123
|
|
|
123
124
|
## States
|
|
@@ -129,6 +130,8 @@ class Microwave3D:
|
|
|
129
130
|
self._simstart: float = 0.0
|
|
130
131
|
self._simend: float = 0.0
|
|
131
132
|
|
|
133
|
+
self.set_order(order)
|
|
134
|
+
|
|
132
135
|
def reset_data(self):
|
|
133
136
|
self.data = MWData()
|
|
134
137
|
|
|
@@ -352,7 +355,7 @@ class Microwave3D:
|
|
|
352
355
|
raise ValueError('The field basis is not yet defined.')
|
|
353
356
|
|
|
354
357
|
logger.debug('Finding PEC TEM conductors')
|
|
355
|
-
pecs: list[PEC] = self.bc.
|
|
358
|
+
pecs: list[PEC] = self.bc.get_conductors() # type: ignore
|
|
356
359
|
mesh = self.mesh
|
|
357
360
|
|
|
358
361
|
# Process all PEC Boundary Conditions
|
|
@@ -472,13 +475,10 @@ class Microwave3D:
|
|
|
472
475
|
if freq is None:
|
|
473
476
|
freq = self.frequencies[0]
|
|
474
477
|
|
|
475
|
-
|
|
476
478
|
k0 = 2*np.pi*freq/299792458
|
|
477
479
|
kmax = k0*np.sqrt(ermax.real*urmax.real)
|
|
478
|
-
|
|
479
|
-
logger.info('Assembling BMA Matrices')
|
|
480
480
|
|
|
481
|
-
Amatrix, Bmatrix, solve_ids, nlf = self.assembler.assemble_bma_matrices(self.basis, er, ur, cond, k0, port, self.bc
|
|
481
|
+
Amatrix, Bmatrix, solve_ids, nlf = self.assembler.assemble_bma_matrices(self.basis, er, ur, cond, k0, port, self.bc)
|
|
482
482
|
|
|
483
483
|
logger.debug(f'Total of {Amatrix.shape[0]} Degrees of freedom.')
|
|
484
484
|
logger.debug(f'Applied frequency: {freq/1e9:.2f}GHz')
|
|
@@ -515,7 +515,7 @@ class Microwave3D:
|
|
|
515
515
|
Emode = Emode * np.exp(-1j*np.angle(np.max(Emode)))
|
|
516
516
|
|
|
517
517
|
beta = min(k0*np.sqrt(ermax*urmax), np.emath.sqrt(-eigen_values[i]))
|
|
518
|
-
|
|
518
|
+
|
|
519
519
|
residuals = -1
|
|
520
520
|
|
|
521
521
|
portfE = nlf.interpolate_Ef(Emode)
|
|
@@ -628,19 +628,21 @@ class Microwave3D:
|
|
|
628
628
|
## DEFINE SOLVE FUNCTIONS
|
|
629
629
|
def get_routine():
|
|
630
630
|
if not hasattr(thread_local, "routine"):
|
|
631
|
-
thread_local.routine = self.solveroutine.duplicate().
|
|
631
|
+
thread_local.routine = self.solveroutine.duplicate()._configure_routine('MT')
|
|
632
632
|
return thread_local.routine
|
|
633
633
|
|
|
634
634
|
def run_job(job: SimJob):
|
|
635
635
|
routine = get_routine()
|
|
636
|
-
for A, b, ids, reuse in job.iter_Ab():
|
|
636
|
+
for A, b, ids, reuse, aux in job.iter_Ab():
|
|
637
637
|
solution, report = routine.solve(A, b, ids, reuse, id=job.id)
|
|
638
|
+
report.add(**aux)
|
|
638
639
|
job.submit_solution(solution, report)
|
|
639
640
|
return job
|
|
640
641
|
|
|
641
642
|
def run_job_single(job: SimJob):
|
|
642
|
-
for A, b, ids, reuse in job.iter_Ab():
|
|
643
|
+
for A, b, ids, reuse, aux in job.iter_Ab():
|
|
643
644
|
solution, report = self.solveroutine.solve(A, b, ids, reuse, id=job.id)
|
|
645
|
+
report.add(**aux)
|
|
644
646
|
job.submit_solution(solution, report)
|
|
645
647
|
return job
|
|
646
648
|
|
|
@@ -753,6 +755,15 @@ class Microwave3D:
|
|
|
753
755
|
thread_local.__dict__.clear()
|
|
754
756
|
logger.info('Solving complete')
|
|
755
757
|
|
|
758
|
+
for freq, job in zip(self.frequencies, results):
|
|
759
|
+
self.data.setreport(job.reports, freq=freq, **self._params)
|
|
760
|
+
|
|
761
|
+
for variables, data in self.data.sim.iterate():
|
|
762
|
+
logger.trace(f'Sim variable: {variables}')
|
|
763
|
+
for item in data['report']:
|
|
764
|
+
item.pretty_print(logger.trace)
|
|
765
|
+
|
|
766
|
+
self.solveroutine.reset()
|
|
756
767
|
### Compute S-parameters and return
|
|
757
768
|
self._post_process(results, er, ur, cond)
|
|
758
769
|
return self.data
|
|
@@ -883,8 +894,6 @@ class Microwave3D:
|
|
|
883
894
|
fielddata._der = np.squeeze(er[0,0,:])
|
|
884
895
|
fielddata._dur = np.squeeze(ur[0,0,:])
|
|
885
896
|
|
|
886
|
-
self.data.setreport(job.reports, freq=freq, **self._params)
|
|
887
|
-
|
|
888
897
|
logger.info(f'Post Processing simulation frequency = {freq/1e9:.3f} GHz')
|
|
889
898
|
|
|
890
899
|
# Recording port information
|
|
@@ -915,20 +924,18 @@ class Microwave3D:
|
|
|
915
924
|
Pout = 0.0 + 0j
|
|
916
925
|
|
|
917
926
|
# Active port power
|
|
918
|
-
logger.debug('Active ports:')
|
|
919
927
|
tris = mesh.get_triangles(active_port.tags)
|
|
920
928
|
tri_vertices = mesh.tris[:,tris]
|
|
921
929
|
pfield, pmode = self._compute_s_data(active_port, fieldf, tri_vertices, k0, ertri[:,:,tris], urtri[:,:,tris])
|
|
922
|
-
logger.debug(f'
|
|
930
|
+
logger.debug(f'[{active_port.port_number}] Active port amplitude = {np.abs(pfield):.3f} (Excitation = {np.abs(pmode):.2f})')
|
|
923
931
|
Pout = pmode
|
|
924
932
|
|
|
925
933
|
#Passive ports
|
|
926
|
-
logger.debug('Passive ports:')
|
|
927
934
|
for bc in all_ports:
|
|
928
935
|
tris = mesh.get_triangles(bc.tags)
|
|
929
936
|
tri_vertices = mesh.tris[:,tris]
|
|
930
937
|
pfield, pmode = self._compute_s_data(bc, fieldf,tri_vertices, k0, ertri[:,:,tris], urtri[:,:,tris])
|
|
931
|
-
logger.debug(f'
|
|
938
|
+
logger.debug(f'[{bc.port_number}] Passive amplitude = {np.abs(pfield):.3f}')
|
|
932
939
|
scalardata.write_S(bc.port_number, active_port.port_number, pfield/Pout)
|
|
933
940
|
active_port.active=False
|
|
934
941
|
|
|
@@ -988,8 +995,8 @@ class Microwave3D:
|
|
|
988
995
|
elif bc.modetype(k0) == 'TM':
|
|
989
996
|
const = 1/((erp[0,0,:] + erp[1,1,:] + erp[2,2,:])/3)
|
|
990
997
|
const = np.squeeze(const)
|
|
991
|
-
field_p = sparam_field_power(self.mesh.nodes, tri_vertices, bc, k0, fieldfunction, const)
|
|
992
|
-
mode_p = sparam_mode_power(self.mesh.nodes, tri_vertices, bc, k0, const)
|
|
998
|
+
field_p = sparam_field_power(self.mesh.nodes, tri_vertices, bc, k0, fieldfunction, const, 5)
|
|
999
|
+
mode_p = sparam_mode_power(self.mesh.nodes, tri_vertices, bc, k0, const, 5)
|
|
993
1000
|
return field_p, mode_p
|
|
994
1001
|
|
|
995
1002
|
# def frequency_domain_single(self, automatic_modal_analysis: bool = False) -> MWData:
|
|
@@ -1099,7 +1106,7 @@ class Microwave3D:
|
|
|
1099
1106
|
# tris = mesh.get_triangles(active_port.tags)
|
|
1100
1107
|
# tri_vertices = mesh.tris[:,tris]
|
|
1101
1108
|
# pfield, pmode = self._compute_s_data(active_port, fieldf, tri_vertices, k0, ertri[:,:,tris], urtri[:,:,tris])
|
|
1102
|
-
# logger.debug(f'
|
|
1109
|
+
# logger.debug(f'Field Amplitude = {np.abs(pfield):.3f}, Excitation = {np.abs(pmode):.2f}')
|
|
1103
1110
|
# Pout = pmode
|
|
1104
1111
|
|
|
1105
1112
|
# #Passive ports
|
|
@@ -1108,7 +1115,7 @@ class Microwave3D:
|
|
|
1108
1115
|
# tris = mesh.get_triangles(bc.tags)
|
|
1109
1116
|
# tri_vertices = mesh.tris[:,tris]
|
|
1110
1117
|
# pfield, pmode = self._compute_s_data(bc, fieldf, tri_vertices, k0, ertri[:,:,tris], urtri[:,:,tris])
|
|
1111
|
-
# logger.debug(f'
|
|
1118
|
+
# logger.debug(f'Field amplitude = {np.abs(pfield):.3f}, Excitation= {np.abs(pmode):.2f}')
|
|
1112
1119
|
# scalardata.write_S(bc.port_number, active_port.port_number, pfield/Pout)
|
|
1113
1120
|
|
|
1114
1121
|
# active_port.active=False
|