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.

Files changed (35) hide show
  1. emerge/__init__.py +2 -2
  2. emerge/_emerge/__init__.py +1 -26
  3. emerge/_emerge/_cache_check.py +46 -0
  4. emerge/_emerge/bc.py +3 -12
  5. emerge/_emerge/const.py +5 -0
  6. emerge/_emerge/elements/nedleg2.py +2 -2
  7. emerge/_emerge/geo/pcb.py +110 -13
  8. emerge/_emerge/geo/pcb_tools/calculator.py +2 -2
  9. emerge/_emerge/geometry.py +1 -1
  10. emerge/_emerge/logsettings.py +29 -13
  11. emerge/_emerge/material.py +4 -0
  12. emerge/_emerge/mesh3d.py +9 -9
  13. emerge/_emerge/mth/integrals.py +1 -1
  14. emerge/_emerge/mth/pairing.py +1 -2
  15. emerge/_emerge/periodic.py +1 -1
  16. emerge/_emerge/physics/microwave/adaptive_freq.py +1 -5
  17. emerge/_emerge/physics/microwave/assembly/assembler.py +62 -39
  18. emerge/_emerge/physics/microwave/assembly/curlcurl.py +1 -8
  19. emerge/_emerge/physics/microwave/microwave_3d.py +33 -26
  20. emerge/_emerge/physics/microwave/microwave_bc.py +97 -27
  21. emerge/_emerge/physics/microwave/microwave_data.py +3 -5
  22. emerge/_emerge/physics/microwave/sc.py +26 -26
  23. emerge/_emerge/physics/microwave/simjob.py +8 -3
  24. emerge/_emerge/selection.py +1 -1
  25. emerge/_emerge/simmodel.py +12 -9
  26. emerge/_emerge/simulation_data.py +5 -1
  27. emerge/_emerge/solve_interfaces/cudss_interface.py +238 -0
  28. emerge/_emerge/solver.py +285 -107
  29. emerge/cli.py +1 -1
  30. emerge/lib.py +54 -40
  31. {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/METADATA +15 -8
  32. {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/RECORD +35 -32
  33. {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/licenses/LICENSE +39 -0
  34. {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/WHEEL +0 -0
  35. {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
- bcs: list[BoundaryCondition]) -> tuple[csr_matrix, csr_matrix, np.ndarray, NedelecLegrange2]:
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 (list[BoundaryCondition]): The other boundary conditions
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
- pecs: list[PEC] = [bc for bc in bcs if isinstance(bc,PEC)]
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('Implementing PEC BCs')
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(' Retreiving cached matricies')
238
+ logger.debug('Using cached matricies.')
240
239
  E, B = self.cached_matrices
241
240
  else:
242
241
  # OTHERWISE, COMPUTE
243
- logger.debug(' Assembling matrices')
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
- # Process all PEC Boundary Conditions
263
- logger.debug(' Implementing PEC Boundary Conditions.')
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
- # Robin BCs
293
+
294
+ ############################################################
295
+ # ROBIN BOUNDARY CONDITIONS #
296
+ ############################################################
297
+
286
298
  if len(robin_bcs) > 0:
287
- logger.debug(' Implementing Robin Boundary Conditions.')
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(' Implementing Periodic Boundary Conditions.')
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(' Assembling matrices')
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(' Implementing PEC Boundary Conditions.')
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(' Implementing Robin Boundary Conditions.')
480
+ logger.debug('Implementing Robin Boundary Conditions.')
458
481
 
459
482
  if len(robin_bcs) > 0:
460
- logger.debug(' Implementing Robin Boundary Conditions.')
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(' Implementing Periodic Boundary Conditions.')
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().configure('MP')
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.oftype(PEC) # type: ignore
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.boundary_conditions)
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
- #beta = np.emath.sqrt(eigen_values[i])
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().configure('MT')
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' Field Amplitude = {np.abs(pfield):.3f}, Excitation = {np.abs(pmode):.2f}')
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' Field amplitude = {np.abs(pfield):.3f}, Excitation= {np.abs(pmode):.2f}')
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' Field Amplitude = {np.abs(pfield):.3f}, Excitation = {np.abs(pmode):.2f}')
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' Field amplitude = {np.abs(pfield):.3f}, Excitation= {np.abs(pmode):.2f}')
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