Beispiel #1
0
def get_structure_from_url(url):
    from pymatflow.structure.crystal import crystal
    from pymatflow.base.atom import Atom

    result = _get_from_url(url)
    out = []
    for item in result["data"]:
        a = crystal()
        a.cell = item["unit_cell"]
        latcell = np.array(a.cell)
        convmat_frac_to_cartesian = latcell.T
        a.atoms = []
        for atm in item["sites"]:
            name = atm.split()[0]
            cartesian = list(
                convmat_frac_to_cartesian.dot(
                    np.array([
                        float(atm.split()[2]),
                        float(atm.split()[3]),
                        float(atm.split()[4])
                    ])))
            a.atoms.append(
                Atom(name=name, x=cartesian[0], y=cartesian[1],
                     z=cartesian[2]))
        out.append(a)
    return out
Beispiel #2
0
def main():
    parser = argparse.ArgumentParser()

    parser.add_argument("-i",
                        "--input",
                        type=str,
                        required=True,
                        help="input structure file")

    args = parser.parse_args()

    # if no argument passed to matflow
    if len(sys.argv) == 1:
        # display help message when no args provided
        parser.print_help()
        sys.exit(1)

    a = read_structure(filepath=args.input)
    for i in range(1, 10):
        supercell = a.build_supercell([i, i, i])
        new_structure = crystal()
        new_structure.get_cell_atoms(cell=supercell["cell"],
                                     atoms=supercell["atoms"])
        # calculate the madelung constant
        # get center atom
        all_x = [atoms.x for atom in new_structure.atoms]
        all_y = [atoms.y for atom in new_structure.atoms]
        all_z = [atoms.z for atom in new_structure.atoms]
Beispiel #3
0
def interpolate(initial, final, nimage, moving_atom):
    """
    :param initial -> instance of pymatflow.structure.crystal.crystal()
    :param final -> instance of pymatflow.structure.crystal.crystal()
    :param nimage -> number of intermediate images(not including initial and final image)
    :param moving_atom -> the index of moving atoms (index starts from 0)
    :return images -> a list of instance of pymatflow.structure.crystal.crystal() 
            as inter images
    Feature:
        only interpolate(linearly) the specified moving atoms. other atoms may have
        different positions between initial and final image, however we use the coordinate
        of the initial image as the cooresponding coordinate for the inter image.
    """
    # use fractional coordinates to interpolate the images
    initial.natom = len(initial.atoms)
    final.natom = len(final.atoms)
    initial_frac = initial.get_fractional()
    final_frac = final.get_fractional()

    #images = []
    images_frac = []
    for i in range(nimage):
        #images.append(copy.deepcopy(initial))
        images_frac.append(copy.deepcopy(initial_frac))

    for i in moving_atom:
        dx = final_frac[i][1] - initial_frac[i][1]
        dy = final_frac[i][2] - initial_frac[i][2]
        dz = final_frac[i][3] - initial_frac[i][3]

        for j in range(nimage):
            x = initial_frac[i][1] + j * dx / (nimage + 1)
            y = initial_frac[i][2] + j * dy / (nimage + 1)
            z = initial_frac[i][3] + j * dz / (nimage + 1)
            #print("fractional x, y, z: %f %f %f\n" % (x, y, z))
            images_frac[j][i][1] = x
            images_frac[j][i][2] = y
            images_frac[j][i][3] = z
    # transform from images_frac to images
    # convert frac to cartesian again
    images = []
    latcell = np.array(initial.cell)
    convmat = latcell.T
    from pymatflow.base.atom import Atom
    from pymatflow.structure.crystal import crystal
    for i in range(nimage):
        img = crystal()
        img.atoms = []
        img.cell = initial.cell
        for atom in images_frac[i]:
            cartesian = list(convmat.dot(np.array([atom[1], atom[2],
                                                   atom[3]])))
            img.atoms.append(
                Atom(name=atom[0],
                     x=cartesian[0],
                     y=cartesian[1],
                     z=cartesian[2]))
        images.append(img)
        #
    return images
Beispiel #4
0
def get_final_structure_from_aurl(aurl):
    """
    Note: get final structure(relaxed using vasp) from aurl, aurl is in format like this:
        aflowlib.duke.edu:AFLOWDATA/LIB3_RAW/Bi_dRh_pvTi_sv/T0003.ABC:LDAU2
        aflowlib.duke.edu:AFLOWDATA/ICSD_WEB/CUB/Cl1Na1_ICSD_622368
    """
    out = crystal()

    geometry = urlopen("http://" + aurl.replace(":AFLOWDATA", "/AFLOWDATA") +
                       "/?geometry").read().decode("utf-8")
    a, b, c, alpha, beta, gamma = [
        float(item) for item in geometry.replace("\n", "").split(",")
    ]
    alpha = alpha / 180 * np.pi
    beta = beta / 180 * np.pi
    gamma = gamma / 180 * np.pi

    out.cell = []
    out.cell.append([a, 0, 0])
    out.cell.append([np.cos(gamma) * b, np.sin(gamma) * b, 0])
    new_c1 = np.cos(beta)
    new_c2 = (np.cos(alpha - np.cos(beta) * np.cos(gamma))) / np.sin(gamma)
    new_c3_square = 1.0 - new_c1 * new_c1 - new_c2 * new_c2
    new_c3 = np.sqrt(new_c3_square)
    out.cell.append([new_c1 * c, new_c2 * c, new_c3 * c])

    elements_list = []
    composition = urlopen("http://" +
                          aurl.replace(":AFLOWDATA", "/AFLOWDATA") +
                          "/?composition").read().decode("utf-8")
    species = urlopen("http://" + aurl.replace(":AFLOWDATA", "/AFLOWDATA") +
                      "/?species").read().decode("utf-8")
    for i, number in enumerate(composition.replace("\n", "").split(",")):
        for j in range(int(number)):
            elements_list.append(species.replace("\n", "").split(",")[i])

    #
    convmat_frac_to_cartesian = np.array(out.cell).T
    out.atoms = []
    positions_fractional = urlopen(
        "http://" + aurl.replace(":AFLOWDATA", "/AFLOWDATA") +
        "/?positions_fractional").read().decode("utf-8")
    for i, item in enumerate(
            positions_fractional.replace("\n", "").split(";")):
        cartesian = convmat_frac_to_cartesian.dot(
            [float(k) for k in item.split(",")])
        out.atoms.append(
            Atom(name=elements_list[i],
                 x=cartesian[0],
                 y=cartesian[1],
                 z=cartesian[2]))
    #
    return out
Beispiel #5
0
def set_frac_min_to_zero(structure):
    """
    :return an object of crystal()
    Note:
        set the fractional coordinate minimum to zero, this is a way of standardize the cif file
    """
    from pymatflow.structure.crystal import crystal
    from pymatflow.base.atom import Atom

    # now calc the fractional coordinates
    atoms_frac = []
    latcell = np.array(structure.cell)
    convmat = np.linalg.inv(latcell.T)
    for i in range(len(structure.atoms)):
        atom = []
        atom.append(structure.atoms[i].name)
        atom = atom + list(
            convmat.dot(
                np.array([
                    structure.atoms[i].x, structure.atoms[i].y,
                    structure.atoms[i].z
                ])))
        atoms_frac.append(atom)

    # set the minimum of fractional coord to to 0
    min_frac_x = min(atoms_frac[:][1])
    min_frac_y = min(atoms_frac[:][2])
    min_frac_z = min(atoms_frac[:][3])
    for i in range(len(atoms_frac)):
        atoms_frac[i][1] -= min_frac_x
        atoms_frac[i][2] -= min_frac_y
        atoms_frac[i][3] -= min_frac_z

    # now convert coord of atom in atoms_frac_within_new_cell to cartesian
    out = crystal()
    out.atoms = []
    out.cell = structure.cell
    latcell = np.array(out.cell)
    convmat_frac_to_cartesian = latcell.T
    for atom in atoms_frac:
        cartesian = list(
            convmat_frac_to_cartesian.dot(np.array([atom[1], atom[2],
                                                    atom[3]])))
        out.atoms.append(
            Atom(name=atom[0], x=cartesian[0], y=cartesian[1], z=cartesian[2]))
    #

    return out
