emerge 1.0.4__py3-none-any.whl → 1.0.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of emerge might be problematic. Click here for more details.
- emerge/__init__.py +2 -2
- emerge/_emerge/geo/horn.py +17 -1
- emerge/_emerge/geo/operations.py +4 -2
- emerge/_emerge/geo/pcb.py +10 -6
- emerge/_emerge/geo/polybased.py +27 -1
- emerge/_emerge/geo/shapes.py +93 -1
- emerge/_emerge/geometry.py +22 -4
- emerge/_emerge/material.py +31 -2
- emerge/_emerge/mesher.py +2 -1
- emerge/_emerge/physics/microwave/assembly/assembler.py +1 -1
- emerge/_emerge/physics/microwave/assembly/curlcurl.py +78 -77
- emerge/_emerge/physics/microwave/microwave_3d.py +12 -9
- emerge/_emerge/physics/microwave/microwave_bc.py +2 -2
- emerge/_emerge/physics/microwave/microwave_data.py +9 -0
- emerge/_emerge/plot/pyvista/display.py +88 -0
- emerge/_emerge/simmodel.py +3 -1
- emerge/_emerge/solver.py +96 -72
- {emerge-1.0.4.dist-info → emerge-1.0.6.dist-info}/METADATA +2 -2
- {emerge-1.0.4.dist-info → emerge-1.0.6.dist-info}/RECORD +22 -22
- {emerge-1.0.4.dist-info → emerge-1.0.6.dist-info}/WHEEL +0 -0
- {emerge-1.0.4.dist-info → emerge-1.0.6.dist-info}/entry_points.txt +0 -0
- {emerge-1.0.4.dist-info → emerge-1.0.6.dist-info}/licenses/LICENSE +0 -0
emerge/_emerge/solver.py
CHANGED
|
@@ -90,11 +90,16 @@ class SolveReport:
|
|
|
90
90
|
sorter: str = 'None'
|
|
91
91
|
precon: str = 'None'
|
|
92
92
|
aux: dict[str, str] = field(default_factory=dict)
|
|
93
|
+
worker_name: str = 'Unknown Worker'
|
|
93
94
|
|
|
94
95
|
def add(self, **kwargs: str):
|
|
95
96
|
for key, value in kwargs.items():
|
|
96
97
|
self.aux[key] = str(value)
|
|
97
98
|
|
|
99
|
+
@property
|
|
100
|
+
def mdof(self) -> float:
|
|
101
|
+
return (self.ndof**2)/((self.simtime+1e-6)*1e6)
|
|
102
|
+
|
|
98
103
|
def logprint(self, print_cal: Callable | None = None):
|
|
99
104
|
if print_cal is None:
|
|
100
105
|
print_cal = print
|
|
@@ -113,6 +118,7 @@ class SolveReport:
|
|
|
113
118
|
parts.append(fmt("DOFsSolve", self.ndof_solve))
|
|
114
119
|
parts.append(fmt("NNZSolve", self.nnz_solve))
|
|
115
120
|
parts.append(fmt("Exit", self.exit_code))
|
|
121
|
+
parts.append(fmt("Worker",self.worker_name))
|
|
116
122
|
|
|
117
123
|
if self.aux:
|
|
118
124
|
for k, v in self.aux.items():
|
|
@@ -155,6 +161,7 @@ class SolveReport:
|
|
|
155
161
|
row("DOFs (Solve)", self.ndof_solve)
|
|
156
162
|
row("NNZ (Solve)", self.nnz_solve)
|
|
157
163
|
row("Exit Code", self.exit_code)
|
|
164
|
+
row("Worker", self.worker_name)
|
|
158
165
|
print_cal(border)
|
|
159
166
|
|
|
160
167
|
if self.aux:
|
|
@@ -164,6 +171,8 @@ class SolveReport:
|
|
|
164
171
|
row(str(k), v)
|
|
165
172
|
print_cal(border)
|
|
166
173
|
|
|
174
|
+
def _pfx(name: str, id: int = 0) -> str:
|
|
175
|
+
return f'[{name}-j{id:03d}]'
|
|
167
176
|
############################################################
|
|
168
177
|
# EIGENMODE FILTER ROUTINE #
|
|
169
178
|
############################################################
|
|
@@ -322,9 +331,10 @@ class Solver:
|
|
|
322
331
|
req_sorter: bool = False
|
|
323
332
|
released_gil: bool = False
|
|
324
333
|
|
|
325
|
-
def __init__(self):
|
|
334
|
+
def __init__(self, pre: str = ''):
|
|
326
335
|
self.own_preconditioner: bool = False
|
|
327
336
|
self.initialized: bool = False
|
|
337
|
+
self.pre: str = pre
|
|
328
338
|
|
|
329
339
|
def __str__(self) -> str:
|
|
330
340
|
return f'{self.__class__.__name__}'
|
|
@@ -360,8 +370,9 @@ class EigSolver:
|
|
|
360
370
|
real_only: bool = False
|
|
361
371
|
req_sorter: bool = False
|
|
362
372
|
|
|
363
|
-
def __init__(self):
|
|
373
|
+
def __init__(self, pre: str = ''):
|
|
364
374
|
self.own_preconditioner: bool = False
|
|
375
|
+
self.pre: str = pre
|
|
365
376
|
|
|
366
377
|
def initialize(self) -> None:
|
|
367
378
|
return None
|
|
@@ -370,7 +381,7 @@ class EigSolver:
|
|
|
370
381
|
return f'{self.__class__.__name__}'
|
|
371
382
|
|
|
372
383
|
def duplicate(self) -> Solver:
|
|
373
|
-
return self.__class__()
|
|
384
|
+
return self.__class__(self.pre)
|
|
374
385
|
|
|
375
386
|
def eig(self, A: csr_matrix | csr_matrix, B: csr_matrix | csr_matrix, nmodes: int = 6,
|
|
376
387
|
target_k0: float = 0.0, which: str = 'LM', sign: float = 1.):
|
|
@@ -444,10 +455,10 @@ class SolverBicgstab(Solver):
|
|
|
444
455
|
|
|
445
456
|
def callback(self, xk):
|
|
446
457
|
convergence = np.linalg.norm((self.A @ xk - self.b))
|
|
447
|
-
logger.info(f'Iteration {convergence:.4f}')
|
|
458
|
+
logger.info(self.pre + f'Iteration {convergence:.4f}')
|
|
448
459
|
|
|
449
460
|
def solve(self, A, b, precon, reuse_factorization: bool = False, id: int = -1) -> tuple[np.ndarray, SolveReport]:
|
|
450
|
-
logger.info(f'
|
|
461
|
+
logger.info(f'{_pfx(self.pre,id)} Calling BiCGStab.')
|
|
451
462
|
self.A = A
|
|
452
463
|
self.b = b
|
|
453
464
|
if precon.M is not None:
|
|
@@ -466,10 +477,10 @@ class SolverGCROTMK(Solver):
|
|
|
466
477
|
|
|
467
478
|
def callback(self, xk):
|
|
468
479
|
convergence = np.linalg.norm((self.A @ xk - self.b))
|
|
469
|
-
logger.info(f'Iteration {convergence:.4f}')
|
|
480
|
+
logger.info(self.pre + f'Iteration {convergence:.4f}')
|
|
470
481
|
|
|
471
482
|
def solve(self, A: csr_matrix, b: np.ndarray, precon: Preconditioner, reuse_factorization: bool = False, id: int = -1) -> tuple[np.ndarray, SolveReport]:
|
|
472
|
-
logger.info(f'
|
|
483
|
+
logger.info(f'{_pfx(self.pre,id)} Calling GCRO-T(m,k) algorithm')
|
|
473
484
|
self.A = A
|
|
474
485
|
self.b = b
|
|
475
486
|
if precon.M is not None:
|
|
@@ -492,10 +503,10 @@ class SolverGMRES(Solver):
|
|
|
492
503
|
|
|
493
504
|
def callback(self, norm):
|
|
494
505
|
#convergence = np.linalg.norm((self.A @ xk - self.b))
|
|
495
|
-
logger.info(f'Iteration {norm:.4f}')
|
|
506
|
+
logger.info(self.pre + f'Iteration {norm:.4f}')
|
|
496
507
|
|
|
497
508
|
def solve(self, A, b, precon, reuse_factorization: bool = False, id: int = -1) -> tuple[np.ndarray, SolveReport]:
|
|
498
|
-
logger.info(f'
|
|
509
|
+
logger.info(f'{_pfx(self.pre,id)} Calling GMRES Function.')
|
|
499
510
|
self.A = A
|
|
500
511
|
self.b = b
|
|
501
512
|
if precon.M is not None:
|
|
@@ -516,8 +527,8 @@ class SolverSuperLU(Solver):
|
|
|
516
527
|
real_only: bool = False
|
|
517
528
|
released_gil: bool = True
|
|
518
529
|
|
|
519
|
-
def __init__(self):
|
|
520
|
-
super().__init__()
|
|
530
|
+
def __init__(self, pre: str):
|
|
531
|
+
super().__init__(pre)
|
|
521
532
|
self.atol = 1e-5
|
|
522
533
|
|
|
523
534
|
self.A: np.ndarray = None
|
|
@@ -527,7 +538,7 @@ class SolverSuperLU(Solver):
|
|
|
527
538
|
self.lu = None
|
|
528
539
|
|
|
529
540
|
def duplicate(self) -> Solver:
|
|
530
|
-
new_solver = self.__class__()
|
|
541
|
+
new_solver = self.__class__(self.pre)
|
|
531
542
|
new_solver._pivoting_threshold = self._pivoting_threshold
|
|
532
543
|
return new_solver
|
|
533
544
|
|
|
@@ -537,11 +548,11 @@ class SolverSuperLU(Solver):
|
|
|
537
548
|
self._pivoting_threshold = pivoting_threshold
|
|
538
549
|
|
|
539
550
|
def solve(self, A, b, precon, reuse_factorization: bool = False, id: int = -1) -> tuple[np.ndarray, SolveReport]:
|
|
540
|
-
logger.info(f'
|
|
551
|
+
logger.info(f'{_pfx(self.pre,id)} Calling SuperLU Solver.')
|
|
541
552
|
|
|
542
553
|
self.single = True
|
|
543
554
|
if not reuse_factorization:
|
|
544
|
-
logger.trace('Computing LU-Decomposition')
|
|
555
|
+
logger.trace(self.pre + 'Computing LU-Decomposition')
|
|
545
556
|
self.lu = splu(A, permc_spec='MMD_AT_PLUS_A', relax=0, diag_pivot_thresh=self._pivoting_threshold, options=self.options)
|
|
546
557
|
x = self.lu.solve(b)
|
|
547
558
|
aux = {
|
|
@@ -554,9 +565,9 @@ class SolverUMFPACK(Solver):
|
|
|
554
565
|
req_sorter = False
|
|
555
566
|
real_only = False
|
|
556
567
|
|
|
557
|
-
def __init__(self):
|
|
558
|
-
super().__init__()
|
|
559
|
-
logger.trace('Creating UMFPACK solver')
|
|
568
|
+
def __init__(self, pre: str):
|
|
569
|
+
super().__init__(pre)
|
|
570
|
+
logger.trace(self.pre + 'Creating UMFPACK solver')
|
|
560
571
|
self.A: np.ndarray = None
|
|
561
572
|
self.b: np.ndarray = None
|
|
562
573
|
|
|
@@ -571,7 +582,7 @@ class SolverUMFPACK(Solver):
|
|
|
571
582
|
def initialize(self):
|
|
572
583
|
if self.initalized:
|
|
573
584
|
return
|
|
574
|
-
logger.trace('Initializing UMFPACK Solver')
|
|
585
|
+
logger.trace(self.pre + 'Initializing UMFPACK Solver')
|
|
575
586
|
self.umfpack = um.UmfpackContext('zl')
|
|
576
587
|
self.umfpack.control[um.UMFPACK_PRL] = 0 # ty: ignore
|
|
577
588
|
self.umfpack.control[um.UMFPACK_IRSTEP] = 2 # ty: ignore
|
|
@@ -584,7 +595,7 @@ class SolverUMFPACK(Solver):
|
|
|
584
595
|
self.initalized = True
|
|
585
596
|
|
|
586
597
|
def reset(self) -> None:
|
|
587
|
-
logger.trace('Resetting UMFPACK solver state')
|
|
598
|
+
logger.trace(self.pre + 'Resetting UMFPACK solver state')
|
|
588
599
|
self.fact_symb = False
|
|
589
600
|
|
|
590
601
|
def set_options(self, pivoting_threshold: float | None = None) -> None:
|
|
@@ -595,23 +606,23 @@ class SolverUMFPACK(Solver):
|
|
|
595
606
|
self._pivoting_threshold = pivoting_threshold
|
|
596
607
|
|
|
597
608
|
def duplicate(self) -> Solver:
|
|
598
|
-
new_solver = self.__class__()
|
|
609
|
+
new_solver = self.__class__(self.pre)
|
|
599
610
|
new_solver.set_options(pivoting_threshold = self._pivoting_threshold)
|
|
600
611
|
return new_solver
|
|
601
612
|
|
|
602
613
|
def solve(self, A, b, precon, reuse_factorization: bool = False, id: int = -1) -> tuple[np.ndarray, SolveReport]:
|
|
603
|
-
logger.info(f'
|
|
614
|
+
logger.info(f'{_pfx(self.pre,id)} Calling UMFPACK Solver.')
|
|
604
615
|
A.indptr = A.indptr.astype(np.int64)
|
|
605
616
|
A.indices = A.indices.astype(np.int64)
|
|
606
617
|
if self.fact_symb is False:
|
|
607
|
-
logger.trace(f'
|
|
618
|
+
logger.trace(f'{_pfx(self.pre,id)} Executing symbollic factorization.')
|
|
608
619
|
self.umfpack.symbolic(A)
|
|
609
620
|
self.fact_symb = True
|
|
610
621
|
if not reuse_factorization:
|
|
611
|
-
logger.trace(f'
|
|
622
|
+
logger.trace(f'{_pfx(self.pre,id)} Executing numeric factorization.')
|
|
612
623
|
self.umfpack.numeric(A)
|
|
613
624
|
self.A = A
|
|
614
|
-
logger.trace(f'
|
|
625
|
+
logger.trace(f'{_pfx(self.pre,id)} Solving linear system.')
|
|
615
626
|
x = self.umfpack.solve(um.UMFPACK_A, self.A, b, autoTranspose = False ) # ty: ignore
|
|
616
627
|
aux = {
|
|
617
628
|
"Pivoting Threshold": str(self._pivoting_threshold),
|
|
@@ -623,8 +634,8 @@ class SolverPardiso(Solver):
|
|
|
623
634
|
real_only: bool = False
|
|
624
635
|
req_sorter: bool = False
|
|
625
636
|
|
|
626
|
-
def __init__(self):
|
|
627
|
-
super().__init__()
|
|
637
|
+
def __init__(self, pre: str):
|
|
638
|
+
super().__init__(pre)
|
|
628
639
|
self.solver: PardisoInterface | None = None
|
|
629
640
|
self.fact_symb: bool = False
|
|
630
641
|
self.A: np.ndarray = None
|
|
@@ -637,29 +648,30 @@ class SolverPardiso(Solver):
|
|
|
637
648
|
self.initialized = True
|
|
638
649
|
|
|
639
650
|
def solve(self, A, b, precon, reuse_factorization: bool = False, id: int = -1) -> tuple[np.ndarray, SolveReport]:
|
|
640
|
-
logger.info(f'
|
|
651
|
+
logger.info(f'{_pfx(self.pre,id)} Calling Pardiso Solver')
|
|
641
652
|
if self.fact_symb is False:
|
|
642
|
-
logger.trace(f'
|
|
653
|
+
logger.trace(f'{_pfx(self.pre,id)} Executing symbollic factorization.')
|
|
643
654
|
self.solver.symbolic(A)
|
|
644
655
|
self.fact_symb = True
|
|
645
656
|
if not reuse_factorization:
|
|
646
|
-
logger.trace(f'
|
|
657
|
+
logger.trace(f'{_pfx(self.pre,id)} Executing numeric factorization.')
|
|
647
658
|
self.solver.numeric(A)
|
|
648
659
|
self.A = A
|
|
649
|
-
logger.trace(f'
|
|
660
|
+
logger.trace(f'{_pfx(self.pre,id)} Solving linear system.')
|
|
650
661
|
x, error = self.solver.solve(A, b)
|
|
651
662
|
if error != 0:
|
|
652
|
-
logger.error(f'
|
|
653
|
-
logger.error(self.solver.get_error(error))
|
|
654
|
-
raise SimulationError(f'
|
|
663
|
+
logger.error(f'{_pfx(self.pre,id)} Terminated with error code {error}')
|
|
664
|
+
logger.error(self.pre + self.solver.get_error(error))
|
|
665
|
+
raise SimulationError(f'{_pfx(self.pre,id)} PARDISO Terminated with error code {error}')
|
|
655
666
|
aux = {}
|
|
656
667
|
return x, SolveReport(solver=str(self), exit_code=error, aux=aux)
|
|
657
668
|
|
|
658
669
|
|
|
659
670
|
class SolverCuDSS(Solver):
|
|
660
671
|
real_only = False
|
|
661
|
-
|
|
662
|
-
|
|
672
|
+
|
|
673
|
+
def __init__(self, pre: str):
|
|
674
|
+
super().__init__(pre)
|
|
663
675
|
self._cudss: CuDSSInterface | None = None
|
|
664
676
|
self.fact_symb: bool = False
|
|
665
677
|
self.fact_numb: bool = False
|
|
@@ -676,18 +688,18 @@ class SolverCuDSS(Solver):
|
|
|
676
688
|
self.fact_numb = False
|
|
677
689
|
|
|
678
690
|
def solve(self, A, b, precon, reuse_factorization: bool = False, id: int = -1):
|
|
679
|
-
logger.info(f'
|
|
691
|
+
logger.info(f'{_pfx(self.pre,id)} Calling cuDSS Solver')
|
|
680
692
|
|
|
681
693
|
if self.fact_symb is False:
|
|
682
|
-
logger.trace(f'
|
|
694
|
+
logger.trace(f'{_pfx(self.pre,id)} Starting from symbollic factorization.')
|
|
683
695
|
x = self._cudss.from_symbolic(A,b)
|
|
684
696
|
self.fact_symb = True
|
|
685
697
|
else:
|
|
686
698
|
if reuse_factorization:
|
|
687
|
-
logger.trace(f'
|
|
699
|
+
logger.trace(f'{_pfx(self.pre,id)} Solving linear system.')
|
|
688
700
|
x = self._cudss.from_solve(b)
|
|
689
701
|
else:
|
|
690
|
-
logger.trace(f'
|
|
702
|
+
logger.trace(f'{_pfx(self.pre,id)} Starting from numeric factorization.')
|
|
691
703
|
x = self._cudss.from_numeric(A,b)
|
|
692
704
|
|
|
693
705
|
return x, SolveReport(solver=str(self), exit_code=0, aux={})
|
|
@@ -699,8 +711,6 @@ class SolverCuDSS(Solver):
|
|
|
699
711
|
|
|
700
712
|
class SolverLAPACK(EigSolver):
|
|
701
713
|
|
|
702
|
-
def __init__(self):
|
|
703
|
-
super().__init__()
|
|
704
714
|
|
|
705
715
|
def eig(self,
|
|
706
716
|
A: csr_matrix | csr_matrix,
|
|
@@ -725,7 +735,7 @@ class SolverLAPACK(EigSolver):
|
|
|
725
735
|
lam : (m,) real ndarray eigenvalues (m = n or k)
|
|
726
736
|
vecs : (n, m) complex ndarray eigenvectors, B-orthonormal (xiᴴ B xj = δij)
|
|
727
737
|
"""
|
|
728
|
-
logger.
|
|
738
|
+
logger.info(f'{_pfx(self.pre)} Calling LAPACK eig solver')
|
|
729
739
|
lam, vecs = eig(A.toarray(), B.toarray(), overwrite_a=True, overwrite_b=True, check_finite=False)
|
|
730
740
|
lam, vecs = filter_real_modes(lam, vecs, target_k0, 2, 2, sign=sign)
|
|
731
741
|
return lam, vecs
|
|
@@ -738,8 +748,6 @@ class SolverLAPACK(EigSolver):
|
|
|
738
748
|
|
|
739
749
|
class SolverARPACK(EigSolver):
|
|
740
750
|
""" Implements the Scipy ARPACK iterative eigenmode solver."""
|
|
741
|
-
def __init__(self):
|
|
742
|
-
super().__init__()
|
|
743
751
|
|
|
744
752
|
def eig(self,
|
|
745
753
|
A: csr_matrix | csr_matrix,
|
|
@@ -748,7 +756,7 @@ class SolverARPACK(EigSolver):
|
|
|
748
756
|
target_k0: float = 0,
|
|
749
757
|
which: str = 'LM',
|
|
750
758
|
sign: float = 1.0) -> tuple[np.ndarray, np.ndarray]:
|
|
751
|
-
logger.info(f'Searching around
|
|
759
|
+
logger.info(f'{_pfx(self.pre)} Searching around β = {target_k0:.2f} rad/m with ARPACK')
|
|
752
760
|
sigma = sign*(target_k0**2)
|
|
753
761
|
eigen_values, eigen_modes = eigs(A, k=nmodes, M=B, sigma=sigma, which=which)
|
|
754
762
|
return eigen_values, eigen_modes
|
|
@@ -758,8 +766,8 @@ class SmartARPACK_BMA(EigSolver):
|
|
|
758
766
|
|
|
759
767
|
The Solver searches in a geometric range around the target wave constant.
|
|
760
768
|
"""
|
|
761
|
-
def __init__(self):
|
|
762
|
-
super().__init__()
|
|
769
|
+
def __init__(self, pre: str):
|
|
770
|
+
super().__init__(pre)
|
|
763
771
|
self.symmetric_steps: int = 41
|
|
764
772
|
self.search_range: float = 2.0
|
|
765
773
|
self.energy_limit: float = 1e-4
|
|
@@ -772,7 +780,7 @@ class SmartARPACK_BMA(EigSolver):
|
|
|
772
780
|
which: str = 'LM',
|
|
773
781
|
sign: float = 1.) -> tuple[np.ndarray, np.ndarray]:
|
|
774
782
|
|
|
775
|
-
logger.info(f'Searching around
|
|
783
|
+
logger.info(f'{_pfx(self.pre)} Searching around β = {target_k0:.2f} rad/m with SmartARPACK (BMA)')
|
|
776
784
|
qs = np.geomspace(1, self.search_range, self.symmetric_steps)
|
|
777
785
|
tot_eigen_values = []
|
|
778
786
|
tot_eigen_modes = []
|
|
@@ -808,8 +816,8 @@ class SmartARPACK(EigSolver):
|
|
|
808
816
|
|
|
809
817
|
The Solver searches in a geometric range around the target wave constant.
|
|
810
818
|
"""
|
|
811
|
-
def __init__(self):
|
|
812
|
-
super().__init__()
|
|
819
|
+
def __init__(self, pre: str):
|
|
820
|
+
super().__init__(pre)
|
|
813
821
|
self.symmetric_steps: int = 3
|
|
814
822
|
self.search_range: float = 2.0
|
|
815
823
|
self.energy_limit: float = 1e-4
|
|
@@ -821,7 +829,7 @@ class SmartARPACK(EigSolver):
|
|
|
821
829
|
target_k0: float = 0,
|
|
822
830
|
which: str = 'LM',
|
|
823
831
|
sign: float = 1.) -> tuple[np.ndarray, np.ndarray]:
|
|
824
|
-
logger.info(f'Searching around β = {target_k0:.2f} rad/m with SmartARPACK')
|
|
832
|
+
logger.info(f'{_pfx(self.pre)} Searching around β = {target_k0:.2f} rad/m with SmartARPACK')
|
|
825
833
|
qs = np.geomspace(1, self.search_range, self.symmetric_steps)
|
|
826
834
|
tot_eigen_values = []
|
|
827
835
|
tot_eigen_modes = []
|
|
@@ -871,14 +879,14 @@ class EMSolver(Enum):
|
|
|
871
879
|
SMART_ARPACK_BMA = 7
|
|
872
880
|
CUDSS = 8
|
|
873
881
|
|
|
874
|
-
def create_solver(self) -> Solver | EigSolver | None:
|
|
882
|
+
def create_solver(self, pre: str) -> Solver | EigSolver | None:
|
|
875
883
|
if self==EMSolver.UMFPACK and not _UMFPACK_AVAILABLE:
|
|
876
884
|
return None
|
|
877
885
|
elif self==EMSolver.PARDISO and not _PARDISO_AVAILABLE:
|
|
878
886
|
return None
|
|
879
887
|
if self==EMSolver.CUDSS and not _CUDSS_AVAILABLE:
|
|
880
888
|
return None
|
|
881
|
-
return self._clss()
|
|
889
|
+
return self._clss(pre)
|
|
882
890
|
|
|
883
891
|
@property
|
|
884
892
|
def _clss(self) -> type[Solver]:
|
|
@@ -907,11 +915,15 @@ class SolveRoutine:
|
|
|
907
915
|
and goes through a sequence of steps to solve a linear system or find eigenmodes.
|
|
908
916
|
|
|
909
917
|
"""
|
|
910
|
-
def __init__(self):
|
|
918
|
+
def __init__(self, thread_nr: int = 0, proc_nr: int = 0):
|
|
919
|
+
|
|
920
|
+
self.pre: str = ''
|
|
921
|
+
self._set_name(thread_nr, proc_nr)
|
|
922
|
+
|
|
911
923
|
|
|
912
924
|
self.sorter: Sorter = ReverseCuthillMckee()
|
|
913
925
|
self.precon: Preconditioner = ILUPrecon()
|
|
914
|
-
self.solvers: dict[EMSolver, Solver | EigSolver] = {slv: slv.create_solver() for slv in EMSolver}
|
|
926
|
+
self.solvers: dict[EMSolver, Solver | EigSolver] = {slv: slv.create_solver(self.pre) for slv in EMSolver}
|
|
915
927
|
self.solvers = {key: solver for key, solver in self.solvers.items() if solver is not None}
|
|
916
928
|
|
|
917
929
|
self.parallel: Literal['SI','MT','MP'] = 'SI'
|
|
@@ -922,8 +934,11 @@ class SolveRoutine:
|
|
|
922
934
|
self.use_sorter: bool = False
|
|
923
935
|
self.use_preconditioner: bool = False
|
|
924
936
|
self.use_direct: bool = True
|
|
937
|
+
|
|
925
938
|
|
|
926
|
-
|
|
939
|
+
def _set_name(self, thread_nr: int, proc_nr: int):
|
|
940
|
+
self.pre = f'p{int(proc_nr):02d}/t{int(thread_nr):02d}'
|
|
941
|
+
|
|
927
942
|
def __str__(self) -> str:
|
|
928
943
|
return 'SolveRoutine()'
|
|
929
944
|
|
|
@@ -936,11 +951,11 @@ class SolveRoutine:
|
|
|
936
951
|
Returns:
|
|
937
952
|
bool: If the solver is legal
|
|
938
953
|
"""
|
|
939
|
-
if any(isinstance(solver, solvertype) for solvertype in self.disabled_solver):
|
|
940
|
-
logger.warning(f'The selected solver {solver} cannot be used as it is disabled.')
|
|
954
|
+
if any(isinstance(solver, solvertype.__class__) for solvertype in self.disabled_solver):
|
|
955
|
+
logger.warning(self.pre + f'The selected solver {solver} cannot be used as it is disabled.')
|
|
941
956
|
return False
|
|
942
957
|
if self.parallel=='MT' and not solver.released_gil:
|
|
943
|
-
logger.warning(f'The selected solver {solver} cannot be used in MultiThreading as it does not release the GIL')
|
|
958
|
+
logger.warning(self.pre + f'The selected solver {solver} cannot be used in MultiThreading as it does not release the GIL')
|
|
944
959
|
return False
|
|
945
960
|
return True
|
|
946
961
|
|
|
@@ -969,9 +984,9 @@ class SolveRoutine:
|
|
|
969
984
|
return solver # type: ignore
|
|
970
985
|
for alternative in self.all_solvers:
|
|
971
986
|
if self._legal_solver(alternative):
|
|
972
|
-
logger.debug(f'Falling back on legal solver: {alternative}')
|
|
987
|
+
logger.debug(self.pre + f'Falling back on legal solver: {alternative}')
|
|
973
988
|
return alternative
|
|
974
|
-
raise RuntimeError(f'No legal solver could be found. The following are disabled: {self.disabled_solver}')
|
|
989
|
+
raise RuntimeError(self.pre + f'No legal solver could be found. The following are disabled: {self.disabled_solver}')
|
|
975
990
|
|
|
976
991
|
def duplicate(self) -> SolveRoutine:
|
|
977
992
|
"""Creates a copy of this SolveRoutine class object.
|
|
@@ -1009,13 +1024,15 @@ class SolveRoutine:
|
|
|
1009
1024
|
"""
|
|
1010
1025
|
for solver in solvers:
|
|
1011
1026
|
if isinstance(solver, EMSolver):
|
|
1012
|
-
self.disabled_solver.append(solver
|
|
1027
|
+
self.disabled_solver.append(self.solvers[solver])
|
|
1013
1028
|
else:
|
|
1014
|
-
self.disabled_solver.append(solver
|
|
1029
|
+
self.disabled_solver.append(solver)
|
|
1015
1030
|
|
|
1016
1031
|
def _configure_routine(self,
|
|
1017
1032
|
parallel: Literal['SI','MT','MP'] = 'SI',
|
|
1018
|
-
smart_search: bool = False
|
|
1033
|
+
smart_search: bool = False,
|
|
1034
|
+
thread_nr: int = 0,
|
|
1035
|
+
proc_nr: int = 0) -> SolveRoutine:
|
|
1019
1036
|
"""Configure the solver with the given settings
|
|
1020
1037
|
|
|
1021
1038
|
Args:
|
|
@@ -1032,6 +1049,12 @@ class SolveRoutine:
|
|
|
1032
1049
|
"""
|
|
1033
1050
|
self.parallel = parallel
|
|
1034
1051
|
self.smart_search = smart_search
|
|
1052
|
+
if thread_nr != 1 or proc_nr != 1:
|
|
1053
|
+
self._set_name(thread_nr, proc_nr)
|
|
1054
|
+
for solver in self.solvers.values():
|
|
1055
|
+
if not isinstance(solver, (Solver, EigSolver)):
|
|
1056
|
+
continue
|
|
1057
|
+
solver.pre = self.pre
|
|
1035
1058
|
return self
|
|
1036
1059
|
|
|
1037
1060
|
def configure(self,
|
|
@@ -1171,10 +1194,10 @@ class SolveRoutine:
|
|
|
1171
1194
|
bsel = b[solve_ids]
|
|
1172
1195
|
nnz = Asel.nnz
|
|
1173
1196
|
|
|
1174
|
-
logger.debug(f'
|
|
1197
|
+
logger.debug(f'{_pfx(self.pre,id)} Removed {NF-NS} prescribed DOFs ({NS:,} left, {nnz:,}≠0)')
|
|
1175
1198
|
|
|
1176
1199
|
if solver.real_only:
|
|
1177
|
-
logger.debug(f'
|
|
1200
|
+
logger.debug(f'{_pfx(self.pre,id)} Converting to real matrix')
|
|
1178
1201
|
Asel, bsel = complex_to_real_block(Asel, bsel)
|
|
1179
1202
|
|
|
1180
1203
|
# SORT
|
|
@@ -1197,8 +1220,8 @@ class SolveRoutine:
|
|
|
1197
1220
|
x_solved, report = solver.solve(Asorted, bsorted, self.precon, reuse_factorization=reuse, id=id)
|
|
1198
1221
|
end = time.time()
|
|
1199
1222
|
simtime = end-start
|
|
1200
|
-
logger.info(f'
|
|
1201
|
-
logger.debug(f'
|
|
1223
|
+
logger.info(f'{_pfx(self.pre,id)} Elapsed time taken: {simtime:.3f} seconds')
|
|
1224
|
+
logger.debug(f'{_pfx(self.pre,id)} O(N²) performance = {(NS**2)/((end-start+1e-6)*1e6):.3f} MDoF/s')
|
|
1202
1225
|
|
|
1203
1226
|
if self.use_sorter and solver.req_sorter:
|
|
1204
1227
|
x = self.sorter.unsort(x_solved)
|
|
@@ -1206,14 +1229,14 @@ class SolveRoutine:
|
|
|
1206
1229
|
x = x_solved
|
|
1207
1230
|
|
|
1208
1231
|
if solver.real_only:
|
|
1209
|
-
logger.debug(f'
|
|
1232
|
+
logger.debug(f'{_pfx(self.pre,id)} Converting back to complex matrix')
|
|
1210
1233
|
x = real_to_complex_block(x)
|
|
1211
1234
|
|
|
1212
1235
|
solution = np.zeros((NF,), dtype=np.complex128)
|
|
1213
1236
|
|
|
1214
1237
|
solution[solve_ids] = x
|
|
1215
1238
|
|
|
1216
|
-
logger.debug(f'
|
|
1239
|
+
logger.debug(f'{_pfx(self.pre,id)} Solver complete!')
|
|
1217
1240
|
report.jobid = id
|
|
1218
1241
|
report.sorter = str(sorter)
|
|
1219
1242
|
report.simtime = simtime
|
|
@@ -1222,6 +1245,7 @@ class SolveRoutine:
|
|
|
1222
1245
|
report.nnz_solve = Asorted.nnz
|
|
1223
1246
|
report.ndof_solve = bsorted.shape[0]
|
|
1224
1247
|
report.precon = precon
|
|
1248
|
+
report.worker_name = self.pre
|
|
1225
1249
|
|
|
1226
1250
|
return solution, report
|
|
1227
1251
|
|
|
@@ -1258,7 +1282,7 @@ class SolveRoutine:
|
|
|
1258
1282
|
NF = A.shape[0]
|
|
1259
1283
|
NS = solve_ids.shape[0]
|
|
1260
1284
|
|
|
1261
|
-
logger.debug(f'Removing {NF-NS} prescribed DOFs ({NS} left)')
|
|
1285
|
+
logger.debug(self.pre + f'Removing {NF-NS} prescribed DOFs ({NS} left)')
|
|
1262
1286
|
|
|
1263
1287
|
Asel = A[np.ix_(solve_ids, solve_ids)]
|
|
1264
1288
|
Bsel = B[np.ix_(solve_ids, solve_ids)]
|
|
@@ -1301,7 +1325,7 @@ class SolveRoutine:
|
|
|
1301
1325
|
NF = A.shape[0]
|
|
1302
1326
|
NS = solve_ids.shape[0]
|
|
1303
1327
|
|
|
1304
|
-
logger.debug(f'Removing {NF-NS} prescribed DOFs ({NS} left)')
|
|
1328
|
+
logger.debug(self.pre + f'Removing {NF-NS} prescribed DOFs ({NS} left)')
|
|
1305
1329
|
|
|
1306
1330
|
Asel = A[np.ix_(solve_ids, solve_ids)]
|
|
1307
1331
|
Bsel = B[np.ix_(solve_ids, solve_ids)]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: emerge
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.6
|
|
4
4
|
Summary: An open source EM FEM simulator in Python
|
|
5
5
|
Project-URL: Homepage, https://github.com/FennisRobert/EMerge
|
|
6
6
|
Project-URL: Issues, https://github.com/FennisRobert/EMerge/issues
|
|
@@ -32,7 +32,7 @@ Hello everybody. Thanks for showing interest in this repository.
|
|
|
32
32
|
Feel free to download your version of EMerge and start playing around with it!
|
|
33
33
|
If you have suggestions/changes/questions either use the Github issue system or join the Discord using the following link:
|
|
34
34
|
|
|
35
|
-
**https://discord.gg/
|
|
35
|
+
**[Discord Invitation](https://discord.gg/VMftDCZcNz)**
|
|
36
36
|
|
|
37
37
|
## How to install
|
|
38
38
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
emerge/__init__.py,sha256=
|
|
1
|
+
emerge/__init__.py,sha256=m1aBdjv_Ae2k7RzIgtl-5CMEH5FQmWw28SOk0V_ro0Y,3162
|
|
2
2
|
emerge/__main__.py,sha256=WVf16sfrOI910QWohrQDaChZdRifMNoS6VKzCT6f3ZA,92
|
|
3
3
|
emerge/cli.py,sha256=NU1uhwuZ6i50680v3_I4kDZPTHqz74gOYK71UBhb8oE,666
|
|
4
4
|
emerge/ext.py,sha256=IBoHH5PQFj5pYMfp6r-uMpNNgbSe8c0g9x8qjBzzVmU,223
|
|
@@ -14,19 +14,19 @@ emerge/_emerge/cs.py,sha256=gULfov6s0jODOdQkH6NmGBbG5wvny1-bJU8fdAlpCHo,19730
|
|
|
14
14
|
emerge/_emerge/dataset.py,sha256=UcSAJ_siLrOjNBBWRWsS3GUZUpayp63EM6pP6ClwKDI,1534
|
|
15
15
|
emerge/_emerge/emerge_update.py,sha256=0G91xr7k7Me5gOlk3pXbKWe-6ALXtoCJ5syTa1Y5Bhw,2042
|
|
16
16
|
emerge/_emerge/geo2d.py,sha256=e_HkX1GQ2iYrdO0zeEgzVOzfGyU1WGJyjeGBAobOttE,3323
|
|
17
|
-
emerge/_emerge/geometry.py,sha256
|
|
17
|
+
emerge/_emerge/geometry.py,sha256=9WnZt2xtF4HEJfdPyT41i_q8gRMZRrG0C9PILaz1PvA,25523
|
|
18
18
|
emerge/_emerge/howto.py,sha256=c4UxUNpA1tygr3OoR-LH-h0UZv-Tf9K8tpCiAU18BKE,8173
|
|
19
19
|
emerge/_emerge/logsettings.py,sha256=OpsH_1dQAdZry_as8y0OQt4yKP_AMFfQG2d5Nz5yywg,4789
|
|
20
|
-
emerge/_emerge/material.py,sha256=
|
|
20
|
+
emerge/_emerge/material.py,sha256=zXmKEZctqz4T574KSfRMdhiT2F_6l-QwiqlxNx6zkI0,17451
|
|
21
21
|
emerge/_emerge/mesh3d.py,sha256=6NWTqJVwyaOhFKQgNghkH3zgrYFWbI0qAEBpvq-JOwI,35790
|
|
22
|
-
emerge/_emerge/mesher.py,sha256=
|
|
22
|
+
emerge/_emerge/mesher.py,sha256=AUrMhXHHf1O5QtEyKlB172kV0B17jq9nzjq4JADZTV4,16079
|
|
23
23
|
emerge/_emerge/periodic.py,sha256=dUuWqjlDR8mHtQR3ecINP2FFjJJ0cKg0blOVZ0PCcAo,12087
|
|
24
24
|
emerge/_emerge/plot.py,sha256=cf1I9mj7EIUJcq8vmANlUkqoV6QqVaJaP-zlC-T9E18,8041
|
|
25
25
|
emerge/_emerge/selection.py,sha256=ltT8ubMFG3-sFrAh7K7iAgSoBt3r25B02ShzMlOGSXQ,21527
|
|
26
26
|
emerge/_emerge/settings.py,sha256=wZFMzQSnMEEJptatu--67El1L0I_YEv9S8QjqI69bfs,265
|
|
27
|
-
emerge/_emerge/simmodel.py,sha256=
|
|
27
|
+
emerge/_emerge/simmodel.py,sha256=yw21pUhO2_BB3vTN4UY7fhZxXuWNvcTaA5xRCcUg7vs,26525
|
|
28
28
|
emerge/_emerge/simulation_data.py,sha256=23o-xbm6Q6s9sYisyK9u1GTmuaXRl0WDGQwzPO7lkr0,15115
|
|
29
|
-
emerge/_emerge/solver.py,sha256=
|
|
29
|
+
emerge/_emerge/solver.py,sha256=imgvQkVE9B3QEA1WmsBhhOLzHO44-Oh-onMXmLnfCFY,52980
|
|
30
30
|
emerge/_emerge/system.py,sha256=p4HNz7d_LMRNE9Gk75vVdFecDH2iN_groAM9u-yQTpk,1618
|
|
31
31
|
emerge/_emerge/elements/__init__.py,sha256=I3n9aic6lJW-oGeqTEZ-Fpxvyl2i-WqsHdnrM3v1oB8,799
|
|
32
32
|
emerge/_emerge/elements/femdata.py,sha256=ZSB7dICyU3GOWbxpuowBc-Khh2mpXa02ZfMkHwdDol4,8377
|
|
@@ -35,13 +35,13 @@ emerge/_emerge/elements/ned2_interp.py,sha256=BGRdJGXCcDdqMBf3pOvc_-m-vngRI1VvE5
|
|
|
35
35
|
emerge/_emerge/elements/nedelec2.py,sha256=OssFCnPp7wkMBcUISGvTgT94jayfGOmX0x-RctIYSuI,6645
|
|
36
36
|
emerge/_emerge/elements/nedleg2.py,sha256=1SA6AvnbChhU2iodS1PVMUdbSn9wF2XKam12WTBDtsw,9049
|
|
37
37
|
emerge/_emerge/geo/__init__.py,sha256=yTeuT4Oexrsdkr7MxRLeTHEY5iP4IHsWeCvit57fK5g,1161
|
|
38
|
-
emerge/_emerge/geo/horn.py,sha256=
|
|
38
|
+
emerge/_emerge/geo/horn.py,sha256=tI-w-O0Fm_siMaVhKpZ_k5URLfZkqcbEpURX94fhKDs,4645
|
|
39
39
|
emerge/_emerge/geo/modeler.py,sha256=_PMz3lFSa7FmJHWdY-4U1Sqbed-Egy85S_AdjlCldC4,15572
|
|
40
|
-
emerge/_emerge/geo/operations.py,sha256=
|
|
41
|
-
emerge/_emerge/geo/pcb.py,sha256=
|
|
40
|
+
emerge/_emerge/geo/operations.py,sha256=WYWfOXWrT0voeKW9U26g-PhQfqJl3ovRQ8uDQXUr7Nc,12459
|
|
41
|
+
emerge/_emerge/geo/pcb.py,sha256=oRx9CnFFzhnDNtwxnw2rcm_CtN1h2y3-0jXOaBqGZ_E,57544
|
|
42
42
|
emerge/_emerge/geo/pmlbox.py,sha256=gaIG_AoZNQnIyJ8C7x64U-Hw5dsmllWMiZDAH4iRoM0,8784
|
|
43
|
-
emerge/_emerge/geo/polybased.py,sha256=
|
|
44
|
-
emerge/_emerge/geo/shapes.py,sha256=
|
|
43
|
+
emerge/_emerge/geo/polybased.py,sha256=D_Ef4anrwV2RArEFrvWppZ_c7oN_Hm5h7ltMi2U3v2o,32891
|
|
44
|
+
emerge/_emerge/geo/shapes.py,sha256=bLZM8ey05yvpKGgZS_DXFDaTQRP5kpsc7Xgp6Xaxc_Q,26903
|
|
45
45
|
emerge/_emerge/geo/step.py,sha256=XcAiEN8W4umNmZdYmrGHX_aJUuiMgc6vgT-UIk8Gbqc,2689
|
|
46
46
|
emerge/_emerge/geo/pcb_tools/calculator.py,sha256=VbMP2xC9i7OFwtqnnwfYgyJSEcJIjr2VIy_Ez1hYqlU,859
|
|
47
47
|
emerge/_emerge/geo/pcb_tools/dxf.py,sha256=Xv7iP_bB0f2Y46sxZloa5KYGyj5dtApXoR-kgL7KHZA,11744
|
|
@@ -54,17 +54,17 @@ emerge/_emerge/mth/pairing.py,sha256=i8bBvTeMmzgF0JdiDNJiTXxx913x4f10777pzD6FJo0
|
|
|
54
54
|
emerge/_emerge/physics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
55
|
emerge/_emerge/physics/microwave/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
56
56
|
emerge/_emerge/physics/microwave/adaptive_freq.py,sha256=aWhijhCVAbnuwkru-I1AaRdY20uyozf6OWRIh9r2ijg,9786
|
|
57
|
-
emerge/_emerge/physics/microwave/microwave_3d.py,sha256=
|
|
58
|
-
emerge/_emerge/physics/microwave/microwave_bc.py,sha256=
|
|
59
|
-
emerge/_emerge/physics/microwave/microwave_data.py,sha256=
|
|
57
|
+
emerge/_emerge/physics/microwave/microwave_3d.py,sha256=mnfD6QPNVqtMMayu73yRdvErqL2-mPSqiKbOte9a3GQ,44632
|
|
58
|
+
emerge/_emerge/physics/microwave/microwave_bc.py,sha256=bMV3SrIE5BNTdBbTncwy0N67TERsYWzzFypzFgDBW54,43697
|
|
59
|
+
emerge/_emerge/physics/microwave/microwave_data.py,sha256=yAjWGzpTa14JfYKJVMMwx3ETONK_mjYRz98iDKEdDk8,49893
|
|
60
60
|
emerge/_emerge/physics/microwave/periodic.py,sha256=wYSUgLFVtCLqSG3EDKoCDRU93iPUzBdXzVRdHTRmbpI,3000
|
|
61
61
|
emerge/_emerge/physics/microwave/port_functions.py,sha256=d-W1D-7P05MfXdOs7WlhPi_RqlSpC0HkYU6yl3GrxgE,2173
|
|
62
62
|
emerge/_emerge/physics/microwave/sc.py,sha256=WZvoPhmHkfEv619RhmN09sXDBV0ryTqybwErA8Rc7lU,4735
|
|
63
63
|
emerge/_emerge/physics/microwave/simjob.py,sha256=aCWCs7IXBfVBWWYhwyHvXSRHY3FOd3CK5ABcaFEsNnM,4927
|
|
64
64
|
emerge/_emerge/physics/microwave/sparam.py,sha256=1SXGyr1UsrPnCIi4ffwobM4pzgkj50y4LrWCr_J5IRY,4946
|
|
65
65
|
emerge/_emerge/physics/microwave/touchstone.py,sha256=pMcCOLWVqIKctcShcJxyaV-0rhRWXMSS1Jz14dVQEyY,5799
|
|
66
|
-
emerge/_emerge/physics/microwave/assembly/assembler.py,sha256=
|
|
67
|
-
emerge/_emerge/physics/microwave/assembly/curlcurl.py,sha256=
|
|
66
|
+
emerge/_emerge/physics/microwave/assembly/assembler.py,sha256=sNsAa2bTSe9-tYMRePTOE2EKrqZhsJChD_anr4GC4Vo,23936
|
|
67
|
+
emerge/_emerge/physics/microwave/assembly/curlcurl.py,sha256=4CwMSUua8pvbp39gq2e3AxwVHOIVuPdr53qQM2BigQo,19688
|
|
68
68
|
emerge/_emerge/physics/microwave/assembly/generalized_eigen.py,sha256=7jNU_hWd7q-ni53wmlhB5kmyJxp2xsx_WyBXZ6hPwo0,16907
|
|
69
69
|
emerge/_emerge/physics/microwave/assembly/generalized_eigen_hb.py,sha256=tGf9EOzmp-dqtTodwYzcswuT_eLeZRtgdAZvgPz9QJo,17340
|
|
70
70
|
emerge/_emerge/physics/microwave/assembly/periodicbc.py,sha256=N64uGx49Qs0PJxi_EH5pLx0zcrgJxqMy6DI1TqVXfmQ,4645
|
|
@@ -76,7 +76,7 @@ emerge/_emerge/plot/simple_plots.py,sha256=szIpmQmO8o6ubzB_E3zTJfEx16mJ3-OXrMYdD
|
|
|
76
76
|
emerge/_emerge/plot/matplotlib/mpldisplay.py,sha256=e8V6EhGdCW7nRkSFvjHCcRO5uR-FcD0yHQ1nxPQCbp4,8674
|
|
77
77
|
emerge/_emerge/plot/pyvista/__init__.py,sha256=CPclatEu6mFnJZzCQk09g6T6Fh20WTbiLAJGSwAnPXU,30
|
|
78
78
|
emerge/_emerge/plot/pyvista/cmap_maker.py,sha256=_GVXYdtXpJwAO9O-Iekjzn6YcR0MVT8LNh12nqvF2IA,2498
|
|
79
|
-
emerge/_emerge/plot/pyvista/display.py,sha256=
|
|
79
|
+
emerge/_emerge/plot/pyvista/display.py,sha256=k5hkIGZCyzYXw1zdDtWCDRwm2dwO0Xz8Sw9YTGGPo5k,45356
|
|
80
80
|
emerge/_emerge/plot/pyvista/display_settings.py,sha256=gV5hjRGEAl3oQeBPobas6b6JzYfMFrXIGtVSaeml4N0,1074
|
|
81
81
|
emerge/_emerge/projects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
82
82
|
emerge/_emerge/projects/_gen_base.txt,sha256=DqQz36PZg6v1ovQjHvPjd0t4AIbmikZdb9dmrNYsK3w,598
|
|
@@ -88,8 +88,8 @@ emerge/beta/dxf.py,sha256=Bw4lVk0TquOgCxTZV23BZN7PrgqxBrMZxbHV1waC5U0,50
|
|
|
88
88
|
emerge/materials/__init__.py,sha256=Z9tu3m_nqj6F9I-FwoVoN0vCTYUlFesH3KxJ38wkZck,19
|
|
89
89
|
emerge/materials/isola.py,sha256=kSDxHJZVn2CcanoUjlwRVKIPvadRbBybURTdIHWx728,18660
|
|
90
90
|
emerge/materials/rogers.py,sha256=4u6ma_XQdXGKWE3WsFkaMTamCQNo9kTYSTU8S1gCAYU,3388
|
|
91
|
-
emerge-1.0.
|
|
92
|
-
emerge-1.0.
|
|
93
|
-
emerge-1.0.
|
|
94
|
-
emerge-1.0.
|
|
95
|
-
emerge-1.0.
|
|
91
|
+
emerge-1.0.6.dist-info/METADATA,sha256=wJysFFkQJJgPoC2pdAtzEvWLsMPB-usHAQweDuNwPqk,3306
|
|
92
|
+
emerge-1.0.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
93
|
+
emerge-1.0.6.dist-info/entry_points.txt,sha256=8rFvAXticpKg4OTC8JEvAksnduW72KIEskCGG9XnFf8,43
|
|
94
|
+
emerge-1.0.6.dist-info/licenses/LICENSE,sha256=VOCXWddrjMN5j7TvnSAOh1Dx7jkugdwq9Lqhycf5inc,17852
|
|
95
|
+
emerge-1.0.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|