phiFEM 0.8.0.dev1__py3-none-any.whl → 0.8.2.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 CHANGED
@@ -380,8 +380,9 @@ def _transfer_tags(
380
380
  # TODO: change this line to allow parallel computing
381
381
  source_tags = source_mesh_tags.values
382
382
 
383
- dest_entities = np.arange(len(emap))
384
- dest_tags = source_tags[emap]
383
+ num_entities = emap.topology.index_map(edim).size_local
384
+ dest_entities = np.arange(num_entities)
385
+ dest_tags = emap.sub_topology_to_topology(source_tags, False)
385
386
 
386
387
  dest_entities_indices = np.hstack(dest_entities).astype(np.int32)
387
388
  dest_entities_markers = np.hstack(dest_tags).astype(np.int32)
@@ -397,10 +398,50 @@ def _transfer_tags(
397
398
  return dest_entities_tags
398
399
 
399
400
 
401
+ def _remove_isolated_cells(
402
+ mesh: dfx.mesh.Mesh,
403
+ exterior_indices: np.ndarray[np.int32],
404
+ cut_indices: np.ndarray[np.int32],
405
+ interior_indices: np.ndarray[np.int32],
406
+ ):
407
+ cdim = mesh.topology.dim
408
+ vdim = 0
409
+ # Create the cell to facet connectivity and reshape it into an array s.t. c2f_map[cell_index] = [facets of this cell index]
410
+ mesh.topology.create_connectivity(cdim, vdim)
411
+ c2v_connect = mesh.topology.connectivity(cdim, vdim)
412
+ num_vertices_per_cell = len(c2v_connect.links(0))
413
+ c2v_map = np.reshape(c2v_connect.array, (-1, num_vertices_per_cell))
414
+
415
+ mesh.topology.create_connectivity(vdim, cdim)
416
+ v2c_connect = mesh.topology.connectivity(vdim, cdim)
417
+ v2c_map, max_offset = _reshape_map(v2c_connect)
418
+
419
+ neighbor_cells = np.reshape(
420
+ v2c_map[c2v_map[cut_indices]], (-1, num_vertices_per_cell * max_offset)
421
+ )
422
+ mask_no_interior_connected = ~np.any(
423
+ np.isin(neighbor_cells, interior_indices), axis=1
424
+ )
425
+ mask_no_exterior_connected = ~np.any(
426
+ np.isin(neighbor_cells, exterior_indices), axis=1
427
+ )
428
+
429
+ cut_disconnected_interior = cut_indices[mask_no_interior_connected]
430
+ cut_disconnected_exterior = cut_indices[mask_no_exterior_connected]
431
+
432
+ cut_indices = np.setdiff1d(
433
+ cut_indices, np.union1d(cut_disconnected_interior, cut_disconnected_exterior)
434
+ )
435
+ exterior_indices = np.union1d(exterior_indices, cut_disconnected_interior)
436
+ interior_indices = np.union1d(interior_indices, cut_disconnected_exterior)
437
+
438
+ return exterior_indices, cut_indices, interior_indices
439
+
440
+
400
441
  def _tag_cells(
401
442
  mesh: Mesh,
402
443
  levelset_expression: Expression,
403
- single_layer_cut: bool = False,
444
+ single_layer_cut: bool,
404
445
  ) -> MeshTags:
405
446
  """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
447
  Strictly inside cell => tag 1
@@ -431,26 +472,9 @@ def _tag_cells(
431
472
  cut_indices = np.where(cut)[0]
432
473
 
433
474
  if single_layer_cut:
434
- vdim = 0
435
- # Create the cell to facet connectivity and reshape it into an array s.t. c2f_map[cell_index] = [facets of this cell index]
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
475
+ exterior_indices, cut_indices, interior_indices = _remove_isolated_cells(
476
+ mesh, exterior_indices, cut_indices, interior_indices
450
477
  )
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
478
 
455
479
  if debug_mode:
456
480
  if len(interior_indices) == 0:
@@ -480,7 +504,6 @@ def _tag_cells(
480
504
  cells_tags = dfx.mesh.meshtags(
481
505
  mesh, mesh.topology.dim, indices[sorted_indices], markers[sorted_indices]
482
506
  )
483
-
484
507
  return cells_tags
485
508
 
486
509
 
@@ -506,9 +529,9 @@ def _cells_facets_pairs(f2c_map, c2f_map, facets):
506
529
  def _tag_facets(
507
530
  mesh: Mesh,
508
531
  levelset_expression_facets: Expression,
532
+ single_layer_cut: bool,
509
533
  cells_tags: MeshTags | None = None,
510
534
  levelset_expression_cells: Expression | None = None,
511
- single_layer_cut: bool = False,
512
535
  ) -> MeshTags:
513
536
  """Tag the mesh facets.
514
537
  Strictly interior facets => tag 1
@@ -531,9 +554,7 @@ def _tag_facets(
531
554
  assert levelset_expression_cells is not None, (
532
555
  "You must either pass cells_tags or a levelset expression over the cells of the domain."
533
556
  )
534
- cells_tags = _tag_cells(
535
- mesh, levelset_expression_cells, single_layer_cut=single_layer_cut
536
- )
557
+ cells_tags = _tag_cells(mesh, levelset_expression_cells, single_layer_cut)
537
558
 
538
559
  cdim = mesh.topology.dim
539
560
  fdim = cdim - 1
@@ -550,21 +571,30 @@ def _tag_facets(
550
571
  interior_facets = np.setdiff1d(all_facets, boundary_facets)
551
572
 
552
573
  cell_facet_pairs = _cells_facets_pairs(f2c_map, c2f_map, interior_facets)
553
- levelset_eval_int = levelset_expression_facets.eval(mesh, cell_facet_pairs)
574
+ levelset_eval_int = levelset_expression_facets.eval(
575
+ mesh, cell_facet_pairs.reshape(-1, 2)
576
+ )
554
577
 
555
- exterior_int = np.min(levelset_eval_int, axis=1) > 0.0
556
- interior_int = np.max(levelset_eval_int, axis=1) < 0.0
578
+ geq_zero_int = np.greater_equal(np.min(levelset_eval_int, axis=1), 0.0)
579
+ leq_zero_int = np.less_equal(np.max(levelset_eval_int, axis=1), 0.0)
557
580
  direct_int = np.isclose(np.sum(np.abs(levelset_eval_int), axis=1), 0.0)
581
+ exterior_int = np.logical_and(geq_zero_int, ~direct_int)
582
+ interior_int = np.logical_and(leq_zero_int, ~direct_int)
558
583
 
559
584
  connected_cells = f2c_map[boundary_facets][:, 0]
560
585
 
561
586
  cell_facet_pairs = _compute_integration_entities(
562
587
  mesh, connected_cells, boundary_facets, 0
563
588
  )[0][1]
564
- levelset_eval_bdy = levelset_expression_facets.eval(mesh, cell_facet_pairs)
565
- exterior_bdy = np.min(levelset_eval_bdy, axis=1) > 0.0
566
- interior_bdy = np.max(levelset_eval_bdy, axis=1) < 0.0
589
+ levelset_eval_bdy = levelset_expression_facets.eval(
590
+ mesh, cell_facet_pairs.reshape(-1, 2)
591
+ )
592
+
593
+ geq_zero_bdy = np.greater_equal(np.min(levelset_eval_bdy, axis=1), 0.0)
594
+ leq_zero_bdy = np.less_equal(np.max(levelset_eval_bdy, axis=1), 0.0)
567
595
  direct_bdy = np.isclose(np.sum(np.abs(levelset_eval_bdy), axis=1), 0.0)
596
+ exterior_bdy = np.logical_and(geq_zero_bdy, ~direct_bdy)
597
+ interior_bdy = np.logical_and(leq_zero_bdy, ~direct_bdy)
568
598
 
569
599
  facets_indices = np.hstack([interior_facets, boundary_facets])
570
600
  exterior = np.hstack([exterior_int, exterior_bdy])
@@ -579,7 +609,10 @@ def _tag_facets(
579
609
  cut_indices = np.setdiff1d(cut_indices, direct_indices)
580
610
 
581
611
  # Compute the list of facets on the boundary of the union of cut cells
582
- boundary_cut_indices = _compute_subdomain_exterior_facets(mesh, cells_tags, [2])
612
+ if len(cells_tags.find(2)) > 0:
613
+ boundary_cut_indices = _compute_subdomain_exterior_facets(mesh, cells_tags, [2])
614
+ else:
615
+ boundary_cut_indices = []
583
616
  boundary_exterior_indices = np.intersect1d(boundary_cut_indices, interior_indices)
584
617
  boundary_exterior_indices = np.setdiff1d(boundary_exterior_indices, direct_indices)
585
618
  interior_indices = np.setdiff1d(interior_indices, boundary_exterior_indices)
@@ -679,7 +712,7 @@ def _compute_codim_interpolation_points(
679
712
  codim_cell_name = codim_mesh.topology.cell_name()
680
713
  new_elmt = element(family_name, codim_cell_name, degree)
681
714
  new_space = dfx.fem.functionspace(codim_mesh, new_elmt)
682
- return new_space.element.interpolation_points()
715
+ return new_space.element.interpolation_points
683
716
 
684
717
 
685
718
  def _levelset_expression(
@@ -746,12 +779,10 @@ def compute_tags_measures(
746
779
  The boundaries measure.
747
780
  Submesh c-map, v-map and n-map.
748
781
  """
749
- interpolation_points = detection_space.element.interpolation_points()
782
+ interpolation_points = detection_space.element.interpolation_points
750
783
  levelset_expression = _levelset_expression(mesh, levelset, interpolation_points)
751
784
 
752
- cells_tags = _tag_cells(
753
- mesh, levelset_expression, single_layer_cut=single_layer_cut
754
- )
785
+ cells_tags = _tag_cells(mesh, levelset_expression, single_layer_cut)
755
786
 
756
787
  codim_interpolation_points = _compute_codim_interpolation_points(detection_space)
757
788
  levelset_expression_facets = _levelset_expression(
@@ -761,9 +792,9 @@ def compute_tags_measures(
761
792
  facets_tags = _tag_facets(
762
793
  mesh,
763
794
  levelset_expression_facets,
764
- cells_tags,
765
- levelset_expression,
766
- single_layer_cut=single_layer_cut,
795
+ single_layer_cut,
796
+ cells_tags=cells_tags,
797
+ levelset_expression_cells=levelset_expression,
767
798
  )
768
799
 
769
800
  if overwrite_tags is not None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: phiFEM
3
- Version: 0.8.0.dev1
3
+ Version: 0.8.2.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
@@ -12,7 +12,7 @@ License-File: COPYING.lesser
12
12
  Classifier: Operating System :: OS Independent
13
13
  Classifier: Programming Language :: Python :: 3
14
14
  Requires-Python: >=3.9
15
- Requires-Dist: fenics-dolfinx==0.9.0
15
+ Requires-Dist: fenics-dolfinx<0.11,>=0.9.0
16
16
  Description-Content-Type: text/markdown
17
17
 
18
18
  <p align="center" width="100%">
@@ -0,0 +1,7 @@
1
+ phifem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ phifem/mesh_scripts.py,sha256=TIAGOjbfsHLrBFbNgvjs08iLEAPTabx-vrYUjmPcy0w,33678
3
+ phifem-0.8.2.dev1.dist-info/METADATA,sha256=dQqGlLjoQ9B5uEGV9c_Gn-qZJeg-xsxQYyHUsceXlLY,5612
4
+ phifem-0.8.2.dev1.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
5
+ phifem-0.8.2.dev1.dist-info/licenses/COPYING,sha256=xTplwv1WHIfqq_EHLvXcq4ZTBCvBUwhGX1JBNYXrYnE,35146
6
+ phifem-0.8.2.dev1.dist-info/licenses/COPYING.lesser,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
7
+ phifem-0.8.2.dev1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.32.4
2
+ Generator: hatchling 1.33.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,7 +0,0 @@
1
- phifem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- phifem/mesh_scripts.py,sha256=g9G_QjgERcNNdo26tCGymidLYaCRzSvMYwVaCOmiDIs,32508
3
- phifem-0.8.0.dev1.dist-info/METADATA,sha256=jFmzNbqBlHFois1398voBC6m7rJyKoUpT_a6s_seKGI,5606
4
- phifem-0.8.0.dev1.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
5
- phifem-0.8.0.dev1.dist-info/licenses/COPYING,sha256=xTplwv1WHIfqq_EHLvXcq4ZTBCvBUwhGX1JBNYXrYnE,35146
6
- phifem-0.8.0.dev1.dist-info/licenses/COPYING.lesser,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
7
- phifem-0.8.0.dev1.dist-info/RECORD,,