emerge 0.6.9__py3-none-any.whl → 0.6.10__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 +12 -3
- emerge/_emerge/cs.py +36 -0
- emerge/_emerge/geo/polybased.py +58 -26
- emerge/_emerge/geo/shapes.py +6 -0
- emerge/_emerge/geometry.py +12 -3
- emerge/_emerge/logsettings.py +13 -2
- emerge/_emerge/material.py +10 -1
- emerge/_emerge/mesh3d.py +15 -4
- emerge/_emerge/physics/microwave/microwave_3d.py +1 -1
- emerge/_emerge/physics/microwave/microwave_bc.py +17 -19
- emerge/_emerge/plot/pyvista/display.py +1 -1
- emerge/_emerge/plot/simple_plots.py +15 -3
- emerge/_emerge/simmodel.py +6 -5
- emerge/_emerge/solve_interfaces/cudss_interface.py +10 -4
- emerge/_emerge/solver.py +14 -4
- {emerge-0.6.9.dist-info → emerge-0.6.10.dist-info}/METADATA +1 -1
- {emerge-0.6.9.dist-info → emerge-0.6.10.dist-info}/RECORD +20 -20
- {emerge-0.6.9.dist-info → emerge-0.6.10.dist-info}/WHEEL +0 -0
- {emerge-0.6.9.dist-info → emerge-0.6.10.dist-info}/entry_points.txt +0 -0
- {emerge-0.6.9.dist-info → emerge-0.6.10.dist-info}/licenses/LICENSE +0 -0
emerge/__init__.py
CHANGED
|
@@ -18,7 +18,7 @@ along with this program; if not, see
|
|
|
18
18
|
"""
|
|
19
19
|
import os
|
|
20
20
|
|
|
21
|
-
__version__ = "0.6.
|
|
21
|
+
__version__ = "0.6.10"
|
|
22
22
|
|
|
23
23
|
############################################################
|
|
24
24
|
# HANDLE ENVIRONMENT VARIABLES #
|
|
@@ -43,12 +43,13 @@ from loguru import logger
|
|
|
43
43
|
|
|
44
44
|
LOG_CONTROLLER.set_default()
|
|
45
45
|
logger.debug('Importing modules')
|
|
46
|
+
LOG_CONTROLLER._set_log_buffer()
|
|
46
47
|
|
|
47
48
|
from ._emerge.simmodel import Simulation
|
|
48
49
|
from ._emerge.material import Material, FreqCoordDependent, FreqDependent, CoordDependent
|
|
49
50
|
from ._emerge import bc
|
|
50
51
|
from ._emerge.solver import SolverBicgstab, SolverGMRES, SolveRoutine, ReverseCuthillMckee, Sorter, SolverPardiso, SolverUMFPACK, SolverSuperLU, EMSolver
|
|
51
|
-
from ._emerge.cs import CoordinateSystem, CS, GCS, Plane, Axis, XAX, YAX, ZAX, XYPLANE, XZPLANE, YZPLANE, YXPLANE, ZXPLANE, ZYPLANE
|
|
52
|
+
from ._emerge.cs import CoordinateSystem, CS, GCS, Plane, Axis, XAX, YAX, ZAX, XYPLANE, XZPLANE, YZPLANE, YXPLANE, ZXPLANE, ZYPLANE, cs
|
|
52
53
|
from ._emerge.coord import Line
|
|
53
54
|
from ._emerge import geo
|
|
54
55
|
from ._emerge.selection import Selection, FaceSelection, DomainSelection, EdgeSelection
|
|
@@ -62,4 +63,12 @@ from ._emerge.howto import _HowtoClass
|
|
|
62
63
|
|
|
63
64
|
howto = _HowtoClass()
|
|
64
65
|
|
|
65
|
-
logger.debug('Importing complete!')
|
|
66
|
+
logger.debug('Importing complete!')
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
############################################################
|
|
70
|
+
# CONSTANTS #
|
|
71
|
+
############################################################
|
|
72
|
+
|
|
73
|
+
CENTER = geo.Alignment.CENTER
|
|
74
|
+
CORNER = geo.Alignment.CORNER
|
emerge/_emerge/cs.py
CHANGED
|
@@ -530,3 +530,39 @@ CS = CoordinateSystem
|
|
|
530
530
|
# The global coordinate system
|
|
531
531
|
GCS = CoordinateSystem(XAX, YAX, ZAX, np.zeros(3), _is_global=True)
|
|
532
532
|
|
|
533
|
+
def cs(axes: str, origin: tuple[float, float, float] = (0.,0.,0.,)) -> CoordinateSystem:
|
|
534
|
+
"""Generate a coordinate system based on a simple string
|
|
535
|
+
The string must contain the letters x, X, y, Y, z and/or Z.
|
|
536
|
+
Small letters refer to positive axes and capitals to negative axes.
|
|
537
|
+
|
|
538
|
+
The string must be 3 characters long.
|
|
539
|
+
|
|
540
|
+
The first position indices which global axis gets assigned to the new local X-axis
|
|
541
|
+
The second position indicates the Y-axis
|
|
542
|
+
The third position indicates the Z-axis
|
|
543
|
+
|
|
544
|
+
Thus, rotating the global XYZ coordinate system 90 degrees around the Z axis would yield: yXz
|
|
545
|
+
|
|
546
|
+
Args:
|
|
547
|
+
axes (str): The axis description
|
|
548
|
+
origin (tuple[float, float, float], optional): The origin of the coordinate system. Defaults to (0.,0.,0.,).
|
|
549
|
+
|
|
550
|
+
Returns:
|
|
551
|
+
CoordinateSystem: The resultant coordinate system
|
|
552
|
+
"""
|
|
553
|
+
if len(axes) != 3:
|
|
554
|
+
raise ValueError('Axis object must be of length 3')
|
|
555
|
+
|
|
556
|
+
axlib = {
|
|
557
|
+
'x': Axis(np.array([1.0,0.,0.])),
|
|
558
|
+
'X': Axis(np.array([-1.0,0.,0.])),
|
|
559
|
+
'y': Axis(np.array([0.,1.0,0.])),
|
|
560
|
+
'Y': Axis(np.array([0.,-1.0,0.])),
|
|
561
|
+
'z': Axis(np.array([0.,0.,1.0])),
|
|
562
|
+
'Z': Axis(np.array([0.,0.,-1.0])),
|
|
563
|
+
}
|
|
564
|
+
ax_obj = [axlib[ax] for ax in axes]
|
|
565
|
+
|
|
566
|
+
return (ax_obj[0]*ax_obj[1]*ax_obj[2]).displace(*origin)
|
|
567
|
+
|
|
568
|
+
|
emerge/_emerge/geo/polybased.py
CHANGED
|
@@ -206,6 +206,7 @@ def orthonormalize(axis: np.ndarray) -> tuple[np.ndarray, np.ndarray, np.ndarray
|
|
|
206
206
|
Zaxis = np.abs(Zaxis/np.linalg.norm(Zaxis))
|
|
207
207
|
return Xaxis, Yaxis, Zaxis
|
|
208
208
|
|
|
209
|
+
|
|
209
210
|
class GeoPrism(GeoVolume):
|
|
210
211
|
"""The GepPrism class generalizes the GeoVolume for extruded convex polygons.
|
|
211
212
|
Besides having a volumetric definitions, the class offers a .front_face
|
|
@@ -216,35 +217,65 @@ class GeoPrism(GeoVolume):
|
|
|
216
217
|
"""
|
|
217
218
|
def __init__(self,
|
|
218
219
|
volume_tag: int,
|
|
219
|
-
front_tag: int,
|
|
220
|
-
side_tags: list[int],
|
|
220
|
+
front_tag: int | None = None,
|
|
221
|
+
side_tags: list[int] | None = None,
|
|
222
|
+
_axis: Axis | None = None):
|
|
221
223
|
super().__init__(volume_tag)
|
|
222
|
-
|
|
223
|
-
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
if front_tag is not None and side_tags is not None:
|
|
228
|
+
self.front_tag: int = front_tag
|
|
229
|
+
self.back_tag: int = None
|
|
224
230
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
n1 = gmsh.model.get_normal(self.front_tag, (0,0))
|
|
228
|
-
self._add_face_pointer('back', o1, n1)
|
|
231
|
+
gmsh.model.occ.synchronize()
|
|
232
|
+
self._add_face_pointer('back', tag=self.front_tag)
|
|
229
233
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
self.back_tag = tag
|
|
239
|
-
break
|
|
234
|
+
tags = gmsh.model.get_boundary(self.dimtags, oriented=False)
|
|
235
|
+
|
|
236
|
+
for dim, tag in tags:
|
|
237
|
+
if (dim,tag) in side_tags:
|
|
238
|
+
continue
|
|
239
|
+
self._add_face_pointer('front',tag=tag)
|
|
240
|
+
self.back_tag = tag
|
|
241
|
+
break
|
|
240
242
|
|
|
241
|
-
|
|
243
|
+
self.side_tags: list[int] = [dt[1] for dt in tags if dt[1]!=self.front_tag and dt[1]!=self.back_tag]
|
|
242
244
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
245
|
+
for tag in self.side_tags:
|
|
246
|
+
|
|
247
|
+
self._add_face_pointer(f'side{tag}', tag=tag)
|
|
248
|
+
self.back_tag = tag
|
|
249
|
+
|
|
250
|
+
elif _axis is not None:
|
|
251
|
+
_axis = _parse_axis(_axis)
|
|
252
|
+
gmsh.model.occ.synchronize()
|
|
253
|
+
tags = gmsh.model.get_boundary(self.dimtags, oriented=False)
|
|
254
|
+
faces = []
|
|
255
|
+
for dim, tag in tags:
|
|
256
|
+
o1 = np.array(gmsh.model.occ.get_center_of_mass(2, tag))
|
|
257
|
+
n1 = np.array(gmsh.model.get_normal(tag, (0,0)))
|
|
258
|
+
if abs(np.sum(n1*_axis.np)) > 0.99:
|
|
259
|
+
dax = sum(o1 * _axis.np)
|
|
260
|
+
faces.append((o1, n1, dax, tag))
|
|
261
|
+
|
|
262
|
+
faces = sorted(faces, key=lambda x: x[2])
|
|
263
|
+
ftags = []
|
|
264
|
+
if len(faces) >= 2:
|
|
265
|
+
ftags.append(faces[0][3])
|
|
266
|
+
ftags.append(faces[-1][3])
|
|
267
|
+
self._add_face_pointer('front',faces[0][0], faces[0][1])
|
|
268
|
+
self._add_face_pointer('back', faces[-1][0], faces[-1][1])
|
|
269
|
+
elif len(faces)==1:
|
|
270
|
+
ftags.append(faces[0][3])
|
|
271
|
+
self._add_face_pointer('cap',faces[0][0], faces[0][1])
|
|
272
|
+
|
|
273
|
+
ictr = 1
|
|
274
|
+
for dim, tag in tags:
|
|
275
|
+
if tag in ftags:
|
|
276
|
+
continue
|
|
277
|
+
self._add_face_pointer(f'side{ictr}', tag=tag)
|
|
278
|
+
ictr += 1
|
|
248
279
|
|
|
249
280
|
def outside(self, *exclude: Literal['front','back']) -> FaceSelection:
|
|
250
281
|
"""Select all outside faces except for the once specified by outside
|
|
@@ -462,9 +493,10 @@ class XYPolygon:
|
|
|
462
493
|
ax, ay, az = axis
|
|
463
494
|
|
|
464
495
|
volume = gmsh.model.occ.revolve(poly_fin.dimtags, x,y,z, ax, ay, az, angle*np.pi/180)
|
|
496
|
+
|
|
465
497
|
tags = [t for d,t in volume if d==3]
|
|
466
|
-
|
|
467
|
-
return GeoPrism(tags,
|
|
498
|
+
poly_fin.remove()
|
|
499
|
+
return GeoPrism(tags, _axis=axis)
|
|
468
500
|
|
|
469
501
|
@staticmethod
|
|
470
502
|
def circle(radius: float,
|
emerge/_emerge/geo/shapes.py
CHANGED
|
@@ -27,6 +27,12 @@ from typing import Literal
|
|
|
27
27
|
from functools import reduce
|
|
28
28
|
|
|
29
29
|
class Alignment(Enum):
|
|
30
|
+
"""The alignment Enum describes if a box, cube or rectangle location
|
|
31
|
+
is specified for the center or the bottom - front - left corner (min X Y and Z)
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
Enum (_type_): _description_
|
|
35
|
+
"""
|
|
30
36
|
CENTER = 1
|
|
31
37
|
CORNER = 2
|
|
32
38
|
|
emerge/_emerge/geometry.py
CHANGED
|
@@ -285,9 +285,18 @@ class GeoObject:
|
|
|
285
285
|
|
|
286
286
|
def _add_face_pointer(self,
|
|
287
287
|
name: str,
|
|
288
|
-
origin: np.ndarray,
|
|
289
|
-
normal: np.ndarray
|
|
290
|
-
|
|
288
|
+
origin: np.ndarray | None = None,
|
|
289
|
+
normal: np.ndarray | None = None,
|
|
290
|
+
tag: int | None = None):
|
|
291
|
+
if tag is not None:
|
|
292
|
+
o = gmsh.model.occ.get_center_of_mass(2, tag)
|
|
293
|
+
n = gmsh.model.get_normal(tag, (0,0))
|
|
294
|
+
self._face_pointers[name] = _FacePointer(o, n)
|
|
295
|
+
return
|
|
296
|
+
if origin is not None and normal is not None:
|
|
297
|
+
self._face_pointers[name] = _FacePointer(origin, normal)
|
|
298
|
+
return
|
|
299
|
+
raise ValueError('Eitehr a tag or an origin + normal must be provided!')
|
|
291
300
|
|
|
292
301
|
def make_copy(self) -> GeoObject:
|
|
293
302
|
new_dimtags = gmsh.model.occ.copy(self.dimtags)
|
emerge/_emerge/logsettings.py
CHANGED
|
@@ -18,11 +18,14 @@
|
|
|
18
18
|
from loguru import logger
|
|
19
19
|
import sys
|
|
20
20
|
from typing import Literal
|
|
21
|
-
from enum import Enum
|
|
22
21
|
from pathlib import Path
|
|
23
22
|
import os
|
|
24
|
-
import
|
|
23
|
+
from collections import deque
|
|
25
24
|
|
|
25
|
+
_LOG_BUFFER = deque()
|
|
26
|
+
|
|
27
|
+
def _log_sink(message):
|
|
28
|
+
_LOG_BUFFER.append(message)
|
|
26
29
|
############################################################
|
|
27
30
|
# FORMATS #
|
|
28
31
|
############################################################
|
|
@@ -82,6 +85,14 @@ class LogController:
|
|
|
82
85
|
format=FORMAT_DICT.get(loglevel, INFO_FORMAT))
|
|
83
86
|
self.std_handlers.append(handle_id)
|
|
84
87
|
|
|
88
|
+
def _set_log_buffer(self):
|
|
89
|
+
logger.add(_log_sink)
|
|
90
|
+
|
|
91
|
+
def _flush_log_buffer(self):
|
|
92
|
+
for msg in list(_LOG_BUFFER):
|
|
93
|
+
logger.opt(depth=6).log(msg.record["level"].name, msg.record["message"])
|
|
94
|
+
_LOG_BUFFER.clear()
|
|
95
|
+
|
|
85
96
|
def set_std_loglevel(self, loglevel: str):
|
|
86
97
|
handler = {"sink": sys.stdout,
|
|
87
98
|
"level": loglevel,
|
emerge/_emerge/material.py
CHANGED
|
@@ -310,6 +310,8 @@ class Material:
|
|
|
310
310
|
|
|
311
311
|
self.color: str = color
|
|
312
312
|
self.opacity: float = opacity
|
|
313
|
+
self._hash_key: int = -1
|
|
314
|
+
|
|
313
315
|
if _neff is None:
|
|
314
316
|
self._neff: Callable = lambda f: np.sqrt(self.ur._fmax(f)*self.er._fmax(f))
|
|
315
317
|
else:
|
|
@@ -318,8 +320,14 @@ class Material:
|
|
|
318
320
|
self._color_rgb = tuple(int(hex_str[i:i+2], 16)/255.0 for i in (0, 2, 4))
|
|
319
321
|
self._metal: bool = _metal
|
|
320
322
|
|
|
323
|
+
def __hash__(self):
|
|
324
|
+
return self._hash_key
|
|
325
|
+
|
|
321
326
|
def __str__(self) -> str:
|
|
322
|
-
return f'Material({self.name})'
|
|
327
|
+
return f'Material({self.name}, {self._hash_key})'
|
|
328
|
+
|
|
329
|
+
def __repr__(self):
|
|
330
|
+
return f'Material({self.name}, {self._hash_key})'
|
|
323
331
|
|
|
324
332
|
def initialize(self, xs: np.ndarray, ys: np.ndarray, zs: np.ndarray, ids: np.ndarray):
|
|
325
333
|
"""Initializes the Material properties to be evaluated at xyz-coordinates for
|
|
@@ -343,6 +351,7 @@ class Material:
|
|
|
343
351
|
self.ur.reset()
|
|
344
352
|
self.tand.reset()
|
|
345
353
|
self.cond.reset()
|
|
354
|
+
self._hash_key = -1
|
|
346
355
|
|
|
347
356
|
@property
|
|
348
357
|
def frequency_dependent(self) -> bool:
|
emerge/_emerge/mesh3d.py
CHANGED
|
@@ -544,22 +544,33 @@ class Mesh3D(Mesh):
|
|
|
544
544
|
#arry = np.zeros((3,3,self.n_tets,), dtype=np.complex128)
|
|
545
545
|
for vol in volumes:
|
|
546
546
|
vol.material.reset()
|
|
547
|
-
|
|
547
|
+
|
|
548
548
|
materials = []
|
|
549
|
+
i = 0
|
|
550
|
+
for vol in volumes:
|
|
551
|
+
if vol.material not in materials:
|
|
552
|
+
materials.append(vol.material)
|
|
553
|
+
vol.material._hash_key = i
|
|
554
|
+
i += 1
|
|
549
555
|
|
|
550
556
|
xs = self.centers[0,:]
|
|
551
557
|
ys = self.centers[1,:]
|
|
552
558
|
zs = self.centers[2,:]
|
|
553
559
|
|
|
560
|
+
matassign = -1*np.ones((self.n_tets,), dtype=np.int64)
|
|
561
|
+
|
|
554
562
|
for volume in sorted(volumes, key=lambda x: x._priority):
|
|
555
563
|
|
|
556
564
|
for dimtag in volume.dimtags:
|
|
557
565
|
etype, etag_list, ntags = gmsh.model.mesh.get_elements(*dimtag)
|
|
558
566
|
for etags in etag_list:
|
|
559
567
|
tet_ids = np.array([self.tet_t2i[t] for t in etags])
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
568
|
+
matassign[tet_ids] = volume.material._hash_key
|
|
569
|
+
|
|
570
|
+
for mat in materials:
|
|
571
|
+
ids = np.argwhere(matassign==mat._hash_key).flatten()
|
|
572
|
+
mat.initialize(xs[ids], ys[ids], zs[ids], ids)
|
|
573
|
+
|
|
563
574
|
|
|
564
575
|
return materials
|
|
565
576
|
|
|
@@ -53,7 +53,7 @@ def run_job_multi(job: SimJob) -> SimJob:
|
|
|
53
53
|
Returns:
|
|
54
54
|
SimJob: The solved SimJob
|
|
55
55
|
"""
|
|
56
|
-
routine = DEFAULT_ROUTINE.
|
|
56
|
+
routine = DEFAULT_ROUTINE._configure_routine('MP')
|
|
57
57
|
for A, b, ids, reuse, aux in job.iter_Ab():
|
|
58
58
|
solution, report = routine.solve(A, b, ids, reuse, id=job.id)
|
|
59
59
|
report.add(**aux)
|
|
@@ -306,11 +306,17 @@ class AbsorbingBoundary(RobinBC):
|
|
|
306
306
|
Returns:
|
|
307
307
|
complex: The γ-constant
|
|
308
308
|
"""
|
|
309
|
-
|
|
309
|
+
if self.order == 2:
|
|
310
|
+
|
|
311
|
+
p0 = 1.06103
|
|
312
|
+
p2 = -0.84883
|
|
313
|
+
ky = k0*0.5
|
|
314
|
+
return 1j*k0*p0 - 1j*p2*ky**2/k0
|
|
315
|
+
else:
|
|
316
|
+
Factor = 1
|
|
317
|
+
return 1j*self.get_beta(k0)*Factor
|
|
310
318
|
|
|
311
|
-
|
|
312
|
-
return np.zeros((3, len(x_local)), dtype=np.complex128)
|
|
313
|
-
|
|
319
|
+
|
|
314
320
|
@dataclass
|
|
315
321
|
class PortMode:
|
|
316
322
|
modefield: np.ndarray
|
|
@@ -825,9 +831,9 @@ class LumpedPort(PortBC):
|
|
|
825
831
|
self.Vdirection: Axis = direction # type: ignore
|
|
826
832
|
self.type = 'TEM'
|
|
827
833
|
|
|
828
|
-
logger.info('Constructing coordinate system from normal port')
|
|
829
|
-
self.cs = Axis(self.selection.normal).construct_cs() # type: ignore
|
|
830
|
-
|
|
834
|
+
# logger.info('Constructing coordinate system from normal port')
|
|
835
|
+
# self.cs = Axis(self.selection.normal).construct_cs() # type: ignore
|
|
836
|
+
self.cs = GCS
|
|
831
837
|
self.vintline: Line | None = None
|
|
832
838
|
self.v_integration = True
|
|
833
839
|
|
|
@@ -881,14 +887,7 @@ class LumpedPort(PortBC):
|
|
|
881
887
|
k0: float,
|
|
882
888
|
which: Literal['E','H'] = 'E') -> np.ndarray:
|
|
883
889
|
''' Compute the port mode E-field in local coordinates (XY) + Z out of plane.'''
|
|
884
|
-
|
|
885
|
-
px, py, pz = self.cs.in_local_basis(*self.Vdirection.np)
|
|
886
|
-
|
|
887
|
-
Ex = px*np.ones_like(x_local)
|
|
888
|
-
Ey = py*np.ones_like(x_local)
|
|
889
|
-
Ez = pz*np.ones_like(x_local)
|
|
890
|
-
Exyz = np.array([Ex, Ey, Ez])
|
|
891
|
-
return Exyz
|
|
890
|
+
raise RuntimeError('This function should never be called in this context.')
|
|
892
891
|
|
|
893
892
|
def port_mode_3d_global(self,
|
|
894
893
|
x_global: np.ndarray,
|
|
@@ -911,10 +910,9 @@ class LumpedPort(PortBC):
|
|
|
911
910
|
Returns:
|
|
912
911
|
np.ndarray: The E-field in (3,N) indexing.
|
|
913
912
|
"""
|
|
914
|
-
|
|
915
|
-
Ex, Ey, Ez = self.
|
|
916
|
-
|
|
917
|
-
return np.array([Exg, Eyg, Ezg])
|
|
913
|
+
ON = np.ones_like(x_global)
|
|
914
|
+
Ex, Ey, Ez = self.Vdirection.np
|
|
915
|
+
return np.array([Ex*ON, Ey*ON, Ez*ON])
|
|
918
916
|
|
|
919
917
|
|
|
920
918
|
class LumpedElement(RobinBC):
|
|
@@ -422,9 +422,14 @@ def plot_sp(f: np.ndarray | list[np.ndarray], S: list[np.ndarray] | np.ndarray,
|
|
|
422
422
|
show_plot: bool = True,
|
|
423
423
|
figdata: tuple | None = None) -> tuple[plt.Figure, plt.Axes, plt.Axes]:
|
|
424
424
|
"""Plot S-parameters in dB and phase
|
|
425
|
+
|
|
426
|
+
One may provide:
|
|
427
|
+
- A single frequency with a single S-parameter
|
|
428
|
+
- A single frequency with a list of S-parameters
|
|
429
|
+
- A list of frequencies with a list of S-parameters
|
|
425
430
|
|
|
426
431
|
Args:
|
|
427
|
-
f (np.ndarray): Frequency vector
|
|
432
|
+
f (np.ndarray | list[np.ndarray]): Frequency vector or list of frequencies
|
|
428
433
|
S (list[np.ndarray] | np.ndarray): S-parameters to plot (list or single array)
|
|
429
434
|
dblim (list, optional): Decibel y-axis limit. Defaults to [-80, 5].
|
|
430
435
|
xunit (str, optional): Frequency unit. Defaults to "GHz".
|
|
@@ -535,7 +540,7 @@ def plot_sp(f: np.ndarray | list[np.ndarray], S: list[np.ndarray] | np.ndarray,
|
|
|
535
540
|
|
|
536
541
|
|
|
537
542
|
def plot_ff(
|
|
538
|
-
theta: np.ndarray,
|
|
543
|
+
theta: np.ndarray | list[np.ndarray],
|
|
539
544
|
E: Union[np.ndarray, Sequence[np.ndarray]],
|
|
540
545
|
grid: bool = True,
|
|
541
546
|
dB: bool = False,
|
|
@@ -554,7 +559,7 @@ def plot_ff(
|
|
|
554
559
|
|
|
555
560
|
Parameters
|
|
556
561
|
----------
|
|
557
|
-
theta : np.ndarray
|
|
562
|
+
theta : np.ndarray | list[np.ndarray]
|
|
558
563
|
Angle array (radians).
|
|
559
564
|
E : np.ndarray or sequence of np.ndarray
|
|
560
565
|
Complex E-field samples; magnitude will be plotted.
|
|
@@ -575,6 +580,12 @@ def plot_ff(
|
|
|
575
580
|
E_list = [E]
|
|
576
581
|
else:
|
|
577
582
|
E_list = list(E)
|
|
583
|
+
|
|
584
|
+
if not isinstance(theta, list):
|
|
585
|
+
thetas = [theta for _ in E_list]
|
|
586
|
+
else:
|
|
587
|
+
thetas = theta
|
|
588
|
+
|
|
578
589
|
n_series = len(E_list)
|
|
579
590
|
|
|
580
591
|
# Style broadcasting
|
|
@@ -591,6 +602,7 @@ def plot_ff(
|
|
|
591
602
|
|
|
592
603
|
fig, ax = plt.subplots()
|
|
593
604
|
for i, Ei in enumerate(E_list):
|
|
605
|
+
theta = thetas[i]
|
|
594
606
|
mag = np.abs(Ei)
|
|
595
607
|
if dB:
|
|
596
608
|
mag = 20*np.log10(mag)
|
emerge/_emerge/simmodel.py
CHANGED
|
@@ -68,7 +68,7 @@ class Simulation:
|
|
|
68
68
|
loglevel: Literal['TRACE','DEBUG','INFO','WARNING','ERROR'] = 'INFO',
|
|
69
69
|
load_file: bool = False,
|
|
70
70
|
save_file: bool = False,
|
|
71
|
-
|
|
71
|
+
write_log: bool = False,
|
|
72
72
|
path_suffix: str = ".EMResults"):
|
|
73
73
|
"""Generate a Simulation class object.
|
|
74
74
|
|
|
@@ -80,7 +80,7 @@ class Simulation:
|
|
|
80
80
|
loglevel ("DEBUG","INFO","WARNING","ERROR", optional): The loglevel to use for loguru. Defaults to 'INFO'.
|
|
81
81
|
load_file (bool, optional): If the simulatio model should be loaded from a file. Defaults to False.
|
|
82
82
|
save_file (bool, optional): if the simulation file should be stored to a file. Defaults to False.
|
|
83
|
-
|
|
83
|
+
write_log (bool, optional): If a file should be created that contains the entire log of the simulation. Defaults to False.
|
|
84
84
|
path_suffix (str, optional): The suffix that will be added to the results directory. Defaults to ".EMResults".
|
|
85
85
|
"""
|
|
86
86
|
|
|
@@ -113,9 +113,10 @@ class Simulation:
|
|
|
113
113
|
self._initialize_simulation()
|
|
114
114
|
|
|
115
115
|
self.set_loglevel(loglevel)
|
|
116
|
-
if
|
|
117
|
-
self.
|
|
116
|
+
if write_log:
|
|
117
|
+
self.set_write_log()
|
|
118
118
|
|
|
119
|
+
LOG_CONTROLLER._flush_log_buffer()
|
|
119
120
|
self._update_data()
|
|
120
121
|
|
|
121
122
|
|
|
@@ -324,7 +325,7 @@ class Simulation:
|
|
|
324
325
|
if loglevel not in ('TRACE','DEBUG'):
|
|
325
326
|
gmsh.option.setNumber("General.Terminal", 0)
|
|
326
327
|
|
|
327
|
-
def
|
|
328
|
+
def set_write_log(self) -> None:
|
|
328
329
|
"""Adds a file output for the logger."""
|
|
329
330
|
LOG_CONTROLLER.set_write_file(self.modelpath)
|
|
330
331
|
|
|
@@ -15,7 +15,16 @@
|
|
|
15
15
|
# along with this program; if not, see
|
|
16
16
|
# <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
|
-
import
|
|
18
|
+
import warnings
|
|
19
|
+
from loguru import logger
|
|
20
|
+
|
|
21
|
+
# Catch the Cuda warning and print it with Loguru.
|
|
22
|
+
with warnings.catch_warnings(record=True) as w:
|
|
23
|
+
warnings.simplefilter("always")
|
|
24
|
+
import cupy as cp
|
|
25
|
+
for warn in w:
|
|
26
|
+
logger.debug(f"{warn.category.__name__}: {warn.message}")
|
|
27
|
+
|
|
19
28
|
import nvmath.bindings.cudss as cudss # ty: ignore
|
|
20
29
|
from nvmath import CudaDataType # ty: ignore
|
|
21
30
|
|
|
@@ -23,9 +32,6 @@ from scipy.sparse import csr_matrix
|
|
|
23
32
|
import numpy as np
|
|
24
33
|
from typing import Literal
|
|
25
34
|
|
|
26
|
-
from loguru import logger
|
|
27
|
-
|
|
28
|
-
|
|
29
35
|
############################################################
|
|
30
36
|
# CONSTANTS #
|
|
31
37
|
############################################################
|
emerge/_emerge/solver.py
CHANGED
|
@@ -504,6 +504,7 @@ class SolverSuperLU(Solver):
|
|
|
504
504
|
logger.info(f'[ID={id}] Calling SuperLU Solver.')
|
|
505
505
|
self.single = True
|
|
506
506
|
if not reuse_factorization:
|
|
507
|
+
logger.trace('Computing LU-Decomposition')
|
|
507
508
|
self.lu = splu(A, permc_spec='MMD_AT_PLUS_A', relax=0, diag_pivot_thresh=self._pivoting_threshold, options=self.options)
|
|
508
509
|
x = self.lu.solve(b)
|
|
509
510
|
aux = {
|
|
@@ -518,6 +519,7 @@ class SolverUMFPACK(Solver):
|
|
|
518
519
|
|
|
519
520
|
def __init__(self):
|
|
520
521
|
super().__init__()
|
|
522
|
+
logger.trace('Creating UMFPACK solver')
|
|
521
523
|
self.A: np.ndarray = None
|
|
522
524
|
self.b: np.ndarray = None
|
|
523
525
|
|
|
@@ -532,6 +534,7 @@ class SolverUMFPACK(Solver):
|
|
|
532
534
|
def initialize(self):
|
|
533
535
|
if self.initalized:
|
|
534
536
|
return
|
|
537
|
+
logger.trace('Initializing UMFPACK Solver')
|
|
535
538
|
self.umfpack = um.UmfpackContext('zl')
|
|
536
539
|
self.umfpack.control[um.UMFPACK_PRL] = 0 # ty: ignore
|
|
537
540
|
self.umfpack.control[um.UMFPACK_IRSTEP] = 2 # ty: ignore
|
|
@@ -542,7 +545,9 @@ class SolverUMFPACK(Solver):
|
|
|
542
545
|
self.umfpack.control[um.UMFPACK_BLOCK_SIZE] = 64 # ty: ignore
|
|
543
546
|
self.umfpack.control[um.UMFPACK_FIXQ] = -1 # ty: ignore
|
|
544
547
|
self.initalized = True
|
|
548
|
+
|
|
545
549
|
def reset(self) -> None:
|
|
550
|
+
logger.trace('Resetting UMFPACK solver state')
|
|
546
551
|
self.fact_symb = False
|
|
547
552
|
|
|
548
553
|
def set_options(self, pivoting_threshold: float | None = None) -> None:
|
|
@@ -562,13 +567,14 @@ class SolverUMFPACK(Solver):
|
|
|
562
567
|
A.indptr = A.indptr.astype(np.int64)
|
|
563
568
|
A.indices = A.indices.astype(np.int64)
|
|
564
569
|
if self.fact_symb is False:
|
|
565
|
-
logger.
|
|
570
|
+
logger.trace(f'[ID={id}] Executing symbollic factorization.')
|
|
566
571
|
self.umfpack.symbolic(A)
|
|
567
572
|
self.fact_symb = True
|
|
568
573
|
if not reuse_factorization:
|
|
569
|
-
|
|
574
|
+
logger.trace(f'[ID={id}] Executing numeric factorization.')
|
|
570
575
|
self.umfpack.numeric(A)
|
|
571
576
|
self.A = A
|
|
577
|
+
logger.trace(f'[ID={id}] Solving linear system.')
|
|
572
578
|
x = self.umfpack.solve(um.UMFPACK_A, self.A, b, autoTranspose = False ) # ty: ignore
|
|
573
579
|
aux = {
|
|
574
580
|
"Pivoting Threshold": str(self._pivoting_threshold),
|
|
@@ -596,12 +602,14 @@ class SolverPardiso(Solver):
|
|
|
596
602
|
def solve(self, A, b, precon, reuse_factorization: bool = False, id: int = -1) -> tuple[np.ndarray, SolveReport]:
|
|
597
603
|
logger.info(f'[ID={id}] Calling Pardiso Solver')
|
|
598
604
|
if self.fact_symb is False:
|
|
599
|
-
logger.
|
|
605
|
+
logger.trace(f'[ID={id}] Executing symbollic factorization.')
|
|
600
606
|
self.solver.symbolic(A)
|
|
601
607
|
self.fact_symb = True
|
|
602
608
|
if not reuse_factorization:
|
|
609
|
+
logger.trace(f'[ID={id}] Executing numeric factorization.')
|
|
603
610
|
self.solver.numeric(A)
|
|
604
611
|
self.A = A
|
|
612
|
+
logger.trace(f'[ID={id}] Solving linear system.')
|
|
605
613
|
x, error = self.solver.solve(A, b)
|
|
606
614
|
if error != 0:
|
|
607
615
|
logger.error(f'[ID={id}] Terminated with error code {error}')
|
|
@@ -634,13 +642,15 @@ class CuDSSSolver(Solver):
|
|
|
634
642
|
logger.info(f'[ID={id}] Calling cuDSS Solver')
|
|
635
643
|
|
|
636
644
|
if self.fact_symb is False:
|
|
637
|
-
logger.
|
|
645
|
+
logger.trace(f'[ID={id}] Starting from symbollic factorization.')
|
|
638
646
|
x = self._cudss.from_symbolic(A,b)
|
|
639
647
|
self.fact_symb = True
|
|
640
648
|
else:
|
|
641
649
|
if reuse_factorization:
|
|
650
|
+
logger.trace(f'[ID={id}] Solving linear system.')
|
|
642
651
|
x = self._cudss.from_solve(b)
|
|
643
652
|
else:
|
|
653
|
+
logger.trace(f'[ID={id}] Starting from numeric factorization.')
|
|
644
654
|
x = self._cudss.from_numeric(A,b)
|
|
645
655
|
|
|
646
656
|
return x, SolveReport(solver=str(self), exit_code=0, aux={})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
emerge/__init__.py,sha256=
|
|
1
|
+
emerge/__init__.py,sha256=8FrSyF_ro5TDOwMM76VyItYnpfiK_LOumuCAugk2DiI,2977
|
|
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
|
|
@@ -10,21 +10,21 @@ emerge/_emerge/_cache_check.py,sha256=_m9rV-VcaC4uNfETZ2Rp1tkA-gZ5FD3xL3KOHlgdvy
|
|
|
10
10
|
emerge/_emerge/bc.py,sha256=TeSVNkDgOGaoHw5raTzhUV0ngtyHa33sXAoL2hRn70M,8077
|
|
11
11
|
emerge/_emerge/const.py,sha256=PTZZTSDOP5NsZ8XnJrKTY2P0tPUhmutBJ1yrm-t7xsI,129
|
|
12
12
|
emerge/_emerge/coord.py,sha256=BKvyrcnHY-_bgHqysnByy5k9_DK4VVfr9KKkRaawG2E,4371
|
|
13
|
-
emerge/_emerge/cs.py,sha256=
|
|
13
|
+
emerge/_emerge/cs.py,sha256=gULfov6s0jODOdQkH6NmGBbG5wvny1-bJU8fdAlpCHo,19730
|
|
14
14
|
emerge/_emerge/dataset.py,sha256=UcSAJ_siLrOjNBBWRWsS3GUZUpayp63EM6pP6ClwKDI,1534
|
|
15
15
|
emerge/_emerge/geo2d.py,sha256=e_HkX1GQ2iYrdO0zeEgzVOzfGyU1WGJyjeGBAobOttE,3323
|
|
16
|
-
emerge/_emerge/geometry.py,sha256=
|
|
16
|
+
emerge/_emerge/geometry.py,sha256=OcQ0wvritkg7Q8oihQI_hLjDGx7JkFaPwfEeJ3_u3Bs,19987
|
|
17
17
|
emerge/_emerge/howto.py,sha256=c4UxUNpA1tygr3OoR-LH-h0UZv-Tf9K8tpCiAU18BKE,8173
|
|
18
|
-
emerge/_emerge/logsettings.py,sha256=
|
|
19
|
-
emerge/_emerge/material.py,sha256=
|
|
20
|
-
emerge/_emerge/mesh3d.py,sha256=
|
|
18
|
+
emerge/_emerge/logsettings.py,sha256=s8UboFEtB0aIuLB2FSL2WIbw0_kB363iHNIy4uGQi7w,3711
|
|
19
|
+
emerge/_emerge/material.py,sha256=bVuMyrmts08at4nUc4ttgYHPsY1cLYNKNmJ4RwgR9TY,15462
|
|
20
|
+
emerge/_emerge/mesh3d.py,sha256=qmdbuuR6W_5nMg7K5fts08v2lk0K8otUO6C4gS0Zjks,35008
|
|
21
21
|
emerge/_emerge/mesher.py,sha256=fKgPb6oZe_bqp0XYfZ6UNgBfRaAS3-tjUtZX8NalJe8,13199
|
|
22
22
|
emerge/_emerge/periodic.py,sha256=xfdKKq3qX7iBBestnRizOzJNfXlpr9lCPkiYhfrRIR8,12013
|
|
23
23
|
emerge/_emerge/plot.py,sha256=cf1I9mj7EIUJcq8vmANlUkqoV6QqVaJaP-zlC-T9E18,8041
|
|
24
24
|
emerge/_emerge/selection.py,sha256=Clx3YopcYwaN61rX4wdDsEJo_0F-DWGe3AP8rPjvTzY,21368
|
|
25
|
-
emerge/_emerge/simmodel.py,sha256=
|
|
25
|
+
emerge/_emerge/simmodel.py,sha256=qycNtzKgNllQvPQrbSlKhimJQ1ucMIEM-BsKCrHJemE,20504
|
|
26
26
|
emerge/_emerge/simulation_data.py,sha256=r9-9lpLeA1Z5HU3jDVOXV1H80GVawnXL5K81_dvmlE4,14506
|
|
27
|
-
emerge/_emerge/solver.py,sha256=
|
|
27
|
+
emerge/_emerge/solver.py,sha256=J7aIpW7Eni56wnVhXL2JSuwRf8HuTBQCUrXKx31u5EU,49927
|
|
28
28
|
emerge/_emerge/system.py,sha256=p4HNz7d_LMRNE9Gk75vVdFecDH2iN_groAM9u-yQTpk,1618
|
|
29
29
|
emerge/_emerge/elements/__init__.py,sha256=I3n9aic6lJW-oGeqTEZ-Fpxvyl2i-WqsHdnrM3v1oB8,799
|
|
30
30
|
emerge/_emerge/elements/femdata.py,sha256=o5P-lRAW_xWEOQ_jrT5zRciFZwq1LqCIXfaWurWdjmw,8082
|
|
@@ -38,8 +38,8 @@ emerge/_emerge/geo/modeler.py,sha256=_PMz3lFSa7FmJHWdY-4U1Sqbed-Egy85S_AdjlCldC4
|
|
|
38
38
|
emerge/_emerge/geo/operations.py,sha256=lqfCU99uiLc0vDGqILpMP1YgKs1e-gwEcSLbI_gE6TA,12441
|
|
39
39
|
emerge/_emerge/geo/pcb.py,sha256=MmY-A-Xnd85aQw6ouOnsZKcui_kH86fw4l0GoR4qQu0,53442
|
|
40
40
|
emerge/_emerge/geo/pmlbox.py,sha256=gaIG_AoZNQnIyJ8C7x64U-Hw5dsmllWMiZDAH4iRoM0,8784
|
|
41
|
-
emerge/_emerge/geo/polybased.py,sha256=
|
|
42
|
-
emerge/_emerge/geo/shapes.py,sha256
|
|
41
|
+
emerge/_emerge/geo/polybased.py,sha256=3Lpbbw6o9ypTvInMNcLa-zF5jP8uOSn9c_Tiv_R85cc,33055
|
|
42
|
+
emerge/_emerge/geo/shapes.py,sha256=i0kcwC1EqOpXonJUhdpRKfed3MaFnPsEc_vgTfRSWwI,23532
|
|
43
43
|
emerge/_emerge/geo/step.py,sha256=XcAiEN8W4umNmZdYmrGHX_aJUuiMgc6vgT-UIk8Gbqc,2689
|
|
44
44
|
emerge/_emerge/geo/pcb_tools/calculator.py,sha256=VbMP2xC9i7OFwtqnnwfYgyJSEcJIjr2VIy_Ez1hYqlU,859
|
|
45
45
|
emerge/_emerge/geo/pcb_tools/macro.py,sha256=0g-0anOFyxrEkFobiSu0cwWFRQ32xB8Az24mmwo0z6M,2992
|
|
@@ -50,8 +50,8 @@ emerge/_emerge/mth/pairing.py,sha256=i8bBvTeMmzgF0JdiDNJiTXxx913x4f10777pzD6FJo0
|
|
|
50
50
|
emerge/_emerge/physics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
51
51
|
emerge/_emerge/physics/microwave/__init__.py,sha256=QHeILGYWmvbfLl1o9wrTiWLm0evfXDgS0JiikUoMTts,28
|
|
52
52
|
emerge/_emerge/physics/microwave/adaptive_freq.py,sha256=aWhijhCVAbnuwkru-I1AaRdY20uyozf6OWRIh9r2ijg,9786
|
|
53
|
-
emerge/_emerge/physics/microwave/microwave_3d.py,sha256=
|
|
54
|
-
emerge/_emerge/physics/microwave/microwave_bc.py,sha256=
|
|
53
|
+
emerge/_emerge/physics/microwave/microwave_3d.py,sha256=ocyLCLt6iZ2FlmqLvNCqxSDKdFRirUFRQYGNi8xgyRk,42367
|
|
54
|
+
emerge/_emerge/physics/microwave/microwave_bc.py,sha256=YaEkSyOsC9Di7-JItijuRKD60ZA9CmEX8Tu8pViMN90,42114
|
|
55
55
|
emerge/_emerge/physics/microwave/microwave_data.py,sha256=njeNfw_Is4bc97H-hefi-Bk8NSGMElXk0yzDb4v6mVk,50365
|
|
56
56
|
emerge/_emerge/physics/microwave/periodic.py,sha256=wYSUgLFVtCLqSG3EDKoCDRU93iPUzBdXzVRdHTRmbpI,3000
|
|
57
57
|
emerge/_emerge/physics/microwave/port_functions.py,sha256=aVU__AkVk8b1kH2J_oDLF5iNReCxC9nzCtesFSSSSQo,2112
|
|
@@ -67,19 +67,19 @@ emerge/_emerge/physics/microwave/assembly/periodicbc.py,sha256=Zg1kgQMccDQA2oVEr
|
|
|
67
67
|
emerge/_emerge/physics/microwave/assembly/robinbc.py,sha256=syJ-NuHHA0WDQECuaPdeW-OfzIGHmxxqalKiokSyJFI,17742
|
|
68
68
|
emerge/_emerge/plot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
69
69
|
emerge/_emerge/plot/display.py,sha256=TQLlKb-LkaG5ZOSLfxp9KXPlZPRFTxNj1LhVQ-Lp1-s,18476
|
|
70
|
-
emerge/_emerge/plot/simple_plots.py,sha256=
|
|
70
|
+
emerge/_emerge/plot/simple_plots.py,sha256=lzAyLpY4yaAgMBgNkpeIxdrdSp5nQH6JmBI_ZfjzuhY,25229
|
|
71
71
|
emerge/_emerge/plot/matplotlib/mpldisplay.py,sha256=szKafDrgdAW5Nyc5UOHuJC87n0WGkXYackOVv182TDQ,8671
|
|
72
72
|
emerge/_emerge/plot/pyvista/__init__.py,sha256=CPclatEu6mFnJZzCQk09g6T6Fh20WTbiLAJGSwAnPXU,30
|
|
73
|
-
emerge/_emerge/plot/pyvista/display.py,sha256=
|
|
73
|
+
emerge/_emerge/plot/pyvista/display.py,sha256=Y8BT3ML9eeSQw_HLDmi3KCe0xtA8qOahOnCPGgvnM2g,38354
|
|
74
74
|
emerge/_emerge/plot/pyvista/display_settings.py,sha256=k4JfiNuaVDpPZrZa0sIuuFFwLvYAWDS17tusUCVHNu0,1036
|
|
75
75
|
emerge/_emerge/projects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
76
76
|
emerge/_emerge/projects/_gen_base.txt,sha256=DqQz36PZg6v1ovQjHvPjd0t4AIbmikZdb9dmrNYsK3w,598
|
|
77
77
|
emerge/_emerge/projects/_load_base.txt,sha256=bHsZ4okxa9uu8qP4UOxSAeIQzuwpRtN0i71rg8wuqMA,473
|
|
78
78
|
emerge/_emerge/projects/generate_project.py,sha256=TNw-0SpLc82MBq0bd9hB_yqvBZCgmuPonCBsHTp91uk,1450
|
|
79
|
-
emerge/_emerge/solve_interfaces/cudss_interface.py,sha256
|
|
79
|
+
emerge/_emerge/solve_interfaces/cudss_interface.py,sha256=Iszyy7RuuCa_FgfROEyTSSWbmR2LzMUkEcR8klzIKOQ,9915
|
|
80
80
|
emerge/_emerge/solve_interfaces/pardiso_interface.py,sha256=iVFxToMmIzhj3hcAP-O_MDHKz82ePFIHY1us11kzUBU,15305
|
|
81
|
-
emerge-0.6.
|
|
82
|
-
emerge-0.6.
|
|
83
|
-
emerge-0.6.
|
|
84
|
-
emerge-0.6.
|
|
85
|
-
emerge-0.6.
|
|
81
|
+
emerge-0.6.10.dist-info/METADATA,sha256=tmedxST_2MpgTZXZK7GGc0RMNt_9DjEMKlJjw6IFh0g,3339
|
|
82
|
+
emerge-0.6.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
83
|
+
emerge-0.6.10.dist-info/entry_points.txt,sha256=8rFvAXticpKg4OTC8JEvAksnduW72KIEskCGG9XnFf8,43
|
|
84
|
+
emerge-0.6.10.dist-info/licenses/LICENSE,sha256=VOCXWddrjMN5j7TvnSAOh1Dx7jkugdwq9Lqhycf5inc,17852
|
|
85
|
+
emerge-0.6.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|