Source code for libcasm.local_configuration._methods

import libcasm.clusterography
import libcasm.configuration
import libcasm.occ_events
import libcasm.xtal


[docs] def make_occevent_suborbits( supercell: libcasm.configuration.Supercell, occ_event: libcasm.occ_events.OccEvent ) -> list[list[libcasm.occ_events.OccEvent]]: r"""Make the sub-orbits of OccEvent in a supercell This method generates the sub-orbits that occur due to a supercell that has less symmetry than the prim. Each sub-orbit is made up of OccEvent that are equivalent with respect to the supercell factor group. OccEvent in different sub-orbits are equivalent with respect to the prim factor group, but not the supercell factor group. Parameters ---------- supercell: ~libcasm.configuration.Supercell The :class:`~libcasm.configuration.Supercell`. occ_event: ~libcasm.occ_events.OccEvent The :class:`~libcasm.occ_events.OccEvent`. Returns ------- suborbits: list[list[~libcasm.occ_events.OccEvent]] The sub-orbits, where `suborbits[i][j]` is the j-th :class:`~libcasm.occ_events.OccEvent` in the i-th sub-orbit. """ prim = supercell.prim prim_factor_group = prim.factor_group prim_rep = libcasm.occ_events.make_occevent_symgroup_rep( prim_factor_group.elements, prim.xtal_prim ) orbit = libcasm.occ_events.make_prim_periodic_orbit(occ_event, prim_rep) def in_any_suborbit(x, suborbits): for suborbit in suborbits: if x in suborbit: return True return False suborbits = [] scel_factor_group = supercell.factor_group scel_rep = libcasm.occ_events.make_occevent_symgroup_rep( scel_factor_group.elements, prim.xtal_prim ) for x in orbit: if in_any_suborbit(x, suborbits): continue new_suborbit = libcasm.occ_events.make_prim_periodic_orbit(x, scel_rep) if new_suborbit not in suborbits: suborbits.append(new_suborbit) return suborbits
def _make_symop_inverse( op: libcasm.xtal.SymOp, ) -> libcasm.xtal.SymOp: """Make the inverse SymOp Parameters ---------- op: libcasm.xtal.SymOp A SymOp Returns ------- op_inv: libcasm.xtal.SymOp The inverse SymOp """ return libcasm.xtal.SymOp( matrix=op.matrix().T, translation=-(op.matrix().T @ op.translation()), time_reversal=op.time_reversal(), )
[docs] def make_equivalents_generators( phenomenal_prototype: libcasm.clusterography.Cluster, generating_group: libcasm.sym_info.SymGroup, prim: libcasm.configuration.Prim, ) -> tuple[ list[libcasm.xtal.SymOp], list[int], list[libcasm.xtal.IntegralSiteCoordinateRep] ]: """Make symmetry operations that generate all the equivalent local orbits in \ the primitive cell. Notes ----- - If the `cluster_specs.generating_group()` is a subgroup of the phenomenal cluster group, then there will be >1 distinct sets of local orbits around the phenomenal cluster. - This method finds the cluster group operations that generate the distinct set of local orbits, then it uses the phenomenal cluster orbit equivalence map to find operations that transform the local orbits sets to the equivalent phenomenal clusters in the primitive cell. Parameters ---------- phenomenal_prototype: casmclust.Cluster The prototype phenomenal cluster. The prototype phenomenal cluster must be chosen from one of the equivalents that is generated by :func:`~libcasm.clusterography.make_periodic_orbit` using the prim factor group. generating_group: sym_info.SymGroup The local orbits generating group. prim: libcasm.configuration.Prim The prim, with symmetry info Returns ------- ops: list[libcasm.xtal.SymOp] Symmetry operations that generate the equivalent local orbits in the primitive unit cell. indices: list[int] Indices of prim factor group operations corresponding to `ops`. site_reps: list[libcasm.xtal.IntegralSiteCoordinateRep] Symmetry group representation for transforming IntegralSiteCoordinate and Cluster corresponding to `ops`. """ import libcasm.clusterography as casmclust # collect needed sym groups factor_grp = prim.factor_group generating_grp = generating_group site_rep = prim.integral_site_coordinate_symgroup_rep phenomenal_cluster_grp = casmclust.make_cluster_group( cluster=phenomenal_prototype, group=factor_grp, lattice=prim.xtal_prim.lattice(), integral_site_coordinate_symgroup_rep=site_rep, ) # find indices of factor group operations # that generate equivalent (but rotated) local basis sets # about the phenomenal cluster. i_factor_grp_equiv_on_phenomenal = set() for i_cluster_grp in range(len(phenomenal_cluster_grp.elements)): i_factor_grp = phenomenal_cluster_grp.head_group_index[i_cluster_grp] i_factor_grp_min = i_factor_grp for j_generating_grp in range(len(generating_grp.elements)): j_factor_grp = generating_grp.head_group_index[j_generating_grp] k_product = factor_grp.mult(j_factor_grp, i_factor_grp) if k_product < i_factor_grp_min: i_factor_grp_min = k_product i_factor_grp_equiv_on_phenomenal.add(i_factor_grp_min) # generate the phenomenal cluster orbit and equivalence map phenomenal_orbit = casmclust.make_periodic_orbit( orbit_element=phenomenal_prototype, integral_site_coordinate_symgroup_rep=site_rep, ) equivalence_map = casmclust.make_periodic_equivalence_map( orbit=phenomenal_orbit, symgroup=factor_grp, lattice=prim.xtal_prim.lattice(), integral_site_coordinate_symgroup_rep=site_rep, ) equivalence_map_indices = casmclust.make_periodic_equivalence_map_indices( orbit=phenomenal_orbit, integral_site_coordinate_symgroup_rep=site_rep, ) # find op and factor group index that transform phenomenal to orbit prototype to_prototype_op = None i_to_prototype = None sorted_phenomenal = phenomenal_prototype.sorted() for i_clust, clust in enumerate(phenomenal_orbit): sorted_clust = clust.sorted() if sorted_clust == sorted_phenomenal: to_prototype_op = _make_symop_inverse(equivalence_map[i_clust][0]) i_to_prototype = factor_grp.inv(equivalence_map_indices[i_clust][0]) break if to_prototype_op is None: raise Exception( "Error in make_equivalents_generators: Failed to find to_prototype_op." "The phenomenal cluster must be chosen from one of the" "equivalents generated by `libcasm.clusterography.make_periodic_orbit`." ) # equiv bset = to_equiv_op * (to_prototype_op * (cluster_grp_op * phenomenal bset)) # ^ distinct bset on phenomenal # ^ bset on prototype # ^ bset on other phenomenal generating_indices = [] for i_factor_grp in i_factor_grp_equiv_on_phenomenal: for i_equiv in range(len(equivalence_map)): i_to_equiv = equivalence_map_indices[i_equiv][0] i_generating_op = factor_grp.mult( i_to_equiv, factor_grp.mult(i_to_prototype, i_factor_grp) ) generating_indices.append(i_generating_op) generating_indices.sort() generating_ops = [] for i in generating_indices: generating_ops.append(factor_grp.elements[i]) generating_site_reps = casmclust.make_integral_site_coordinate_symgroup_rep( group_elements=generating_ops, xtal_prim=prim.xtal_prim, ) return (generating_ops, generating_indices, generating_site_reps)
[docs] def make_occevent_equivalents_generators( prototype_event: libcasm.occ_events.OccEvent, prim: libcasm.configuration.Prim, ) -> tuple[ list[libcasm.xtal.SymOp], list[int], list[libcasm.xtal.IntegralSiteCoordinateRep] ]: """Make symmetry operations that generate all the equivalent OccEvent in \ the primitive cell. Parameters ---------- prototype_event: libcasm.occ_events.OccEvent The prototype OccEvent. The underlying cluster `prototype_event.cluster` must be chosen from one of the equivalents that is generated by :func:`~libcasm.clusterography.make_periodic_orbit` using the prim factor group. prim: libcasm.configuration.Prim The prim, with symmetry info Returns ------- ops: list[libcasm.xtal.SymOp] Symmetry operations that generate the equivalent local orbits in the primitive unit cell. indices: list[int] Indices of prim factor group operations corresponding to `ops`. site_reps: list[libcasm.xtal.IntegralSiteCoordinateRep] Symmetry group representation for transforming IntegralSiteCoordinate and Cluster corresponding to `ops`. """ occevent_symgroup_rep = libcasm.occ_events.make_occevent_symgroup_rep( prim.factor_group.elements, prim.xtal_prim ) generating_group = libcasm.occ_events.make_occevent_group( occ_event=prototype_event, group=prim.factor_group, lattice=prim.xtal_prim.lattice(), occevent_symgroup_rep=occevent_symgroup_rep, ) return make_equivalents_generators( phenomenal_prototype=prototype_event.cluster(), generating_group=generating_group, prim=prim, )