Example #1
0
def random_purturbation_index():
    if is_pbc():
       struct=readstructure(crystal=True,molecule=False)
       natom=len(struct)
       d=np.zeros(2,dtype=int)
       while d[0]==d[1]:
           d=np.random.randint(0,natom,2)
       coord=struct.frac_coords
       coord[[d[0], d[1]], :] = coord[[d[1], d[0]], :]
       tmp_struct=Structure(struct.lattice,struct.species,coord)
       fname='swap_'+str(d[0]+1)+'_'+str(d[1]+1)+'.vasp'
       proc_str="Saving data to "+ fname +" File ..."
       procs(proc_str,0,sp='-->>')
       tmp_struct.to(filename=fname,fmt='poscar')
    else:
       struct=readstructure(crystal=False,molecule=True)
      # print(struct)     
       coord=struct.cart_coords
       natom=len(struct)
       d=np.zeros(2,dtype=int)
       while d[0]==d[1]:
           d=np.random.randint(0,natom,2)
       coord[[d[0], d[1]], :] = coord[[d[1], d[0]], :]
       tmp_struct=Molecule(struct.species,coord)
       fname='swap_'+str(d[0]+1)+'_'+str(d[1]+1)+'.xyz'
       proc_str="Saving data to "+ fname +" File ..."
       procs(proc_str,0,sp='-->>')
       tmp_struct.to(filename=fname,fmt='xyz')
    return
Example #2
0
def random_disturbing_lat():
    struct=readstructure(crystal=True,molecule=False)
    print("input the maximum displacement and with fix diagonal ")
    print("or non-diagonal element like this:  0.01 T F")
    print("it means maximum displacement is 0.01 ")
    print("the diagonal element will be fixed,") 
    print("while random disturbing will be add to non-digaonal element")
    wait_sep()
    in_str=""
    while in_str=="":
       in_str=input().strip().split()
#    print(in_str)
    maxdelta=float(in_str[0])
    diag=in_str[1].lower()=='t'
    nondiag=in_str[2].lower()=='t'
#    print(diag)
#    print(nondiag)
    stress_eps = np.random.random(6) * 2 * maxdelta - maxdelta
    if diag:
       stress_eps[:3] = 0
    if nondiag:
       stress_eps[-3:] = 0
    new_lattice=deform_cell(struct,stress_eps)
    tmp_struct=Structure(new_lattice,struct.species,struct.frac_coords)
    fname='random.vasp'
    proc_str="Saving data to "+ fname +" File ..."
    procs(proc_str,0,sp='-->>')
    tmp_struct.to(filename=fname,fmt='poscar')
    return
Example #3
0
def poscar_elong(poscar_in, poscar_out, elong, shift_center=True):
    with open(poscar_in, 'r') as fin:
        lines = list(fin)
    if lines[7][0].upper() != 'C':
        raise RuntimeError("only works for Cartesian POSCAR")
    sboxz = lines[4].split()
    boxz = np.array([float(sboxz[0]), float(sboxz[1]), float(sboxz[2])])
    boxzl = np.linalg.norm(boxz)
    elong_ratio = elong / boxzl
    boxz = boxz * (1. + elong_ratio)
    lines[4] = '%.16e %.16e %.16e\n' % (boxz[0], boxz[1], boxz[2])
    if shift_center:
        poscar_str = "".join(lines)
        st = Structure.from_str(poscar_str, fmt='poscar')
        cart_coords = st.cart_coords
        z_mean = cart_coords[:, 2].mean()
        z_shift = st.lattice.c / 2 - z_mean
        cart_coords[:, 2] = cart_coords[:, 2] + z_shift
        nst = Structure(st.lattice,
                        st.species,
                        coords=cart_coords,
                        coords_are_cartesian=True)
        nst.to('poscar', poscar_out)
    else:
        with open(poscar_out, 'w') as fout:
            fout.write("".join(lines))
Example #4
0
def split(structs,
          fnames,
          atom_index,
          in_str,
          SplitDistance,
          NumberSplitSite,
          ProperDist=3.5,
          DenseFrac=0.75):
    # len(structs)==1
    '''
    split one or several layers from bulk or structures 

    Args:
        structs: list of Structure obj.
        fnames: list of str for input file name.
        atom_index: list, which atom will be split .
        SplitDistance: float, the largest distance for splitting.
        NumberSplitSite: int, how many structures to be constructured during split 

    Returns:
        None
    Output:
        split_xxxx.dat  
        Num_xxx.vasp
    '''
    col_head = "#%(key1)+12s  %(key2)+12s" % {
        'key1': 'index',
        'key2': 'distance/Ang'
    }
    for struct, fname in zip(structs, fnames):
        DensityN = int(NumberSplitSite * DenseFrac)
        SparseN = NumberSplitSite - DensityN + 1
        dist = ProperDist / (DensityN - 1)
        SplitDistanceArray = np.zeros(NumberSplitSite + 1)
        for Nsite in range(DensityN):
            SplitDistanceArray[Nsite] = (Nsite) * dist

        dist = (SplitDistance - ProperDist) / SparseN
        for Nsite in range(SparseN):
            SplitDistanceArray[Nsite +
                               DensityN] = ProperDist + (Nsite + 1) * dist

        coords = struct.cart_coords
        for Nsite in range(NumberSplitSite + 1):
            coords = struct.cart_coords
            for atom in atom_index:
                coords[atom, 2] = coords[atom, 2] + SplitDistanceArray[Nsite]
            tmp_struct = Structure(struct.lattice,
                                   struct.species,
                                   coords,
                                   coords_are_cartesian=True)
            filename = str(Nsite) + '_' + fname + '.vasp'
            tmp_struct.to(filename=filename, fmt='poscar')
        data = np.zeros((NumberSplitSite + 1, 2))
        for i, j in enumerate(SplitDistanceArray):
            data[i][0] = i
            data[i][1] = j
        ret = DataIO(data, col_head=col_head, fmt_all="%12d %12.6f" + '\n')
        filename = 'split_' + fname + '.dat'
        ret.write(filename)
Example #5
0
    def output_clusters(self, fmt, periodic=None):
        """
        Outputs the unique unit cell clusters from the graph

        Args:
        fmt (str): output format for pymatgen structures set up from clusters
        periodic (Boolean): Whether to output only periodic clusters

        Outputs:
        CLUS_*."fmt": A cluster structure file for each cluster in the graph
        """

        if fmt == "poscar":
            tail = "vasp"
        else:
            tail = fmt

        site_sets = []

        for cluster in self.clusters:
            if periodic:
                if cluster.periodic > 0:
                    site_sets.append(
                        frozenset([
                            int(node.labels["UC_index"])
                            for node in cluster.nodes
                        ]))
            else:
                site_sets.append(
                    frozenset([
                        int(node.labels["UC_index"]) for node in cluster.nodes
                    ]))

        site_sets = set(site_sets)

        for index, site_list in enumerate(site_sets):
            cluster_structure = Structure(lattice=self.structure.lattice,
                                          species=[],
                                          coords=[])
            symbols = [species for species in self.structure.symbol_set]
            if "X" in set(symbols):
                symbols.remove("X")
                symbols.append("X0+")
            for symbol in symbols:
                for site in site_list:

                    site = self.structure.sites[site]

                    if site.species_string == symbol:
                        cluster_structure.append(symbol,
                                                 site.coords,
                                                 coords_are_cartesian=True)

            cluster_structure.to(fmt=fmt,
                                 filename="CLUS_" + str(index) + "." + tail)
