phiFEM 0.7.2.dev2__py3-none-any.whl → 0.8.1.dev1__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 +117 -44
- {phifem-0.7.2.dev2.dist-info → phifem-0.8.1.dev1.dist-info}/METADATA +1 -1
- phifem-0.8.1.dev1.dist-info/RECORD +7 -0
- phifem-0.7.2.dev2.dist-info/RECORD +0 -7
- {phifem-0.7.2.dev2.dist-info → phifem-0.8.1.dev1.dist-info}/WHEEL +0 -0
- {phifem-0.7.2.dev2.dist-info → phifem-0.8.1.dev1.dist-info}/licenses/COPYING +0 -0
- {phifem-0.7.2.dev2.dist-info → phifem-0.8.1.dev1.dist-info}/licenses/COPYING.lesser +0 -0
phifem/mesh_scripts.py
CHANGED
|
@@ -397,10 +397,50 @@ def _transfer_tags(
|
|
|
397
397
|
return dest_entities_tags
|
|
398
398
|
|
|
399
399
|
|
|
400
|
+
def _remove_isolated_cells(
|
|
401
|
+
mesh: dfx.mesh.Mesh,
|
|
402
|
+
exterior_indices: np.ndarray[np.int32],
|
|
403
|
+
cut_indices: np.ndarray[np.int32],
|
|
404
|
+
interior_indices: np.ndarray[np.int32],
|
|
405
|
+
):
|
|
406
|
+
cdim = mesh.topology.dim
|
|
407
|
+
vdim = 0
|
|
408
|
+
# Create the cell to facet connectivity and reshape it into an array s.t. c2f_map[cell_index] = [facets of this cell index]
|
|
409
|
+
mesh.topology.create_connectivity(cdim, vdim)
|
|
410
|
+
c2v_connect = mesh.topology.connectivity(cdim, vdim)
|
|
411
|
+
num_vertices_per_cell = len(c2v_connect.links(0))
|
|
412
|
+
c2v_map = np.reshape(c2v_connect.array, (-1, num_vertices_per_cell))
|
|
413
|
+
|
|
414
|
+
mesh.topology.create_connectivity(vdim, cdim)
|
|
415
|
+
v2c_connect = mesh.topology.connectivity(vdim, cdim)
|
|
416
|
+
v2c_map, max_offset = _reshape_map(v2c_connect)
|
|
417
|
+
|
|
418
|
+
neighbor_cells = np.reshape(
|
|
419
|
+
v2c_map[c2v_map[cut_indices]], (-1, num_vertices_per_cell * max_offset)
|
|
420
|
+
)
|
|
421
|
+
mask_no_interior_connected = ~np.any(
|
|
422
|
+
np.isin(neighbor_cells, interior_indices), axis=1
|
|
423
|
+
)
|
|
424
|
+
mask_no_exterior_connected = ~np.any(
|
|
425
|
+
np.isin(neighbor_cells, exterior_indices), axis=1
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
cut_disconnected_interior = cut_indices[mask_no_interior_connected]
|
|
429
|
+
cut_disconnected_exterior = cut_indices[mask_no_exterior_connected]
|
|
430
|
+
|
|
431
|
+
cut_indices = np.setdiff1d(
|
|
432
|
+
cut_indices, np.union1d(cut_disconnected_interior, cut_disconnected_exterior)
|
|
433
|
+
)
|
|
434
|
+
exterior_indices = np.union1d(exterior_indices, cut_disconnected_interior)
|
|
435
|
+
interior_indices = np.union1d(interior_indices, cut_disconnected_exterior)
|
|
436
|
+
|
|
437
|
+
return exterior_indices, cut_indices, interior_indices
|
|
438
|
+
|
|
439
|
+
|
|
400
440
|
def _tag_cells(
|
|
401
441
|
mesh: Mesh,
|
|
402
442
|
levelset_expression: Expression,
|
|
403
|
-
single_layer_cut: bool
|
|
443
|
+
single_layer_cut: bool,
|
|
404
444
|
) -> MeshTags:
|
|
405
445
|
"""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.
|
|
406
446
|
Strictly inside cell => tag 1
|
|
@@ -431,26 +471,9 @@ def _tag_cells(
|
|
|
431
471
|
cut_indices = np.where(cut)[0]
|
|
432
472
|
|
|
433
473
|
if single_layer_cut:
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
mesh.topology.create_connectivity(cdim, vdim)
|
|
437
|
-
c2v_connect = mesh.topology.connectivity(cdim, vdim)
|
|
438
|
-
num_vertices_per_cell = len(c2v_connect.links(0))
|
|
439
|
-
c2v_map = np.reshape(c2v_connect.array, (-1, num_vertices_per_cell))
|
|
440
|
-
|
|
441
|
-
mesh.topology.create_connectivity(vdim, cdim)
|
|
442
|
-
v2c_connect = mesh.topology.connectivity(vdim, cdim)
|
|
443
|
-
v2c_map, max_offset = _reshape_map(v2c_connect)
|
|
444
|
-
|
|
445
|
-
neighbor_cells = np.reshape(
|
|
446
|
-
v2c_map[c2v_map[cut_indices]], (-1, num_vertices_per_cell * max_offset)
|
|
447
|
-
)
|
|
448
|
-
mask_connected_cut_cells = np.any(
|
|
449
|
-
np.isin(neighbor_cells, interior_indices), axis=1
|
|
474
|
+
exterior_indices, cut_indices, interior_indices = _remove_isolated_cells(
|
|
475
|
+
mesh, exterior_indices, cut_indices, interior_indices
|
|
450
476
|
)
|
|
451
|
-
isolated_cut_cells = cut_indices[~mask_connected_cut_cells]
|
|
452
|
-
cut_indices = np.setdiff1d(cut_indices, isolated_cut_cells)
|
|
453
|
-
exterior_indices = np.union1d(exterior_indices, isolated_cut_cells)
|
|
454
477
|
|
|
455
478
|
if debug_mode:
|
|
456
479
|
if len(interior_indices) == 0:
|
|
@@ -480,7 +503,6 @@ def _tag_cells(
|
|
|
480
503
|
cells_tags = dfx.mesh.meshtags(
|
|
481
504
|
mesh, mesh.topology.dim, indices[sorted_indices], markers[sorted_indices]
|
|
482
505
|
)
|
|
483
|
-
|
|
484
506
|
return cells_tags
|
|
485
507
|
|
|
486
508
|
|
|
@@ -506,9 +528,9 @@ def _cells_facets_pairs(f2c_map, c2f_map, facets):
|
|
|
506
528
|
def _tag_facets(
|
|
507
529
|
mesh: Mesh,
|
|
508
530
|
levelset_expression_facets: Expression,
|
|
531
|
+
single_layer_cut: bool,
|
|
509
532
|
cells_tags: MeshTags | None = None,
|
|
510
533
|
levelset_expression_cells: Expression | None = None,
|
|
511
|
-
single_layer_cut: bool = False,
|
|
512
534
|
) -> MeshTags:
|
|
513
535
|
"""Tag the mesh facets.
|
|
514
536
|
Strictly interior facets => tag 1
|
|
@@ -531,9 +553,7 @@ def _tag_facets(
|
|
|
531
553
|
assert levelset_expression_cells is not None, (
|
|
532
554
|
"You must either pass cells_tags or a levelset expression over the cells of the domain."
|
|
533
555
|
)
|
|
534
|
-
cells_tags = _tag_cells(
|
|
535
|
-
mesh, levelset_expression_cells, single_layer_cut=single_layer_cut
|
|
536
|
-
)
|
|
556
|
+
cells_tags = _tag_cells(mesh, levelset_expression_cells, single_layer_cut)
|
|
537
557
|
|
|
538
558
|
cdim = mesh.topology.dim
|
|
539
559
|
fdim = cdim - 1
|
|
@@ -579,7 +599,10 @@ def _tag_facets(
|
|
|
579
599
|
cut_indices = np.setdiff1d(cut_indices, direct_indices)
|
|
580
600
|
|
|
581
601
|
# Compute the list of facets on the boundary of the union of cut cells
|
|
582
|
-
|
|
602
|
+
if len(cells_tags.find(2)) > 0:
|
|
603
|
+
boundary_cut_indices = _compute_subdomain_exterior_facets(mesh, cells_tags, [2])
|
|
604
|
+
else:
|
|
605
|
+
boundary_cut_indices = []
|
|
583
606
|
boundary_exterior_indices = np.intersect1d(boundary_cut_indices, interior_indices)
|
|
584
607
|
boundary_exterior_indices = np.setdiff1d(boundary_exterior_indices, direct_indices)
|
|
585
608
|
interior_indices = np.setdiff1d(interior_indices, boundary_exterior_indices)
|
|
@@ -662,6 +685,60 @@ def _overwrite_tags(mesh, tags_to_overwrite, new_tags):
|
|
|
662
685
|
return overwritten_tags
|
|
663
686
|
|
|
664
687
|
|
|
688
|
+
def _compute_codim_interpolation_points(
|
|
689
|
+
space: dfx.fem.FunctionSpace,
|
|
690
|
+
) -> np.ndarray[np.float64]:
|
|
691
|
+
"""Compute the same FunctionSpace but defined over a submesh of codim 1.
|
|
692
|
+
|
|
693
|
+
Args:
|
|
694
|
+
space: the original space.
|
|
695
|
+
|
|
696
|
+
Return: a new space defined on a mesh of codim 1.
|
|
697
|
+
"""
|
|
698
|
+
family_name = space.ufl_element().basix_element.family.name
|
|
699
|
+
degree = space.ufl_element().basix_element.degree
|
|
700
|
+
tdim = space.mesh.topology.dim
|
|
701
|
+
codim_mesh = dfx.mesh.create_submesh(space.mesh, tdim - 1, np.array([0.0]))[0]
|
|
702
|
+
codim_cell_name = codim_mesh.topology.cell_name()
|
|
703
|
+
new_elmt = element(family_name, codim_cell_name, degree)
|
|
704
|
+
new_space = dfx.fem.functionspace(codim_mesh, new_elmt)
|
|
705
|
+
return new_space.element.interpolation_points()
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
def _levelset_expression(
|
|
709
|
+
mesh: dfx.mesh.Mesh,
|
|
710
|
+
levelset: Function | Callable,
|
|
711
|
+
interpolation_points: np.NDarray[np.float64],
|
|
712
|
+
) -> Expression:
|
|
713
|
+
"""Sanitize the levelset input by turning it into an Expression.
|
|
714
|
+
|
|
715
|
+
Args:
|
|
716
|
+
levelset: the levelset function.
|
|
717
|
+
detection_space: the detection space.
|
|
718
|
+
|
|
719
|
+
Return: the levelset as an Expression object.
|
|
720
|
+
"""
|
|
721
|
+
|
|
722
|
+
# Sanitize levelset input
|
|
723
|
+
try:
|
|
724
|
+
# Test if levelset is a dolfinx.fem.Function
|
|
725
|
+
_ = levelset.function_space
|
|
726
|
+
levelset_expression = dfx.fem.Expression(
|
|
727
|
+
levelset, interpolation_points, comm=mesh.comm
|
|
728
|
+
)
|
|
729
|
+
except AttributeError:
|
|
730
|
+
try:
|
|
731
|
+
x = ufl.SpatialCoordinate(mesh)
|
|
732
|
+
levelset_expression = dfx.fem.Expression(
|
|
733
|
+
levelset(x), interpolation_points, comm=mesh.comm
|
|
734
|
+
)
|
|
735
|
+
except TypeError:
|
|
736
|
+
print(
|
|
737
|
+
"Invalid levelset type: must be either a dolfinx.fem.Function or a UFL based Callable."
|
|
738
|
+
)
|
|
739
|
+
return levelset_expression
|
|
740
|
+
|
|
741
|
+
|
|
665
742
|
def compute_tags_measures(
|
|
666
743
|
mesh: Mesh,
|
|
667
744
|
levelset: Function | Callable,
|
|
@@ -692,27 +769,23 @@ def compute_tags_measures(
|
|
|
692
769
|
The boundaries measure.
|
|
693
770
|
Submesh c-map, v-map and n-map.
|
|
694
771
|
"""
|
|
772
|
+
interpolation_points = detection_space.element.interpolation_points()
|
|
773
|
+
levelset_expression = _levelset_expression(mesh, levelset, interpolation_points)
|
|
695
774
|
|
|
696
|
-
|
|
697
|
-
try:
|
|
698
|
-
levelset_expression = dfx.fem.Expression(
|
|
699
|
-
levelset, detection_space.element.interpolation_points()
|
|
700
|
-
)
|
|
701
|
-
except AttributeError:
|
|
702
|
-
try:
|
|
703
|
-
x = mesh.SpatialCoordinate(mesh)
|
|
704
|
-
levelset_expression = dfx.fem.Expression(
|
|
705
|
-
levelset(x), detection_space.element.interpolation_points()
|
|
706
|
-
)
|
|
707
|
-
except TypeError:
|
|
708
|
-
print(
|
|
709
|
-
"Invalid levelset type: must be either a dolfinx.fem.Function or a UFL based Callable."
|
|
710
|
-
)
|
|
775
|
+
cells_tags = _tag_cells(mesh, levelset_expression, single_layer_cut)
|
|
711
776
|
|
|
712
|
-
|
|
713
|
-
|
|
777
|
+
codim_interpolation_points = _compute_codim_interpolation_points(detection_space)
|
|
778
|
+
levelset_expression_facets = _levelset_expression(
|
|
779
|
+
mesh, levelset, codim_interpolation_points
|
|
780
|
+
)
|
|
781
|
+
|
|
782
|
+
facets_tags = _tag_facets(
|
|
783
|
+
mesh,
|
|
784
|
+
levelset_expression_facets,
|
|
785
|
+
single_layer_cut,
|
|
786
|
+
cells_tags=cells_tags,
|
|
787
|
+
levelset_expression_cells=levelset_expression,
|
|
714
788
|
)
|
|
715
|
-
facets_tags = _tag_facets(mesh, cells_tags, discrete_levelset, detection_degree)
|
|
716
789
|
|
|
717
790
|
if overwrite_tags is not None:
|
|
718
791
|
if "cells" in overwrite_tags:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: phiFEM
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.1.dev1
|
|
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
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
phifem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
phifem/mesh_scripts.py,sha256=AAUsA75d8UVjKTcjbie9Ap9GS0zFBR2rvNPRiAfT9L0,33222
|
|
3
|
+
phifem-0.8.1.dev1.dist-info/METADATA,sha256=9N9PgoSH6zNVh_jN3XSkp_QVseI74H8y-3yYRESOLRM,5606
|
|
4
|
+
phifem-0.8.1.dev1.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
5
|
+
phifem-0.8.1.dev1.dist-info/licenses/COPYING,sha256=xTplwv1WHIfqq_EHLvXcq4ZTBCvBUwhGX1JBNYXrYnE,35146
|
|
6
|
+
phifem-0.8.1.dev1.dist-info/licenses/COPYING.lesser,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
|
|
7
|
+
phifem-0.8.1.dev1.dist-info/RECORD,,
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
phifem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
phifem/mesh_scripts.py,sha256=Im8vPg3NxA44qiynUmVkCvyu6C6tYcQLKhJpDY0FJbA,30820
|
|
3
|
-
phifem-0.7.2.dev2.dist-info/METADATA,sha256=pggXcQxyYtwUxScyjZtHvFlmkiakNl8kLtbr9qCdj4s,5606
|
|
4
|
-
phifem-0.7.2.dev2.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
5
|
-
phifem-0.7.2.dev2.dist-info/licenses/COPYING,sha256=xTplwv1WHIfqq_EHLvXcq4ZTBCvBUwhGX1JBNYXrYnE,35146
|
|
6
|
-
phifem-0.7.2.dev2.dist-info/licenses/COPYING.lesser,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
|
|
7
|
-
phifem-0.7.2.dev2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|