Beispiel #6
0
def set_frac_within_zero_and_one(structure):
    """
    :return an object of crystal()
    Note:
        set the fractional coordinate within the range of 0 and 1, this is a way of standardize the cif file
    """
    from pymatflow.structure.crystal import crystal
    from pymatflow.base.atom import Atom

    # now calc the fractional coordinates
    atoms_frac = []
    latcell = np.array(structure.cell)
    convmat = np.linalg.inv(latcell.T)
    for i in range(len(structure.atoms)):
        atom = []
        atom.append(structure.atoms[i].name)
        atom = atom + list(
            convmat.dot(
                np.array([
                    structure.atoms[i].x, structure.atoms[i].y,
                    structure.atoms[i].z
                ])))
        atoms_frac.append(atom)

    # set the fractional coordinates within 0 and 1
    for i in range(len(atoms_frac)):
        for j in range(1, 4):
            while atoms_frac[i][j] >= 1:
                atoms_frac[i][j] -= 1
            while atoms_frac[i][j] < 0:
                atoms_frac[i][j] += 1

    # now convert coord of atom in atoms_frac_within_new_cell to cartesian
    out = crystal()
    out.atoms = []
    out.cell = structure.cell
    latcell = np.array(out.cell)
    convmat_frac_to_cartesian = latcell.T
    for atom in atoms_frac:
        cartesian = list(
            convmat_frac_to_cartesian.dot(np.array([atom[1], atom[2],
                                                    atom[3]])))
        out.atoms.append(
            Atom(name=atom[0], x=cartesian[0], y=cartesian[1], z=cartesian[2]))
    #
    return out
Beispiel #7
0
def read_structure(filepath):
    """
    read in input structure

    :param filepath: file path for the input structure file
        it will judge the file type by the suffix of the file

    :return a: an instance of pymatflow.structure.crystal
    """
    if filepath.split(".")[-1] == "xyz":
        from pymatflow.structure.crystal import crystal
        a = crystal()
        a.from_xyz_file(filepath)
    elif filepath.split(".")[-1] == "cif":
        from pymatflow.structure.crystal import crystal
        import pymatflow.third.aseio as aseio
        a = crystal()
        a.cell, a.atoms = aseio.read_cif(filepath)
    elif filepath.split(".")[-1] == "xsd":
        from pymatflow.structure.crystal import crystal
        import pymatflow.third.aseio as aseio
        a = crystal()
        a.cell, a.atoms = aseio.read_xsd(filepath)
    elif filepath.split(".")[-1] == "xsf":
        from pymatflow.structure.crystal import crystal
        import pymatflow.third.aseio as aseio
        a = crystal()
        a.cell, a.atoms = aseio.read_xsf(filepath)
    elif filepath.split(".")[-1] == "cfg":
        from pymatflow.structure.crystal import crystal
        import pymatflow.third.aseio as aseio
        a = crystal()
        a.cell, a.atoms = aseio.read_cfg(filepath)
    elif os.path.basename(filepath) == "POSCAR" or os.path.basename(
            filepath) == "CONTCAR":
        from pymatflow.structure.crystal import crystal
        import pymatflow.third.aseio as aseio
        a = crystal()
        a.cell, a.atoms = aseio.read_poscar(filepath)
    elif filepath.split(".")[-1] == "lammps" or filepath.split(
            ".")[-1] == "lmp":
        from pymatflow.structure.crystal import crystal
        import pymatflow.third.aseio as aseio
        a = crystal()
        a.cell, a.atoms = aseio.read_lammps_data(filepath)
    else:
        pass
    return a