Example #6
0
def to_pos(name: str):
    s = IMolecule.from_file(name)
    arr = '''     6.0189552714770000    0.0000000000000000    0.0000000000000000
    -3.0094776357390001    5.2125681693410000    0.0000000000000000
     0.0000000000000000    0.0000000000000000   17.3716845998769998
'''.split()
    arr = np.array(arr)
    arr.reshape((3, 3))
    lat = Lattice(arr)
    s = Structure(lat, s.species, s.cart_coords, coords_are_cartesian=True)
    s.to('POSCAR', name.replace('xyz', 'vasp'))
    print('ok')
Example #7
0
def make_atom_poscar_dirs(path: Path, elems: List[Element] = None):
    elems = [str(e) for e in elems] if elems else mags.keys()

    for element in elems:
        d = path / element
        Path(d).mkdir()
        structure = Structure(Lattice.cubic(10), [element], [[0.5] * 3])
        structure.to(fmt="POSCAR", filename=str(d / "POSCAR"))
        nupdown = mags[element]
        prior_info = {
            "incar": {
                "ISPIN": 2,
                "NUPDOWN": nupdown,
                "NELM": 300
            },
            "is_cluster": True
        }
        (d / "prior_info.yaml").write_text(yaml.dump(prior_info))
Example #8
0
def random_disturbing_pos():

    def random_move_one_atom(coords, mu=0.1, sigma=0.01):

        index = random.randint(0, len(coords) - 1)
        radius = np.abs(np.random.normal(mu, sigma))
        theta_x = 2 * np.pi * np.random.random_sample()
        theta_y = 2 * np.pi * np.random.random_sample()
        theta_z = 2 * np.pi * np.random.random_sample()
        vector = apply_rotation([1, 0, 0], theta_x, theta_y, theta_z)
        coords[index] += vector*radius
        return coords
    
    print("input the maximum displacement(<0.25 in Angstrom)")
    wait_sep()
    in_str=""
    while in_str=="":
       in_str=input().strip()
    epsilon=float(in_str)
    assert epsilon < 0.3
    
    if is_pbc():
       struct=readstructure(crystal=True,molecule=False)
       coords=struct.cart_coords
       for iatom in range(len(struct)):
           coords=random_move_one_atom(coords,mu=epsilon)
       tmp_struct=Structure(struct.lattice,struct.species,coords,coords_are_cartesian=True)
       fname='random.vasp'
       proc_str="Saving data to "+ fname +" File ..."
       procs(proc_str,0,sp='-->>')
       tmp_struct.to(filename=fname,fmt='poscar')
    else:
       struct=readstructure(crystal=False,molecule=True)
       coords=struct.cart_coords
       for iatom in range(len(struct)):
           coords=random_move_one_atom(coords,mu=epsilon)

       tmp_struct=Molecule(struct.species,coords)
       fname='random.xyz'
       proc_str="Saving data to "+ fname +" File ..."
       procs(proc_str,0,sp='-->>')
       tmp_struct.to(filename=fname,fmt='xyz')        
    return
Example #9
0
def circle_strain(structs, fnames, C11, C12, C22, C66, sigma, nps=37):
    for struct, fname in zip(structs, fnames):
        if not struct.lattice.is_orthogonal:
            warn_tip(0, "{} is not orthogonal, skip it !!!".format(fname))
            continue
        new_struct = move_to_zcenter(struct)
        orig_struct = new_struct.copy()
        new_struct = new_struct.copy()
        natom = orig_struct.num_sites
        lat = orig_struct.lattice.matrix.copy()
        pos = orig_struct.frac_coords
        phi = np.linspace(0, 360, nps) * np.pi / 180
        vzz = C12 / C22
        temp_num = (C11 * C22 - C12**2) / (C22 * C66)
        d1 = C11 / C22 + 1.0 - temp_num
        d2 = -(2.0 * C12 / C22 - temp_num)
        d3 = C11 / C22
        F = sigma * C22 / (C11 * C22 - C12**2.0)
        Poisson=(vzz*(np.cos(phi))**4.0-d1*(np.cos(phi))**2.0*(np.sin(phi))**2.0+vzz*(np.sin(phi))**4.0)/\
                ((np.cos(phi))**4.0+d2*(np.cos(phi))**2.0*(np.sin(phi))**2.0+d3*(np.sin(phi))**4.0)

        eps_theta = F * ((np.cos(phi))**4 + d2 * (np.cos(phi))**2.0 *
                         (np.sin(phi))**2.0 + d3 * (np.sin(phi))**4.0)
        t = sympy.Symbol('t', real=True)
        e = sympy.Symbol('e', real=True)
        v = sympy.Symbol('v', real=True)
        eprim = sympy.Matrix([[e + 1, 0], [0, 1 - e * v]])
        R = sympy.Matrix([[sympy.cos(t), -sympy.sin(t)],
                          [sympy.sin(t), sympy.cos(t)]])
        eps_mat = R * eprim * R.adjugate()
        for k in range(len(phi)):
            cur__phi = phi[k] * 180 / np.pi
            Rot = eps_mat.subs({e: eps_theta[k], v: Poisson[k], t: phi[k]})
            filename = str(k) + "_" + fname + '.vasp'
            final_lat = np.matrix(np.eye(3))
            final_lat[0, 0] = Rot[0, 0]
            final_lat[0, 1] = Rot[0, 1]
            final_lat[1, 0] = Rot[1, 0]
            final_lat[1, 1] = Rot[1, 1]
            lat_new = lat * final_lat
            tmp_struct = Structure(lat_new, new_struct.species, pos)
            tmp_struct.to(filename=filename, fmt='poscar')
