@@ -112,6 +112,15 @@ def f2t(self):
112
112
self ._f2t = self .build_inverse (self .t , self .t2f )
113
113
return self ._f2t
114
114
115
+ @property
116
+ def f2e (self ):
117
+ if not hasattr (self , '_f2e' ):
118
+ _ , self ._f2e = self .build_entities (
119
+ self .facets ,
120
+ self .bndelem .refdom .facets ,
121
+ )
122
+ return self ._f2e
123
+
115
124
@property
116
125
def edges (self ):
117
126
if not hasattr (self , '_edges' ):
@@ -573,6 +582,13 @@ def is_valid(self, raise_=False) -> bool:
573
582
logger .debug ("Mesh validation completed with no warnings." )
574
583
return True
575
584
585
+ @staticmethod
586
+ def _remove_duplicate_nodes (p , t ):
587
+ tmp = np .ascontiguousarray (p .T )
588
+ tmp , ixa , ixb = np .unique (tmp .view ([('' , tmp .dtype )] * tmp .shape [1 ]),
589
+ return_index = True , return_inverse = True )
590
+ return p [:, ixa ], ixb [t ]
591
+
576
592
def __iter__ (self ):
577
593
return iter ((self .doflocs , self .t ))
578
594
@@ -606,12 +622,7 @@ def __add__(self, other):
606
622
p = np .hstack ((self .p .round (decimals = 8 ),
607
623
other .p .round (decimals = 8 )))
608
624
t = np .hstack ((self .t , other .t + self .p .shape [1 ]))
609
- tmp = np .ascontiguousarray (p .T )
610
- tmp , ixa , ixb = np .unique (tmp .view ([('' , tmp .dtype )] * tmp .shape [1 ]),
611
- return_index = True , return_inverse = True )
612
- p = p [:, ixa ]
613
- t = ixb [t ]
614
- return cls (p , t )
625
+ return cls (* self ._remove_duplicate_nodes (p , t ))
615
626
616
627
def __repr__ (self ):
617
628
rep = ""
@@ -1038,27 +1049,42 @@ def restrict(self, elements):
1038
1049
newf [self .boundaries [k ]])
1039
1050
for k in self .boundaries }
1040
1051
if self .boundaries is not None else None ),
1041
- _subdomains = ({k : newt [np .intersect1d (self .subdomains [k ], elements )]
1052
+ _subdomains = ({k : newt [np .intersect1d (self .subdomains [k ],
1053
+ elements ).astype (np .int64 )]
1042
1054
for k in self .subdomains }
1043
1055
if self .subdomains is not None else None ),
1044
1056
)
1045
1057
1046
- def remove_elements (self , element_indices : ndarray ):
1058
+ def remove_elements (self , elements ):
1047
1059
"""Construct a new mesh by removing elements.
1048
1060
1049
1061
Parameters
1050
1062
----------
1051
- element_indices
1052
- List of element indices to remove.
1063
+ elements
1064
+ Criteria of which elements to include. This input is normalized
1065
+ using ``self.normalize_elements``.
1053
1066
1054
1067
"""
1055
- p , t , _ = self ._reix (np .delete (self .t , element_indices , axis = 1 ))
1068
+ elements = self .normalize_elements (elements )
1069
+ return self .restrict (np .setdiff1d (np .arange (self .t .shape [1 ],
1070
+ dtype = np .int64 ),
1071
+ elements ))
1072
+
1073
+ def remove_unused_nodes (self ):
1074
+ p , t , _ = self ._reix (self .t )
1075
+ return replace (
1076
+ self ,
1077
+ doflocs = p ,
1078
+ t = t ,
1079
+ )
1080
+
1081
+ def remove_duplicate_nodes (self ):
1082
+ p , t = self ._remove_duplicate_nodes (self .doflocs ,
1083
+ self .t )
1056
1084
return replace (
1057
1085
self ,
1058
1086
doflocs = p ,
1059
1087
t = t ,
1060
- _boundaries = None ,
1061
- _subdomains = None ,
1062
1088
)
1063
1089
1064
1090
def element_finder (self , mapping = None ):
0 commit comments