Beispiel #8
0
def main():
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(
        dest="driver",
        title="subcommands",
        description="choose one and only one subcommand")

    # --------------------------------------------------------------------------
    # supercell builder
    # --------------------------------------------------------------------------
    subparser = subparsers.add_parser("supercell",
                                      help="using supercell subcommand")

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           required=True,
                           help="input structure file")

    subparser.add_argument("-o",
                           "--output",
                           type=str,
                           required=True,
                           help="output structure file")

    subparser.add_argument("-n",
                           "--supern",
                           nargs="+",
                           type=int,
                           help="bulid supern:[int, int, int] supercell")

    # --------------------------------------------------------------------------
    # fix atoms
    # --------------------------------------------------------------------------
    subparser = subparsers.add_parser("fix", help="using fix subcommand")

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           required=True,
                           help="input structure file")

    subparser.add_argument("-o",
                           "--output",
                           type=str,
                           required=True,
                           help="output structure file")

    subparser.add_argument(
        "--fix",
        help=
        "list of fixed atoms, index start from 1, have privilege over --around-z",
        nargs='+',
        type=int,
        default=None)

    subparser.add_argument(
        "--around-z",
        type=float,
        nargs=3,
        default=None,
        help=
        "select atoms around specified z in Angstrom with tolerance, like this --around-z 10 -0.5 0.5"
    )

    subparser.add_argument(
        "--color",
        type=str,
        default="white",
        choices=["red", "green", "blue", "white"],
        help=
        "select color to color the fix atoms in xsd file, can be: red green blue and white"
    )

    # --------------------------------------------------------------------------
    # convert file type
    # --------------------------------------------------------------------------
    subparser = subparsers.add_parser("convert",
                                      help="using convert subcommand")

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           required=True,
                           help="input structure file")

    subparser.add_argument("-o",
                           "--output",
                           type=str,
                           required=True,
                           help="output structure file")

    # --------------------------------------------------------------------------
    # kpath
    # --------------------------------------------------------------------------
    subparser = subparsers.add_parser("kpath", help="using kpath subcommand")

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           required=True,
                           help="input structure file")

    subparser.add_argument("--engine",
                           type=str,
                           default="seekpath",
                           choices=["seekpath"],
                           help="choose tool to generate kpath")

    subparser.add_argument("--kpath-file",
                           type=str,
                           default="kpath-from-seekpath.txt",
                           help="the output kpoints file")

    # ---------------------------------------------------------------------------------
    # move atoms along one direction
    # ---------------------------------------------------------------------------------
    subparser = subparsers.add_parser("move",
                                      help="move atoms along one direction")

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           required=True,
                           help="input structure file")

    subparser.add_argument("-o",
                           "--output",
                           type=str,
                           required=True,
                           help="output structure file")

    subparser.add_argument("--atoms",
                           type=int,
                           nargs="+",
                           help="atoms to move, index start from 1")

    subparser.add_argument(
        "--direction",
        type=float,
        nargs=3,
        help=
        "direction to move the atoms, in format of crystal orientation index")

    subparser.add_argument(
        "--disp",
        type=float,
        help="displacement along the moving direction, in unit of Anstrom")

    # ---------------------------------------------------------------------------------
    # remove atoms
    # ---------------------------------------------------------------------------------
    subparser = subparsers.add_parser("remove", help="remove specified atoms")

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           required=True,
                           help="input structure file")

    subparser.add_argument("-o",
                           "--output",
                           type=str,
                           required=True,
                           help="output structure file")

    subparser.add_argument("--atoms",
                           type=int,
                           nargs="+",
                           help="atoms to remove, index start from 1")

    subparser.add_argument("--elements",
                           type=str,
                           nargs="+",
                           help="elements to remove")

    # ---------------------------------------------------------------------------------
    # vacuum layer
    # ---------------------------------------------------------------------------------
    subparser = subparsers.add_parser("vacuum", help="add vacuum layer")

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           required=True,
                           help="input structure file")

    subparser.add_argument("-o",
                           "--output",
                           type=str,
                           required=True,
                           help="output structure file")

    subparser.add_argument(
        "--plane",
        type=int,
        default=1,
        help="on which plane to add vacuum layer. 1: ab, 2: ac, 3: bc")

    subparser.add_argument(
        "--thick",
        type=float,
        default=10,
        help="thickness of the vacuum layer, in unit of Angstrom, default is 10"
    )

    # ---------------------------------------------------------------------------------
    # inverse atoms against geometric center
    # ---------------------------------------------------------------------------------
    subparser = subparsers.add_parser("inverse",
                                      help="inverse against geo center")

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           required=True,
                           help="input structure file")

    subparser.add_argument("-o",
                           "--output",
                           type=str,
                           required=True,
                           help="output structure file")

    subparser.add_argument("-c",
                           "--center",
                           type=str,
                           default="cell",
                           choices=["geo", "cell"],
                           help="inversion center, can geo or cell")

    # ---------------------------------------------------------------------------------
    # redefine lattice
    # ---------------------------------------------------------------------------------
    subparser = subparsers.add_parser("redefine", help="redefine lattice")

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           required=True,
                           help="input structure file")

    subparser.add_argument("-o",
                           "--output",
                           type=str,
                           required=True,
                           help="output structure file")

    subparser.add_argument("-a",
                           type=int,
                           nargs=3,
                           default=[1, 0, 0],
                           help="a from old a b c")

    subparser.add_argument("-b",
                           type=int,
                           nargs=3,
                           default=[0, 1, 0],
                           help="b from old a b c")

    subparser.add_argument("-c",
                           type=int,
                           nargs=3,
                           default=[0, 0, 1],
                           help="c from old a b c")

    subparser.add_argument(
        "--precision",
        type=float,
        default=1.0e-8,
        help=
        "a value that is less than 1 and infinitely close to 1 used to judge whether one atom is in another periodic of the redefined cell"
    )

    # ---------------------------------------------------------------------------------
    # cleave surface
    # ---------------------------------------------------------------------------------
    subparser = subparsers.add_parser("cleave", help="cleave surface")

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           required=True,
                           help="input structure file")

    subparser.add_argument("-o",
                           "--output",
                           type=str,
                           required=True,
                           help="output structure file")

    subparser.add_argument("--direction",
                           type=int,
                           nargs=3,
                           default=[0, 0, 1],
                           help="direction of the surface plane to cleave")

    subparser.add_argument(
        "--thick",
        type=float,
        help="thickness of the vacuum layer, in unit of Angstrom, default is 10"
    )

    subparser.add_argument(
        "--precision",
        type=float,
        default=1.0e-8,
        help=
        "a value that is large than 0 and infinitely close to 0 used to judge whether one atom is in another periodic of the redefined cell used in cleave surface"
    )

    # ---------------------------------------------------------------------------------
    # merge layers | ab plane
    # ---------------------------------------------------------------------------------
    subparser = subparsers.add_parser("merge", help="merge layers | ab plane")

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           nargs=2,
                           required=True,
                           help="input structure files")

    subparser.add_argument("-o",
                           "--output",
                           type=str,
                           required=True,
                           help="output structure file")

    #subparser.add_argument("--direction", type=int, nargs=3, default=[0, 0, 1],
    #        help="direction of the surface plane to cleave")

    subparser.add_argument(
        "--usecell",
        type=str,
        default="average",
        choices=["1", "2", "average"],
        help="use cell of structure 1 or 2 , otherwise average by default")

    subparser.add_argument(
        "--thick",
        type=float,
        help="thickness of the vacuum layer, in unit of Angstrom, default is 10"
    )

    subparser.add_argument(
        "--distance",
        type=float,
        help="distance between the layer, in unit of Angstrom, default is 3.4")

    # ---------------------------------------------------------------------------------
    # nanotube builder
    # ---------------------------------------------------------------------------------
    subparser = subparsers.add_parser(
        "tube",
        help=
        "nanotube along b direction(a must be perpendicular to b and ab is the surface plane)"
    )

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           required=True,
                           help="input structure files")

    subparser.add_argument("-o",
                           "--output",
                           type=str,
                           required=True,
                           help="output structure file")

    subparser.add_argument(
        "--plane",
        type=int,
        default=1,
        help="on which plane to add vacuum layer. 1: ab, 2: ac, 3: bc")

    subparser.add_argument(
        "--axis",
        type=str,
        default="b",
        choices=["a", "b", "c"],
        help="build nanotube along an axis parallel to axis specified")

    # -----------------------------------------------------------------------------------
    # set frac within zero and one
    # ------------------------------------------------------------------------------------
    subparser = subparsers.add_parser(
        "std", help="set fractional coordinates within zero and one")

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           required=True,
                           help="input structure file")

    subparser.add_argument("-o",
                           "--output",
                           type=str,
                           required=True,
                           help="output structure file")

    # ------------------------------------------------------------------------------------
    # generate series of cell volume changed structures
    # ------------------------------------------------------------------------------------
    subparser = subparsers.add_parser(
        "cv", help="generate series of cell volume changed structures")

    subparser.add_argument("-i",
                           "--input",
                           type=str,
                           required=True,
                           help="input structure file")

    subparser.add_argument("-d",
                           "--directory",
                           type=str,
                           default="./",
                           help="directory to put the generated structures")

    subparser.add_argument(
        "--range",
        type=float,
        nargs=3,
        default=[0.95, 1.05, 0.01],
        help="cell volume change ratio, default is [0.95, 1.05, 0.01]")

    # ==========================================================
    # transfer parameters from the arg subparser to static_run setting
    # ==========================================================

    args = parser.parse_args()

    # if no argument passed to matflow
    if len(sys.argv) == 1:
        # display help message when no args provided
        parser.print_help()
        sys.exit(1)

    if args.driver == "supercell":
        from pymatflow.base.xyz import base_xyz
        from pymatflow.structure.crystal import crystal

        a = read_structure(filepath=args.input)
        supercell = a.build_supercell(args.supern)
        new_structure = crystal()
        new_structure.get_cell_atoms(cell=supercell["cell"],
                                     atoms=supercell["atoms"])
        write_structure(structure=new_structure, filepath=args.output)

        print("=========================================================\n")
        print("              structflow supercell builder\n")
        print("---------------------------------------------------------\n")
        print("you are trying to bulid supercell from %s\n" % args.input)
        print("the output structure file is -> %s\n" % args.output)

    elif args.driver == "fix":
        # can only write xyz and poscar file
        a = read_structure(filepath=args.input)
        if args.fix != None:
            fix = args.fix
        elif args.around_z != None:
            atoms_index_from_1 = []
            for i in range(len(a.atoms)):
                if a.atoms[i].z > (args.around_z[0] +
                                   args.around_z[1]) and a.atoms[i].z < (
                                       args.around_z[0] + args.around_z[2]):
                    atoms_index_from_1.append(i + 1)
            fix = atoms_index_from_1
        else:
            fix = []

        if args.output.split(".")[-1] == "xyz":
            fix_str = ""
            for i in fix:
                fix_str += "%d " % i
            os.system("xyz-fix-atoms.py -i %s -o %s --fix %s" %
                      (args.input, args.output, fix_str))
        elif os.path.basename(args.output) == "POSCAR":
            from pymatflow.vasp.base.poscar import vasp_poscar
            for i in fix:
                a.atoms[i - 1].fix = [True, True, True]
            poscar = vasp_poscar()
            poscar.xyz.cell = a.cell
            poscar.xyz.atoms = a.atoms
            poscar.xyz.natom = len(poscar.xyz.atoms)
            poscar.xyz.set_species_number()  # needed for poscar output
            poscar.selective_dynamics = True
            with open(args.output, 'w') as fout:
                poscar.to_poscar(fout=fout, coordtype="Direct")
        else:
            print(
                "===============================================================\n"
            )
            print("                      WARNING !!!\n")
            print(
                "---------------------------------------------------------------\n"
            )
            print("structflow fix now only supports write of xyz and POSCAR\n")
            sys.exit(1)
        # output an xsd file with fixed atoms colored specifically so that user can check the atoms fixed
        from xml.etree.ElementTree import parse
        os.system("mkdir -p /tmp/structflow/fix")
        write_structure(a, filepath="/tmp/structflow/fix/tmp.xsd")
        # read xsd file
        xsd = parse("/tmp/structflow/fix/tmp.xsd")

        # ID of Atom3D in xsd file start from 4
        imap = xsd.getroot().find("AtomisticTreeRoot").find(
            "SymmetrySystem").find("MappingSet").find("MappingFamily").find(
                "IdentityMapping")
        atoms = imap.findall("Atom3d")
        if args.color == "white":
            RGB = [255, 255, 255]
        elif args.color == "red":
            RGB = [255, 0, 0]
        elif args.color == "green":
            RGB = [0, 255, 0]
        elif args.color == "blue":
            RGB = [0, 0, 255]
        else:
            RGB = [255, 255, 255]  # default

        for i in fix:
            atoms[i - 1].set("Color",
                             "%f, %f, %f, %f" % (RGB[0], RGB[1], RGB[2], 1))

        # write xsd file
        xsd.write(args.input + ".coloring.atoms.fixed.xsd")

    elif args.driver == "convert":
        # will convert file type according to the suffix of the specified input and output file

        a = read_structure(filepath=args.input)
        write_structure(structure=a, filepath=args.output)

        print("=========================================================\n")
        print("              structflow convert\n")
        print("---------------------------------------------------------\n")
        print("with the help from ase.io\n")

    elif args.driver == "kpath":
        if args.engine == "seekpath":
            os.system("kpath-xyz-seekpath.py -i %s -o %s" %
                      (args.input, args.output))
        else:
            pass
    elif args.driver == "move":
        from pymatflow.structure.tools import move_along
        # input structure
        a = read_structure(filepath=args.input)
        # move atoms
        print("=========================================================\n")
        print("                   structflow\n")
        print("----------------------------------------------------------\n")
        print("you are trying to move atoms:\n")
        print(args.atoms)
        for i in args.atoms:
            print("%d -> %s\n" % (i, a.atoms[i - 1].name))
        print("\n")
        print("along direction:\n")
        print(args.direction)
        print("\n")
        print("by length of -> %f, in unit of Angstrom\n" % args.disp)
        move_along(a,
                   atoms_to_move=[i - 1 for i in args.atoms],
                   direc=args.direction,
                   disp=args.disp)

        # output structure
        write_structure(structure=a, filepath=args.output)

    elif args.driver == "remove":
        from pymatflow.structure.tools import remove_atoms
        a = read_structure(filepath=args.input)
        # remove atoms
        print(
            "=======================================================================\n"
        )
        print("                       structflow\n")
        print(
            "-----------------------------------------------------------------------\n"
        )
        print(
            "you are trying to remove from %s the following list of atoms:\n" %
            args.input)
        print(args.atoms)
        if args.atoms != None:
            for i in args.atoms:
                print("%d -> %s\n" % (i, a.atoms[i - 1].name))
        else:
            pass
        print("\n")
        print("also the following elements will be removed:\n")
        print(args.elements)
        print("the output structure file is -> %s\n" % args.output)

        if args.atoms != None:
            remove_atoms(a, atoms_to_remove=[i - 1 for i in args.atoms])

        # we should first remove atoms specified by args.atoms
        # and remove atoms specified by args.elements
        # as remove atom will change the index of atom
        if args.elements != None:
            element_atoms_to_remove = []
            for i in range(len(a.atoms)):
                if a.atoms[i].name in args.elements:
                    element_atoms_to_remove.append(i)
            remove_atoms(a, atoms_to_remove=element_atoms_to_remove)

        # output structure
        write_structure(structure=a, filepath=args.output)

    elif args.driver == "vacuum":
        from pymatflow.structure.tools import vacuum_layer
        a = read_structure(filepath=args.input)
        # add vacuum layer
        print(
            "=======================================================================\n"
        )
        print("                       structflow\n")
        print(
            "-----------------------------------------------------------------------\n"
        )
        if args.plane == 1:
            plane = "ab"
        elif args.plane == 2:
            plane = "ac"
        elif args.plane == 3:
            plane = "bc"
        print(
            "you are trying to add vacuum layer of %f Angstrom on %s plane\n" %
            (args.thick, plane))
        print("from %s\n" % args.input)
        print("\n")
        print("the output structure file is -> %s\n" % args.output)

        vacuum_layer(a,
                     plane=args.plane,
                     thickness=args.thick if args.thick != None else 10.0)

        # output structure
        write_structure(structure=a, filepath=args.output)
    elif args.driver == "inverse":
        from pymatflow.structure.tools import inverse_geo_center
        from pymatflow.structure.tools import inverse_cell_center
        a = read_structure(filepath=args.input)
        print(
            "=======================================================================\n"
        )
        print("                       structflow\n")
        print(
            "-----------------------------------------------------------------------\n"
        )
        if args.center == "geo":
            print(
                "you are trying to inverse the system against the geometric center\n"
            )
        elif args.center == "cell":
            print(
                "you are trying to inverse the system against the cell center\n"
            )
        print("from %s\n" % args.input)
        print("\n")
        print("the output structure file is -> %s\n" % args.output)

        if args.center == "geo":
            inverse_geo_center(a)
        elif args.center == "cell":
            inverse_cell_center(a)

        # output structure
        write_structure(structure=a, filepath=args.output)
    elif args.driver == "redefine":
        from pymatflow.structure.tools import redefine_lattice
        a = read_structure(filepath=args.input)
        print(
            "=======================================================================\n"
        )
        print("                       structflow\n")
        print(
            "-----------------------------------------------------------------------\n"
        )
        print("you are trying to redefine the lattice\n")
        print("from %s\n" % args.input)
        print("\n")
        print("the output structure file is -> %s\n" % args.output)

        redefined = redefine_lattice(structure=a,
                                     a=args.a,
                                     b=args.b,
                                     c=args.c,
                                     precision=args.precision)

        # output structure
        write_structure(structure=redefined, filepath=args.output)
    elif args.driver == "cleave":
        from pymatflow.structure.tools import cleave_surface
        a = read_structure(filepath=args.input)
        print(
            "=======================================================================\n"
        )
        print("                       structflow\n")
        print(
            "-----------------------------------------------------------------------\n"
        )
        print("you are trying to cleave the surface of (%d, %d, %d)\n" %
              (args.direction[0], args.direction[1], args.direction[2]))
        print("from %s\n" % args.input)
        print("\n")
        print("the output structure file is -> %s\n" % args.output)

        cleaved = cleave_surface(
            structure=a,
            direction=args.direction,
            thickness=args.thick if args.thick != None else 10.0,
            precision=args.precision)

        # output structure
        write_structure(structure=cleaved, filepath=args.output)
    elif args.driver == "merge":
        from pymatflow.structure.tools import merge_layers
        a_list = []
        for i in range(2):
            a_list.append(read_structure(filepath=args.input[i]))
        print(
            "=======================================================================\n"
        )
        print("                       structflow\n")
        print(
            "-----------------------------------------------------------------------\n"
        )
        print("you are trying to merge layers on ab plane\n")
        print("from %s\n" % (args.input[0]))
        print("and %s\n" % (args.input[1]))
        print("\n")
        print("the output structure file is -> %s\n" % args.output)

        if args.usecell == "1":
            usecell = 1
        elif args.usecell == "2":
            usecell = 2
        else:
            usecell = "average"
        merged = merge_layers(
            structure1=a_list[0],
            structure2=a_list[1],
            use_cell=usecell,
            distance=args.distance if args.distance != None else 3.4,
            thickness=args.thick if args.thick != None else 10.0)

        # output structure
        write_structure(structure=merged, filepath=args.output)
    elif args.driver == "tube":
        a = read_structure(filepath=args.input)
        if args.plane == 1:
            plane = "ab"
        elif args.plane == 2:
            plane = "ac"
        elif args.plane == 3:
            plane = "bc"
        print(
            "=======================================================================\n"
        )
        print("                       structflow\n")
        print(
            "-----------------------------------------------------------------------\n"
        )
        print(
            "you are trying to build nanotube of %s plane along %s vector\n" %
            (plane, args.axis))
        print("from %s\n" % (args.input))
        print("the output structure file is -> %s\n" % args.output)
        tube = None
        if plane == "ab":
            from pymatflow.structure.tools import build_nanotube_ab
            if args.axis not in "ab":
                print(
                    "building nanotube of ab plane along axis parallel to c is unphysical!!!\n"
                )
                sys.exit()
            else:
                tube = build_nanotube_ab(structure=a, axis=args.axis)
        if plane == "ac":
            from pymatflow.structure.tools import build_nanotube_ac
            if args.axis not in "ac":
                print(
                    "building nanotube of ac plane along axis parallel to b is unphysical!!!\n"
                )
                sys.exit()
            else:
                tube = build_nanotube_ac(structure=a, axis=args.axis)
        if plane == "bc":
            from pymatflow.structure.tools import build_nanotube_bc
            if args.axis not in "bc":
                print(
                    "building nanotube of bc plane along axis parallel to a is unphysical!!!\n"
                )
                sys.exit()
            else:
                tube = build_nanotube_bc(structure=a, axis=args.axis)

        # output structure
        if tube != None:
            write_structure(structure=tube, filepath=args.output)
    elif args.driver == "std":
        from pymatflow.structure.tools import set_frac_within_zero_and_one
        a = read_structure(filepath=args.input)
        print(
            "=======================================================================\n"
        )
        print("                       structflow\n")
        print(
            "-----------------------------------------------------------------------\n"
        )
        print("you are trying to set fractional coords within 0 and 1\n")
        print("from %s\n" % (args.input))
        print("\n")
        print("the output structure file is -> %s\n" % args.output)

        normalized = set_frac_within_zero_and_one(structure=a)
        # output structure
        write_structure(structure=normalized, filepath=args.output)
    elif args.driver == "cv":
        from pymatflow.structure.crystal import crystal
        from pymatflow.base.atom import Atom
        a = read_structure(filepath=args.input)
        print(
            "=======================================================================\n"
        )
        print("                       structflow\n")
        print(
            "-----------------------------------------------------------------------\n"
        )
        print(
            "you are trying to get a series of structure with different volume\n"
        )
        print("from %s\n" % (args.input))
        print("\n")
        print("the output dir for structure file is -> %s\n" % args.directory)

        # now calc the fractional coordinates
        atoms_frac = []
        latcell = np.array(a.cell)
        convmat = np.linalg.inv(latcell.T)
        for i in range(len(a.atoms)):
            atom = []
            atom.append(a.atoms[i].name)
            atom = atom + list(
                convmat.dot(
                    np.array([a.atoms[i].x, a.atoms[i].y, a.atoms[i].z])))
            atoms_frac.append(atom)
        #
        out = crystal()
        os.system("mkdir -p %s" % args.directory)
        for i, ratio_v in enumerate(
                np.arange(args.range[0], args.range[1], args.range[2])):
            ratio = np.power(ratio_v, 1 / 3)

            # now convert coord of atom in atoms_frac_within_new_cell to cartesian
            out.atoms = []
            out.cell = (np.array(a.cell) * ratio).tolist()
            latcell = np.array(out.cell)
            convmat_frac_to_cartesian = latcell.T
            for atom in atoms_frac:
                cartesian = list(
                    convmat_frac_to_cartesian.dot(
                        np.array([atom[1], atom[2], atom[3]])))
                out.atoms.append(
                    Atom(name=atom[0],
                         x=cartesian[0],
                         y=cartesian[1],
                         z=cartesian[2]))
            output_name = ".".join(
                os.path.basename(args.input).split(".")[:-1] +
                ["%d" % i, "cif"])
            write_structure(out,
                            filepath=os.path.join(args.directory, output_name))
            #
        with open(os.path.join(args.directory, "log.txt"), 'w') as fout:
            fout.write("# index\tratio_v\tvolume(Angstrom^3)\n")
            for i, ratio_v in enumerate(
                    np.arange(args.range[0], args.range[1], args.range[2])):
                ratio = np.power(ratio_v, 1 / 3)
                cell_now = (np.array(a.cell) * ratio).tolist()
                fout.write("%d\t%f\t%f\n" %
                           (i, ratio_v, np.linalg.det(cell_now)))
