def SrTiO3(): c = crystal.Crystal(3.9034, 3.9304, 3.9304) c.setSpaceGroup('Pm3-m') c.addAtom('Ti1', 'Ti', '4+', 0.5, 0.5, 0.5) c.addAtom('Sr1', 'Sr', '', 0., 0., 0.) c.addAtom('O1', 'O', '2-', 0., 0.5, 0.5) return c
def readPOSCAR(fileName=str): with open(fileName, "r") as f: lines = f.readlines() title = lines[0] scalingFactor = float(lines[1]) latticeVecs = [[float(lines[2].split()[0]), float(lines[2].split()[1]), float(lines[2].split()[2])], \ [float(lines[3].split()[0]), float(lines[3].split()[1]), float(lines[3].split()[2])], \ [float(lines[4].split()[0]), float(lines[4].split()[1]), float(lines[4].split()[2])],] # If the next line is not an int, assume they are atomic symbols symbols = [] i = 5 if not lines[5].split()[0].isdigit(): symbols = lines[5].split() i += 1 numOfEachType = lines[i].split() # if symbols never got defined, we will just define them as 'a', 'b', 'c', etc... if len(symbols) == 0: # Loop through alphabet letters for c in ascii_lowercase: symbols.append(c) if len(symbols) == len(numOfEachType): break i += 1 # Convert them to integers numOfEachType = [int(j) for j in numOfEachType] cartesian = False if lines[i][0] == 'C' or lines[i][0] == 'c' or \ lines[i][0] == 'K' or lines[i][0] == 'k': cartesian = True if isinstance(lines[i].split()[0], str): i += 1 atoms = [] symbolsInd = 0 # Now iterate over the atom coordinates for numAtoms in numOfEachType: for j in range(numAtoms): vec = crystal.Vector3d(float(lines[i].split()[0]), float(lines[i].split()[1]), float(lines[i].split()[2])) atoms.append(crystal.Atom(symbols[symbolsInd], vec)) i += 1 symbolsInd += 1 # Create the crystal object crys = crystal.Crystal(title, scalingFactor, latticeVecs, cartesian, atoms) return crys
def Nickelate(x = 0): c = crystal.Crystal(3.822647, 3.822647, 12.72239) c.setSpaceGroup('I4/mmm') Sr = x / 2. La = (2 - x) / 2. c.addAtom('Ni', 'Ni', '2+', 0, 0, 0) c.addAtom('LaSr', 'La', '', 0, 0, 0.36180, occ = La) c.addAtom('LaSr', 'Sr', '', 0, 0, 0.36180, occ = Sr) c.addAtom('O1', 'O', '2-', 0, 0, 0.17372) c.addAtom('O2', 'O', '2-', 0.5, 0, 0) return c
def BilayerManganite(x = 0, la = 0, sr = 0, thermal = False): """Return crystal object for a bilayer manganite""" if (la is 0) and (sr is 0): La = 2 - (2 * x) Sr = 1 + (2 * x) else: La = la Sr = sr print la, sr if thermal: U1 = 0.0021 U2 = 0.0051 U3 = 0.0098 U4 = 0.0077 else: U1 = 0. U2 = 0. U3 = 0. U4 = 0. c = crystal.Crystal(3.852, 3.852, 19.76) c.setSpaceGroup('I4/mmm') c.addAtom('Mn1', 'Mn', '3+', 0, 0, 0.09701, U = U1) c.addAtom('LaSr1', 'Sr', '', 0, 0, 0.5, occ = sr, U = U2) c.addAtom('LaSr1', 'La', '', 0, 0, 0.5, occ = la, U = U2) c.addAtom('LaSr2', 'La', '', 0, 0, 0.318198, occ = la, U = U2) c.addAtom('LaSr2', 'Sr', '', 0, 0, 0.318198, occ = sr, U = U2) c.addAtom('O1', 'O', '', 0, 0, 0, U = U3) c.addAtom('O2', 'O', '', 0, 0, 0.1951613, U = U3) c.addAtom('O3', 'O', '', 0.5, 0, 0.094909, U = U4) return c
#!/usr/bin/env python # -*- coding: utf-8 -*- import crystal import visualise_geom geomfile = "geom.csv" mycry = crystal.Crystal(a=3.0, lattice="cubic") mycry.populateUnitCell("fcc", geom_filename=geomfile, nx=2, ny=2, nz=2, PBCs=True) outputfile = "geometry" visualise_geom.save_geom_as_pdf(geomfile, outputfile) visualise_geom.make_xyz_file(geomfile,outputfile)
def adsorb(mol, slab, atmol, atslab, z, img = None, shift = [0., 0., 0.], \ out = "POSCAR_ads.vasp", versbose = False): """ Add molecule `mol` on the surface `slab` at a distance from the slab `z`. The list `atmol` defines the atoms of the molecule which will be adsorbed. The list `atslab` define the adsorption site on the slab. The function assumes that the slab surface is perpendicular to the z axes. :param mol: The molecule to adsorb :type mol: Molecule object see :py:class:`Molecule` :param slab: The slab where adsorb the molecule :type slab: Crystal object see the class ̀ Crystal <http://gvallver.perso.univ-pau.fr/vasptools/crystal.html`_ :param atmol: list of atom's number of the molecule which will be adsorbed :type atmol: list :param atslab: List of atom's number of the slab which define the adsorption site :type atslab: list :param z: distance between the molecule and the slab :type z: float :param img: translations which define periodic images of atoms belonging to the slab :type img: list of list :param shift: shift vector of the molecule :type shift: list :param out: name of the POSCAR file on output :type out: string :param verbose: Control the verbosity of the method :type verbose: bool :return: A crystal object with the molecule adsorbed on the slab :rtype: Crystal object All parameters are mandatory except the POSCAR name of the output file, the periodic images definition (img), the shift vector and the verbosity control. The adsorption site type on the slab is defined by the `atslab` list. This list contains the atom number of atoms belonging to the slab on which we will adsorb the molecule. * 1 atom : top site * 2 atom : bridge site (2fold site) * 3 atom : hollow bridge site (3fold site) * 4 atom : 4 fold site * ... The img parameter define for each atom present in the atslab list, the periodic image which has to be used in order to build the adsorption site. This parameter is necessary if the adsorption site is defined between an atom belonging to the cell and a periodic image of another atoms of the cell. The z axes will be kept perpendicular to the slab. Thus take care to prepare the molecule in a way that the adsorption will be done along the z axes. The distance z, will be the distance between the atoms of the molecule defined by the parameter `atmol` and the barycenter of the slab's atoms defined by the `atslab` parameter. The barycenter is not computed using atoms mass. Herafter are several examples : >>> import adsorption >>> import crystal >>> >>> # load a molecule >>> # --------------- >>> so2 = adsorption.Molecule.fromXYZ("../SO2.xyz") >>> so2.setLocalAxes(origin = 1, iatx = 2, iaty = 3) >>> >>> # load a slab >>> # ----------- >>> surf104 = crystal.Crystal.fromPOSCAR("POSCAR_5c_4x2.vasp") >>> >>> # adsorption site 1fold >>> # --------------------- >>> so2.rotate(axes = "x", angle = 90.) >>> so2.rotate(axes = "y", angle = -30.) >>> adsorption.adsorb(so2, surf104, atmol = 1, atslab = 90, z = 1.5, \ ... out = "POSCAR_1f_O-Co.vasp") >>> >>> # adsorption site 2fold >>> # --------------------- >>> so2.rotate(axes = "x", angle = 90.) >>> so2.rotate(axes = "y", angle = -30.) >>> adsorption.adsorb(so2, surf104, atmol = 1, atslab = [21, 23], \ ... z = 1.5, out = "POSCAR_2f_d3.vasp") >>> >>> # adsorption site 2fold with periodic images >>> # ------------------------------------------ >>> so2.rotate(axes = "x", angle = 90.) >>> so2.rotate(axes = "y", angle = -30.) >>> adsorption.adsorb(so2, surf104, atmol = 1, atslab = [21, 23], \ ... img = [[0., 1., 0.], [0., 0., 0.]], z = 1.5, out = "POSCAR_2f_d1.vasp") >>> """ # check # ----- if not isinstance(mol, Molecule): print("mol must be a Molecule object") exit(1) if not isinstance(slab, crystal.Crystal): print("slab must be a Crystal object") exit(1) if not isinstance(atmol, list): print("atmol must be a list of atom number") print("atmol : {0}".format(atmol)) exit(1) if img is not None: if len(img) != len(atslab): print("You must give imaging information for all atslab atoms") exit(1) if not isinstance(atslab, list): print("atslab must be a list of atom number") print("atslab : {0}".format(atslab)) exit(1) if not isinstance(shift, list) and not isinstance(shift, np.ndarray): print("shift must be a list or a ndarray") exit(1) elif len(shift) != 3: print("shift length must be 3") print("len(shift) = " + str(len(shift))) exit(1) # 1-fold (top) site site_1fold = (len(atslab) == 1) # convert lattice vectors to numpy array lattice = [np.array(slab.veca), np.array(slab.vecb), np.array(slab.vecc)] # axes (Oz) z_axes = np.array([0., 0., 1.]) # compute xyz coordinate if needed if slab.XYZCoord == []: slab.computeXYZCoord() # default value for periodic images if img is None: img = [[0., 0., 0.] for i in range(len(atslab))] # convert shift to numpy array if not isinstance(shift, np.ndarray): shift = np.array(shift) # shift atom number because they start at 0 # ----------------------------------------- atslab = [iat - 1 for iat in atslab] atmol = [iat - 1 for iat in atmol] # move slab's atoms of the adsorption site according to img vectors # xyz_site are the coordinate of slab's atom which define the asorption site # -------------------------------------------------------------------------- xyz_site = list() for i, iat in enumerate(atslab): imgtrans = np.zeros(3) for k in range(3): imgtrans += img[i][k] * lattice[k] xyz_site.append(np.array(slab.XYZCoord[iat]) + imgtrans) xyz_site = np.array(xyz_site) # coordinate of the barycenter of the adsorption site : Gslab # ----------------------------------------------------------- Gslab = np.zeros(3) for i in range(len(atslab)): Gslab += xyz_site[i] Gslab /= float(len(atslab)) # coordinate of the barycenter of molecule's atoms : Gmol # ------------------------------------------------------- Gmol = np.zeros(3) for iat in atmol: Gmol += mol.atoms[iat].xyz Gmol /= float(len(atmol)) # translate the molecule # ---------------------- if site_1fold: # top site ztrans = z_axes elif len(atslab) == 2: # bridge or 2-fold site u = xyz_site[1] - xyz_site[0] u /= np.sqrt((u**2).sum()) ztrans = z_axes - np.dot(u, z_axes) * u elif len(atslab) == 3: # 3-fold site : ztrans is the cross product u = xyz_site[1] - xyz_site[0] u /= np.sqrt((u**2).sum()) v = xyz_site[2] - xyz_site[0] v = v - np.dot(u, v) * v v /= np.sqrt((v**2).sum()) ztrans = np.cross(u, v) # ztrans and z axes in the same direction if np.dot(ztrans, np.array([0., 0., 1.])) < 0: ztrans *= -1. else: # TODO: average plane print("WARNING : z shift along z axes from barycenter of atoms") ztrans = np.array([0., 0., 1.]) trans = Gslab - Gmol + z * ztrans + shift mol.translate(trans) # create the new slab with the adsorbed molecule # ---------------------------------------------- ads = crystal.Crystal(veca=slab.veca, vecb=slab.vecb, vecc=slab.vecc) ads.name = "Adsorption of {0} on {1}".format(mol.name, slab.name) ads.XYZCoord = slab.XYZCoord ads.atomNames = slab.atomNames for atom in mol.atoms: ads.XYZCoord.append(atom.xyz.tolist()) ads.atomNames.append(atom.name) ads.Natoms = len(ads.XYZCoord) ads.computeRedCoord() ads.toPOSCAR(filename=out) #, sort = False) return ads
if (line.find("DESCRP") >= 0): header = "XYZ %s\n" % (token[1]) count = 0 elif (line.find("CRYSTX") >= 0): a = token[1] b = token[2] c = token[3] alpha = token[4] beta = token[5] gamma = token[6] cry = crystal.Crystal(a=a, b=b, c=c, alpha=alpha, beta=beta, gamma=gamma) lattice = "Lattice=\"%f %f %f %f %f %f %f %f %f\"" % ( cry.veca[0], cry.veca[1], cry.veca[2], cry.vecb[0], cry.vecb[1], cry.vecb[2], cry.vecc[0], cry.vecc[1], cry.vecc[2]) elif (line.find("HETATM") >= 0): xyz = xyz + "%s %s %s %s\n" % (token[2], token[3], token[4], token[5]) count += 1 elif len(token) == 0: fout.write(header) fout.write("%d\n" % count) fout.write(lattice + " Properties=species:S:1:pos:R:3\n") fout.write(xyz + "\n")
exit(1) lignes = open(sys.argv[1], "r").readlines() sectionCoord = False tmp = list() for i, ligne in enumerate(lignes): if "DEFINITION OF THE NEW LATTICE VECTORS" in ligne: while "LATTICE PARAMETERS (ANGSTROM" not in ligne: i += 1 ligne = lignes[i] valeurs = [float(val) for val in lignes[i+2].split() ] slab = crystal.Crystal(a = valeurs[0], \ b = valeurs[1], \ c = valeurs[2], \ alpha = valeurs[3], \ beta = valeurs[4], \ gamma = valeurs[5], \ name = "slab CRYSTAL") print(slab) if "COORDINATES OF THE ATOMS BELONGING TO THE SLAB" in ligne: sectionCoord = True continue if sectionCoord: # on saute la premiere ligne if "LAB" in ligne: continue # si ligne blanche on sort
0.250000000 0.833333015 0.750000000 0.750000000 0.833333015 0.250000000 """ xyz = [[0.000000, 0.000000, 0.000000], [1.524324, 0.719145, 0.723054], [4.399324, 1.172628, 2.169162], [2.746620, 3.142242, 2.169162], [3.871620, 2.688760, 0.723054]] red = [[0., 0., 0.], [0.25, 1. / 6., 0.25], [0.75, 1. / 6., 0.75], [0.25, 5. / 6., 0.75], [0.75, 5. / 6., 0.25]] th = 1.e-5 # create a reference crystal # -------------------------- refCrystal = crystal.Crystal(a=4., b=3., c=3.5, alpha=70., beta=60., gamma=80.) print(refCrystal) refCrystal.printLatticeVectors() # test XYZ coordinates # -------------------- refCrystal.redCoord = red refCrystal.computeXYZCoord() print("Test red -> XYZ Coordinates") res = True for xyz1, xyz2 in zip(refCrystal.XYZCoord, xyz): for x1, x2 in zip(xyz1, xyz2): if fabs(x1 - x2) > th: res = False print(res)