Example #10
0
def cry2cif(filename,
            to="cif",
            center=False,
            sortx=False,
            sortz=False,
            b_dum=50,
            c_dum=50,
            istruct=-1):
    """
    Read a CRYSTAL output file and return the structure in a cif or POSCAR format.

    Args:
        filename (str): crystal output filename
        to (str): 'cif' or 'vasp', format of the output file (default is cif)
        center (bool): if True, the slab or nanotube is translated to the center of
                       the box (default is False)
        sortx (bool): Nanotube : if True, atoms are sorted along x axes (default is False).
        sortz (bool): slab : if True, atoms are sorted along z axes (default is False).
        b_dum (float): dummy lattice paramters b in angstrom for nanotubes (default 50 A)
        c_dum (float): dummy lattice paramters c in angstrom for nanotubes and slabs (default 50 A)
        istruct (int): structure to be extracted

    """
    cryout = CrystalOutfile(filename)

    print("title      : ", cryout.title)
    if cryout.group:
        print("group      : ", cryout.group)

    # print("Number of structure read: ", len(cryout.structures))

    if istruct == -1:
        print("structure  : Final structure")
        structure = cryout.final_structure
    else:
        print("structure  : Structure %d" % istruct)
        structure = cryout.get_structure(istruct)
    print("# atom     : ", structure.num_sites)
    print("composition: ", structure.composition)
    print("Cell parameters:")
    print("a     : %10.4f" % structure.lattice.a)
    print("b     : %10.4f" % structure.lattice.b)
    print("c     : %10.4f" % structure.lattice.c)
    print("alpha : %10.4f" % structure.lattice.alpha)
    print("beta  : %10.4f" % structure.lattice.beta)
    print("gamma : %10.4f" % structure.lattice.gamma)

    # ----------------------------------------------------------
    #  New b and c axes
    # ----------------------------------------------------------
    if cryout.slab:
        frac_coords = structure.frac_coords
        frac_coords[:, 2] *= structure.lattice.c / c_dum
        matrix = structure.lattice.matrix.copy()
        matrix[2, 2] = c_dum
        structure = Structure(Lattice(matrix), structure.species, frac_coords)
    if cryout.nanotube:
        frac_coords = structure.frac_coords
        frac_coords[:, 1] *= structure.lattice.c / c_dum
        frac_coords[:, 2] *= structure.lattice.b / b_dum
        matrix = structure.lattice.matrix.copy()
        matrix[1, 1] = b_dum
        matrix[2, 2] = c_dum
        structure = Structure(Lattice(matrix), structure.species, frac_coords)

    # ----------------------------------------------------------
    #  move slab or nanotube to the center of the box
    # ----------------------------------------------------------
    if center:
        if cryout.slab:
            coords = structure.frac_coords.copy()
            coords[:, 2] += .5
            structure = Structure(structure.lattice, structure.species, coords)
        elif cryout.nanotube:
            coords = structure.frac_coords
            coords += .5
            structure = Structure(structure.lattice, structure.species, coords)

    # ----------------------------------------------------------
    #  sort atom along x or z axis for slab
    # ----------------------------------------------------------
    if sortz:
        isort = 2
    elif sortx:
        isort = 0

    axes = {2: "z", 0: "x"}
    if sortz or sortx:
        print("\nSort atoms along %s" % axes[isort])
        data = zip(structure.species, structure.frac_coords)
        data = sorted(data, key=lambda d: d[-1][isort], reverse=True)

        species = [d[0] for d in data]
        coords = [d[1] for d in data]
        structure = Structure(structure.lattice, species, coords)

    # ----------------------------------------------------------
    # export in the given format
    # ----------------------------------------------------------
    basename, _ = os.path.splitext(filename)
    if to.lower() == "cif":
        ext = ".cif"
    elif to.lower() == "vasp":
        to = "POSCAR"
        ext = ".vasp"
    else:
        to = "POSCAR"
        ext = ".vasp"
    structure.to(to, filename=basename + ext)
Example #11
0
matplotlib.rcParams.update({'font.size': 18})
fig_size = [15, 12]
plt.rcParams["figure.figsize"] = fig_size


# In[ ]:


# Create beta-CsCl structure
a = 6.923 #Angstrom
latt = Lattice.cubic(a)
structure = Structure(latt, ["Cs", "Cs", "Cs", "Cs", "Cl", "Cl", 
"Cl", "Cl"], [[0, 0, 0], [0.5, 0.5, 0], [0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0.5], [0, 0, 0.5], [0, 0.5, 0], [0.5, 0, 0]])

temp_cif = NamedTemporaryFile(delete=False)
structure.to("cif", temp_cif.name)
xu_cif = CIFFile(temp_cif.name)
xu_crystal = Crystal(name="b-CsCl", lat=xu_cif.SGLattice())
temp_cif.close()

two_theta = numpy.arange(0, 80, 0.01)