Beispiel #9
0
def main():
    parser = argparse.ArgumentParser()

    parser.add_argument("-i",
                        "--input",
                        type=str,
                        required=True,
                        help="input cube file")

    parser.add_argument("--output-structure",
                        type=str,
                        default="cube.cif",
                        help="output stucture contained in PARCHG")

    parser.add_argument("-o",
                        "--output",
                        type=str,
                        default="cube",
                        help="prefix of the output image file name")

    parser.add_argument("--levels",
                        type=int,
                        default=10,
                        help="levels of the color map or color bar")

    parser.add_argument(
        "-z",
        "--z",
        type=float,
        default=1,
        help=
        "a value between 0 and 1, indicat height of in z direction to print the plot"
    )

    parser.add_argument("--cmap",
                        type=str,
                        default="gray",
                        choices=[
                            "gray", "hot", "afmhot", "Spectral", "plasma",
                            "magma", "hsv", "rainbow", "brg"
                        ])
    # ==========================================================
    # transfer parameters from the arg subparser to static_run setting
    # ==========================================================

    args = parser.parse_args()

    cube_filepath = args.input

    with open(cube_filepath, "r") as fin:
        cube = fin.readlines()

    ngridx = int(cube[3].split()[0])
    ngridy = int(cube[4].split()[0])
    ngridz = int(cube[5].split()[0])

    # read structure info
    natom = abs(int(
        cube[2].split()
        [0]))  # it might be negative, if MO infor are included in cube file
    bohr_to_angstrom = 0.529177249
    structure = crystal()
    structure.cell = []
    for i in range(3):
        tmp = []
        for j in range(3):
            tmp.append(
                int(cube[i + 3].split()[0]) *
                float(cube[i + 3].split()[j + 1]) * bohr_to_angstrom)
        structure.cell.append(tmp)
    atoms_list = []
    for i in range(natom):
        atomic_number = int(cube[i + 6].split()[0])
        for e in elem:
            if elem[e].number == atomic_number:
                label = e
        atoms_list.append([
            label,
            float(cube[i + 6].split()[2]) * bohr_to_angstrom,
            float(cube[i + 6].split()[3]) * bohr_to_angstrom,
            float(cube[i + 6].split()[4]) * bohr_to_angstrom,
        ])
    structure.get_atoms(atoms_list)
    # end read structure info
    write_structure(structure=structure, filepath=args.output_structure)

    # read grid value
    tmp_str = "".join(cube[natom + 6:])
    data = np.fromstring(tmp_str, sep="\n")

    #data = data.reshape(ngridz, ngridy, ngridx)
    # grid data in cube is iterated in different compared to *CHG* of vasp
    data = data.reshape(ngridx, ngridy, ngridz)
    # charge data in cube file is in shape (ngridx, ngridy, ngridz)
    # while charge in *CHG* file is in shape (ngzf, ngyf, ngxf)
    # they are different!

    # -------------------------------------------------------
    # matrix image only for z direction
    # may not work for triclinic and monoclinic crystal system
    # -------------------------------------------------------

    zi = int((data.shape[2] - 1) * args.z)
    img = data[::, ::,
               zi].T  #.reshape(ngridy, ngridx) should be transpose here but not reshape
    img = (img - img.min()) / (img.max() - img.min()) * 255
    # need to do a transform when the cell is not Orthorhombic
    # skew the image
    a = np.array(structure.cell[0])
    b = np.array(structure.cell[1])
    cosangle = a.dot(b) / (np.linalg.norm(a) * np.linalg.norm(b))
    angle = np.arccos(cosangle) * 180 / np.pi
    ax = plt.axes()  #plt.figure()
    n1 = ngridx
    n2 = ngridy
    n1_right = n1
    n1_left = -(n2 * np.tan((angle - 90) / 180 * np.pi))
    #im = ax.imshow(img, cmap="gray", extent=[0, n1, 0, n2], interpolation="none", origin="lower", clip_on=True)
    im = ax.imshow(img,
                   cmap=args.cmap,
                   extent=[0, n1, 0, n2],
                   interpolation="none",
                   origin="lower",
                   clip_on=True)
    #im = plt.imshow(data[i, :, :], cmap="gray")
    trans_data = mtransforms.Affine2D().skew_deg(90 - angle, 0) + ax.transData
    im.set_transform(trans_data)
    # display intended extent of the image
    x1, x2, y1, y2 = im.get_extent()
    # do not view the line, but it is needed to be plot so the intended image is dispalyed completely
    ax.plot([x1, x2, x2, x1, x1], [y1, y1, y2, y2, y1],
            "y--",
            transform=trans_data,
            visible=False)
    #ax.set_xlim(n1_left, n1_right)
    #ax.set_ylim(0, n2)
    plt.colorbar(im)
    ax.autoscale()
    plt.tight_layout()
    plt.savefig(args.output + "-z-%f.matrix-image.png" % args.z)
    plt.close()

    # -----------------------------------------------------------------------------
    # 2D contour plot
    #------------------------------------------------------------------------------

    nx = np.linspace(0, 1, ngridx)
    ny = np.linspace(0, 1, ngridy)
    X, Y = np.meshgrid(
        nx, ny
    )  # now this Mesh grid cannot be used directly, we have to calc the real x y for it
    for xi in range(len(nx)):
        for yi in range(len(ny)):
            X[yi, xi] = structure.cell[0][0] * nx[xi] + structure.cell[1][
                0] * ny[yi]
            Y[yi, xi] = structure.cell[0][1] * nx[xi] + structure.cell[1][
                1] * ny[yi]

    Z = data[::, ::,
             zi].T  #.reshape(ngridy, ngridx) should be transpose here but not reshape
    Z = (Z - Z.min()) / (Z.max() - Z.min()) * 255
    # fill color, three color are divided into three layer(6)
    # cmap = plt.cm.hot means using thermostat plot(graduated red yellow)
    #cset = plt.contourf(X, Y, Z, levels=args.levels, cmap=plt.cm.hot)
    #cset = plt.contourf(X, Y, Z, levels=args.levels, cmap=plt.cm.gray)
    cset = plt.contourf(X, Y, Z, levels=args.levels, cmap=args.cmap)
    contour = plt.contour(X, Y, Z, levels=[20, 40], colors='k')
    plt.colorbar(cset)
    plt.autoscale()
    plt.tight_layout()
    #plt.show()
    plt.axis("equal")  # set axis equally spaced
    plt.xlabel('x')
    plt.ylabel('y')
    plt.savefig(args.output + ".2d-contour-z-%f.png" % args.z)
    plt.close()
