def symm_ops(gpname, axes=None): if axes is not None: raise PointGroupSymmetryError('TODO: non-standard orientation') op1 = numpy.eye(3) opi = -1 opc2z = -numpy.eye(3) opc2z[2, 2] = 1 opc2x = -numpy.eye(3) opc2x[0, 0] = 1 opc2y = -numpy.eye(3) opc2y[1, 1] = 1 opcsz = numpy.dot(opc2z, opi) opcsx = numpy.dot(opc2x, opi) opcsy = numpy.dot(opc2y, opi) opdic = { 'E': op1, 'C2z': opc2z, 'C2x': opc2x, 'C2y': opc2y, 'i': opi, 'sz': opcsz, 'sx': opcsx, 'sy': opcsy, } return opdic
def as_subgroup(topgroup, axes, subgroup=None): from pyscf.symm import std_symb from pyscf.symm.param import SUBGROUP groupname, axes = get_subgroup(topgroup, axes) if isinstance(subgroup, (str, unicode)): subgroup = std_symb(subgroup) if groupname == 'C2v' and subgroup == 'Cs': axes = numpy.einsum('ij,kj->ki', rotation_mat(axes[1], numpy.pi / 2), axes) elif (groupname == 'D2' and re.search(r'D\d+d', topgroup) and subgroup in ('C2v', 'Cs')): # Special treatment for D2d, D4d, .... get_subgroup gives D2 by # default while C2v is also D2d's subgroup. groupname = 'C2v' axes = numpy.einsum('ij,kj->ki', rotation_mat(axes[2], numpy.pi / 4), axes) elif topgroup in ('Td', 'T', 'Th') and subgroup == 'C2v': x, y, z = axes x = _normalize(x + y) y = numpy.cross(z, x) axes = numpy.array((x, y, z)) elif subgroup not in SUBGROUP[groupname]: raise PointGroupSymmetryError('%s not in Ablien subgroup of %s' % (subgroup, topgroup)) groupname = subgroup return groupname, axes
def symm_identical_atoms(gpname, atoms): ''' Requires ''' from pyscf import gto # Dooh Coov for linear molecule if gpname == 'Dooh': coords = numpy.array([a[1] for a in atoms], dtype=float) idx0 = argsort_coords(coords) coords0 = coords[idx0] opdic = symm_ops(gpname) newc = numpy.dot(coords, opdic['sz']) idx1 = argsort_coords(newc) dup_atom_ids = numpy.sort((idx0, idx1), axis=0).T uniq_idx = numpy.unique(dup_atom_ids[:, 0], return_index=True)[1] eql_atom_ids = dup_atom_ids[uniq_idx] eql_atom_ids = [list(sorted(set(i))) for i in eql_atom_ids] return eql_atom_ids elif gpname == 'Coov': eql_atom_ids = [[i] for i, a in enumerate(atoms)] return eql_atom_ids coords = numpy.array([a[1] for a in atoms]) # charges = numpy.array([gto.charge(a[0]) for a in atoms]) # center = numpy.einsum('z,zr->r', charges, coords)/charges.sum() # if not numpy.allclose(center, 0, atol=TOLERANCE): # sys.stderr.write('WARN: Molecular charge center %s is not on (0,0,0)\n' # % center) opdic = symm_ops(gpname) ops = [opdic[op] for op in OPERATOR_TABLE[gpname]] idx = argsort_coords(coords) coords0 = coords[idx] dup_atom_ids = [] for op in ops: newc = numpy.dot(coords, op) idx = argsort_coords(newc) if not numpy.allclose(coords0, newc[idx], atol=TOLERANCE): raise PointGroupSymmetryError('Symmetry identical atoms not found') dup_atom_ids.append(idx) dup_atom_ids = numpy.sort(dup_atom_ids, axis=0).T uniq_idx = numpy.unique(dup_atom_ids[:, 0], return_index=True)[1] eql_atom_ids = dup_atom_ids[uniq_idx] eql_atom_ids = [list(sorted(set(i))) for i in eql_atom_ids] return eql_atom_ids
def linearmole_irrep_symb2id(gpname, symb): if gpname == 'Dooh': if symb in DOOH_IRREP_ID_TABLE: return DOOH_IRREP_ID_TABLE[symb] else: n = int(''.join([i for i in symb if i.isdigit()])) if n % 2: return (n // 2) * 10 + DOOH_IRREP_ID_TABLE['_odd' + symb[-2:]] else: return (n // 2) * 10 + DOOH_IRREP_ID_TABLE['_even' + symb[-2:]] elif gpname == 'Coov': if symb in COOV_IRREP_ID_TABLE: return COOV_IRREP_ID_TABLE[symb] else: n = int(''.join([i for i in symb if i.isdigit()])) if n % 2: return (n // 2) * 10 + COOV_IRREP_ID_TABLE['_odd' + symb[-1]] else: return (n // 2) * 10 + COOV_IRREP_ID_TABLE['_even' + symb[-1]] else: raise PointGroupSymmetryError('%s is not proper for linear molecule.' % gpname)
def dump_symm_adapted_basis(mol, so): raise PointGroupSymmetryError('TODO')
def irrep_name(pgname, irrep_id): raise PointGroupSymmetryError( 'This function was obsoleted. Use irrep_id2name')