powder = xru.simpack.smaterials.Powder(xu_crystal, 1)
pm = xru.simpack.PowderModel(powder, I0=100)
intensities = pm.simulate(two_theta)
plt.plot(two_theta,intensities)
plt.xlim(0,80)
ax = plt.axes()
ax.xaxis.set_major_locator(ticker.MultipleLocator(5))
ax.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.4f'))
plt.title("XRD Pattern for " + xu_crystal.name)
Example #12
0
    def constrained_opt_run(cls, vasp_cmd, lattice_direction, initial_strain,
                            atom_relax=True, max_steps=20, algo="bfgs",
                            **vasp_job_kwargs):
        """
        Returns a generator of jobs for a constrained optimization run. Typical
        use case is when you want to approximate a biaxial strain situation,
        e.g., you apply a defined strain to a and b directions of the lattice,
        but allows the c-direction to relax.

        Some guidelines on the use of this method:
        i.  It is recommended you do not use the Auto kpoint generation. The
            grid generated via Auto may fluctuate with changes in lattice
            param, resulting in numerical noise.
        ii. Make sure your EDIFF/EDIFFG is properly set in your INCAR. The
            optimization relies on these values to determine convergence.

        Args:
            vasp_cmd (str): Command to run vasp as a list of args. For example,
                if you are using mpirun, it can be something like
                ["mpirun", "pvasp.5.2.11"]
            lattice_direction (str): Which direction to relax. Valid values are
                "a", "b" or "c".
            initial_strain (float): An initial strain to be applied to the
                lattice_direction. This can usually be estimated as the
                negative of the strain applied in the other two directions.
                E.g., if you apply a tensile strain of 0.05 to the a and b
                directions, you can use -0.05 as a reasonable first guess for
                initial strain.
            atom_relax (bool): Whether to relax atomic positions.
            max_steps (int): The maximum number of runs. Defaults to 20 (
                highly unlikely that this limit is ever reached).
            algo (str): Algorithm to use to find minimum. Default is "bfgs",
                which is fast, but can be sensitive to numerical noise
                in energy calculations. The alternative is "bisection",
                which is more robust but can be a bit slow. The code does fall
                back on the bisection when bfgs gives a non-sensical result,
                e.g., negative lattice params.
            \*\*vasp_job_kwargs: Passthrough kwargs to VaspJob. See
                :class:`custodian.vasp.jobs.VaspJob`.

        Returns:
            Generator of jobs. At the end of the run, an "EOS.txt" is written
            which provides a quick look at the E vs lattice parameter.
        """
        nsw = 99 if atom_relax else 0

        incar = Incar.from_file("INCAR")

        # Set the energy convergence criteria as the EDIFFG (if present) or
        # 10 x EDIFF (which itself defaults to 1e-4 if not present).
        if incar.get("EDIFFG") and incar.get("EDIFFG") > 0:
            etol = incar["EDIFFG"]
        else:
            etol = incar.get("EDIFF", 1e-4) * 10

        if lattice_direction == "a":
            lattice_index = 0
        elif lattice_direction == "b":
            lattice_index = 1
        else:
            lattice_index = 2

        energies = {}

        for i in range(max_steps):
            if i == 0:
                settings = [
                        {"dict": "INCAR",
                         "action": {"_set": {"ISIF": 2, "NSW": nsw}}}]
                structure = Poscar.from_file("POSCAR").structure
                x = structure.lattice.abc[lattice_index]
                backup = True
            else:
                backup = False
                v = Vasprun("vasprun.xml")
                structure = v.final_structure
                energy = v.final_energy
                lattice = structure.lattice

                x = lattice.abc[lattice_index]

                energies[x] = energy

                if i == 1:
                    x *= (1 + initial_strain)
                else:
                    # Sort the lattice parameter by energies.
                    min_x = min(energies.keys(), key=lambda e: energies[e])
                    sorted_x = sorted(energies.keys())
                    ind = sorted_x.index(min_x)
                    if ind == 0:
                        other = ind + 1
                    elif ind == len(sorted_x) - 1:
                        other = ind - 1
                    else:
                        other = ind + 1 \
                            if energies[sorted_x[ind + 1]] \
                            < energies[sorted_x[ind - 1]] \
                            else ind - 1
                    if abs(energies[min_x]
                           - energies[sorted_x[other]]) < etol:
                        logger.info("Stopping optimization! Final %s = %f"
                                    % (lattice_direction, min_x))
                        break

                    if ind == 0 and len(sorted_x) > 2:
                        # Lowest energy lies outside of range of lowest value.
                        # we decrease the lattice parameter in the next
                        # iteration to find a minimum. This applies only when
                        # there are at least 3 values.
                        x = sorted_x[0] - abs(sorted_x[1] - sorted_x[0])
                        logger.info("Lowest energy lies below bounds. "
                                    "Setting %s = %f." % (lattice_direction, x))
                    elif ind == len(sorted_x) - 1 and len(sorted_x) > 2:
                        # Lowest energy lies outside of range of highest value.
                        # we increase the lattice parameter in the next
                        # iteration to find a minimum. This applies only when
                        # there are at least 3 values.
                        x = sorted_x[-1] + abs(sorted_x[-1] - sorted_x[-2])
                        logger.info("Lowest energy lies above bounds. "
                                    "Setting %s = %f." % (lattice_direction, x))
                    else:
                        if algo.lower() == "bfgs" and len(sorted_x) >= 4:
                            try:
                                # If there are more than 4 data points, we will
                                # do a quadratic fit to accelerate convergence.
                                x1 = list(energies.keys())
                                y1 = [energies[j] for j in x1]
                                z1 = np.polyfit(x1, y1, 2)
                                pp = np.poly1d(z1)
                                from scipy.optimize import minimize
                                result = minimize(
                                    pp, min_x,
                                    bounds=[(sorted_x[0], sorted_x[-1])])
                                if (not result.success) or result.x[0] < 0:
                                    raise ValueError(
                                        "Negative lattice constant!")
                                x = result.x[0]
                                logger.info("BFGS minimized %s = %f."
                                            % (lattice_direction, x))
                            except ValueError as ex:
                                # Fall back on bisection algo if the bfgs fails.
                                logger.info(str(ex))
                                x = (min_x + sorted_x[other]) / 2
                                logger.info("Falling back on bisection %s = %f."
                                            % (lattice_direction, x))
                        else:
                            x = (min_x + sorted_x[other]) / 2
                            logger.info("Bisection %s = %f."
                                        % (lattice_direction, x))

                lattice = lattice.matrix
                lattice[lattice_index] = lattice[lattice_index] / \
                    np.linalg.norm(lattice[lattice_index]) * x

                s = Structure(lattice, structure.species, structure.frac_coords)
                fname = "POSCAR.%f" % x
                s.to(filename=fname)

                incar_update = {"ISTART": 1, "NSW": nsw, "ISIF": 2}

                settings = [
                    {"dict": "INCAR",
                     "action": {"_set": incar_update}},
                    {"file": fname,
                     "action": {"_file_copy": {"dest": "POSCAR"}}}]

            logger.info("Generating job = %d with parameter %f!" % (i + 1, x))
            yield VaspJob(vasp_cmd, final=False, backup=backup,
                          suffix=".static.%f" % x,
                          settings_override=settings, **vasp_job_kwargs)

        with open("EOS.txt", "wt") as f:
            f.write("# %s energy\n" % lattice_direction)
            for k in sorted(energies.keys()):
                f.write("%f %f\n" % (k, energies[k]))
Example #13
0
def run_mcsqs(
    structure: Structure,
    clusters: Dict[int, float],
    scaling: Union[int, List[int]],
    search_time: float = 0.01,
) -> Optional[Sqs]:
    """
    Helper function for calling mcsqs with different arguments
    Args:
        structure (Structure): disordered pymatgen Structure object
        clusters (dict): dictionary of cluster interactions with entries in the form
            number of atoms: cutoff in angstroms
        scaling (int or list): scaling factor to determine supercell. Two options are possible:
                a. (preferred) Scales number of atoms, e.g., for a structure with 8 atoms,
                   scaling=4 would lead to a 32 atom supercell
                b. An sequence of three scaling factors, e.g., [2, 1, 1], which
                   specifies that the supercell should have dimensions 2a x b x c
        search_time (int): The time spent looking for the ideal SQS in minutes

    Returns:
        Tuple of Pymatgen structure, which is an SQS of the input structure, and the
            mcsqs objective function
    """

    num_atoms = len(structure)

    if structure.is_ordered:
        raise ValueError("Pick a disordered structure")

    with ScratchDir("."):

        if isinstance(scaling, (int, float)):

            if scaling % 1:
                raise ValueError(
                    "Scaling should be an integer, not {}".format(scaling))

            mcsqs_find_sqs_cmd = ["mcsqs", "-n {}".format(scaling * num_atoms)]

        else:

            # Set supercell to identity (will make supercell with pymatgen)
            with open("sqscell.out", "w") as f:
                f.write("1\n" "1 0 0\n" "0 1 0\n" "0 0 1\n")

            structure = structure * scaling
            mcsqs_find_sqs_cmd = ["mcsqs", "-rc", "-n {}".format(num_atoms)]

        structure.to(filename="rndstr.in")

        # Generate clusters
        mcsqs_generate_clusters_cmd = ["mcsqs"]
        for num in clusters:
            mcsqs_generate_clusters_cmd.append("-" + str(num) + "=" +
                                               str(clusters[num]))

        # Run mcsqs to find clusters
        p = subprocess.Popen(mcsqs_generate_clusters_cmd)
        p.communicate()

        # Run mcsqs to find sqs structure
        p = subprocess.Popen(mcsqs_find_sqs_cmd)

        try:
            p.communicate(timeout=search_time * 60)
            raise Exception("mcsqs exited before timeout reached")
        except subprocess.TimeoutExpired:
            p.kill()
            p.communicate()
            if os.path.exists("bestsqs.out") and os.path.exists(
                    "bestcorr.out"):

                # Convert output sqs structure to cif file
                p = subprocess.Popen("str2cif < bestsqs.out > bestsqs.cif",
                                     shell=True)
                p.communicate()

                # Get objective function
                with open('bestcorr.out', 'r') as f:
                    lines = f.readlines()
                objective_function = float(lines[-1].split('=')[-1].strip())

                return Sqs(bestsqs=Structure.from_file("bestsqs.cif"),
                           objective_function=objective_function)

            else:
                raise TimeoutError("Cluster expansion took too long.")
