def stab(self): """Computing stabilizer of a bilayer(or any 2 fragments). self.layers must contain 2 Layers L_0 and L_1. IMPORTANT: L_1 = g*L_0 so that if S_0 = stab(L_0) => L_1 = g*S_0*L_0. The latter means tha coset g*S_O contains all symops to generate L_1 from L_0. The stabilizer of the bilayer is then a union of 2 sets: 1. set1 contains all common symmetry elements of S_0 and S_1. El-ts of this set simply transform each of the layers into itself 2. set2 contains symmetry elements that transform L_0 into L_1 and at the same time L_1 into L_0. El-ts that transform L_0 into L_1 are in the coset: g*S_0 (that's why it is important that L_1 = g*L_O, that the corresponding coset attributes of the layers are set correctly) so g' from g*S_0 applied to L_1 should yield L_0: g'*L_1=L_0 and since g'L_0 = L_1 =>g'*g'L_0 = L_0 => g'*g' or g'^2 should belong to S_0. Hence set2 contains elements of coset g*S_0 (or L_1.coset) which squares belong to S_0. """ if self._stab: return self._stab #finding overlap between stabilizers of the constituent layers stab_overlap = \ [item for item in self.layers[1].stab if item in self.layers[0].stab] #for a layer that is generated from the other one by a stacking oper: #finding coset members whose 2 orders belong to stabilizer of the basic #layer unit_element = core.xyzt2augmat('x,y,z') sec_ord_elts = [] for nr,layer in enumerate(self.layers): if unit_element not in layer.coset: for symop in layer.coset: if core.modulo_n(symop*symop,1) in self.layers[1-nr].stab \ and symop not in stab_overlap: sec_ord_elts.append(symop) self._stab = stab_overlap + sec_ord_elts #performing some basic checks coset_union = self.layers[0].coset + self.layers[1].coset #print len(self.layers[0].coset) assert core.cosets_are_disjoint([self.layers[0].coset, self.layers[1].coset]), "Cosets are not disjoint!" assert len(self.layers[1].coset) == len(self.layers[0].coset),\ "Coset attributes for the constituent layers are of different order!" return self._stab
def fragments(self, fragments): nr_frags = len(fragments) assert nr_frags >= 0 "The layer contains no fragments!"#fragments is non-empty if nr_frags == 1: item_fragments = [] basic_fragment = fragments[0] order_basic = len(basic_fragment.stab) order_self = len(self.stab) #basic checks that can be switched off #1a in __init__ assert order_self % order_basic == 0,\ "Order of Fragment.stab does not divide that of Layer.stab!" #1b ... assert all([item in self.stab for item in basic_fragment.stab]),\ "There are symops in Fragment.stab that are not in Layer.stab!" lcosets = core.cosets_mod(basic_fragment.stab, self.stab) for lcoset in lcosets: item_fragments.append(Fragment.leftmult(basic_fragment, lcoset[0])) self._fragments = item_fragments #basic checks to do after coset decomposition #1c assert all([core.coset_in_stab((coset, self.stab)) \ for coset in lcosets]),\ """Cosets of the consituent fragments do not belong to the stabilizer of the layer!""" #1d assert all([core.divides((coset, self.stab)) for coset in lcosets]),\ """Order of cosets of consituent fragments does not devides order of the layers's stabilizer""" else: self._fragments = fragments #basic checks that can be switched off coset_list = [fragment.coset for fragment in self._fragments] stab_list = [fragment.stab for fragment in self._fragments] #1e assert core.cosets_are_disjoint(coset_list), "Cosets are not disjoint!" #1f assert all([core.divides((stab, self.stab)) for stab in stab_list]),\ """Order of stabilizer of some constituent fragments does not devide order of the layers's stabilizer""" #1g assert all([core.coset_in_stab((stab, self.stab)) \ for stab in stab_list]),\ """Stabilizers of the consituent fragments