phiFEM 0.7.0.dev1__py3-none-any.whl → 0.7.1.dev2__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.
- phifem/mesh_scripts.py +181 -139
- {phifem-0.7.0.dev1.dist-info → phifem-0.7.1.dev2.dist-info}/METADATA +11 -1
- phifem-0.7.1.dev2.dist-info/RECORD +7 -0
- {phifem-0.7.0.dev1.dist-info → phifem-0.7.1.dev2.dist-info}/WHEEL +1 -1
- phifem-0.7.0.dev1.dist-info/RECORD +0 -7
- {phifem-0.7.0.dev1.dist-info → phifem-0.7.1.dev2.dist-info}/licenses/COPYING +0 -0
- {phifem-0.7.0.dev1.dist-info → phifem-0.7.1.dev2.dist-info}/licenses/COPYING.lesser +0 -0
phifem/mesh_scripts.py
CHANGED
|
@@ -118,35 +118,31 @@ def _compute_detection_vector(
|
|
|
118
118
|
detection_denom_form = dfx.fem.form(detection_denom)
|
|
119
119
|
detection_denom_vec = assemble_vector(detection_denom_form)
|
|
120
120
|
|
|
121
|
-
imap = dg_0_space.dofmap.index_map
|
|
122
|
-
detection_vector = dfx.la.vector(imap)
|
|
123
121
|
# detection_denom_vec is not supposed to be zero, this would mean that the levelset is zero at all dofs in a cell.
|
|
124
122
|
# However, in practice it can happen that for a very small cut triangle, detection_denom_vec is of the order of the machine precision.
|
|
125
123
|
# In this case, we set the value of detection_vector to 0.5, meaning we consider the cell as cut.
|
|
124
|
+
mask = np.where(detection_denom_vec.array > 0.0)
|
|
125
|
+
detection_vector = np.full_like(detection_num_vec.array, 0.5)
|
|
126
|
+
detection_vector[mask] = (
|
|
127
|
+
detection_num_vec.array[mask] / detection_denom_vec.array[mask]
|
|
128
|
+
)
|
|
126
129
|
if np.any(np.isclose(detection_denom_vec.array, 0.0)):
|
|
127
130
|
warnings.warn(
|
|
128
|
-
"The
|
|
131
|
+
"The detection function is zero everywhere on a cell. We mark it as 'cut' but this can be incorrect and should be carefully checked.",
|
|
129
132
|
RuntimeWarning,
|
|
130
133
|
)
|
|
131
|
-
mask = np.where(detection_denom_vec.array > 0.0)
|
|
132
|
-
detection_vector.array[:] = 0.5
|
|
133
|
-
detection_vector.array[mask] = (
|
|
134
|
-
detection_num_vec.array[mask] / detection_denom_vec.array[mask]
|
|
135
|
-
)
|
|
136
|
-
detection_vector.scatter_forward()
|
|
137
134
|
return detection_vector
|
|
138
135
|
|
|
139
136
|
|
|
140
137
|
def _compute_integration_entities(
|
|
141
|
-
mesh: Mesh, integration_cells: list[int], integration_facets: list[int]
|
|
142
|
-
) ->
|
|
138
|
+
mesh: Mesh, integration_cells: list[int], integration_facets: list[int]
|
|
139
|
+
) -> list[int]:
|
|
143
140
|
"""Compute the integration entities in order to build a one-sided integral over a set of given edges. This script is inspired from https://github.com/jorgensd/dolfinx-tutorial/issues/158.
|
|
144
141
|
|
|
145
142
|
Args:
|
|
146
143
|
mesh: the mesh on which we compute the measure.
|
|
147
144
|
integration_cells: list of cells indices from which the integral is computed.
|
|
148
145
|
integration_facets: list of facets indices on which the integral is computed.
|
|
149
|
-
ind: index used in the measure.
|
|
150
146
|
Returns: the integration entities.
|
|
151
147
|
"""
|
|
152
148
|
cdim = mesh.topology.dim
|
|
@@ -192,7 +188,7 @@ def _compute_integration_entities(
|
|
|
192
188
|
np.column_stack((right_side_cells_rep, local_indices))
|
|
193
189
|
).astype(np.int32)
|
|
194
190
|
|
|
195
|
-
return
|
|
191
|
+
return integration_entities
|
|
196
192
|
|
|
197
193
|
|
|
198
194
|
def _reshape_map(connect: AdjacencyList_int32) -> npt.NDArray[np.int32]:
|
|
@@ -217,31 +213,71 @@ def _reshape_map(connect: AdjacencyList_int32) -> npt.NDArray[np.int32]:
|
|
|
217
213
|
return emap, max_offset
|
|
218
214
|
|
|
219
215
|
|
|
220
|
-
def
|
|
221
|
-
|
|
216
|
+
def _transfer_tags(
|
|
217
|
+
source_mesh_tags: MeshTags,
|
|
218
|
+
dest_mesh: Mesh,
|
|
222
219
|
cmap: npt.NDArray[Any],
|
|
223
|
-
|
|
224
|
-
) ->
|
|
220
|
+
source_mesh: Mesh = None,
|
|
221
|
+
) -> MeshTags:
|
|
225
222
|
"""Given entities tags (cells or facets) from a source mesh, a destination mesh and the source mesh-destination mesh cells mapping, transfers the entities tags to the destination mesh.
|
|
226
223
|
|
|
227
224
|
Args:
|
|
228
|
-
|
|
225
|
+
source_mesh_tags: the tags on the source mesh.
|
|
229
226
|
dest_mesh: the destination mesh.
|
|
230
227
|
cmap: the source mesh-destination mesh cells mapping.
|
|
228
|
+
source_mesh: the source mesh mandatory to transfer facets tags.
|
|
231
229
|
|
|
232
230
|
Returns:
|
|
233
231
|
Cells tags on the destination mesh.
|
|
234
232
|
"""
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
233
|
+
cdim = dest_mesh.topology.dim
|
|
234
|
+
fdim = cdim - 1
|
|
235
|
+
edim = source_mesh_tags.dim
|
|
236
|
+
|
|
237
|
+
if edim == cdim:
|
|
238
|
+
emap = cmap
|
|
239
|
+
elif edim == fdim:
|
|
240
|
+
if source_mesh is None:
|
|
241
|
+
raise ValueError("You must pass a source_mesh to transfer facets tags.")
|
|
242
|
+
|
|
243
|
+
source_mesh.topology.create_connectivity(cdim, fdim)
|
|
244
|
+
c2f_connect = source_mesh.topology.connectivity(cdim, fdim)
|
|
245
|
+
num_facets_per_cell = len(c2f_connect.links(0))
|
|
246
|
+
source_c2f_map = np.reshape(c2f_connect.array, (-1, num_facets_per_cell))
|
|
247
|
+
dest_mesh.topology.create_connectivity(cdim, fdim)
|
|
248
|
+
c2f_connect = dest_mesh.topology.connectivity(cdim, fdim)
|
|
249
|
+
num_facets_per_cell = len(c2f_connect.links(0))
|
|
250
|
+
dest_c2f_map = np.reshape(c2f_connect.array, (-1, num_facets_per_cell))
|
|
251
|
+
source_c2f_dest_map = source_c2f_map[cmap]
|
|
252
|
+
source_c2f_dest_map = source_c2f_dest_map.reshape(
|
|
253
|
+
-1,
|
|
254
|
+
)
|
|
255
|
+
dest_c2f_map = dest_c2f_map.reshape(
|
|
256
|
+
-1,
|
|
257
|
+
)
|
|
258
|
+
unique_indices, sorted_indices = np.unique(dest_c2f_map, return_index=True)
|
|
259
|
+
emap = source_c2f_dest_map[sorted_indices]
|
|
260
|
+
else:
|
|
261
|
+
raise ValueError("The source_mesh_tags can only be cells tags or facets tags.")
|
|
262
|
+
|
|
263
|
+
# TODO: change this line to allow parallel computing
|
|
264
|
+
source_tags = source_mesh_tags.values
|
|
265
|
+
|
|
266
|
+
dest_entities = np.arange(len(emap))
|
|
267
|
+
dest_tags = source_tags[emap]
|
|
268
|
+
|
|
269
|
+
dest_entities_indices = np.hstack(dest_entities).astype(np.int32)
|
|
270
|
+
dest_entities_markers = np.hstack(dest_tags).astype(np.int32)
|
|
271
|
+
sorted_indices = np.argsort(dest_entities_indices)
|
|
272
|
+
|
|
273
|
+
dest_entities_tags = dfx.mesh.meshtags(
|
|
274
|
+
dest_mesh,
|
|
275
|
+
edim,
|
|
276
|
+
dest_entities_indices[sorted_indices],
|
|
277
|
+
dest_entities_markers[sorted_indices],
|
|
240
278
|
)
|
|
241
|
-
dest_markers = dfx.la.vector(sub_index_map)
|
|
242
|
-
dest_markers.array[:] = source_markers.array[emap]
|
|
243
279
|
|
|
244
|
-
return
|
|
280
|
+
return dest_entities_tags
|
|
245
281
|
|
|
246
282
|
|
|
247
283
|
def _tag_cells(
|
|
@@ -249,7 +285,7 @@ def _tag_cells(
|
|
|
249
285
|
discrete_levelset: Function,
|
|
250
286
|
detection_degree: int,
|
|
251
287
|
single_layer_cut: bool = False,
|
|
252
|
-
) ->
|
|
288
|
+
) -> MeshTags:
|
|
253
289
|
"""Tag the mesh cells by computing detection = Σ f(dof)/Σ|f(dof)| where 'dof' are coming from a custom quadrature rule with points on the boundary of the cell only.
|
|
254
290
|
Strictly inside cell => tag 1
|
|
255
291
|
Cut cell => tag 2
|
|
@@ -262,7 +298,7 @@ def _tag_cells(
|
|
|
262
298
|
single_layer_cut: boolean, if True force a single layer of cut cells.
|
|
263
299
|
|
|
264
300
|
Returns:
|
|
265
|
-
The cells
|
|
301
|
+
The cells tags as a MeshTags object.
|
|
266
302
|
"""
|
|
267
303
|
if single_layer_cut:
|
|
268
304
|
cdim = mesh.topology.dim
|
|
@@ -304,12 +340,10 @@ def _tag_cells(
|
|
|
304
340
|
mesh, discrete_levelset, detection_measure
|
|
305
341
|
)
|
|
306
342
|
cut_indices = np.where(
|
|
307
|
-
np.logical_and(
|
|
308
|
-
detection_vector.array[:] > -1.0, detection_vector.array[:] < 1.0
|
|
309
|
-
)
|
|
343
|
+
np.logical_and(detection_vector > -1.0, detection_vector < 1.0)
|
|
310
344
|
)[0]
|
|
311
|
-
exterior_indices = np.where(
|
|
312
|
-
interior_indices = np.where(
|
|
345
|
+
exterior_indices = np.where(detection_vector == 1.0)[0]
|
|
346
|
+
interior_indices = np.where(detection_vector == -1.0)[0]
|
|
313
347
|
|
|
314
348
|
if single_layer_cut:
|
|
315
349
|
neighbor_cells = np.reshape(
|
|
@@ -337,21 +371,30 @@ def _tag_cells(
|
|
|
337
371
|
assert np.logical_not(np.isin(exterior_indices, interior_indices).any()), (
|
|
338
372
|
"The sets of outside cells and inside cells have a non-empty intersection"
|
|
339
373
|
)
|
|
340
|
-
cells_markers = dfx.la.vector(detection_vector.index_map)
|
|
341
|
-
cells_markers.array[interior_indices] = 1
|
|
342
|
-
cells_markers.array[cut_indices] = 2
|
|
343
|
-
cells_markers.array[exterior_indices] = 3
|
|
344
|
-
cells_markers.scatter_forward()
|
|
345
374
|
|
|
346
|
-
|
|
375
|
+
# Create the meshtags from the indices.
|
|
376
|
+
indices = np.hstack([exterior_indices, interior_indices, cut_indices]).astype(
|
|
377
|
+
np.int32
|
|
378
|
+
)
|
|
379
|
+
interior_marker = np.full_like(interior_indices, 1).astype(np.int32)
|
|
380
|
+
exterior_marker = np.full_like(exterior_indices, 3).astype(np.int32)
|
|
381
|
+
cut_marker = np.full_like(cut_indices, 2).astype(np.int32)
|
|
382
|
+
markers = np.hstack([exterior_marker, interior_marker, cut_marker]).astype(np.int32)
|
|
383
|
+
sorted_indices = np.argsort(indices)
|
|
384
|
+
|
|
385
|
+
cells_tags = dfx.mesh.meshtags(
|
|
386
|
+
mesh, mesh.topology.dim, indices[sorted_indices], markers[sorted_indices]
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
return cells_tags
|
|
347
390
|
|
|
348
391
|
|
|
349
392
|
def _tag_facets(
|
|
350
393
|
mesh: Mesh,
|
|
351
|
-
|
|
394
|
+
cells_tags: MeshTags,
|
|
352
395
|
discrete_levelset: Function,
|
|
353
396
|
detection_degree: int,
|
|
354
|
-
) ->
|
|
397
|
+
) -> MeshTags:
|
|
355
398
|
"""Tag the mesh facets.
|
|
356
399
|
Strictly interior facets => tag 1
|
|
357
400
|
Cut facets => tag 2
|
|
@@ -362,13 +405,12 @@ def _tag_facets(
|
|
|
362
405
|
|
|
363
406
|
Args:
|
|
364
407
|
mesh: the background mesh.
|
|
365
|
-
|
|
408
|
+
cells_tags: the MeshTags object containing cells tags.
|
|
366
409
|
discrete_levelset: the discretization of the levelset.
|
|
367
410
|
detection_degree: the degree of the custom quadrature rule used to detect cut entities.
|
|
368
411
|
|
|
369
412
|
Returns:
|
|
370
|
-
The facets
|
|
371
|
-
The wireframe mesh containing all facets.
|
|
413
|
+
The facets tags as a MeshTags object.
|
|
372
414
|
"""
|
|
373
415
|
cdim = mesh.topology.dim
|
|
374
416
|
fdim = cdim - 1
|
|
@@ -379,9 +421,9 @@ def _tag_facets(
|
|
|
379
421
|
c2f_map = np.reshape(c2f_connect.array, (-1, num_facets_per_cell))
|
|
380
422
|
|
|
381
423
|
# Get tagged cells
|
|
382
|
-
interior_cells =
|
|
383
|
-
cut_cells =
|
|
384
|
-
exterior_cells =
|
|
424
|
+
interior_cells = cells_tags.find(1)
|
|
425
|
+
cut_cells = cells_tags.find(2)
|
|
426
|
+
exterior_cells = cells_tags.find(3)
|
|
385
427
|
|
|
386
428
|
# Check which background mesh boundary facets are cut by the interface
|
|
387
429
|
background_mesh_boundary_facets = dfx.mesh.locate_entities_boundary(
|
|
@@ -403,7 +445,7 @@ def _tag_facets(
|
|
|
403
445
|
mesh, discrete_levelset, detection_measure
|
|
404
446
|
)
|
|
405
447
|
mask_cut_indices_cells = np.logical_and(
|
|
406
|
-
detection_vector
|
|
448
|
+
detection_vector > -1.0, detection_vector < 1.0
|
|
407
449
|
)
|
|
408
450
|
cut_indices_cells = np.where(mask_cut_indices_cells)[0]
|
|
409
451
|
comp_indices_cells = np.where(np.logical_not(mask_cut_indices_cells))[0]
|
|
@@ -477,26 +519,52 @@ def _tag_facets(
|
|
|
477
519
|
+ " have a non-empty intersection!"
|
|
478
520
|
)
|
|
479
521
|
|
|
480
|
-
#
|
|
481
|
-
|
|
482
|
-
|
|
522
|
+
# Create the meshtags from the indices.
|
|
523
|
+
indices = np.hstack(
|
|
524
|
+
[
|
|
525
|
+
exterior_facets,
|
|
526
|
+
interior_facets,
|
|
527
|
+
interior_boundary_facets,
|
|
528
|
+
cut_facets,
|
|
529
|
+
boundary_facets,
|
|
530
|
+
direct_interface_facets,
|
|
531
|
+
]
|
|
532
|
+
).astype(np.int32)
|
|
533
|
+
interior_marker = np.full_like(interior_facets, 1).astype(np.int32)
|
|
534
|
+
cut_marker = np.full_like(cut_facets, 2).astype(np.int32)
|
|
535
|
+
interior_boundary_marker = np.full_like(interior_boundary_facets, 3).astype(
|
|
536
|
+
np.int32
|
|
537
|
+
)
|
|
538
|
+
boundary_marker = np.full_like(boundary_facets, 4).astype(np.int32)
|
|
539
|
+
exterior_marker = np.full_like(exterior_facets, 5).astype(np.int32)
|
|
540
|
+
direct_interface_marker = np.full_like(direct_interface_facets, 6).astype(np.int32)
|
|
541
|
+
markers = np.hstack(
|
|
542
|
+
[
|
|
543
|
+
exterior_marker,
|
|
544
|
+
interior_marker,
|
|
545
|
+
interior_boundary_marker,
|
|
546
|
+
cut_marker,
|
|
547
|
+
boundary_marker,
|
|
548
|
+
direct_interface_marker,
|
|
549
|
+
]
|
|
550
|
+
).astype(np.int32)
|
|
551
|
+
sorted_indices = np.argsort(indices)
|
|
552
|
+
|
|
553
|
+
facets_tags = dfx.mesh.meshtags(
|
|
554
|
+
mesh, fdim, indices[sorted_indices], markers[sorted_indices]
|
|
483
555
|
)
|
|
484
|
-
wireframe = dfx.mesh.create_submesh(mesh, 1, all_facets)[0]
|
|
485
|
-
cell_name_wf = wireframe.topology.cell_name()
|
|
486
|
-
dg0_element_wf = element("DG", cell_name_wf, 0)
|
|
487
|
-
dg0_space_wf = dfx.fem.functionspace(wireframe, dg0_element_wf)
|
|
488
|
-
imap = dg0_space_wf.dofmap.index_map
|
|
489
|
-
facets_markers = dfx.la.vector(imap)
|
|
490
556
|
|
|
491
|
-
|
|
492
|
-
facets_markers.array[cut_facets] = 2
|
|
493
|
-
facets_markers.array[interior_boundary_facets] = 3
|
|
494
|
-
facets_markers.array[boundary_facets] = 4
|
|
495
|
-
facets_markers.array[exterior_facets] = 5
|
|
496
|
-
facets_markers.array[direct_interface_facets] = 6
|
|
497
|
-
facets_markers.scatter_forward()
|
|
557
|
+
return facets_tags
|
|
498
558
|
|
|
499
|
-
|
|
559
|
+
|
|
560
|
+
def _overwrite_tags(mesh, tags_to_overwrite, new_tags):
|
|
561
|
+
stack_indices = np.hstack([new_tags.indices, tags_to_overwrite.indices])
|
|
562
|
+
stack_values = np.hstack([new_tags.values, tags_to_overwrite.values])
|
|
563
|
+
overwritten_indices, ind = np.unique(stack_indices, return_index=True)
|
|
564
|
+
overwritten_values = stack_values[ind]
|
|
565
|
+
|
|
566
|
+
overwritten_tags = dfx.mesh.meshtags(mesh, tags_to_overwrite.dim, overwritten_indices, overwritten_values)
|
|
567
|
+
return overwritten_tags
|
|
500
568
|
|
|
501
569
|
|
|
502
570
|
def compute_tags_measures(
|
|
@@ -505,6 +573,7 @@ def compute_tags_measures(
|
|
|
505
573
|
detection_degree: int,
|
|
506
574
|
box_mode: bool = False,
|
|
507
575
|
single_layer_cut: bool = False,
|
|
576
|
+
overwrite_tags: dict[str,MeshTags] | dict = {},
|
|
508
577
|
) -> Tuple[
|
|
509
578
|
MeshTags,
|
|
510
579
|
MeshTags,
|
|
@@ -528,98 +597,71 @@ def compute_tags_measures(
|
|
|
528
597
|
The boundaries measure.
|
|
529
598
|
Submesh c-map, v-map and n-map.
|
|
530
599
|
"""
|
|
531
|
-
|
|
600
|
+
cells_tags = _tag_cells(
|
|
532
601
|
mesh, discrete_levelset, detection_degree, single_layer_cut=single_layer_cut
|
|
533
602
|
)
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
)
|
|
603
|
+
facets_tags = _tag_facets(mesh, cells_tags, discrete_levelset, detection_degree)
|
|
604
|
+
|
|
605
|
+
if "cells" in overwrite_tags.keys():
|
|
606
|
+
ow_cells_tags = overwrite_tags["cells"]
|
|
607
|
+
if np.any(np.isin([1, 2, 3], ow_cells_tags.values)):
|
|
608
|
+
raise ValueError("Cannot overwrite cells tags with values 1, 2 or 3.")
|
|
609
|
+
cells_tags = _overwrite_tags(mesh, cells_tags, ow_cells_tags)
|
|
610
|
+
if "facets" in overwrite_tags.keys():
|
|
611
|
+
ow_facets_tags = overwrite_tags["facets"]
|
|
612
|
+
if np.any(np.isin([1, 2, 3, 4, 5, 6], ow_facets_tags.values)):
|
|
613
|
+
raise ValueError("Cannot overwrite facets tags with values 1, 2, 3, 4, 5, 6, 100 or 101.")
|
|
614
|
+
facets_tags = _overwrite_tags(mesh, facets_tags, ow_facets_tags)
|
|
537
615
|
|
|
538
616
|
if box_mode:
|
|
539
617
|
submesh = None
|
|
540
|
-
integration_cells = np.union1d(
|
|
541
|
-
np.where(np.isclose(cells_markers.array[:], 2)),
|
|
542
|
-
np.where(np.isclose(cells_markers.array[:], 1)),
|
|
543
|
-
)
|
|
618
|
+
integration_cells = np.union1d(cells_tags.find(2), cells_tags.find(1))
|
|
544
619
|
integration_entities_outside = _compute_integration_entities(
|
|
545
|
-
mesh,
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
100,
|
|
549
|
-
)
|
|
550
|
-
integration_cells = np.union1d(
|
|
551
|
-
np.where(np.isclose(cells_markers.array[:], 2)),
|
|
552
|
-
np.where(np.isclose(cells_markers.array[:], 3)),
|
|
553
|
-
)
|
|
620
|
+
mesh, integration_cells, facets_tags.find(4))
|
|
621
|
+
integration_entities_outside = [(100, integration_entities_outside)]
|
|
622
|
+
integration_cells = np.union1d(cells_tags.find(2), cells_tags.find(3))
|
|
554
623
|
integration_entities_inside = _compute_integration_entities(
|
|
555
|
-
mesh,
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
)
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
)
|
|
624
|
+
mesh, integration_cells, facets_tags.find(3))
|
|
625
|
+
integration_entities_inside = [(101, integration_entities_inside)]
|
|
626
|
+
combined_integration_entities = integration_entities_outside + integration_entities_inside
|
|
627
|
+
|
|
628
|
+
non_phifem_mask = ~np.isin(facets_tags.values, [1, 2, 3, 4, 5, 6])
|
|
629
|
+
fdim = facets_tags.dim
|
|
630
|
+
boundary_facets = dfx.mesh.locate_entities_boundary(mesh, fdim, lambda x: np.ones_like(x[0]).astype(bool))
|
|
631
|
+
non_phifem_facets_bdy = np.isin(facets_tags.indices, boundary_facets)
|
|
632
|
+
non_phifem_mask *= non_phifem_facets_bdy
|
|
633
|
+
non_phifem_facets_ind = np.arange(len(facets_tags.indices))[non_phifem_mask]
|
|
634
|
+
non_phifem_facets = facets_tags.indices[non_phifem_facets_ind]
|
|
635
|
+
non_phifem_facets_tags = np.unique(facets_tags.values[non_phifem_facets_ind])
|
|
636
|
+
|
|
637
|
+
for tag in non_phifem_facets_tags:
|
|
638
|
+
cdim = mesh.topology.dim
|
|
639
|
+
fdim = cdim - 1
|
|
640
|
+
mesh.topology.create_connectivity(fdim, cdim)
|
|
641
|
+
f2c_connect = mesh.topology.connectivity(fdim, cdim)
|
|
642
|
+
f2c_map = _reshape_map(f2c_connect)[0]
|
|
643
|
+
|
|
644
|
+
non_phifem_facets_cells = f2c_map[non_phifem_facets]
|
|
645
|
+
|
|
646
|
+
assert len(non_phifem_facets_cells) == len(non_phifem_facets)
|
|
647
|
+
|
|
648
|
+
combined_integration_entities += [(tag, _compute_integration_entities(mesh, non_phifem_facets_cells, facets_tags.find(tag)))]
|
|
563
649
|
|
|
564
650
|
boundaries_measure = ufl.Measure(
|
|
565
651
|
"ds", domain=mesh, subdomain_data=combined_integration_entities
|
|
566
652
|
)
|
|
567
653
|
submesh_maps = None
|
|
568
|
-
indices = np.arange(
|
|
569
|
-
cells_markers.index_map.size_local + cells_markers.index_map.num_ghosts
|
|
570
|
-
)
|
|
571
|
-
cells_tags = dfx.mesh.meshtags(
|
|
572
|
-
mesh, mesh.topology.dim, indices, cells_markers.array[:]
|
|
573
|
-
)
|
|
574
|
-
indices = np.arange(
|
|
575
|
-
facets_markers.index_map.size_local + facets_markers.index_map.num_ghosts
|
|
576
|
-
)
|
|
577
|
-
facets_tags = dfx.mesh.meshtags(
|
|
578
|
-
mesh, mesh.topology.dim - 1, indices, facets_markers.array[:]
|
|
579
|
-
)
|
|
580
654
|
else:
|
|
581
655
|
# We create the submesh
|
|
582
|
-
omega_h_cells = np.unique(
|
|
583
|
-
np.hstack(
|
|
584
|
-
[
|
|
585
|
-
np.where(np.isclose(cells_markers.array[:], 1)),
|
|
586
|
-
np.where(np.isclose(cells_markers.array[:], 2)),
|
|
587
|
-
]
|
|
588
|
-
)
|
|
589
|
-
)
|
|
656
|
+
omega_h_cells = np.unique(np.hstack([cells_tags.find(1), cells_tags.find(2)]))
|
|
590
657
|
submesh, c_map, v_map, n_map = dfx.mesh.create_submesh(
|
|
591
658
|
mesh, mesh.topology.dim, omega_h_cells
|
|
592
|
-
)
|
|
593
|
-
submesh_maps = [c_map, v_map, n_map]
|
|
659
|
+
) # type: ignore
|
|
594
660
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
)
|
|
598
|
-
submesh.topology.create_entities(submesh.topology.dim - 1)
|
|
599
|
-
submesh_imap = submesh.topology.index_map(submesh.topology.dim - 1)
|
|
600
|
-
submesh_facets = np.arange(submesh_imap.size_local + submesh_imap.num_ghosts)
|
|
601
|
-
wf_submesh, wf_map = dfx.mesh.create_submesh(
|
|
602
|
-
submesh, submesh.topology.dim - 1, submesh_facets
|
|
603
|
-
)[:2]
|
|
604
|
-
wf_submesh.topology.create_entities(wf_submesh.topology.dim)
|
|
605
|
-
facets_markers_subwf = _transfer_markers(
|
|
606
|
-
facets_markers, wf_map, submesh.topology.dim - 1
|
|
607
|
-
)
|
|
661
|
+
cells_tags = _transfer_tags(cells_tags, submesh, c_map)
|
|
662
|
+
facets_tags = _transfer_tags(facets_tags, submesh, c_map, source_mesh=mesh)
|
|
608
663
|
boundaries_measure = ufl.Measure("ds", domain=submesh)
|
|
609
|
-
|
|
610
|
-
indices = np.arange(
|
|
611
|
-
cells_markers_submesh.index_map.size_local
|
|
612
|
-
+ cells_markers_submesh.index_map.num_ghosts
|
|
613
|
-
)
|
|
614
|
-
cells_tags = dfx.mesh.meshtags(
|
|
615
|
-
submesh, submesh.topology.dim, indices, cells_markers_submesh.array[:]
|
|
616
|
-
)
|
|
617
|
-
facets_tags = dfx.mesh.meshtags(
|
|
618
|
-
submesh,
|
|
619
|
-
submesh.topology.dim - 1,
|
|
620
|
-
submesh_facets,
|
|
621
|
-
facets_markers_subwf.array[submesh_facets],
|
|
622
|
-
)
|
|
664
|
+
submesh_maps = [c_map, v_map, n_map]
|
|
623
665
|
|
|
624
666
|
return (
|
|
625
667
|
cells_tags,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: phiFEM
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1.dev2
|
|
4
4
|
Summary: phiFEM: convenience tools to use the phiFEM immersed boundary finite element method with dolfinx.
|
|
5
5
|
Project-URL: Homepage, https://github.com/PhiFEM/phiFEM
|
|
6
6
|
Project-URL: Issues, https://github.com/PhiFEM/phiFEM/issues
|
|
@@ -113,6 +113,16 @@ To run the demos first clone the repository.
|
|
|
113
113
|
pytest
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
+
## Disclaimer
|
|
117
|
+
|
|
118
|
+
The author Raphaël Bulle guarantees that his contributions to this project are generative-ai-free.
|
|
119
|
+
|
|
120
|
+
<p align="center" width="50%">
|
|
121
|
+
<img width="30%" src="https://github.com/PhiFEM/phiFEM/raw/main/logo/sw_wbg.png">
|
|
122
|
+
</p>
|
|
123
|
+
|
|
124
|
+
For more information, see [here (in french)](https://doi.org/10.58079/1591s).
|
|
125
|
+
|
|
116
126
|
## License
|
|
117
127
|
|
|
118
128
|
`phiFEM` is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
phifem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
phifem/mesh_scripts.py,sha256=NSciUpSeABNaZAHdihEI4yUqYZGSFk-NvjuRkSUqrhk,26963
|
|
3
|
+
phifem-0.7.1.dev2.dist-info/METADATA,sha256=JxTs9hdtq3hgmaVLZM4F8iCUkuSOb4SNkBfmawf01wo,5603
|
|
4
|
+
phifem-0.7.1.dev2.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
5
|
+
phifem-0.7.1.dev2.dist-info/licenses/COPYING,sha256=xTplwv1WHIfqq_EHLvXcq4ZTBCvBUwhGX1JBNYXrYnE,35146
|
|
6
|
+
phifem-0.7.1.dev2.dist-info/licenses/COPYING.lesser,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
|
|
7
|
+
phifem-0.7.1.dev2.dist-info/RECORD,,
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
phifem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
phifem/mesh_scripts.py,sha256=jVRTsIQRmEffTfhWHyJrqiImqtWZoiCBnSpuhW4W-Ho,24614
|
|
3
|
-
phifem-0.7.0.dev1.dist-info/METADATA,sha256=R0NitwqmCfRUTMiH-p907mLfKPWTX1RTEXJaKO-f0YY,5285
|
|
4
|
-
phifem-0.7.0.dev1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
5
|
-
phifem-0.7.0.dev1.dist-info/licenses/COPYING,sha256=xTplwv1WHIfqq_EHLvXcq4ZTBCvBUwhGX1JBNYXrYnE,35146
|
|
6
|
-
phifem-0.7.0.dev1.dist-info/licenses/COPYING.lesser,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
|
|
7
|
-
phifem-0.7.0.dev1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|