Beispiel #10
0
def main():
    parser = argparse.ArgumentParser()

    parser.add_argument("-i",
                        "--input",
                        type=str,
                        required=True,
                        help="input  cube file, -i xxx.cube")

    parser.add_argument("--output-structure",
                        type=str,
                        default="chg",
                        help="output stucture contained in cube file")

    parser.add_argument("-o",
                        "--output",
                        type=str,
                        default="chg",
                        help="prefix of the output image file name")

    parser.add_argument("--levels",
                        type=int,
                        default=10,
                        help="levels of the color map or color bar")

    parser.add_argument(
        "-z",
        "--z",
        type=float,
        default=1,
        help=
        "a value between 0 and 1, indicat height of in z direction to print the plot"
    )

    parser.add_argument("--cmap",
                        type=str,
                        default="gray",
                        choices=[
                            "gray", "hot", "afmhot", "Spectral", "plasma",
                            "magma", "hsv", "rainbow", "brg"
                        ])

    parser.add_argument(
        "--abscissa",
        type=str,
        nargs="+",
        default=["a", "b", "c"],
        choices=["a", "b", "c"],
        help="choose the direction to do the dimension reduction")

    # ==========================================================
    # transfer parameters from the arg subparser to static_run setting
    # ==========================================================

    args = parser.parse_args()

    cube_filepath = args.input

    with open(cube_filepath, "r") as fin:
        cube = fin.readlines()

    bohr_to_angstrom = 0.529177249
    # read structure info
    natom = abs(int(
        cube[2].split()
        [0]))  # it might be negative, if MO infor are included in cube file
    structure = crystal()
    structure.cell = []
    for i in range(3):
        tmp = []
        for j in range(3):
            tmp.append(
                int(cube[i + 3].split()[0]) *
                float(cube[i + 3].split()[j + 1]) * bohr_to_angstrom)
        structure.cell.append(tmp)
    atoms_list = []
    for i in range(natom):
        atomic_number = int(cube[i + 6].split()[0])
        for e in elem:
            if elem[e].number == atomic_number:
                label = e
        atoms_list.append([
            label,
            float(cube[i + 6].split()[2]) * bohr_to_angstrom,
            float(cube[i + 6].split()[3]) * bohr_to_angstrom,
            float(cube[i + 6].split()[4]) * bohr_to_angstrom,
        ])
    structure.get_atoms(atoms_list)
    # end read structure info
    write_structure(structure=structure,
                    filepath=args.output_structure + ".cif")

    a = np.linalg.norm(structure.cell[0])
    b = np.linalg.norm(structure.cell[1])
    c = np.linalg.norm(structure.cell[2])

    # assume three cube file have the same ngridx ngridy and ngridz
    ngridx = int(cube[3].split()[0])
    ngridy = int(cube[4].split()[0])
    ngridz = int(cube[5].split()[0])

    # read grid value
    tmp_str = "".join(cube[natom + 6:])
    data = np.fromstring(tmp_str, sep="\n")

    # grid data in cube is iterated in different compared to *CHG* of vasp
    data = data.reshape(ngridx, ngridy, ngridz)

    # charge data in cube file is in shape (ngridx, ngridy, ngridz)
    # while charge in *CHG* file is in shape (ngzf, ngyf, ngxf)
    # they are different!

    # data dimension reduction
    # the unit of value is actually not physical now!
    #
    # cell_volume are in unit of Angstrom^3
    cell_volume = np.dot(
        np.cross(np.array(structure.cell[0]), np.array(structure.cell[1])),
        np.array(structure.cell[2]))
    cell_volume_per_unit = cell_volume / (ngridx * ngridy * ngridz)

    # value in cube file are \rho(r)_of_electrons in unit of e/Bohr^3
    # namely number of electrons each Borh^3
    # so we have to convert it to e/Angstrom^23, through divide it by borh_to_angstrom**3
    total_electrons = np.sum(data) * cell_volume_per_unit / bohr_to_angstrom**3
    #

    print("======================================================\n")
    print("           Information collected\n")
    print("------------------------------------------------------\n")
    print("cell volume: %f (A^3)\n" % cell_volume)
    print("total electrons: %f\n" % total_electrons)

    # data is in unit of e/Bohr^3
    # we will build data_red_? to be in unit of e/Anstrom, namely number of electrons per Angstrom
    # to do this we have to time the volume density with bohr_to_angstrom^-3
    data_red_a = []
    data_red_b = []
    data_red_c = []
    if "c" in args.abscissa:
        len_ci = c / ngridz
        for ci in range(data.shape[2]):
            tmp = 0
            for bi in range(data.shape[1]):
                tmp += np.sum(data[:, bi, ci])
            nelect_ci = tmp * cell_volume_per_unit / bohr_to_angstrom**3
            rho_line = nelect_ci / len_ci
            data_red_c.append(rho_line)
    if "b" in args.abscissa:
        len_bi = b / ngridy
        for bi in range(data.shape[1]):
            tmp = 0
            for ai in range(data.shape[0]):
                tmp += np.sum(data[ai, bi, :])
            nelect_bi = tmp * cell_volume_per_unit / bohr_to_angstrom**3
            rho_line = nelect_bi / len_bi
            data_red_b.append(rho_line)
    if "a" in args.abscissa:
        len_ai = a / ngridx
        for ai in range(data.shape[0]):
            tmp = 0
            for ci in range(data.shape[2]):
                tmp += np.sum(data[ai, :, ci])
            nelect_ai = tmp * cell_volume_per_unit / bohr_to_angstrom**3
            rho_line = nelect_ai / len_ai
            data_red_a.append(rho_line)

    # output the data and make the plot
    if "c" in args.abscissa:
        with open(args.output + ".1d.c.data", 'w') as fout:
            fout.write(
                "#c(angstrom) rho(e) (number of electron per Angstrom)\n")
            c_coord = np.linspace(0, c, len(data_red_c))
            for i in range(len(data_red_c)):
                fout.write("%f %f\n" % (c_coord[i], data_red_c[i]))
        plt.plot(np.linspace(0, c, len(data_red_c)), data_red_c)
        plt.ylabel(r"$\rho (e/\AA)$")
        plt.tight_layout()
        plt.savefig(args.output + ".1d.c.png")
        plt.close()
    if "b" in args.abscissa:
        with open(args.output + ".1d.b.data", 'w') as fout:
            fout.write(
                "#b(angstrom) rho(e) (number of electron per Angstrom)\n")
            b_coord = np.linspace(0, b, len(data_red_b))
            for i in range(len(data_red_b)):
                fout.write("%f %f\n" % (b_coord[i], data_red_b[i]))
        plt.plot(np.linspace(0, b, len(data_red_b)), data_red_b)
        plt.ylabel(r"$\rho (e/\AA)$")
        plt.tight_layout()
        plt.savefig(args.output + ".1d.b.png")
        plt.close()
    if "a" in args.abscissa:
        with open(args.output + ".1d.a.data", 'w') as fout:
            fout.write(
                "#a(angstrom) rho(e) (number of electron per Angstrom)\n")
            a_coord = np.linspace(0, a, len(data_red_a))
            for i in range(len(data_red_a)):
                fout.write("%f %f\n" % (a_coord[i], data_red_a[i]))
        plt.plot(np.linspace(0, a, len(data_red_a)), data_red_a)
        plt.ylabel(r"$\rho (e/\AA)$")
        plt.tight_layout()
        plt.savefig(args.output + ".1d.a.png")
        plt.close()
