emerge 0.5.1__py3-none-any.whl → 0.5.3__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 (54) hide show
  1. emerge/_emerge/bc.py +14 -20
  2. emerge/_emerge/const.py +5 -0
  3. emerge/_emerge/cs.py +2 -2
  4. emerge/_emerge/elements/femdata.py +14 -14
  5. emerge/_emerge/elements/index_interp.py +1 -1
  6. emerge/_emerge/elements/ned2_interp.py +1 -1
  7. emerge/_emerge/elements/nedelec2.py +4 -4
  8. emerge/_emerge/elements/nedleg2.py +10 -10
  9. emerge/_emerge/geo/horn.py +1 -1
  10. emerge/_emerge/geo/modeler.py +18 -19
  11. emerge/_emerge/geo/operations.py +13 -10
  12. emerge/_emerge/geo/pcb.py +180 -82
  13. emerge/_emerge/geo/pcb_tools/calculator.py +2 -2
  14. emerge/_emerge/geo/pcb_tools/macro.py +14 -13
  15. emerge/_emerge/geo/pmlbox.py +1 -1
  16. emerge/_emerge/geometry.py +47 -33
  17. emerge/_emerge/logsettings.py +15 -16
  18. emerge/_emerge/material.py +15 -11
  19. emerge/_emerge/mesh3d.py +81 -59
  20. emerge/_emerge/mesher.py +26 -21
  21. emerge/_emerge/mth/integrals.py +1 -1
  22. emerge/_emerge/mth/pairing.py +2 -2
  23. emerge/_emerge/periodic.py +34 -31
  24. emerge/_emerge/physics/microwave/adaptive_freq.py +15 -16
  25. emerge/_emerge/physics/microwave/assembly/assembler.py +120 -93
  26. emerge/_emerge/physics/microwave/assembly/curlcurl.py +1 -8
  27. emerge/_emerge/physics/microwave/assembly/generalized_eigen.py +43 -8
  28. emerge/_emerge/physics/microwave/assembly/robinbc.py +5 -5
  29. emerge/_emerge/physics/microwave/microwave_3d.py +71 -44
  30. emerge/_emerge/physics/microwave/microwave_bc.py +206 -117
  31. emerge/_emerge/physics/microwave/microwave_data.py +36 -38
  32. emerge/_emerge/physics/microwave/sc.py +26 -26
  33. emerge/_emerge/physics/microwave/simjob.py +20 -15
  34. emerge/_emerge/physics/microwave/sparam.py +12 -12
  35. emerge/_emerge/physics/microwave/touchstone.py +1 -1
  36. emerge/_emerge/plot/display.py +12 -6
  37. emerge/_emerge/plot/pyvista/display.py +44 -39
  38. emerge/_emerge/plot/pyvista/display_settings.py +1 -1
  39. emerge/_emerge/plot/simple_plots.py +15 -15
  40. emerge/_emerge/selection.py +35 -39
  41. emerge/_emerge/simmodel.py +41 -47
  42. emerge/_emerge/simulation_data.py +24 -15
  43. emerge/_emerge/solve_interfaces/cudss_interface.py +238 -0
  44. emerge/_emerge/solve_interfaces/pardiso_interface.py +24 -18
  45. emerge/_emerge/solver.py +314 -136
  46. emerge/cli.py +1 -1
  47. emerge/lib.py +245 -248
  48. {emerge-0.5.1.dist-info → emerge-0.5.3.dist-info}/METADATA +5 -1
  49. emerge-0.5.3.dist-info/RECORD +83 -0
  50. emerge/_emerge/plot/grapher.py +0 -93
  51. emerge-0.5.1.dist-info/RECORD +0 -82
  52. {emerge-0.5.1.dist-info → emerge-0.5.3.dist-info}/WHEEL +0 -0
  53. {emerge-0.5.1.dist-info → emerge-0.5.3.dist-info}/entry_points.txt +0 -0
  54. {emerge-0.5.1.dist-info → emerge-0.5.3.dist-info}/licenses/LICENSE +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[np.ndarray, np.ndarray, 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:
@@ -194,12 +191,11 @@ class Assembler:
194
191
  tids = nedlegfield.tri_to_field[:, i2]
195
192
  pec_ids.extend(list(tids))
196
193
 
197
- port._field = nedlegfield
198
- port._pece = pec_edges
199
- port._pecv = pec_vertices
200
194
  # Process all port boundary Conditions
201
- pec_ids = set(pec_ids)
202
- solve_ids = [i for i in range(nedlegfield.n_field) if i not in pec_ids]
195
+ pec_ids_set: set[int] = set(pec_ids)
196
+
197
+ logger.trace(f'.total of {len(pec_ids_set)} pec DoF to remove.')
198
+ solve_ids = [i for i in range(nedlegfield.n_field) if i not in pec_ids_set]
203
199
 
204
200
  return E, B, np.array(solve_ids), nedlegfield
205
201
 
@@ -234,16 +230,16 @@ class Assembler:
234
230
 
235
231
  mesh = field.mesh
236
232
  er = er - 1j*sig/(W0*EPS0)*np.repeat(np.eye(3)[:, :, np.newaxis], er.shape[2], axis=2)
237
- is_frequency_dependent: bool = np.any((sig > 0) & (sig < self.conductivity_limit))
233
+ is_frequency_dependent: bool = np.any((sig > 0) & (sig < self.conductivity_limit)) # type: ignore
238
234
 
239
235
 
240
236
  if cache_matrices and not is_frequency_dependent and self.cached_matrices is not None:
241
237
  # IF CACHED AND AVAILABLE PULL E AND B FROM CACHE
242
- logger.debug(' Retreiving cached matricies')
238
+ logger.debug('Using cached matricies.')
243
239
  E, B = self.cached_matrices
244
240
  else:
245
241
  # OTHERWISE, COMPUTE
246
- logger.debug(' Assembling matrices')
242
+ logger.debug('Assembling matrices')
247
243
  E, B = tet_mass_stiffness_matrices(field, er, ur)
248
244
  self.cached_matrices = (E, B)
249
245
 
@@ -254,7 +250,7 @@ class Assembler:
254
250
 
255
251
  # ISOLATE BOUNDARY CONDITIONS TO ASSEMBLE
256
252
  pec_bcs: list[PEC] = [bc for bc in bcs if isinstance(bc,PEC)]
257
- robin_bcs: list[RectangularWaveguide] = [bc for bc in bcs if isinstance(bc,RobinBC)]
253
+ robin_bcs: list[RobinBC] = [bc for bc in bcs if isinstance(bc,RobinBC)]
258
254
  port_bcs: list[PortBC] = [bc for bc in bcs if isinstance(bc, PortBC)]
259
255
  periodic_bcs: list[Periodic] = [bc for bc in bcs if isinstance(bc, Periodic)]
260
256
 
@@ -262,15 +258,24 @@ class Assembler:
262
258
  b = np.zeros((E.shape[0],)).astype(np.complex128)
263
259
  port_vectors = {port.port_number: np.zeros((E.shape[0],)).astype(np.complex128) for port in port_bcs}
264
260
 
265
- # Process all PEC Boundary Conditions
266
- logger.debug(' Implementing PEC Boundary Conditions.')
267
- pec_ids = []
261
+
262
+ ############################################################
263
+ # PEC BOUNDARY CONDITIONS #
264
+ ############################################################
265
+
266
+ logger.debug('Implementing PEC Boundary Conditions.')
267
+ pec_ids: list[int] = []
268
268
  # Conductivity above al imit, consider it all PEC
269
+ ipec = 0
269
270
  for itet in range(field.n_tets):
270
271
  if sig[itet] > self.conductivity_limit:
272
+ ipec+=1
271
273
  pec_ids.extend(field.tet_to_field[:,itet])
272
-
274
+ if ipec>0:
275
+ logger.trace(f'Extended PEC with {ipec} tets with a conductivity > {self.conductivity_limit}.')
276
+
273
277
  for pec in pec_bcs:
278
+ logger.trace(f'Implementing: {pec}')
274
279
  if len(pec.tags)==0:
275
280
  continue
276
281
  face_tags = pec.tags
@@ -285,14 +290,18 @@ class Assembler:
285
290
  tids = field.tri_to_field[:, ii]
286
291
  pec_ids.extend(list(tids))
287
292
 
288
- # Robin BCs
293
+
294
+ ############################################################
295
+ # ROBIN BOUNDARY CONDITIONS #
296
+ ############################################################
297
+
289
298
  if len(robin_bcs) > 0:
290
- logger.debug(' Implementing Robin Boundary Conditions.')
299
+ logger.debug('Implementing Robin Boundary Conditions.')
291
300
 
292
301
  gauss_points = gaus_quad_tri(4)
293
302
  Bempty = field.empty_tri_matrix()
294
303
  for bc in robin_bcs:
295
-
304
+ logger.trace(f'.Implementing {bc}')
296
305
  for tag in bc.tags:
297
306
  face_tags = [tag,]
298
307
 
@@ -301,6 +310,7 @@ class Assembler:
301
310
  edge_ids = list(mesh.tri_to_edge[:,tri_ids].flatten())
302
311
 
303
312
  gamma = bc.get_gamma(K0)
313
+ logger.trace(f'..robin bc γ={gamma:.3f}')
304
314
 
305
315
  def Ufunc(x,y):
306
316
  return bc.get_Uinc(x,y,K0)
@@ -309,38 +319,42 @@ class Assembler:
309
319
  if ibasis is None:
310
320
  basis = plane_basis_from_points(mesh.nodes[:,nodes]) + 1e-16
311
321
  ibasis = np.linalg.pinv(basis)
322
+ logger.trace(f'..Using computed basis: {ibasis.flatten()}')
312
323
  if bc._include_force:
313
-
314
- Bempty, b_p = assemble_robin_bc_excited(field, Bempty, tri_ids, Ufunc, gamma, ibasis, bc.cs.origin, gauss_points)
315
-
316
- port_vectors[bc.port_number] += b_p
317
-
324
+ Bempty, b_p = assemble_robin_bc_excited(field, Bempty, tri_ids, Ufunc, gamma, ibasis, bc.cs.origin, gauss_points) # type: ignore
325
+ port_vectors[bc.port_number] += b_p # type: ignore
326
+ logger.trace(f'..included force vector term with norm {np.linalg.norm(b_p):.3f}')
318
327
  else:
319
- Bempty = assemble_robin_bc(field, Bempty, tri_ids, gamma)
328
+ Bempty = assemble_robin_bc(field, Bempty, tri_ids, gamma) # type: ignore
320
329
  B_p = field.generate_csr(Bempty)
321
330
  K = K + B_p
322
331
 
323
332
  if len(periodic_bcs) > 0:
324
- logger.debug(' Implementing Periodic Boundary Conditions.')
333
+ logger.debug('Implementing Periodic Boundary Conditions.')
334
+
335
+
336
+ ############################################################
337
+ # PERIODIC BOUNDARY CONDITIONS #
338
+ ############################################################
325
339
 
326
-
327
- # Periodic BCs
328
340
  Pmats = []
329
- remove = set()
341
+ remove: set[int] = set()
330
342
  has_periodic = False
331
343
 
332
- for bc in periodic_bcs:
344
+ for pbc in periodic_bcs:
345
+ logger.trace(f'.Implementing {pbc}')
333
346
  has_periodic = True
334
- tri_ids_1 = mesh.get_triangles(bc.face1.tags)
335
- edge_ids_1 = mesh.get_edges(bc.face1.tags)
336
- tri_ids_2 = mesh.get_triangles(bc.face2.tags)
337
- edge_ids_2 = mesh.get_edges(bc.face2.tags)
338
- dv = np.array(bc.dv)
347
+ tri_ids_1 = mesh.get_triangles(pbc.face1.tags)
348
+ edge_ids_1 = mesh.get_edges(pbc.face1.tags)
349
+ tri_ids_2 = mesh.get_triangles(pbc.face2.tags)
350
+ edge_ids_2 = mesh.get_edges(pbc.face2.tags)
351
+ dv = np.array(pbc.dv)
352
+ logger.trace(f'..displacement vector {dv}')
339
353
  linked_tris = pair_coordinates(mesh.tri_centers, tri_ids_1, tri_ids_2, dv, 1e-9)
340
354
  linked_edges = pair_coordinates(mesh.edge_centers, edge_ids_1, edge_ids_2, dv, 1e-9)
341
- dv = np.array(bc.dv)
342
- phi = bc.phi(K0)
343
-
355
+ dv = np.array(pbc.dv)
356
+ phi = pbc.phi(K0)
357
+ logger.trace(f'..ϕ={phi} rad/m')
344
358
  Pmat, rows = gen_periodic_matrix(tri_ids_1,
345
359
  edge_ids_1,
346
360
  field.tri_to_field,
@@ -351,20 +365,26 @@ class Assembler:
351
365
  phi)
352
366
  remove.update(rows)
353
367
  Pmats.append(Pmat)
354
-
368
+
355
369
  if Pmats:
370
+ logger.trace(f'.periodic bc removes {len(remove)} boundary DoF')
356
371
  Pmat = Pmats[0]
357
372
  for P2 in Pmats[1:]:
358
373
  Pmat = Pmat @ P2
359
- remove = np.array(sorted(list(remove)))
374
+ remove_array = np.sort(np.unique(list(remove)))
360
375
  all_indices = np.arange(NF)
361
- keep_indices = np.setdiff1d(all_indices, remove)
376
+ keep_indices = np.setdiff1d(all_indices, remove_array)
362
377
  Pmat = Pmat[:,keep_indices]
363
378
  else:
364
379
  Pmat = None
365
380
 
366
- pec_ids = set(pec_ids)
367
- solve_ids = np.array([i for i in range(E.shape[0]) if i not in pec_ids])
381
+
382
+ ############################################################
383
+ # FINALIZE #
384
+ ############################################################
385
+
386
+ pec_ids_set = set(pec_ids)
387
+ solve_ids = np.array([i for i in range(E.shape[0]) if i not in pec_ids_set])
368
388
 
369
389
  if has_periodic:
370
390
  mask = np.zeros((NF,))
@@ -419,20 +439,20 @@ class Assembler:
419
439
 
420
440
  er = er - 1j*sig/(w0*EPS0)*np.repeat(np.eye(3)[:, :, np.newaxis], er.shape[2], axis=2)
421
441
 
422
- logger.debug(' Assembling matrices')
442
+ logger.debug('Assembling matrices')
423
443
  E, B = tet_mass_stiffness_matrices(field, er, ur)
424
444
  self.cached_matrices = (E, B)
425
445
 
426
446
  NF = E.shape[0]
427
447
 
428
448
  pecs: list[PEC] = [bc for bc in bcs if isinstance(bc,PEC)]
429
- robin_bcs: list[RectangularWaveguide] = [bc for bc in bcs if isinstance(bc,RobinBC)]
449
+ robin_bcs: list[RectangularWaveguide] = [bc for bc in bcs if isinstance(bc,RobinBC)] # type: ignore
430
450
  periodic: list[Periodic] = [bc for bc in bcs if isinstance(bc, Periodic)]
431
451
 
432
452
  # Process all PEC Boundary Conditions
433
- pec_ids = []
453
+ pec_ids: list = []
434
454
 
435
- logger.debug(' Implementing PEC Boundary Conditions.')
455
+ logger.debug('Implementing PEC Boundary Conditions.')
436
456
 
437
457
  # Conductivity above a limit, consider it all PEC
438
458
  for itet in range(field.n_tets):
@@ -457,45 +477,52 @@ class Assembler:
457
477
 
458
478
  # Robin BCs
459
479
  if len(robin_bcs) > 0:
460
- logger.debug(' Implementing Robin Boundary Conditions.')
480
+ logger.debug('Implementing Robin Boundary Conditions.')
481
+
482
+ if len(robin_bcs) > 0:
483
+ logger.debug('Implementing Robin Boundary Conditions.')
461
484
 
462
- for bc in robin_bcs:
463
- for tag in bc.tags:
464
- face_tags = [tag,]#bc.tags
465
-
466
- tri_ids = mesh.get_triangles(face_tags)
467
- nodes = mesh.get_nodes(face_tags)
468
- edge_ids = list(mesh.tri_to_edge[:,tri_ids].flatten())
469
-
470
- gamma = bc.get_gamma(k0)
471
-
472
- ibasis = bc.get_inv_basis()
473
- if ibasis is None:
474
- basis = plane_basis_from_points(mesh.nodes[:,nodes]) + 1e-16
475
- ibasis = np.linalg.pinv(basis)
476
- B_p = assemble_robin_bc(field, tri_ids, gamma)
477
- if bc._include_stiff:
478
- B = B + B_p
485
+ gauss_points = gaus_quad_tri(4)
486
+ Bempty = field.empty_tri_matrix()
487
+ for bc in robin_bcs:
488
+
489
+ for tag in bc.tags:
490
+ face_tags = [tag,]
491
+
492
+ tri_ids = mesh.get_triangles(face_tags)
493
+ nodes = mesh.get_nodes(face_tags)
494
+ edge_ids = list(mesh.tri_to_edge[:,tri_ids].flatten())
495
+
496
+ gamma = bc.get_gamma(k0)
497
+
498
+ ibasis = bc.get_inv_basis()
499
+ if ibasis is None:
500
+ basis = plane_basis_from_points(mesh.nodes[:,nodes]) + 1e-16
501
+ ibasis = np.linalg.pinv(basis)
502
+
503
+ Bempty = assemble_robin_bc(field, Bempty, tri_ids, gamma) # type: ignore
504
+ B_p = field.generate_csr(Bempty)
505
+ B = B + B_p
479
506
 
480
507
  if len(periodic) > 0:
481
- logger.debug(' Implementing Periodic Boundary Conditions.')
508
+ logger.debug('Implementing Periodic Boundary Conditions.')
482
509
 
483
510
  # Periodic BCs
484
511
  Pmats = []
485
512
  remove = set()
486
513
  has_periodic = False
487
514
 
488
- for bc in periodic:
515
+ for bcp in periodic:
489
516
  has_periodic = True
490
- tri_ids_1 = mesh.get_triangles(bc.face1.tags)
491
- edge_ids_1 = mesh.get_edges(bc.face1.tags)
492
- tri_ids_2 = mesh.get_triangles(bc.face2.tags)
493
- edge_ids_2 = mesh.get_edges(bc.face2.tags)
494
- dv = np.array(bc.dv)
517
+ tri_ids_1 = mesh.get_triangles(bcp.face1.tags)
518
+ edge_ids_1 = mesh.get_edges(bcp.face1.tags)
519
+ tri_ids_2 = mesh.get_triangles(bcp.face2.tags)
520
+ edge_ids_2 = mesh.get_edges(bcp.face2.tags)
521
+ dv = np.array(bcp.dv)
495
522
  linked_tris = pair_coordinates(mesh.tri_centers, tri_ids_1, tri_ids_2, dv, 1e-9)
496
523
  linked_edges = pair_coordinates(mesh.edge_centers, edge_ids_1, edge_ids_2, dv, 1e-9)
497
- dv = np.array(bc.dv)
498
- phi = bc.phi(k0)
524
+ dv = np.array(bcp.dv)
525
+ phi = bcp.phi(k0)
499
526
 
500
527
  Pmat, rows = gen_periodic_matrix(tri_ids_1,
501
528
  edge_ids_1,
@@ -513,15 +540,15 @@ class Assembler:
513
540
  for P2 in Pmats[1:]:
514
541
  Pmat = Pmat @ P2
515
542
  Pmat = Pmat.tocsr()
516
- remove = np.array(sorted(list(remove)))
543
+ remove_array = np.sort(np.array(list(remove)))
517
544
  all_indices = np.arange(NF)
518
- keep_indices = np.setdiff1d(all_indices, remove)
545
+ keep_indices = np.setdiff1d(all_indices, remove_array)
519
546
  Pmat = Pmat[:,keep_indices]
520
547
  else:
521
548
  Pmat = None
522
549
 
523
- pec_ids = set(pec_ids)
524
- solve_ids = np.array([i for i in range(E.shape[0]) if i not in pec_ids])
550
+ pec_ids_set = set(pec_ids)
551
+ solve_ids = np.array([i for i in range(E.shape[0]) if i not in pec_ids_set])
525
552
 
526
553
  if has_periodic:
527
554
  mask = np.zeros((NF,))
@@ -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)
@@ -17,21 +17,33 @@
17
17
 
18
18
  import numpy as np
19
19
  from ....elements.nedleg2 import NedelecLegrange2
20
- from scipy.sparse import coo_matrix
20
+ from scipy.sparse import csr_matrix
21
21
  from numba_progress import ProgressBar, ProgressBarType
22
22
  from ....mth.optimized import local_mapping, matinv, compute_distances
23
23
  from numba import c16, types, f8, i8, njit, prange
24
24
 
25
+
26
+
27
+ ############################################################
28
+ # FIELD MAPPING #
29
+ ############################################################
30
+
25
31
  @njit(i8[:,:](i8, i8[:,:], i8[:,:], i8[:,:]), cache=True, nogil=True)
26
32
  def local_tri_to_edgeid(itri: int, tris, edges, tri_to_edge) -> np.ndarray:
27
33
  global_edge_map = edges[:, tri_to_edge[:,itri]]
28
34
  return local_mapping(tris[:, itri], global_edge_map)
29
35
 
36
+
37
+
38
+ ############################################################
39
+ # PYTHON INTERFACE #
40
+ ############################################################
41
+
30
42
  def generelized_eigenvalue_matrix(field: NedelecLegrange2,
31
43
  er: np.ndarray,
32
44
  ur: np.ndarray,
33
45
  basis: np.ndarray,
34
- k0: float,) -> tuple[coo_matrix, coo_matrix]:
46
+ k0: float,) -> tuple[csr_matrix, csr_matrix]:
35
47
 
