emerge 1.0.5__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/pcb.py +10 -6
- emerge/_emerge/geo/polybased.py +16 -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 +1 -1
- emerge/_emerge/solver.py +92 -72
- {emerge-1.0.5.dist-info → emerge-1.0.6.dist-info}/METADATA +1 -1
- {emerge-1.0.5.dist-info → emerge-1.0.6.dist-info}/RECORD +21 -21
- {emerge-1.0.5.dist-info → emerge-1.0.6.dist-info}/WHEEL +0 -0
- {emerge-1.0.5.dist-info → emerge-1.0.6.dist-info}/entry_points.txt +0 -0
- {emerge-1.0.5.dist-info → emerge-1.0.6.dist-info}/licenses/LICENSE +0 -0
emerge/_emerge/solver.py
CHANGED
|
@@ -90,6 +90,7 @@ 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():
|
|
@@ -117,6 +118,7 @@ class SolveReport:
|
|
|
117
118
|
parts.append(fmt("DOFsSolve", self.ndof_solve))
|
|
118
119
|
parts.append(fmt("NNZSolve", self.nnz_solve))
|
|
119
120
|
parts.append(fmt("Exit", self.exit_code))
|
|
121
|
+
parts.append(fmt("Worker",self.worker_name))
|
|
120
122
|
|
|
121
123
|
if self.aux:
|
|
122
124
|
for k, v in self.aux.items():
|
|
@@ -159,6 +161,7 @@ class SolveReport:
|
|
|
159
161
|
row("DOFs (Solve)", self.ndof_solve)
|
|
160
162
|
row("NNZ (Solve)", self.nnz_solve)
|
|
161
163
|
row("Exit Code", self.exit_code)
|
|
164
|
+
row("Worker", self.worker_name)
|
|
162
165
|
print_cal(border)
|
|
163
166
|
|
|
164
167
|
if self.aux:
|
|
@@ -168,6 +171,8 @@ class SolveReport:
|
|
|
168
171
|
row(str(k), v)
|
|
169
172
|
print_cal(border)
|
|
170
173
|
|
|
174
|
+
def _pfx(name: str, id: int = 0) -> str:
|
|
175
|
+
return f'[{name}-j{id:03d}]'
|
|
171
176
|
############################################################
|
|
172
177
|
# EIGENMODE FILTER ROUTINE #
|
|
173
178
|
############################################################
|
|
@@ -326,9 +331,10 @@ class Solver:
|
|
|
326
331
|
req_sorter: bool = False
|
|
327
332
|
released_gil: bool = False
|
|
328
333
|
|
|
329
|
-
def __init__(self):
|
|
334
|
+
def __init__(self, pre: str = ''):
|
|
330
335
|
self.own_preconditioner: bool = False
|
|
331
336
|
self.initialized: bool = False
|
|
337
|
+
self.pre: str = pre
|
|
332
338
|
|
|
333
339
|
def __str__(self) -> str:
|
|
334
340
|
return f'{self.__class__.__name__}'
|
|
@@ -364,8 +370,9 @@ class EigSolver:
|
|
|
364
370
|
real_only: bool = False
|
|
365
371
|
req_sorter: bool = False
|
|
366
372
|
|
|
367
|
-
def __init__(self):
|
|
373
|
+
def __init__(self, pre: str = ''):
|
|
368
374
|
self.own_preconditioner: bool = False
|
|
375
|
+
self.pre: str = pre
|
|
369
376
|
|
|
370
377
|
def initialize(self) -> None:
|
|
371
378
|
return None
|
|
@@ -374,7 +381,7 @@ class EigSolver:
|
|
|
374
381
|
return f'{self.__class__.__name__}'
|
|
375
382
|
|
|
376
383
|
def duplicate(self) -> Solver:
|
|
377
|
-
return self.__class__()
|
|
384
|
+
return self.__class__(self.pre)
|
|
378
385
|
|
|
379
386
|
def eig(self, A: csr_matrix | csr_matrix, B: csr_matrix | csr_matrix, nmodes: int = 6,
|
|
380
387
|
target_k0: float = 0.0, which: str = 'LM', sign: float = 1.):
|
|
@@ -448,10 +455,10 @@ class SolverBicgstab(Solver):
|
|
|
448
455
|
|
|
449
456
|
def callback(self, xk):
|
|
450
457
|
convergence = np.linalg.norm((self.A @ xk - self.b))
|
|
451
|
-
logger.info(f'Iteration {convergence:.4f}')
|
|
458
|
+
logger.info(self.pre + f'Iteration {convergence:.4f}')
|
|
452
459
|
|
|
453
460
|
def solve(self, A, b, precon, reuse_factorization: bool = False, id: int = -1) -> tuple[np.ndarray, SolveReport]:
|
|
454
|
-
logger.info(f'
|
|
461
|
+
logger.info(f'{_pfx(self.pre,id)} Calling BiCGStab.')
|
|
455
462
|
self.A = A
|
|
456
463
|
self.b = b
|
|
457
464
|
if precon.M is not None:
|
|
@@ -470,10 +477,10 @@ class SolverGCROTMK(Solver):
|
|
|
470
477
|
|
|
471
478
|
def callback(self, xk):
|
|
472
479
|
convergence = np.linalg.norm((self.A @ xk - self.b))
|
|
473
|
-
logger.info(f'Iteration {convergence:.4f}')
|
|
480
|
+
logger.info(self.pre + f'Iteration {convergence:.4f}')
|
|
474
481
|
|
|
475
482
|
def solve(self, A: csr_matrix, b: np.ndarray, precon: Preconditioner, reuse_factorization: bool = False, id: int = -1) -> tuple[np.ndarray, SolveReport]:
|
|
476
|
-
logger.info(f'
|
|
483
|
+
logger.info(f'{_pfx(self.pre,id)} Calling GCRO-T(m,k) algorithm')
|
|
477
484
|
self.A = A
|
|
478
485
|
self.b = b
|
|
479
486
|
if precon.M is not None:
|
|
@@ -496,10 +503,10 @@ class SolverGMRES(Solver):
|
|
|
496
503
|
|
|
497
504
|
def callback(self, norm):
|
|
498
505
|
#convergence = np.linalg.norm((self.A @ xk - self.b))
|
|
499
|
-
logger.info(f'Iteration {norm:.4f}')
|
|
506
|
+
logger.info(self.pre + f'Iteration {norm:.4f}')
|
|
500
507
|
|
|
501
508
|
def solve(self, A, b, precon, reuse_factorization: bool = False, id: int = -1) -> tuple[np.ndarray, SolveReport]:
|
|
502
|
-
logger.info(f'
|
|
509
|
+
logger.info(f'{_pfx(self.pre,id)} Calling GMRES Function.')
|
|
503
510
|
self.A = A
|
|
504
511
|
self.b = b
|
|
505
512
|
if precon.M is not None:
|
|
@@ -520,8 +527,8 @@ class SolverSuperLU(Solver):
|
|
|
520
527
|
real_only: bool = False
|
|
521
528
|
released_gil: bool = True
|
|
522
529
|
|
|
523
|
-
def __init__(self):
|
|
524
|
-
super().__init__()
|
|
530
|
+
def __init__(self, pre: str):
|
|
531
|
+
super().__init__(pre)
|
|
525
532
|
self.atol = 1e-5
|
|
526
533
|
|
|
527
534
|
self.A: np.ndarray = None
|
|
@@ -531,7 +538,7 @@ class SolverSuperLU(Solver):
|
|
|
531
538
|
self.lu = None
|
|
532
539
|
|
|
533
540
|
def duplicate(self) -> Solver:
|
|
534
|
-
new_solver = self.__class__()
|
|
541
|
+
new_solver = self.__class__(self.pre)
|
|
535
542
|
new_solver._pivoting_threshold = self._pivoting_threshold
|
|
536
543
|
return new_solver
|
|
537
544
|
|
|
@@ -541,11 +548,11 @@ class SolverSuperLU(Solver):
|
|
|
541
548
|
self._pivoting_threshold = pivoting_threshold
|
|
542
549
|
|
|
543
550
|
def solve(self, A, b, precon, reuse_factorization: bool = False, id: int = -1) -> tuple[np.ndarray, SolveReport]:
|
|
544
|
-
logger.info(f'
|
|
551
|
+
logger.info(f'{_pfx(self.pre,id)} Calling SuperLU Solver.')
|
|
545
552
|
|
|
546
553
|
self.single = True
|
|
547
554
|
if not reuse_factorization:
|
|
548
|
-
logger.trace('Computing LU-Decomposition')
|
|
555
|
+
logger.trace(self.pre + 'Computing LU-Decomposition')
|
|
549
556
|
self.lu = splu(A, permc_spec='MMD_AT_PLUS_A', relax=0, diag_pivot_thresh=self._pivoting_threshold, options=self.options)
|
|
550
557
|
x = self.lu.solve(b)
|
|
551
558
|
aux = {
|
|
@@ -558,9 +565,9 @@ class SolverUMFPACK(Solver):
|
|
|
558
565
|
req_sorter = False
|
|
559
566
|
real_only = False
|
|
560
567
|
|
|
561
|
-
def __init__(self):
|
|
562
|
-
super().__init__()
|
|
563
|
-
logger.trace('Creating UMFPACK solver')
|
|
568
|
+
def __init__(self, pre: str):
|
|
569
|
+
super().__init__(pre)
|
|
570
|
+
logger.trace(self.pre + 'Creating UMFPACK solver')
|
|
564
571
|
self.A: np.ndarray = None
|
|
565
572
|
self.b: np.ndarray = None
|
|
566
573
|
|
|
@@ -575,7 +582,7 @@ class SolverUMFPACK(Solver):
|
|
|
575
582
|
def initialize(self):
|
|
576
583
|
if self.initalized:
|
|
577
584
|
return
|
|
578
|
-
logger.trace('Initializing UMFPACK Solver')
|
|
585
|
+
logger.trace(self.pre + 'Initializing UMFPACK Solver')
|
|
579
586
|
self.umfpack = um.UmfpackContext('zl')
|
|
580
587
|
self.umfpack.control[um.UMFPACK_PRL] = 0 # ty: ignore
|
|
581
588
|
self.umfpack.control[um.UMFPACK_IRSTEP] = 2 # ty: ignore
|
|
@@ -588,7 +595,7 @@ class SolverUMFPACK(Solver):
|
|
|
588
595
|
self.initalized = True
|
|
589
596
|
|
|
590
597
|
def reset(self) -> None:
|
|
591
|
-
logger.trace('Resetting UMFPACK solver state')
|
|
598
|
+
logger.trace(self.pre + 'Resetting UMFPACK solver state')
|
|
592
599
|
self.fact_symb = False
|
|
593
600
|
|
|
594
601
|
def set_options(self, pivoting_threshold: float | None = None) -> None:
|
|
@@ -599,23 +606,23 @@ class SolverUMFPACK(Solver):
|
|
|
599
606
|
self._pivoting_threshold = pivoting_threshold
|
|
600
607
|
|
|
601
608
|
def duplicate(self) -> Solver:
|
|
602
|
-
new_solver = self.__class__()
|
|
609
|
+
new_solver = self.__class__(self.pre)
|
|
603
610
|
new_solver.set_options(pivoting_threshold = self._pivoting_threshold)
|
|
604
611
|
return new_solver
|
|
605
612
|
|
|
606
613
|
def solve(self, A, b, precon, reuse_factorization: bool = False, id: int = -1) -> tuple[np.ndarray, SolveReport]:
|
|
607
|
-
logger.info(f'
|
|
614
|
+
logger.info(f'{_pfx(self.pre,id)} Calling UMFPACK Solver.')
|
|
608
615
|
A.indptr = A.indptr.astype(np.int64)
|
|
609
616
|
A.indices = A.indices.astype(np.int64)
|
|
610
617
|
if self.fact_symb is False:
|
|
611
|
-
logger.trace(f'
|
|
618
|
+
logger.trace(f'{_pfx(self.pre,id)} Executing symbollic factorization.')
|
|
612
619
|
self.umfpack.symbolic(A)
|
|
613
620
|
self.fact_symb = True
|
|
614
621
|
if not reuse_factorization:
|
|
615
|
-
logger.trace(f'
|
|
622
|
+
logger.trace(f'{_pfx(self.pre,id)} Executing numeric factorization.')
|
|
616
623
|
self.umfpack.numeric(A)
|
|
617
624
|
self.A = A
|
|
618
|
-
logger.trace(f'
|
|
625
|
+
logger.trace(f'{_pfx(self.pre,id)} Solving linear system.')
|
|
619
626
|
x = self.umfpack.solve(um.UMFPACK_A, self.A, b, autoTranspose = False ) # ty: ignore
|
|
620
627
|
aux = {
|
|
621
628
|
"Pivoting Threshold": str(self._pivoting_threshold),
|
|
@@ -627,8 +634,8 @@ class SolverPardiso(Solver):
|
|
|
627
634
|
real_only: bool = False
|
|
628
635
|
req_sorter: bool = False
|
|
629
636
|
|
|
630
|
-
def __init__(self):
|
|
631
|
-
super().__init__()
|
|
637
|
+
def __init__(self, pre: str):
|
|
638
|
+
super().__init__(pre)
|
|
632
639
|
self.solver: PardisoInterface | None = None
|
|
633
640
|
self.fact_symb: bool = False
|
|
634
641
|
self.A: np.ndarray = None
|
|
@@ -641,29 +648,30 @@ class SolverPardiso(Solver):
|
|
|
641
648
|
self.initialized = True
|
|
642
649
|
|
|
643
650
|
def solve(self, A, b, precon, reuse_factorization: bool = False, id: int = -1) -> tuple[np.ndarray, SolveReport]:
|
|
644
|
-
logger.info(f'
|
|
651
|
+
logger.info(f'{_pfx(self.pre,id)} Calling Pardiso Solver')
|
|
645
652
|
if self.fact_symb is False:
|
|
646
|
-
logger.trace(f'
|
|
653
|
+
logger.trace(f'{_pfx(self.pre,id)} Executing symbollic factorization.')
|
|
647
654
|
self.solver.symbolic(A)
|
|
648
655
|
self.fact_symb = True
|
|
649
656
|
if not reuse_factorization:
|
|
650
|
-
logger.trace(f'
|
|
657
|
+
logger.trace(f'{_pfx(self.pre,id)} Executing numeric factorization.')
|
|
651
658
|
self.solver.numeric(A)
|
|
652
659
|
self.A = A
|
|
653
|
-
logger.trace(f'
|
|
660
|
+
logger.trace(f'{_pfx(self.pre,id)} Solving linear system.')
|
|
654
661
|
x, error = self.solver.solve(A, b)
|
|
655
662
|
if error != 0:
|
|
656
|
-
logger.error(f'
|
|
657
|
-
logger.error(self.solver.get_error(error))
|
|
658
|
-
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}')
|
|
659
666
|
aux = {}
|
|
660
667
|
return x, SolveReport(solver=str(self), exit_code=error, aux=aux)
|
|
661
668
|
|
|
662
669
|
|
|
663
670
|
class SolverCuDSS(Solver):
|
|
664
671
|
real_only = False
|
|
665
|
-
|
|
666
|
-
|
|
672
|
+
|
|
673
|
+
def __init__(self, pre: str):
|
|
674
|
+
super().__init__(pre)
|
|
667
675
|
self._cudss: CuDSSInterface | None = None
|
|
668
676
|
self.fact_symb: bool = False
|
|
669
677
|
self.fact_numb: bool = False
|
|
@@ -680,18 +688,18 @@ class SolverCuDSS(Solver):
|
|
|
680
688
|
self.fact_numb = False
|
|
681
689
|
|
|
682
690
|
def solve(self, A, b, precon, reuse_factorization: bool = False, id: int = -1):
|
|
683
|
-
logger.info(f'
|
|
691
|
+
logger.info(f'{_pfx(self.pre,id)} Calling cuDSS Solver')
|
|
684
692
|
|
|
685
693
|
if self.fact_symb is False:
|
|
686
|
-
logger.trace(f'
|
|
694
|
+
logger.trace(f'{_pfx(self.pre,id)} Starting from symbollic factorization.')
|
|
687
695
|
x = self._cudss.from_symbolic(A,b)
|
|
688
696
|
self.fact_symb = True
|
|
689
697
|
else:
|
|
690
698
|
if reuse_factorization:
|
|
691
|
-
logger.trace(f'
|
|
699
|
+
logger.trace(f'{_pfx(self.pre,id)} Solving linear system.')
|
|
692
700
|
x = self._cudss.from_solve(b)
|
|
693
701
|
else:
|
|
694
|
-
logger.trace(f'
|
|
702
|
+
logger.trace(f'{_pfx(self.pre,id)} Starting from numeric factorization.')
|
|
695
703
|
x = self._cudss.from_numeric(A,b)
|
|
696
704
|
|
|
697
705
|
return x, SolveReport(solver=str(self), exit_code=0, aux={})
|
|
@@ -703,8 +711,6 @@ class SolverCuDSS(Solver):
|
|
|
703
711
|
|
|
704
712
|
class SolverLAPACK(EigSolver):
|
|
705
713
|
|
|
706
|
-
def __init__(self):
|
|
707
|
-
super().__init__()
|
|
708
714
|
|
|
709
715
|
def eig(self,
|
|
710
716
|
A: csr_matrix | csr_matrix,
|
|
@@ -729,7 +735,7 @@ class SolverLAPACK(EigSolver):
|
|
|
729
735
|
lam : (m,) real ndarray eigenvalues (m = n or k)
|
|
730
736
|
vecs : (n, m) complex ndarray eigenvectors, B-orthonormal (xiᴴ B xj = δij)
|
|
731
737
|
"""
|
|
732
|
-
logger.
|
|
738
|
+
logger.info(f'{_pfx(self.pre)} Calling LAPACK eig solver')
|
|
733
739
|
lam, vecs = eig(A.toarray(), B.toarray(), overwrite_a=True, overwrite_b=True, check_finite=False)
|
|
734
740
|
lam, vecs = filter_real_modes(lam, vecs, target_k0, 2, 2, sign=sign)
|
|
735
741
|
return lam, vecs
|
|
@@ -742,8 +748,6 @@ class SolverLAPACK(EigSolver):
|
|
|
742
748
|
|
|
743
749
|
class SolverARPACK(EigSolver):
|
|
744
750
|
""" Implements the Scipy ARPACK iterative eigenmode solver."""
|
|
745
|
-
def __init__(self):
|
|
746
|
-
super().__init__()
|
|
747
751
|
|
|
748
752
|
def eig(self,
|
|
749
753
|
A: csr_matrix | csr_matrix,
|
|
@@ -752,7 +756,7 @@ class SolverARPACK(EigSolver):
|
|
|
752
756
|
target_k0: float = 0,
|
|
753
757
|
which: str = 'LM',
|
|
754
758
|
sign: float = 1.0) -> tuple[np.ndarray, np.ndarray]:
|
|
755
|
-
logger.info(f'Searching around
|
|
759
|
+
logger.info(f'{_pfx(self.pre)} Searching around β = {target_k0:.2f} rad/m with ARPACK')
|
|
756
760
|
sigma = sign*(target_k0**2)
|
|
757
761
|
eigen_values, eigen_modes = eigs(A, k=nmodes, M=B, sigma=sigma, which=which)
|
|
758
762
|
return eigen_values, eigen_modes
|
|
@@ -762,8 +766,8 @@ class SmartARPACK_BMA(EigSolver):
|
|
|
762
766
|
|
|
763
767
|
The Solver searches in a geometric range around the target wave constant.
|
|
764
768
|
"""
|
|
765
|
-
def __init__(self):
|
|
766
|
-
super().__init__()
|
|
769
|
+
def __init__(self, pre: str):
|
|
770
|
+
super().__init__(pre)
|
|
767
771
|
self.symmetric_steps: int = 41
|
|
768
772
|
self.search_range: float = 2.0
|
|
769
773
|
self.energy_limit: float = 1e-4
|
|
@@ -776,7 +780,7 @@ class SmartARPACK_BMA(EigSolver):
|
|
|
776
780
|
which: str = 'LM',
|
|
777
781
|
sign: float = 1.) -> tuple[np.ndarray, np.ndarray]:
|
|
778
782
|
|
|
779
|
-
logger.info(f'Searching around
|
|
783
|
+
logger.info(f'{_pfx(self.pre)} Searching around β = {target_k0:.2f} rad/m with SmartARPACK (BMA)')
|
|
780
784
|
qs = np.geomspace(1, self.search_range, self.symmetric_steps)
|
|
781
785
|
tot_eigen_values = []
|
|
782
786
|
tot_eigen_modes = []
|
|
@@ -812,8 +816,8 @@ class SmartARPACK(EigSolver):
|
|
|
812
816
|
|
|
813
817
|
The Solver searches in a geometric range around the target wave constant.
|
|
814
818
|
"""
|
|
815
|
-
def __init__(self):
|
|
816
|
-
super().__init__()
|
|
819
|
+
def __init__(self, pre: str):
|
|
820
|
+
super().__init__(pre)
|
|
817
821
|
self.symmetric_steps: int = 3
|
|
818
822
|
self.search_range: float = 2.0
|
|
819
823
|
self.energy_limit: float = 1e-4
|
|
@@ -825,7 +829,7 @@ class SmartARPACK(EigSolver):
|
|
|
825
829
|
target_k0: float = 0,
|
|
826
830
|
which: str = 'LM',
|
|
827
831
|
sign: float = 1.) -> tuple[np.ndarray, np.ndarray]:
|
|
828
|
-
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')
|
|
829
833
|
qs = np.geomspace(1, self.search_range, self.symmetric_steps)
|
|
830
834
|
tot_eigen_values = []
|
|
831
835
|
tot_eigen_modes = []
|
|
@@ -875,14 +879,14 @@ class EMSolver(Enum):
|
|
|
875
879
|
SMART_ARPACK_BMA = 7
|
|
876
880
|
CUDSS = 8
|
|
877
881
|
|
|
878
|
-
def create_solver(self) -> Solver | EigSolver | None:
|
|
882
|
+
def create_solver(self, pre: str) -> Solver | EigSolver | None:
|
|
879
883
|
if self==EMSolver.UMFPACK and not _UMFPACK_AVAILABLE:
|
|
880
884
|
return None
|
|
881
885
|
elif self==EMSolver.PARDISO and not _PARDISO_AVAILABLE:
|
|
882
886
|
return None
|
|
883
887
|
if self==EMSolver.CUDSS and not _CUDSS_AVAILABLE:
|
|
884
888
|
return None
|
|
885
|
-
return self._clss()
|
|
889
|
+
return self._clss(pre)
|
|
886
890
|
|
|
887
891
|
@property
|
|
888
892
|
def _clss(self) -> type[Solver]:
|
|
@@ -911,11 +915,15 @@ class SolveRoutine:
|
|
|
911
915
|
and goes through a sequence of steps to solve a linear system or find eigenmodes.
|
|
912
916
|
|
|
913
917
|
"""
|
|
914
|
-
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
|
+
|
|
915
923
|
|
|
916
924
|
self.sorter: Sorter = ReverseCuthillMckee()
|
|
917
925
|
self.precon: Preconditioner = ILUPrecon()
|
|
918
|
-
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}
|
|
919
927
|
self.solvers = {key: solver for key, solver in self.solvers.items() if solver is not None}
|
|
920
928
|
|
|
921
929
|
self.parallel: Literal['SI','MT','MP'] = 'SI'
|
|
@@ -926,8 +934,11 @@ class SolveRoutine:
|
|
|
926
934
|
self.use_sorter: bool = False
|
|
927
935
|
self.use_preconditioner: bool = False
|
|
928
936
|
self.use_direct: bool = True
|
|
937
|
+
|
|
929
938
|
|
|
930
|
-
|
|
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
|
+
|
|
931
942
|
def __str__(self) -> str:
|
|
932
943
|
return 'SolveRoutine()'
|
|
933
944
|
|
|
@@ -940,11 +951,11 @@ class SolveRoutine:
|
|
|
940
951
|
Returns:
|
|
941
952
|
bool: If the solver is legal
|
|
942
953
|
"""
|
|
943
|
-
if any(isinstance(solver, solvertype) for solvertype in self.disabled_solver):
|
|
944
|
-
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.')
|
|
945
956
|
return False
|
|
946
957
|
if self.parallel=='MT' and not solver.released_gil:
|
|
947
|
-
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')
|
|
948
959
|
return False
|
|
949
960
|
return True
|
|
950
961
|
|
|
@@ -973,9 +984,9 @@ class SolveRoutine:
|
|
|
973
984
|
return solver # type: ignore
|
|
974
985
|
for alternative in self.all_solvers:
|
|
975
986
|
if self._legal_solver(alternative):
|
|
976
|
-
logger.debug(f'Falling back on legal solver: {alternative}')
|
|
987
|
+
logger.debug(self.pre + f'Falling back on legal solver: {alternative}')
|
|
977
988
|
return alternative
|
|
978
|
-
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}')
|
|
979
990
|
|
|
980
991
|
def duplicate(self) -> SolveRoutine:
|
|
981
992
|
"""Creates a copy of this SolveRoutine class object.
|
|
@@ -1013,13 +1024,15 @@ class SolveRoutine:
|
|
|
1013
1024
|
"""
|
|
1014
1025
|
for solver in solvers:
|
|
1015
1026
|
if isinstance(solver, EMSolver):
|
|
1016
|
-
self.disabled_solver.append(solver
|
|
1027
|
+
self.disabled_solver.append(self.solvers[solver])
|
|
1017
1028
|
else:
|
|
1018
|
-
self.disabled_solver.append(solver
|
|
1029
|
+
self.disabled_solver.append(solver)
|
|
1019
1030
|
|
|
1020
1031
|
def _configure_routine(self,
|
|
1021
1032
|
parallel: Literal['SI','MT','MP'] = 'SI',
|
|
1022
|
-
smart_search: bool = False
|
|
1033
|
+
smart_search: bool = False,
|
|
1034
|
+
thread_nr: int = 0,
|
|
1035
|
+
proc_nr: int = 0) -> SolveRoutine:
|
|
1023
1036
|
"""Configure the solver with the given settings
|
|
1024
1037
|
|
|
1025
1038
|
Args:
|
|
@@ -1036,6 +1049,12 @@ class SolveRoutine:
|
|
|
1036
1049
|
"""
|
|
1037
1050
|
self.parallel = parallel
|
|
1038
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
|
|
1039
1058
|
return self
|
|
1040
1059
|
|
|
1041
1060
|
def configure(self,
|
|
@@ -1175,10 +1194,10 @@ class SolveRoutine:
|
|
|
1175
1194
|
bsel = b[solve_ids]
|
|
1176
1195
|
nnz = Asel.nnz
|
|
1177
1196
|
|
|
1178
|
-
logger.debug(f'
|
|
1197
|
+
logger.debug(f'{_pfx(self.pre,id)} Removed {NF-NS} prescribed DOFs ({NS:,} left, {nnz:,}≠0)')
|
|
1179
1198
|
|
|
1180
1199
|
if solver.real_only:
|
|
1181
|
-
logger.debug(f'
|
|
1200
|
+
logger.debug(f'{_pfx(self.pre,id)} Converting to real matrix')
|
|
1182
1201
|
Asel, bsel = complex_to_real_block(Asel, bsel)
|
|
1183
1202
|
|
|
1184
1203
|
# SORT
|
|
@@ -1201,8 +1220,8 @@ class SolveRoutine:
|
|
|
1201
1220
|
x_solved, report = solver.solve(Asorted, bsorted, self.precon, reuse_factorization=reuse, id=id)
|
|
1202
1221
|
end = time.time()
|
|
1203
1222
|
simtime = end-start
|
|
1204
|
-
logger.info(f'
|
|
1205
|
-
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')
|
|
1206
1225
|
|
|
1207
1226
|
if self.use_sorter and solver.req_sorter:
|
|
1208
1227
|
x = self.sorter.unsort(x_solved)
|
|
@@ -1210,14 +1229,14 @@ class SolveRoutine:
|
|
|
1210
1229
|
x = x_solved
|
|
1211
1230
|
|
|
1212
1231
|
if solver.real_only:
|
|
1213
|
-
logger.debug(f'
|
|
1232
|
+
logger.debug(f'{_pfx(self.pre,id)} Converting back to complex matrix')
|
|
1214
1233
|
x = real_to_complex_block(x)
|
|
1215
1234
|
|
|
1216
1235
|
solution = np.zeros((NF,), dtype=np.complex128)
|
|
1217
1236
|
|
|
1218
1237
|
solution[solve_ids] = x
|
|
1219
1238
|
|
|
1220
|
-
logger.debug(f'
|
|
1239
|
+
logger.debug(f'{_pfx(self.pre,id)} Solver complete!')
|
|
1221
1240
|
report.jobid = id
|
|
1222
1241
|
report.sorter = str(sorter)
|
|
1223
1242
|
report.simtime = simtime
|
|
@@ -1226,6 +1245,7 @@ class SolveRoutine:
|
|
|
1226
1245
|
report.nnz_solve = Asorted.nnz
|
|
1227
1246
|
report.ndof_solve = bsorted.shape[0]
|
|
1228
1247
|
report.precon = precon
|
|
1248
|
+
report.worker_name = self.pre
|
|
1229
1249
|
|
|
1230
1250
|
return solution, report
|
|
1231
1251
|
|
|
@@ -1262,7 +1282,7 @@ class SolveRoutine:
|
|
|
1262
1282
|
NF = A.shape[0]
|
|
1263
1283
|
NS = solve_ids.shape[0]
|
|
1264
1284
|
|
|
1265
|
-
logger.debug(f'Removing {NF-NS} prescribed DOFs ({NS} left)')
|
|
1285
|
+
logger.debug(self.pre + f'Removing {NF-NS} prescribed DOFs ({NS} left)')
|
|
1266
1286
|
|
|
1267
1287
|
Asel = A[np.ix_(solve_ids, solve_ids)]
|
|
1268
1288
|
Bsel = B[np.ix_(solve_ids, solve_ids)]
|
|
@@ -1305,7 +1325,7 @@ class SolveRoutine:
|
|
|
1305
1325
|
NF = A.shape[0]
|
|
1306
1326
|
NS = solve_ids.shape[0]
|
|
1307
1327
|
|
|
1308
|
-
logger.debug(f'Removing {NF-NS} prescribed DOFs ({NS} left)')
|
|
1328
|
+
logger.debug(self.pre + f'Removing {NF-NS} prescribed DOFs ({NS} left)')
|
|
1309
1329
|
|
|
1310
1330
|
Asel = A[np.ix_(solve_ids, solve_ids)]
|
|
1311
1331
|
Bsel = B[np.ix_(solve_ids, solve_ids)]
|
|
@@ -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
40
|
emerge/_emerge/geo/operations.py,sha256=WYWfOXWrT0voeKW9U26g-PhQfqJl3ovRQ8uDQXUr7Nc,12459
|
|
41
|
-
emerge/_emerge/geo/pcb.py,sha256=
|
|
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
|