Beispiel #11
0
    element_n_list = []
    for i in range(len(xdatcar[5].split())):
        element = {}
        element["label"] = xdatcar[5].split()[i]
        element["n"] = int(xdatcar[6].split()[i])
        element_n_list.append(element)

    element_list = []
    for i in range(len(element_n_list)):
        for j in range(element_n_list[i]["n"]):
            element_list.append(element_n_list[i]["label"])

    images = []

    for i in range(nimage):
        image = crystal()
        image.cell = []
        if i == 0:
            for j in range(3):
                tmp = [
                    float(xdatcar[2 + j].split()[0]),
                    float(xdatcar[2 + j].split()[1]),
                    float(xdatcar[2 + j].split()[2])
                ]
                image.cell.append(tmp)
        else:
            if vc == False:
                image.cell = images[-1].cell
            else:
                for j in range(3):
                    tmp = [
Beispiel #12
0
def merge_layers(structure1,
                 structure2,
                 use_cell=None,
                 distance=3.4,
                 thickness=10):
    """
    :param structure1: an instance of crystal()
    :param structure2: an instance of crystal()    
    :param use_cell: use cell parameter of structure 1 or 2 or None(average) to set the new a b cell parameter
        attention: c vector is not handled this way
        
    :param distance: the distance between layers
    :param thickness: the vaccum layer thickness of the combined system
    
    :return an object of crystal()
    Note:
        only merge layers with ab plane as the surface plane
    """
    from pymatflow.structure.crystal import crystal
    from pymatflow.base.atom import Atom

    structure1 = set_frac_within_zero_and_one(structure1)
    structure2 = set_frac_within_zero_and_one(structure2)

    old_cell_1 = copy.deepcopy(structure1.cell)
    old_cell_2 = copy.deepcopy(structure2.cell)

    # first transfer to fractional coordinate
    structure1.natom = len(structure1.atoms)
    frac_1 = structure1.get_fractional()
    structure2.natom = len(structure2.atoms)
    frac_2 = structure2.get_fractional()

    average_cell = []
    for i in range(3):
        average_cell.append(
            list((np.array(old_cell_1[i]) + np.array(old_cell_2[i])) / 2))

    out = crystal()

    if use_cell == 1:
        latcell_frac_to_cart_1 = old_cell_1
        latcell_frac_to_cart_2 = old_cell_1[0:2]
        latcell_frac_to_cart_2.append(old_cell_2[2])
    elif use_cell == 2:
        latcell_frac_to_cart_2 = old_cell_2
        latcell_frac_to_cart_1 = old_cell_2[0:2]
        latcell_frac_to_cart_1.append(old_cell_1[2])
    else:
        #average_ab = []
        #for i in range(2):
        #    vec = []
        #    for j in range(3):
        #        vec.append((old_cell_1[i][j] + old_cell_2[i][j]) / 2 )
        #    average_ab.append(vec)

        latcell_frac_to_cart_1 = average_cell
        latcell_frac_to_cart_1[2] = old_cell_1[2]
        latcell_frac_to_cart_2 = average_cell
        latcell_frac_to_cart_2[2] = old_cell_2[2]

    # convert frac to cartesian again
    convmat_1 = np.array(latcell_frac_to_cart_1).T
    convmat_2 = np.array(latcell_frac_to_cart_2).T

    cart_1 = []
    for atom in frac_1:
        cartesian = list(convmat_1.dot(np.array([atom[1], atom[2], atom[3]])))
        cart_1.append([atom[0], cartesian[0], cartesian[1], cartesian[2]])

    cart_2 = []
    for atom in frac_2:
        cartesian = list(convmat_2.dot(np.array([atom[1], atom[2], atom[3]])))
        cart_2.append([atom[0], cartesian[0], cartesian[1], cartesian[2]])

    # make distance gap between cart_1 and cart_2 is the value of distance
    z_1 = []
    for atom in cart_1:
        z_1.append(atom[3])
    z_2 = []
    for atom in cart_2:
        z_2.append(atom[3])
    max_z_1 = max(z_1)
    min_z_2 = min(z_2)

    for i in range(len(cart_2)):
        cart_2[i][3] += distance - (min_z_2 - max_z_1)

    cart_all = cart_1 + cart_2
    out.atoms = []
    for atom in cart_all:
        out.atoms.append(Atom(name=atom[0], x=atom[1], y=atom[2], z=atom[3]))

    if use_cell == 1:
        out.cell = old_cell_1
        factor = (np.linalg.norm(np.array(old_cell_1[2])) + np.linalg.norm(
            np.array(old_cell_2[2]))) / np.linalg.norm(np.array(old_cell_1[2]))
        out.cell[2] = list(np.array(old_cell_1[2]) * factor)
    elif use_cell == 2:
        out.cell = old_cell_2
        factor = (np.linalg.norm(np.array(old_cell_1[2])) + np.linalg.norm(
            np.array(old_cell_2[2]))) / np.linalg.norm(np.array(old_cell_2[2]))
        out.cell[2] = list(np.array(old_cell_2[2]) * factor)
    else:
        out.cell = average_cell
        factor = (np.linalg.norm(np.array(old_cell_1[2])) + np.linalg.norm(
            np.array(old_cell_2[2]))) / np.linalg.norm(np.array(out.cell[2]))
        out.cell[2] = list(np.array(out.cell[2]) * factor)

    vacuum_layer(structure=out, plane=1, thickness=thickness)

    return out
Beispiel #13
0
def redefine_lattice(structure, a, b, c, precision=1.0e-8):
    """
    :param a, b, c: new lattice vectors in terms of old.
        new_a = a[0] * old_a + a[1] * old_b + a[2] * old_c
        like a=[1, 0, 0], b=[0, 1, 0], c=[0, 0, 1] actually defines the
        same lattice as old.
    :param precision, a value that is less than 1 and infinitely close to 1
        used to judge whether one atom is in another periodic of the redefined cell
    :return an object of crystal()
    Method:
        first make a large enough supercell, which guarantee that all the atoms in the new lattice are inside
        the supercell.
        then redfine the cell, and calc the fractional coord of all atoms with regarding the new cell
        finally remove those atoms who's fractional coord is not within range [0, 1), and we can convert fractional
        coords to cartesian.
    Note:
        relationship among convertion of coords. the most important point is that all coords actually have one common
        reference system, namely the General XYZ coordinate system. all the cell are defined with XYZ as reference,
        and the convmat build from the cell(with XYZ as reference) can be applied only to atoms also with XYZ as ference,
        finally we convert frac to cartesian using convmat also defined using cell with XYZ as reference, so we get 
        the cartesian with general XYZ as reference. In the last all the coord of atoms and cell have the general 
        XYZ  system as reference. So it works!
    """
    from pymatflow.structure.crystal import crystal
    from pymatflow.base.atom import Atom
    old_cell = copy.deepcopy(structure.cell)
    new_cell = copy.deepcopy(structure.cell)
    new_cell[0] = list(a[0] * np.array(old_cell[0]) +
                       a[1] * np.array(old_cell[1]) +
                       a[2] * np.array(old_cell[2]))
    new_cell[1] = list(b[0] * np.array(old_cell[0]) +
                       b[1] * np.array(old_cell[1]) +
                       b[2] * np.array(old_cell[2]))
    new_cell[2] = list(c[0] * np.array(old_cell[0]) +
                       c[1] * np.array(old_cell[1]) +
                       c[2] * np.array(old_cell[2]))

    # enlarge the system
    atoms_container = crystal()
    atoms_container.get_atoms(
        enlarge_atoms_new_cell(structure=structure, new_cell=new_cell))

    print("atoms_container.size(): %d\n" % len(atoms_container.atoms))
    # now calc the fractional coordinates of all atoms in atoms_container with new_cell as reference
    atoms_frac = []
    latcell_new = np.array(new_cell)
    convmat_new = np.linalg.inv(latcell_new.T)
    for i in range(len(atoms_container.atoms)):
        atom = []
        atom.append(atoms_container.atoms[i].name)
        atom = atom + list(
            convmat_new.dot(
                np.array([
                    atoms_container.atoms[i].x, atoms_container.atoms[i].y,
                    atoms_container.atoms[i].z
                ])))
        atoms_frac.append(atom)

    atoms_frac_within_new_cell = []
    for atom in atoms_frac:
        if (0 <= atom[1] <
            (1 - precision)) and (0 <= atom[2] <
                                  (1 - precision)) and (0 <= atom[3] <
                                                        (1 - precision)):
            atoms_frac_within_new_cell.append(atom)

    # now convert coord of atom in atoms_frac_within_new_cell to cartesian
    out = crystal()
    out.atoms = []
    latcell_new = np.array(new_cell)
    convmat_frac_to_cartesian = latcell_new.T
    for atom in atoms_frac_within_new_cell:
        cartesian = list(
            convmat_frac_to_cartesian.dot(np.array([atom[1], atom[2],
                                                    atom[3]])))
        out.atoms.append(
            Atom(name=atom[0], x=cartesian[0], y=cartesian[1], z=cartesian[2]))
    #

    out.cell = new_cell

    return out
Beispiel #14
0
def main():
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(
        dest="driver",
        title="subcommands",
        description="choose one and only one calculator")

    # --------------------------------------------------------------------------
    # LAMMPS
    # --------------------------------------------------------------------------
    subparser = subparsers.add_parser("lmp", help="using lammps as calculator")

    subparser.add_argument(
        "-r",
        "--runtype",
        type=int,
        default=0,
        choices=[0, 1, 2, 3, 4, 5, 6, 7],
        help=
        "choices of runtype. 0->static_run; 1->optimization; 2->cubic-cell; 3->hexagonal-cell; 4->tetragonal-cell; 5->neb; 6->vasp-phonon; 7->phonopy"
    )

    subparser.add_argument("-d",
                           "--directory",
                           type=str,
                           default="matflow-running",
                           help="Directory for the running.")

    # --------------------------------------------------------------------------
    # LAMMPS data
    # --------------------------------------------------------------------------
    subparser = subparsers.add_parser("data",
                                      help="lammps structure data operation")

    subparser.add_argument(
        "-i",
        "--input",
        type=str,
        help="input structure file, canbe xxx.cif, xxx.xyz, xxx.xsd, xxx.cube")

    subparser.add_argument(
        "-o",
        "--output",
        type=str,
        default="lammps.data",
        help="output lammps data file containing the structure information")
    # ==========================================================
    # transfer parameters from the arg subparser to static_run setting
    # ==========================================================

    args = parser.parse_args()

    # if no argument passed to matflow
    if len(sys.argv) == 1:
        # display help message when no args provided
        parser.print_help()
        sys.exit(1)

    if args.driver == "lmp":
        pass
    elif args.driver == "data":
        # will convert file type according to the suffix of the specified input
        # input structure
        if args.input.split(".")[-1] == "xyz":
            from pymatflow.structure.crystal import crystal
            a = crystal()
            a.from_xyz_file(args.input)
        elif args.input.split(".")[-1] == "cif":
            from pymatflow.structure.crystal import crystal
            import pymatflow.third.aseio as aseio
            a = crystal()
            a.cell, a.atoms = aseio.read_cif(args.input)
        elif args.input.split(".")[-1] == "xsd":
            from pymatflow.structure.crystal import crystal
            import pymatflow.third.aseio as aseio
            a = crystal()
            a.cell, a.atoms = aseio.read_xsd(args.input)
        elif args.input.split(".")[-1] == "xsf":
            from pymatflow.structure.crystal import crystal
            import pymatflow.third.aseio as aseio
            a = crystal()
            a.cell, a.atoms = aseio.read_xsf(args.input)
        elif os.path.basename(args.input) == "POSCAR" or os.path.basename(
                args.input) == "CONTCAR":
            from pymatflow.structure.crystal import crystal
            import pymatflow.third.aseio as aseio
            a = crystal()
            a.cell, a.atoms = aseio.read_poscar(args.input)

        # output structure
        import pymatflow.third.aseio
        aseio.write_lammps_data(cell=a.cell,
                                atoms=a.atoms,
                                filepath=args.output)

        print("=========================================================\n")
        print("              lmpflow data\n")
        print("---------------------------------------------------------\n")
        print("with the help from ase.io\n")
"""
usage:
    xyz-build-supercell.py -i input.xyz -o output.xyz -n n1 n2 n3
    n1, n2, n3 are the three repeated number in
    the three direct of three basis vectors
"""


if __name__ == '__main__':
    parser = argparse.ArgumentParser()

    parser.add_argument("-i", "--input", type=str,
            help="input xyz file")

    parser.add_argument("-o", "--output", type=str,
            help="output xyz file")

    parser.add_argument("-n", "--supern", nargs="+", type=int,
            help="bulid supern:[int, int, int] supercell")

    args = parser.parse_args()

    xyz = base_xyz()
    xyz.get_xyz(args.input)
    structure = crystal()
    new_structure = crystal()
    structure.from_base_xyz(xyz)
    supercell = structure.build_supercell(args.supern)
    new_structure.get_cell_atoms(cell=supercell["cell"], atoms=supercell["atoms"])
    new_structure.to_base_xyz().to_xyz_file(args.output)