@@ -509,68 +509,6 @@ class ClosureOrdering(enum.Enum):
509
509
FIAT = "fiat"
510
510
511
511
512
- # TODO do we need to ensure that the cell orientation is always zero?
513
- # Note that the permutation is expressed numbering each entity type from zero,
514
- # meaning that the indices shown in the diagrams must be offset.
515
- _PLEX_TO_FIAT_CLOSURE_PERM = {
516
- # UFCInterval:
517
- #
518
- # 0---2---1
519
- #
520
- # PETSc.DM.PolytopeType.SEGMENT:
521
- #
522
- # 1---0---2
523
- "interval" : {
524
- 0 : np .array ([1 , 2 ]) - 1 ,
525
- 1 : np .array ([0 ]),
526
- },
527
-
528
- # UFCTriangle:
529
- #
530
- # 1
531
- # | \
532
- # 5 3
533
- # | 6 \
534
- # 0---4---2
535
- #
536
- # PETSc.DM.PolytopeType.TRIANGLE:
537
- #
538
- # 4
539
- # | \
540
- # 3 1
541
- # | 0 \
542
- # 6---2---5
543
- "triangle" : {
544
- 0 : np .array ([6 , 4 , 5 ]) - 1 - 3 ,
545
- 1 : np .array ([1 , 2 , 3 ]) - 1 ,
546
- 2 : np .array ([0 ]),
547
- },
548
-
549
- # UFCQuadrilateral:
550
- #
551
- # 1---7---3
552
- # | |
553
- # 4 8 5
554
- # | |
555
- # 0---6---2
556
- #
557
- # PETSc.DM.PolytopeType.QUADRILATERAL
558
- #
559
- # 5---4---8
560
- # | |
561
- # 1 0 3
562
- # | |
563
- # 6---2---7
564
- "quadrilateral" : {
565
- 0 : np .array ([6 , 5 , 7 , 8 ]) - 1 - 4 ,
566
- 1 : np .array ([1 , 3 , 2 , 4 ]) - 1 ,
567
- 2 : np .array ([0 ]),
568
- }
569
- }
570
- """
571
- """
572
-
573
-
574
512
class AbstractMeshTopology (abc .ABC ):
575
513
"""A representation of an abstract mesh topology without a concrete
576
514
PETSc DM implementation"""
@@ -670,19 +608,6 @@ def callback(self):
670
608
# entity_dofs[-2] = 1
671
609
# facet_numbering = self.create_section(entity_dofs)
672
610
# self._facet_ordering = dmcommon.get_facet_ordering(self.topology_dm, facet_numbering)
673
- # Derive a cell numbering from the Plex renumbering
674
- # these can all be determined from the axes and are only required
675
- # internally for things like map construction (which I also do internally)
676
- # entity_dofs = np.zeros(tdim+1, dtype=IntType)
677
- # entity_dofs[-1] = 1
678
- # self._cell_numbering = self.create_section(entity_dofs)
679
- # entity_dofs[:] = 0
680
- # entity_dofs[0] = 1
681
- # self._vertex_numbering = self.create_section(entity_dofs)
682
- # entity_dofs[:] = 0
683
- # entity_dofs[-2] = 1
684
- # facet_numbering = self.create_section(entity_dofs)
685
- # self._facet_ordering = dmcommon.get_facet_ordering(self.topology_dm, facet_numbering)
686
611
687
612
points = op3 .Axis (
688
613
{
@@ -737,6 +662,34 @@ def _renumber_entities(self, reorder):
737
662
"""Renumber entities."""
738
663
pass
739
664
665
+ @utils .cached_property
666
+ def _vertex_numbering (self ):
667
+ assert not hasattr (self , "_callback" ), "Mesh must be initialised"
668
+ return self ._entity_numbering (self .vertex_label )
669
+
670
+ @utils .cached_property
671
+ def _cell_numbering (self ):
672
+ assert not hasattr (self , "_callback" ), "Mesh must be initialised"
673
+ return self ._entity_numbering (self .cell_label )
674
+
675
+ @utils .cached_property
676
+ def _facet_numbering (self ):
677
+ assert not hasattr (self , "_callback" ), "Mesh must be initialised"
678
+ return self ._entity_numbering (self .facet_label )
679
+
680
+ def _entity_numbering (self , label ):
681
+ component_index = tuple (c .label for c in self .points .components ).index (label )
682
+
683
+ section = PETSc .Section ().create (self ._comm )
684
+ section .setChart (* self .topology_dm .getChart ())
685
+
686
+ renumbering = self .points ._default_to_applied_numbering [component_index ]
687
+ for old_component_num , new_component_num in enumerate (renumbering ):
688
+ old_pt = old_component_num + self .points ._component_offsets [component_index ]
689
+ section .setOffset (old_pt , new_component_num )
690
+
691
+ return section
692
+
740
693
@property
741
694
def comm (self ):
742
695
return self .user_comm
@@ -901,19 +854,6 @@ def _closure_map(self, ordering):
901
854
# closure_ordering
902
855
closure_data_concat = np .concatenate (closure_data , axis = 1 )
903
856
904
- if self .comm .size > 1 :
905
- # TODO determine the *global* vertex numbering, else ranks may disagree
906
- # on the direction of some edges/faces
907
- # TODO cache this
908
- # vertex_numbering = self._vertex_numbering.createGlobalSection(
909
- # self.topology_dm.getPointSF()
910
- # )
911
- raise NotImplementedError
912
- # ah, but the vertices have already been renumbered! Therefore don't
913
- # want to use the component_numbering but instead an identity numbering
914
- # vertex_numbering = self.points.component_numbering(self.vert_label)
915
- vertex_numbering = None # change this when implemented
916
-
917
857
cell = self .ufl_cell ()
918
858
if cell .is_simplex ():
919
859
topology = FIAT .ufc_cell (cell ).get_topology ()
@@ -924,12 +864,42 @@ def _closure_map(self, ordering):
924
864
reordered = dmcommon .closure_ordering (
925
865
self ,
926
866
closure_data_concat ,
927
- vertex_numbering ,
867
+ None , # vertex numbering already applied, clean up Cython to reflect this
928
868
entity_per_cell
929
869
)
930
- # reordered is ordered in order of increasing dimension
870
+ # reordered is ordered in order of increasing dimension, now
871
+ # split it apart by dimension
931
872
closure_data = tuple (
932
- reordered [:, start :stop ] for start , stop in pairwise (steps (closure_sizes ))
873
+ reordered [:, start :stop ]
874
+ for start , stop in pairwise (steps (closure_sizes ))
875
+ )
876
+
877
+ elif cell .cellname () == "quadrilateral" :
878
+ from firedrake_citations import Citations
879
+
880
+ Citations ().register ("Homolya2016" )
881
+ Citations ().register ("McRae2016" )
882
+
883
+ plex = self .topology_dm
884
+ cell_ranks = dmcommon .get_cell_remote_ranks (plex )
885
+ facet_orientations = dmcommon .quadrilateral_facet_orientations (
886
+ plex , self ._global_vertex_numbering , cell_ranks
887
+ )
888
+ cell_orientations = dmcommon .orientations_facet2cell (
889
+ plex ,
890
+ self ._global_vertex_numbering ,
891
+ cell_ranks ,
892
+ facet_orientations ,
893
+ self ._cell_numbering ,
894
+ )
895
+ dmcommon .exchange_cell_orientations (
896
+ plex , self ._cell_numbering , cell_orientations
897
+ )
898
+
899
+ # do not return...
900
+ # TODO pass closure data here, don't do inside
901
+ XXX = dmcommon .quadrilateral_closure_ordering (
902
+ plex , vertex_numbering , cell_numbering , cell_orientations
933
903
)
934
904
else :
935
905
raise NotImplementedError
@@ -1198,6 +1168,12 @@ def mark_entities(self, tf, label_value, label_name=None):
1198
1168
def extruded_periodic (self ):
1199
1169
return self .cell_set ._extruded_periodic
1200
1170
1171
+ @utils .cached_property
1172
+ def _global_vertex_numbering (self ):
1173
+ return self ._vertex_numbering .createGlobalSection (
1174
+ self .topology_dm .getPointSF ()
1175
+ )
1176
+
1201
1177
1202
1178
class MeshTopology (AbstractMeshTopology ):
1203
1179
"""A representation of mesh topology implemented on a PETSc DMPlex."""
@@ -2029,7 +2005,7 @@ def cell_closure(self):
2029
2005
2030
2006
# Cell numbering and global vertex numbering
2031
2007
cell_numbering = self ._cell_numbering
2032
- vertex_numbering = self ._vertex_numbering . createGlobalSection ( swarm . getPointSF ())
2008
+ vertex_numbering = self ._global_vertex_numbering
2033
2009
2034
2010
cell = self .ufl_cell ()
2035
2011
assert tdim == cell .topological_dimension ()
0 commit comments