emerge 1.0.6__py3-none-any.whl → 1.0.7__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 +1 -1
- emerge/_emerge/elements/index_interp.py +45 -0
- emerge/_emerge/material.py +1 -1
- emerge/_emerge/mesh3d.py +33 -3
- emerge/_emerge/mesher.py +22 -4
- emerge/_emerge/physics/microwave/adaptive_mesh.py +576 -0
- emerge/_emerge/physics/microwave/assembly/assembler.py +6 -5
- emerge/_emerge/physics/microwave/microwave_3d.py +125 -12
- emerge/_emerge/physics/microwave/microwave_bc.py +25 -3
- emerge/_emerge/physics/microwave/microwave_data.py +23 -6
- emerge/_emerge/plot/pyvista/display.py +5 -2
- emerge/_emerge/simmodel.py +86 -15
- emerge/_emerge/solver.py +1 -1
- {emerge-1.0.6.dist-info → emerge-1.0.7.dist-info}/METADATA +3 -2
- {emerge-1.0.6.dist-info → emerge-1.0.7.dist-info}/RECORD +18 -17
- {emerge-1.0.6.dist-info → emerge-1.0.7.dist-info}/WHEEL +0 -0
- {emerge-1.0.6.dist-info → emerge-1.0.7.dist-info}/entry_points.txt +0 -0
- {emerge-1.0.6.dist-info → emerge-1.0.7.dist-info}/licenses/LICENSE +0 -0
emerge/__init__.py
CHANGED
|
@@ -61,3 +61,48 @@ def index_interp(coords: np.ndarray,
|
|
|
61
61
|
prop[inside] = itet
|
|
62
62
|
|
|
63
63
|
return prop
|
|
64
|
+
|
|
65
|
+
@njit(f8[:](f8[:,:], i8[:,:], f8[:,:], i8[:], f8[:]), cache=True, nogil=True)
|
|
66
|
+
def constant_interp(coords: np.ndarray,
|
|
67
|
+
tets: np.ndarray,
|
|
68
|
+
nodes: np.ndarray,
|
|
69
|
+
tetids: np.ndarray,
|
|
70
|
+
value: np.ndarray):
|
|
71
|
+
''' Nedelec 2 tetrahedral interpolation of the analytic curl'''
|
|
72
|
+
# Solution has shape (nEdges, nsols)
|
|
73
|
+
nNodes = coords.shape[1]
|
|
74
|
+
|
|
75
|
+
prop = np.full((nNodes, ), 0, dtype=np.float64)
|
|
76
|
+
|
|
77
|
+
for i_iter in range(tetids.shape[0]):
|
|
78
|
+
itet = tetids[i_iter]
|
|
79
|
+
|
|
80
|
+
iv1, iv2, iv3, iv4 = tets[:, itet]
|
|
81
|
+
|
|
82
|
+
v1 = nodes[:,iv1]
|
|
83
|
+
v2 = nodes[:,iv2]
|
|
84
|
+
v3 = nodes[:,iv3]
|
|
85
|
+
v4 = nodes[:,iv4]
|
|
86
|
+
|
|
87
|
+
bv1 = v2 - v1
|
|
88
|
+
bv2 = v3 - v1
|
|
89
|
+
bv3 = v4 - v1
|
|
90
|
+
|
|
91
|
+
blocal = np.zeros((3,3))
|
|
92
|
+
blocal[:,0] = bv1
|
|
93
|
+
blocal[:,1] = bv2
|
|
94
|
+
blocal[:,2] = bv3
|
|
95
|
+
basis = np.linalg.pinv(blocal)
|
|
96
|
+
|
|
97
|
+
coords_offset = coords - v1[:,np.newaxis]
|
|
98
|
+
coords_local = (basis @ (coords_offset))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
inside = ((coords_local[0,:] + coords_local[1,:] + coords_local[2,:]) <= 1.00000001) & (coords_local[0,:] >= -1e-6) & (coords_local[1,:] >= -1e-6) & (coords_local[2,:] >= -1e-6)
|
|
102
|
+
|
|
103
|
+
if inside.sum() == 0:
|
|
104
|
+
continue
|
|
105
|
+
|
|
106
|
+
prop[inside] = value[itet]
|
|
107
|
+
|
|
108
|
+
return prop
|
emerge/_emerge/material.py
CHANGED
|
@@ -59,7 +59,7 @@ class MatProperty:
|
|
|
59
59
|
self._z: np.ndarray = np.array([], dtype=np.float64)
|
|
60
60
|
|
|
61
61
|
self._fmax = lambda f: value
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
def initialize(self, x: np.ndarray, y: np.ndarray, z: np.ndarray, ids: np.ndarray) -> None:
|
|
64
64
|
self._apply_to = np.concatenate([self._apply_to, ids])
|
|
65
65
|
self._x = np.concatenate([self._x, x])
|
emerge/_emerge/mesh3d.py
CHANGED
|
@@ -196,7 +196,6 @@ class Mesh3D(Mesh):
|
|
|
196
196
|
raise ValueError(f'There is no tetrahedron with indices {i1}, {i2}, {i3}, {i4}')
|
|
197
197
|
return output
|
|
198
198
|
|
|
199
|
-
|
|
200
199
|
def get_tetrahedra(self, vol_tags: Union[int, list[int]]) -> np.ndarray:
|
|
201
200
|
if isinstance(vol_tags, int):
|
|
202
201
|
vol_tags = [vol_tags,]
|
|
@@ -270,6 +269,37 @@ class Mesh3D(Mesh):
|
|
|
270
269
|
nodes.update(self.get_nodes(tags))
|
|
271
270
|
return np.array([i for i, tet in enumerate(self.tets.T) if not set(tet).isdisjoint(nodes)])
|
|
272
271
|
|
|
272
|
+
def _get_dimtags(self, nodes: list[int] | None = None, edges: list[int] | None = None) -> list[tuple[int, int]]:
|
|
273
|
+
"""Returns the geometry dimtags associated with a set of nodes and edges"""
|
|
274
|
+
if nodes is None:
|
|
275
|
+
nodes = []
|
|
276
|
+
if edges is None:
|
|
277
|
+
edges = []
|
|
278
|
+
nodes = set(nodes)
|
|
279
|
+
edges = set(edges)
|
|
280
|
+
dimtags = []
|
|
281
|
+
|
|
282
|
+
# Test faces
|
|
283
|
+
for tag, f_nodes in self.ftag_to_node.items():
|
|
284
|
+
if set(f_nodes).isdisjoint(nodes):
|
|
285
|
+
continue
|
|
286
|
+
dimtags.append((2,tag))
|
|
287
|
+
|
|
288
|
+
for tag, f_edges in self.ftag_to_edge.items():
|
|
289
|
+
if set(f_edges).isdisjoint(edges):
|
|
290
|
+
continue
|
|
291
|
+
dimtags.append((2,tag))
|
|
292
|
+
|
|
293
|
+
# test volumes
|
|
294
|
+
for tag, f_tets in self.vtag_to_tet.items():
|
|
295
|
+
v_nodes = set(self.tets[:,f_tets].flatten())
|
|
296
|
+
if not v_nodes.isdisjoint(nodes):
|
|
297
|
+
dimtags.append((3,tag))
|
|
298
|
+
v_edges = set(self.tet_to_edge[:,f_tets].flatten())
|
|
299
|
+
if not v_edges.isdisjoint(edges):
|
|
300
|
+
dimtags.append((3,tag))
|
|
301
|
+
return sorted(dimtags)
|
|
302
|
+
|
|
273
303
|
def get_nodes(self, face_tags: Union[int, list[int]]) -> np.ndarray:
|
|
274
304
|
'''Returns a numpyarray of all the nodes that belong to the given face tags'''
|
|
275
305
|
if isinstance(face_tags, int):
|
|
@@ -572,7 +602,7 @@ class Mesh3D(Mesh):
|
|
|
572
602
|
materials.append(vol.material)
|
|
573
603
|
vol.material._hash_key = i
|
|
574
604
|
i += 1
|
|
575
|
-
|
|
605
|
+
|
|
576
606
|
xs = self.centers[0,:]
|
|
577
607
|
ys = self.centers[1,:]
|
|
578
608
|
zs = self.centers[2,:]
|
|
@@ -597,7 +627,7 @@ class Mesh3D(Mesh):
|
|
|
597
627
|
def plot_gmsh(self) -> None:
|
|
598
628
|
gmsh.fltk.run()
|
|
599
629
|
|
|
600
|
-
def find_edge_groups(self, edge_ids: np.ndarray) -> list[tuple[
|
|
630
|
+
def find_edge_groups(self, edge_ids: np.ndarray) -> list[tuple[int,...]]:
|
|
601
631
|
"""
|
|
602
632
|
Find the groups of edges in the mesh.
|
|
603
633
|
|
emerge/_emerge/mesher.py
CHANGED
|
@@ -75,6 +75,7 @@ class Mesher:
|
|
|
75
75
|
self.objects: list[GeoObject] = []
|
|
76
76
|
self.size_definitions: list[tuple[int, float]] = []
|
|
77
77
|
self.mesh_fields: list[int] = []
|
|
78
|
+
self._amr_fields: list[int] = []
|
|
78
79
|
self.min_size: float = None
|
|
79
80
|
self.max_size: float = None
|
|
80
81
|
self.periodic_cell: PeriodicCell = None
|
|
@@ -222,8 +223,13 @@ class Mesher:
|
|
|
222
223
|
gmsh.model.mesh.field.set_numbers(ctag, "CurvesList", tags)
|
|
223
224
|
gmsh.model.mesh.field.set_number(ctag, "VIn", max_size)
|
|
224
225
|
self.mesh_fields.append(ctag)
|
|
226
|
+
|
|
227
|
+
def _reset_amr_points(self) -> None:
|
|
228
|
+
for tag in self._amr_fields:
|
|
229
|
+
gmsh.model.mesh.field.remove(tag)
|
|
230
|
+
self._amr_fields = []
|
|
225
231
|
|
|
226
|
-
def
|
|
232
|
+
def _set_amr_point(self, tags: list[int], max_size: float) -> None:
|
|
227
233
|
"""Define the size of the mesh on a point
|
|
228
234
|
|
|
229
235
|
Args:
|
|
@@ -233,7 +239,7 @@ class Mesher:
|
|
|
233
239
|
ctag = gmsh.model.mesh.field.add("Constant")
|
|
234
240
|
gmsh.model.mesh.field.set_numbers(ctag, "PointsList", tags)
|
|
235
241
|
gmsh.model.mesh.field.set_number(ctag, "VIn", max_size)
|
|
236
|
-
self.
|
|
242
|
+
self._amr_fields.append(ctag)
|
|
237
243
|
|
|
238
244
|
def _configure_mesh_size(self, discretizer: Callable, resolution: float):
|
|
239
245
|
"""Defines the mesh sizes based on a discretization callable.
|
|
@@ -267,7 +273,7 @@ class Mesher:
|
|
|
267
273
|
logger.debug(f'Setting mesh size:{1000*size:.3f}mm in domains: {tag}')
|
|
268
274
|
self._set_size_in_domain([tag,], size)
|
|
269
275
|
|
|
270
|
-
gmsh.model.mesh.field.setNumbers(mintag, "FieldsList", self.mesh_fields)
|
|
276
|
+
gmsh.model.mesh.field.setNumbers(mintag, "FieldsList", self.mesh_fields + self._amr_fields)
|
|
271
277
|
gmsh.model.mesh.field.setAsBackgroundMesh(mintag)
|
|
272
278
|
|
|
273
279
|
for tag, size in self.size_definitions:
|
|
@@ -279,7 +285,19 @@ class Mesher:
|
|
|
279
285
|
logger.trace(f'Unsetting mesh size constraint for domains: {dimtags}')
|
|
280
286
|
for dimtag in dimtags:
|
|
281
287
|
gmsh.model.mesh.setSizeFromBoundary(dimtag[0], dimtag[1], 0)
|
|
282
|
-
|
|
288
|
+
|
|
289
|
+
def add_refinement_point(self,
|
|
290
|
+
coordinate: np.ndarray,
|
|
291
|
+
refinement: float,
|
|
292
|
+
size: float,
|
|
293
|
+
gr: float = 1.5):
|
|
294
|
+
x0, y0, z0 = coordinate
|
|
295
|
+
disttag = gmsh.model.mesh.field.add("MathEval")
|
|
296
|
+
newsize = refinement*size
|
|
297
|
+
funcstr = f"({newsize})/({gr}) - (1-{gr})/({gr}) * Sqrt((x-({x0}))^2+ (y-({y0}))^2 + (z-({z0}))^2)"
|
|
298
|
+
gmsh.model.mesh.field.setString(disttag, "F", funcstr)
|
|
299
|
+
self.mesh_fields.append(disttag)
|
|
300
|
+
|
|
283
301
|
def set_boundary_size(self,
|
|
284
302
|
boundary: GeoObject | Selection | Iterable,
|
|
285
303
|
size:float,
|