36
48
  tris = field.mesh.tris
37
49
  edges = field.mesh.edges
@@ -47,11 +59,16 @@ def generelized_eigenvalue_matrix(field: NedelecLegrange2,
47
59
 
48
60
  nfield = field.n_field
49
61
 
50
- E = coo_matrix((dataE, (rows, cols)), shape=(nfield, nfield)).tocsr()
51
- B = coo_matrix((dataB, (rows, cols)), shape=(nfield, nfield)).tocsr()
62
+ E = csr_matrix((dataE, (rows, cols)), shape=(nfield, nfield))
63
+ B = csr_matrix((dataB, (rows, cols)), shape=(nfield, nfield))
52
64
 
53
65
  return E, B
54
66
 
67
+
68
+ ############################################################
69
+ # MATRIX MULTIPLICATION #
70
+ ############################################################
71
+
55
72
  @njit(c16[:,:](c16[:,:], c16[:,:]), cache=True, nogil=True)
56
73
  def matmul(a, b):
57
74
  out = np.empty((2,b.shape[1]), dtype=np.complex128)
@@ -59,7 +76,10 @@ def matmul(a, b):
59
76
  out[1,:] = a[1,0]*b[0,:] + a[1,1]*b[1,:]
60
77
  return out
61
78
 
62
- ### GAUSS QUADRATURE IMPLEMENTATION
79
+
80
+ ############################################################
81
+ # GAUSS QUADRATURE IMPLEMENTATION #
82
+ ############################################################
63
83
 
64
84
  @njit(c16(c16[:], c16[:], types.Array(types.float64, 1, 'A', readonly=True)), cache=True, nogil=True)
65
85
  def _gqi(v1, v2, W):
@@ -185,7 +205,12 @@ def _nf2_curl(coeff, coords):
185
205
  ys = coords[1,:]
186
206
  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
207
 
188
- ####
208
+
209
+ ############################################################
210
+ # TRIANGLE BARYCENTRIC COORDINATE LIN. COEFFICIENTS #
211
+ ############################################################
212
+
213
+
189
214
  @njit(types.Tuple((f8[:], f8[:], f8[:], f8))(f8[:], f8[:]), cache = True, nogil=True)
190
215
  def tri_coefficients(vxs, vys):
191
216
 
@@ -211,13 +236,23 @@ def tri_coefficients(vxs, vys):
211
236
  Cs = np.array([c1, c2, c3])*sign
212
237
  return As, Bs, Cs, A
213
238
 
214
- #DPTS = gaus_quad_tri(4).astype(np.float64)
239
+
240
+ ############################################################
241
+ # CONSTANT DEFINITION #
242
+ ############################################################
243
+
215
244
 
216
245
  DPTS = np.array([[0.22338159, 0.22338159, 0.22338159, 0.10995174, 0.10995174, 0.10995174],
217
246
  [0.10810302, 0.44594849, 0.44594849, 0.81684757, 0.09157621, 0.09157621],
218
247
  [0.44594849, 0.44594849, 0.10810302, 0.09157621, 0.09157621, 0.81684757],
219
248
  [0.44594849, 0.10810302, 0.44594849, 0.09157621, 0.81684757, 0.09157621]], dtype=np.float64)
220
249
 
250
+
251
+ ############################################################
252
+ # NUMBA OPTIMIZED ASSEMBLER #
253
+ ############################################################
254
+
255
+
221
256
  @njit(types.Tuple((c16[:,:], c16[:,:]))(f8[:,:], i8[:,:], c16[:,:], c16[:,:], f8), cache=True, nogil=True)
222
257
  def generalized_matrix_GQ(tri_vertices, local_edge_map, Ms, Mm, k0):
223
258
  '''Nedelec-2 Triangle stiffness and mass submatrix'''
@@ -402,7 +437,7 @@ def _matrix_builder(nodes, tris, edges, tri_to_field, ur, er, k0, pgb: ProgressB
402
437
 
403
438
  tri_to_edge = tri_to_field[:3,:]
404
439
 
405
- for itri in prange(ntritot):
440
+ for itri in prange(ntritot): # type: ignore
406
441
  p = itri*196
407
442
  if np.mod(itri,10)==0:
408
443
  pgb.update(10)
@@ -252,7 +252,7 @@ def ned2_tri_stiff_force(lcs_vertices, gamma, lcs_Uinc, DPTs):
252
252
  def compute_bc_entries_excited(vertices_local, tris, Bmat, Bvec, surf_triangle_indices, gamma, Ulocal_all, DPTs, tri_to_field):
253
253
  N = 64
254
254
  Niter = surf_triangle_indices.shape[0]
255
- for i in prange(Niter):
255
+ for i in prange(Niter): # type: ignore
256
256
  itri = surf_triangle_indices[i]
257
257
 
258
258
  vertex_ids = tris[:, itri]
@@ -388,7 +388,7 @@ def ned2_tri_stiff(vertices, edge_lengths, gamma):
388
388
  def compute_bc_entries(vertices, tris, Bmat, all_edge_lengths, surf_triangle_indices, gamma):
389
389
  N = 64
390
390
  Niter = surf_triangle_indices.shape[0]
391
- for i in prange(Niter):
391
+ for i in prange(Niter): # type: ignore
392
392
  itri = surf_triangle_indices[i]
393
393
 
394
394
  vertex_ids = tris[:, itri]
@@ -404,7 +404,7 @@ def assemble_robin_bc_excited(field: Nedelec2,
404
404
  Bmat: np.ndarray,
405
405
  surf_triangle_indices: np.ndarray,
406
406
  Ufunc: Callable,
407
- gamma: np.ndarray,
407
+ gamma: complex,
408
408
  local_basis: np.ndarray,
409
409
  origin: np.ndarray,
410
410
  DPTs: np.ndarray):
@@ -424,8 +424,8 @@ def assemble_robin_bc_excited(field: Nedelec2,
424
424
 
425
425
  def assemble_robin_bc(field: Nedelec2,
426
426
  Bmat: np.ndarray,
427
- surf_triangle_indices: np.ndarray,
428
- gamma: np.ndarray):
427
+ surf_triangle_indices: np.ndarray,
428
+ gamma: np.ndarray):
429
429
  vertices = field.mesh.nodes
430
430
  all_edge_lengths = field.mesh.edge_lengths[field.mesh.tri_to_edge]
431
431
  Bmat = compute_bc_entries(vertices, field.mesh.tris, Bmat, all_edge_lengths, surf_triangle_indices, gamma)