Пример #1
0
    def plotBoundOrbital(self):
        selected = self.orbitalSelection.selectedItems()
        assert len(selected) == 1
        selected_orbital = self.orbital_dict[str(selected[0].text())]

        self.mo_bound = self.bound_orbs[:, selected_orbital]
        # shift geometry so that the expectation value of the dipole operator vanishes
        # dipole matrix
        dipole = np.tensordot(self.mo_bound,
                              np.tensordot(self.tddftb.dftb2.D,
                                           self.mo_bound,
                                           axes=(1, 0)),
                              axes=(0, 0))
        print "expectation value of dipole: %s" % dipole
        # shift molecule R -> R - dipole
        self.atomlist = MolCo.transform_molecule(
            self.tddftb.dftb2.getGeometry(), (0, 0, 0), -dipole)
        # load bound basis functions
        self.bs_bound = AtomicBasisSet(self.atomlist)
        # plot selected orbital
        (xmin, xmax), (ymin, ymax), (zmin, zmax) = Cube.get_bbox(self.atomlist,
                                                                 dbuff=5.0)
        dx, dy, dz = xmax - xmin, ymax - ymin, zmax - zmin
        ppb = 3.0  # Points per bohr
        nx, ny, nz = int(dx * ppb), int(dy * ppb), int(dz * ppb)
        x, y, z = np.mgrid[xmin:xmax:nx * 1j, ymin:ymax:ny * 1j,
                           zmin:zmax:nz * 1j]
        grid = (x, y, z)
        amplitude_bound = Cube.orbital_amplitude(grid,
                                                 self.bs_bound.bfs,
                                                 self.mo_bound,
                                                 cache=False)

        bound_cube = CubeData()
        bound_cube.data = amplitude_bound.real
        bound_cube.grid = grid
        bound_cube.atomlist = self.atomlist

        self.boundOrbitalViewer.setCubes([bound_cube])
Пример #2
0
def build_water_cluster(atomlist_template, orbital_names, phases):
    """
    build a cluster orbital as a linear combination of monomer orbitals with the correct orientation.
    The position and orientation of the water molecules is taken from the template. 
    
    Parameters:
    ===========
    atomlist_template: molecular geometry for cluster with n water molecules
    orbital_names: list of orbital names ('1b1', '3a1', '1b2' or '2a1') for each of the n water molecules
    phases: list of +1 or -1's for each orbital

    Returns:
    ========
    water_cluster: molecular geometry of the cluster
    orb_cluster: cluster orbital, that is a linear combination of the monomer orbitals.
    """
    # water geometry in bohr
    water_std = [(1, (0.0,  0.8459947982381987,  -1.4473477675908173)),
                 (8, (0.0, -0.21392561795490195,  0.0               )),
                 (1, (0.0,  0.8459947982381987,   1.4473477675908173))]
    valorbs, radial_val = load_pseudo_atoms(water_std)

    # Orbitals for H2O monomer in standard orientation:
    # molecular plane = yz-plane, oxygen lies on the negative y-axis, H-H bond is parallel to z-axis
        #                  H1-1s   O-2s    O-2py   O-2pz   O-2px   H2-1s  
    monomer_orbitals = {
        "1b1": np.array([ 0.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000]),
        "3a1": np.array([ 0.7816,-0.6842, 0.6989, 0.0000, 0.0000, 0.7816]),
        "1b2": np.array([-0.7264, 0.0000, 0.0000, 0.9429, 0.0000, 0.7264]),
        "2a1": np.array([ 0.1730, 0.8662, 0.0393, 0.0000, 0.0000, 0.1730])
    }

    # First the individual water molecules in the template are identified and their positions
    # and orientations are extracted.
    fragments = MolecularGraph.disconnected_fragments(atomlist_template)
    assert len(fragments) == len(orbital_names) == len(phases), "For each water fragment in the cluster you need to specify one fragment orbital ('1b1', '3a1', '1b2' or '2a1') and its phase"
    orb_cluster = []    # list of MO coefficients
    water_cluster = []  # list of atoms
    for i,water in enumerate(fragments):
        # the Euler angles (a,b,g) specify the orientation of the i-th water molecule
        water_std_i, (a,b,g), cm = MolCo.molecular_frame_transformation(water)
        print "WATER STANDARD"
        for (Zi,posi) in water_std:
            print "  %s   %8.6f  %8.6f  %8.6f" % (Zi, posi[0], posi[1], posi[2])
        print "WATER STANDARD %d" % i
        for (Zi,posi) in water_std_i:
            print "  %s   %8.6f  %8.6f  %8.6f" % (Zi, posi[0], posi[1], posi[2])
        # The desired orbital is placed on the i-th water molecule and is
        # rotated to match the orientation of the molecule.
        orb_monomer = monomer_orbitals[orbital_names[i]]
        # rotate orbital
        orb_monomer_rot = OrbitalRotations.rotate_orbitals(water_std, valorbs, orb_monomer, (a,b,g))
        # add orbital with desired phase to cluster MOs
        orb_cluster += list(phases[i] * orb_monomer_rot)
        # rotate geometry
        water_rot = MolCo.transform_molecule(water_std, (a,b,g), cm)
        XYZ.write_xyz("/tmp/water_std.xyz", [water_std, water_rot])
        water_cluster += water_rot
    # Assuming that the overlap between orbitals on different water molecules is negligible,
    # we can normalize the cluster orbital by dividing through sqrt(number of water molecules)
    n = np.sum(abs(np.array(phases))) # a phase of 0 indicates no orbital
    orb_cluster /= np.sqrt(n)
    
    return water_cluster, orb_cluster