Example #14
0
    def constrained_opt_run(cls,
                            vasp_cmd,
                            lattice_direction,
                            initial_strain,
                            atom_relax=True,
                            max_steps=20,
                            algo="bfgs",
                            **vasp_job_kwargs):
        """
        Returns a generator of jobs for a constrained optimization run. Typical
        use case is when you want to approximate a biaxial strain situation,
        e.g., you apply a defined strain to a and b directions of the lattice,
        but allows the c-direction to relax.

        Some guidelines on the use of this method:
        i.  It is recommended you do not use the Auto kpoint generation. The
            grid generated via Auto may fluctuate with changes in lattice
            param, resulting in numerical noise.
        ii. Make sure your EDIFF/EDIFFG is properly set in your INCAR. The
            optimization relies on these values to determine convergence.

        Args:
            vasp_cmd (str): Command to run vasp as a list of args. For example,
                if you are using mpirun, it can be something like
                ["mpirun", "pvasp.5.2.11"]
            lattice_direction (str): Which direction to relax. Valid values are
                "a", "b" or "c".
            initial_strain (float): An initial strain to be applied to the
                lattice_direction. This can usually be estimated as the
                negative of the strain applied in the other two directions.
                E.g., if you apply a tensile strain of 0.05 to the a and b
                directions, you can use -0.05 as a reasonable first guess for
                initial strain.
            atom_relax (bool): Whether to relax atomic positions.
            max_steps (int): The maximum number of runs. Defaults to 20 (
                highly unlikely that this limit is ever reached).
            algo (str): Algorithm to use to find minimum. Default is "bfgs",
                which is fast, but can be sensitive to numerical noise
                in energy calculations. The alternative is "bisection",
                which is more robust but can be a bit slow. The code does fall
                back on the bisection when bfgs gives a non-sensical result,
                e.g., negative lattice params.
            \*\*vasp_job_kwargs: Passthrough kwargs to VaspJob. See
                :class:`custodian.vasp.jobs.VaspJob`.

        Returns:
            Generator of jobs. At the end of the run, an "EOS.txt" is written
            which provides a quick look at the E vs lattice parameter.
        """
        nsw = 99 if atom_relax else 0

        incar = Incar.from_file("INCAR")

        # Set the energy convergence criteria as the EDIFFG (if present) or
        # 10 x EDIFF (which itself defaults to 1e-4 if not present).
        if incar.get("EDIFFG") and incar.get("EDIFFG") > 0:
            etol = incar["EDIFFG"]
        else:
            etol = incar.get("EDIFF", 1e-4) * 10

        if lattice_direction == "a":
            lattice_index = 0
        elif lattice_direction == "b":
            lattice_index = 1
        else:
            lattice_index = 2

        energies = {}

        for i in range(max_steps):
            if i == 0:
                settings = [{
                    "dict": "INCAR",
                    "action": {
                        "_set": {
                            "ISIF": 2,
                            "NSW": nsw
                        }
                    }
                }]
                structure = Poscar.from_file("POSCAR").structure
                x = structure.lattice.abc[lattice_index]
                backup = True
            else:
                backup = False
                v = Vasprun("vasprun.xml")
                structure = v.final_structure
                energy = v.final_energy
                lattice = structure.lattice

                x = lattice.abc[lattice_index]

                energies[x] = energy

                if i == 1:
                    x *= (1 + initial_strain)
                else:
                    # Sort the lattice parameter by energies.
                    min_x = min(energies.keys(), key=lambda e: energies[e])
                    sorted_x = sorted(energies.keys())
                    ind = sorted_x.index(min_x)
                    if ind == 0:
                        other = ind + 1
                    elif ind == len(sorted_x) - 1:
                        other = ind - 1
                    else:
                        other = ind + 1 \
                            if energies[sorted_x[ind + 1]] \
                            < energies[sorted_x[ind - 1]] \
                            else ind - 1
                    if abs(energies[min_x] - energies[sorted_x[other]]) < etol:
                        logger.info("Stopping optimization! Final %s = %f" %
                                    (lattice_direction, min_x))
                        break

                    if ind == 0 and len(sorted_x) > 2:
                        # Lowest energy lies outside of range of lowest value.
                        # we decrease the lattice parameter in the next
                        # iteration to find a minimum. This applies only when
                        # there are at least 3 values.
                        x = sorted_x[0] - abs(sorted_x[1] - sorted_x[0])
                        logger.info("Lowest energy lies below bounds. "
                                    "Setting %s = %f." %
                                    (lattice_direction, x))
                    elif ind == len(sorted_x) - 1 and len(sorted_x) > 2:
                        # Lowest energy lies outside of range of highest value.
                        # we increase the lattice parameter in the next
                        # iteration to find a minimum. This applies only when
                        # there are at least 3 values.
                        x = sorted_x[-1] + abs(sorted_x[-1] - sorted_x[-2])
                        logger.info("Lowest energy lies above bounds. "
                                    "Setting %s = %f." %
                                    (lattice_direction, x))
                    else:
                        if algo.lower() == "bfgs" and len(sorted_x) >= 4:
                            try:
                                # If there are more than 4 data points, we will
                                # do a quadratic fit to accelerate convergence.
                                x1 = list(energies.keys())
                                y1 = [energies[j] for j in x1]
                                z1 = np.polyfit(x1, y1, 2)
                                pp = np.poly1d(z1)
                                from scipy.optimize import minimize
                                result = minimize(pp,
                                                  min_x,
                                                  bounds=[(sorted_x[0],
                                                           sorted_x[-1])])
                                if (not result.success) or result.x[0] < 0:
                                    raise ValueError(
                                        "Negative lattice constant!")
                                x = result.x[0]
                                logger.info("BFGS minimized %s = %f." %
                                            (lattice_direction, x))
                            except ValueError as ex:
                                # Fall back on bisection algo if the bfgs fails.
                                logger.info(str(ex))
                                x = (min_x + sorted_x[other]) / 2
                                logger.info(
                                    "Falling back on bisection %s = %f." %
                                    (lattice_direction, x))
                        else:
                            x = (min_x + sorted_x[other]) / 2
                            logger.info("Bisection %s = %f." %
                                        (lattice_direction, x))

                lattice = lattice.matrix
                lattice[lattice_index] = lattice[lattice_index] / \
                    np.linalg.norm(lattice[lattice_index]) * x

                s = Structure(lattice, structure.species,
                              structure.frac_coords)
                fname = "POSCAR.%f" % x
                s.to(filename=fname)

                incar_update = {"ISTART": 1, "NSW": nsw, "ISIF": 2}

                settings = [{
                    "dict": "INCAR",
                    "action": {
                        "_set": incar_update
                    }
                }, {
                    "file": fname,
                    "action": {
                        "_file_copy": {
                            "dest": "POSCAR"
                        }
                    }
                }]

            logger.info("Generating job = %d with parameter %f!" % (i + 1, x))
            yield VaspJob(vasp_cmd,
                          final=False,
                          backup=backup,
                          suffix=".static.%f" % x,
                          settings_override=settings,
                          **vasp_job_kwargs)

        with open("EOS.txt", "wt") as f:
            f.write("# %s energy\n" % lattice_direction)
            for k in sorted(energies.keys()):
                f.write("%f %f\n" % (k, energies[k]))
Example #15
0
import math
from pymatgen import Structure, Molecule, Lattice
import os

os.chdir(
    '/home/jinho93/oxides/perobskite/lanthanum-aluminate/slab/gulp/nonstochio/La-vac/two'
)

m = Molecule.from_file('tail.xyz')
l = Lattice.from_lengths_and_angles([11.46615, 15.2882, 50], [90, 90, 90])

s = Structure(l, m.species, m.cart_coords, coords_are_cartesian=True)
s.make_supercell([[4, 0, 0], [0, 3, 0], [0, 0, 1]])
s.make_supercell([[1, 1, 0], [1, -1, 0], [0, 0, 1]])
s.sort()
# ll = Lattice.from_lengths_and_angles([s.lattice.a / 2, s.lattice.b / 2, s.lattice.c], s.lattice.angles)
ll = Lattice.from_lengths_and_angles(s.lattice.abc, s.lattice.angles)
s = Structure(ll, s.species, s.cart_coords, coords_are_cartesian=True)

indi = []
for i, site in enumerate(s.sites):
    if site.x + site.y < ll.b / math.sqrt(2):
        indi.append(i)

# s.remove_sites(indi)

# s = Structure(ll, s.species, s.cart_coords, coords_are_cartesian=True)

# s.to('POSCAR', 'POSCAR')
s.to('POSCAR', 'CONTCAR')
Example #16
0
for i, struct in enumerate([struct1, struct2]):
    position, ev = get_fragment_position_and_orientation(struct, [1] * 18)

    print_xyz(coordinates=get_dipole_in_basis(
        np.array(coordinates_monomer).T, ev_dipole, ev).T +
              np.array([position] * 18),
              symbols=symbols_monomer)

    print('Molecule {}\n---------------'.format(i + 1))
    params = get_rotation_angles(ev)

    print('orientation: {} {} {}'.format(*params))
    print('position', position)

    # store structure in file
    struct_c.to(filename='naphtalene.cif')
    struct_c.to(filename='POSCAR')

    scale_factor = 50
    molecule = Molecule(
        states=[State(label='gs', energy=0.0),
                State(label='s1', energy=1.0)],
        transition_moment={
            ('s1', 'gs'): dipole * scale_factor,
            ('s2', 'gs'): dipole2 * scale_factor
        },  # transition dipole moment of the molecule (Debye)
    )

    system = crystal_system(conditions={},
                            molecules=[molecule],
                            scaled_site_coordinates=[position],
Example #17
0
#%%

from pymatgen import Structure, Molecule
from pymatgen.io.xyz import XYZ

import os

os.chdir(
    '/home/jinho93/new/oxides/perobskite/lanthanum-aluminate/periodic_step/vasp/stengel/013/from_gulp/all'
)
os.chdir(
    '/home/jinho93/new/oxides/perobskite/lanthanum-aluminate/periodic_step/gulp/013/all'
)
xyz = XYZ.from_file('lao.xyz')

tmp = Structure.from_file('POSCAR')

for m in xyz.all_molecules[:1]:
    s = Structure(tmp.lattice,
                  m.species,
                  m.cart_coords,
                  coords_are_cartesian=True)
    prim = s.get_primitive_structure(1e-1)
    if len(prim.sites) < 540:
        print(len(prim.sites))
        out_str = s

s.to('POSCAR', 'NPOSCAR')

print(len(s.sites))
print(len(prim.sites))
Example #18
0
# twod file path
twod_file = '../test_files/POSCAR_2D'
sub = Structure.from_file(sub_file)
twod = Structure.from_file(twod_file)

# provide input match constraints as a dictionary
match_constraints = {
    'max_area': 90,
    'max_mismatch': 0.06,
    'max_angle_diff': 2,
    'r1r2_tol': 0.04,
    'separation': 2.2,
    'nlayers_substrate': 1,
    'nlayers_2d': 1,
    'sd_layers': 0,
    'best_match': 'area'
}
#########################################

# Lowest area (default) or minimum uv mismatched lattice match
# is returned based on 'best_match' option in match_constraints
# best_match should be either 'area' or 'mismatch'
iface, n_sub, z_ub = transformations.run_lat_match(sub, twod,
                                                   match_constraints)

if iface is None:
    print('Current twod lattice matches with substrate. No changes needed!')
else:
    strct = Structure(iface.lattice, iface.species, iface.frac_coords)
    strct.to(filename='../test_files/POSCAR_iface', fmt='poscar')
Example #19
0
def run_mcsqs(
    structure: Structure,
    clusters: Dict[int, float],
    scaling: Union[int, List[int]] = 1,
    search_time: float = 60,
    directory: Optional[str] = None,
    instances: Optional[int] = None,
    temperature: Union[int, float] = 1,
    wr: float = 1,
    wn: float = 1,
    wd: float = 0.5,
    tol: float = 1e-3,
) -> Sqs:
    """
    Helper function for calling mcsqs with different arguments
    Args:
        structure (Structure): Disordered pymatgen Structure object
        clusters (dict): Dictionary of cluster interactions with entries in the form
            number of atoms: cutoff in angstroms
        scaling (int or list): Scaling factor to determine supercell. Two options are possible:
                a. (preferred) Scales number of atoms, e.g., for a structure with 8 atoms,
                   scaling=4 would lead to a 32 atom supercell
                b. A sequence of three scaling factors, e.g., [2, 1, 1], which
                   specifies that the supercell should have dimensions 2a x b x c
            Defaults to 1.
        search_time (float): Time spent looking for the ideal SQS in minutes (default: 60)
        directory (str): Directory to run mcsqs calculation and store files (default: None
            runs calculations in a temp directory)
        instances (int): Specifies the number of parallel instances of mcsqs to run
            (default: number of cpu cores detected by Python)
        temperature (int or float): Monte Carlo temperature (default: 1), "T" in atat code
        wr (int or float): Weight assigned to range of perfect correlation match in objective
            function (default = 1)
        wn (int or float): Multiplicative decrease in weight per additional point in cluster (default: 1)
        wd (int or float): Exponent of decay in weight as function of cluster diameter (default: 0.5)
        tol (int or float): Tolerance for matching correlations (default: 1e-3)

    Returns:
        Tuple of Pymatgen structure SQS of the input structure, the mcsqs objective function,
            list of all SQS structures, and the directory where calculations are run
    """

    num_atoms = len(structure)

    if structure.is_ordered:
        raise ValueError("Pick a disordered structure")

    if instances is None:
        # os.cpu_count() can return None if detection fails
        instances = os.cpu_count()

    original_directory = os.getcwd()
    if not directory:
        directory = tempfile.mkdtemp()
    os.chdir(directory)

    if isinstance(scaling, (int, float)):

        if scaling % 1:
            raise ValueError("Scaling should be an integer, not {}".format(scaling))
        mcsqs_find_sqs_cmd = ["mcsqs", "-n {}".format(scaling * num_atoms)]

    else:

        # Set supercell to identity (will make supercell with pymatgen)
        with open("sqscell.out", "w") as f:
            f.write("1\n1 0 0\n0 1 0\n0 0 1\n")
        structure = structure * scaling
        mcsqs_find_sqs_cmd = ["mcsqs", "-rc", "-n {}".format(num_atoms)]

    structure.to(filename="rndstr.in")

    # Generate clusters
    mcsqs_generate_clusters_cmd = ["mcsqs"]
    for num in clusters:
        mcsqs_generate_clusters_cmd.append("-" + str(num) + "=" + str(clusters[num]))

    # Run mcsqs to find clusters
    p = Popen(mcsqs_generate_clusters_cmd)
    p.communicate()

    # Generate SQS structures
    add_ons = [
        "-T {}".format(temperature),
        "-wr {}".format(wr),
        "-wn {}".format(wn),
        "-wd {}".format(wd),
        "-tol {}".format(tol),
    ]

    mcsqs_find_sqs_processes = []
    if instances and instances > 1:
        # if multiple instances, run a range of commands using "-ip"
        for i in range(instances):
            instance_cmd = ["-ip {}".format(i + 1)]
            cmd = mcsqs_find_sqs_cmd + add_ons + instance_cmd
            p = Popen(cmd)
            mcsqs_find_sqs_processes.append(p)
    else:
        # run normal mcsqs command
        cmd = mcsqs_find_sqs_cmd + add_ons
        p = Popen(cmd)
        mcsqs_find_sqs_processes.append(p)

    try:
        for idx, p in enumerate(mcsqs_find_sqs_processes):
            p.communicate(timeout=search_time * 60)

        if instances and instances > 1:
            p = Popen(["mcsqs", "-best"])
            p.communicate()

        if os.path.exists("bestsqs.out") and os.path.exists("bestcorr.out"):
            return _parse_sqs_path(".")

        raise RuntimeError("mcsqs exited before timeout reached")

    except TimeoutExpired:
        for p in mcsqs_find_sqs_processes:
            p.kill()
            p.communicate()

        # Find the best sqs structures
        if instances and instances > 1:

            if not os.path.exists("bestcorr1.out"):
                raise RuntimeError(
                    "mcsqs did not generate output files, "
                    "is search_time sufficient or are number of instances too high?"
                )

            p = Popen(["mcsqs", "-best"])
            p.communicate()

        if os.path.exists("bestsqs.out") and os.path.exists("bestcorr.out"):
            sqs = _parse_sqs_path(".")
            return sqs

        os.chdir(original_directory)
        raise TimeoutError("Cluster expansion took too long.")
Example #20
0
def cry2cif(filename, to="cif", center=False, sortx=False, sortz=False,
            b_dum=50, c_dum=50, istruct=-1):
    """
    Read a CRYSTAL output file and return the structure in a cif or POSCAR format.

    Args:
        filename (str): crystal output filename
        to (str): 'cif' or 'vasp', format of the output file (default is cif)
        center (bool): if True, the slab or nanotube is translated to the center of
                       the box (default is False)
        sortx (bool): Nanotube : if True, atoms are sorted along x axes (default is False).
        sortz (bool): slab : if True, atoms are sorted along z axes (default is False).
        b_dum (float): dummy lattice paramters b in angstrom for nanotubes (default 50 A)
        c_dum (float): dummy lattice paramters c in angstrom for nanotubes and slabs (default 50 A)
        istruct (int): structure to be extracted

    """
    cryout = CrystalOutfile(filename)

    print("title      : ", cryout.title)
    if cryout.group:
        print("group      : ", cryout.group)

    # print("Number of structure read: ", len(cryout.structures))

    if istruct == -1:
        print("structure  : Final structure")
        structure = cryout.final_structure
    else:
        print("structure  : Structure %d" % istruct)
        structure = cryout.get_structure(istruct)
    print("# atom     : ", structure.num_sites)
    print("composition: ", structure.composition)
    print("Cell parameters:")
    print("a     : %10.4f" % structure.lattice.a)
    print("b     : %10.4f" % structure.lattice.b)
    print("c     : %10.4f" % structure.lattice.c)
    print("alpha : %10.4f" % structure.lattice.alpha)
    print("beta  : %10.4f" % structure.lattice.beta)
    print("gamma : %10.4f" % structure.lattice.gamma)

    # ----------------------------------------------------------
    #  New b and c axes
    # ----------------------------------------------------------
    if cryout.slab:
        frac_coords = structure.frac_coords
        frac_coords[:, 2] *= structure.lattice.c / c_dum
        matrix = structure.lattice.matrix
        matrix[2, 2] = c_dum
        structure = Structure(Lattice(matrix), structure.species, frac_coords)
    if cryout.nanotube:
        frac_coords = structure.frac_coords
        frac_coords[:, 1] *= structure.lattice.c / c_dum
        frac_coords[:, 2] *= structure.lattice.b / b_dum
        matrix = structure.lattice.matrix
        matrix[1, 1] = b_dum
        matrix[2, 2] = c_dum
        structure = Structure(Lattice(matrix), structure.species, frac_coords)

    # ----------------------------------------------------------
    #  move slab or nanotube to the center of the box
    # ----------------------------------------------------------
    if center:
        if cryout.slab:
            coords = structure.frac_coords.copy()
            coords[:, 2] += .5
            structure = Structure(structure.lattice, structure.species, coords)
        elif cryout.nanotube:
            coords = structure.frac_coords
            coords += .5
            structure = Structure(structure.lattice, structure.species, coords)

    # ----------------------------------------------------------
    #  sort atom along x or z axis for slab
    # ----------------------------------------------------------
    if sortz:
        isort = 2
    elif sortx:
        isort = 0

    axes = {2: "z", 0: "x"}
    if sortz or sortx:
        print("\nSort atoms along %s" % axes[isort])
        data = zip(structure.species, structure.coords)
        data = sorted(data, key=lambda d: d[-1][isort], reverse=True)

        species = [d[0] for d in data]
        coords = [d[1] for d in data]
        structure = Structure(structure.lattice, species, coords)

    # ----------------------------------------------------------
    # export in the given format
    # ----------------------------------------------------------
    basename, _ = os.path.splitext(filename)
    if to.lower() == "cif":
        ext = ".cif"
    elif to.lower() == "vasp":
        to = "POSCAR"
        ext = ".vasp"
    else:
        to = "POSCAR"
        ext = ".vasp"
    structure.to(to, filename=basename + ext)
Example #21
0
#%%

from pymatgen import Molecule, Structure
import os
import numpy as np
from pymatgen.core.lattice import Lattice

os.chdir('/home/jinho93/oxides/perobskite/lanthanum-aluminate/slab/nvt.para.6/island/len-19/step1')

s = Molecule.from_file('POSCAR.xyz')
sp = []
coords = []
for i in s.sites:
    if i.x < 7 and i.y < 7:
        sp.append(i.specie)
        coords.append(i.coords)
        
new = Structure(Lattice(np.identity(3) * 7.648200),sp, coords, coords_are_cartesian=True)
new.to('POSCAR', 'ini_pot/reduced')

# %%

#%%

from pymatgen.command_line.gulp_caller import GulpIO
gio = GulpIO()
gio.buckingham_input(new, keywords=['conv'], uc=False)

# %%
Example #22
0
def ripple(structs,
           fnames,
           supercell,
           strain_range,
           atom_index,
           auto_fix,
           margin_dist=1.0):
    '''
    build ripple structures and strained ones 

    Args:
        structs: list of Structure obj.
        fnames: list of str for input file name.
        supercell: list, used to build supercell along x or y direction.
        strain_range: list of strain 
        atom_index: int , specify which atom will be constrained
        auto_fix: boolean, whether decide which atoms to be constrained automaticly
        margin_dist: float,
    Returns:
        None
    Output:
        0.04000_wo_xxxx.vasp  
        0.04000_w_xxxx.vasp
    '''
    for struct, fname in zip(structs, fnames):
        if not struct.lattice.is_orthogonal:
            warn_tip(0, "{} is not orthogonal, skip it !!!".format(fname))
            continue
        struct_sc = struct.copy()
        struct_sc.make_supercell(supercell)
        natom = struct_sc.num_sites
        min_z = np.min(struct_sc.cart_coords[:, 2])
        tmp_coords = np.ones((struct_sc.num_sites, 1)) * min_z
        cart_coords = struct_sc.cart_coords
        cart_coords[:, 2] = cart_coords[:, 2] - tmp_coords.T + 0.01
        frac_coords_new = np.dot(
            cart_coords, np.linalg.inv(struct_sc.lattice.matrix.copy()))
        for i_strain in strain_range:
            new_lat_matrix = struct_sc.lattice.matrix.copy()
            new_lat_matrix[direction, direction] = struct_sc.lattice.matrix[
                direction, direction] * (1 - i_strain)
            # structure only applied with in-plan strain
            filename = "%10.5f" % (i_strain) + '_wo_' + fname + '.vasp'
            struct_wo_ripple = Structure(new_lat_matrix, struct_sc.species,
                                         frac_coords_new)
            struct_wo_ripple.to(filename=filename.strip(), fmt='poscar')
            frac_coords_new_cp = struct_wo_ripple.frac_coords.copy()
            cart_coords_new_cp = struct_wo_ripple.cart_coords.copy()
            nz = 0
            selective_dynamics = [[True for col in range(3)]
                                  for row in range(natom)]
            z_shift = np.zeros((natom, 3))
            for i_atom in range(natom):
                #To do : z_shit should support more function
                z_shift[i_atom,
                        2] = 40 * (2 * i_strain - 10 * i_strain**2) * np.sin(
                            cart_coords_new_cp[i_atom, direction] * np.pi /
                            new_lat_matrix[direction, direction])
                if cart_coords_new_cp[i_atom,
                                      direction] < nz or cart_coords_new_cp[
                                          i_atom, direction] > new_lat_matrix[
                                              direction, direction] - nz:
                    z_shift[i_atom, 2] = 0.0

                if auto_fix:
                    if struct_wo_ripple[i_atom].coords[direction]<margin_dist or \
                       struct_wo_ripple[i_atom].coords[direction] > new_lat_matrix[direction,direction]-margin_dist:
                        selective_dynamics[i_atom] = [False, False, False]
                else:
                    if i_atom in atom_index:
                        selective_dynamics[i_atom] = [False, False, False]

            struct_w_ripple=Structure(new_lat_matrix,struct_sc.species,cart_coords_new_cp+z_shift,coords_are_cartesian=True,\
                                     site_properties={'selective_dynamics':selective_dynamics})
            # structure  applied with in-plan strain  and ripple
            filename = "%10.5f" % (i_strain) + '_w_' + fname + '.vasp'
            struct_w_ripple.to(filename=filename.strip(), fmt='poscar')
Example #23
0
# ax1.set_xlim((120,140))

# %%
from pymatgen.io.vasp import Xdatcar

xdat = Xdatcar.from_file('XDATCAR')

xdat.structures[70].to('POSCAR', 'NEWPOSCAR')

# %%
from pymatgen import Structure
coords = []
s: Structure
for s in xdat.structures[70:]:
    coords.append(s.frac_coords)
    
coords = np.array(coords)
#%%
aver = np.sum(coords, axis=0) / coords.shape[0]
print(aver.shape)
poscar = Structure.from_file('POSCAR')
new = Structure(poscar.lattice, poscar.species, aver)
new.to('POSCAR', 'NEWPOSCAR')
# np.sum(coords)
# %%
new = dip[loop]
new = new[280:]
plt.scatter(range(len(new)), new)
# %%