Ejemplo n.º 1
0
def calc_cells_dispmats(n):
    """
    Computes the correspondence between the SPOSCAR in the thirdorder
    convention and the one in the generate_conf convention.
    """
    poscar = generate_conf.read_POSCAR("POSCAR")
    sposcar = thirdorder_common.gen_SPOSCAR(poscar, n[0], n[1], n[2])
    sposcar2 = generate_conf.read_POSCAR("SPOSCAR")
    natoms = poscar["numbers"].sum()
    ncells = n[0] * n[1] * n[2]
    corresp = calc_corresp(poscar, sposcar, [n[0], n[1], n[2]])
    corresp2 = calc_corresp(poscar, sposcar2, [n[0], n[1], n[2]])
    print("corresp: " + str(corresp))
    print("corresp2: " + str(corresp2))
    M = np.zeros((ncells, natoms * ncells, natoms * ncells))
    for icell in range(ncells):
        for iatom in range(natoms * ncells):
            nacell, nbcell, nccell = np.unravel_index(icell,
                                                      (n[0], n[1], n[2]))
            i1cell, na1cell, nb1cell, nc1cell = corresp[iatom]
            jatom = corresp2.index([
                i1cell, (na1cell + nacell) % n[0], (nb1cell + nbcell) % n[1],
                (nc1cell + nccell) % n[2]
            ])
            M[icell, iatom, jatom] = 1.
    np.set_printoptions(threshold=sys.maxsize)
    N = np.zeros((ncells * natoms, ncells * natoms))
    for iatom in range(natoms * ncells):
        i1cell, na1cell, nb1cell, nc1cell = corresp2[iatom]
        icell = np.ravel_multi_index((na1cell, nb1cell, nc1cell),
                                     (n[0], n[1], n[2]))
        N[iatom, icell * natoms + i1cell] = 1.
    return M, N
Ejemplo n.º 2
0
def calc_kinetic_term(iteration_min, weights):
    """
    Computes the kinetic contribution to pressure from a virial-like expression
    """
    conn = sqlite3.connect("QSCAILD.db")
    cur = conn.cursor()
    cur.execute(
        "SELECT id, displacements, forces, iteration FROM configurations"
        " WHERE iteration >=?", (iteration_min, ))
    config = cur.fetchall()
    conn.commit()
    conn.close()
    sposcar = generate_conf.read_POSCAR("SPOSCAR_CURRENT")
    newweights = weights.reshape((len(config), -1))[:, 0]
    newweights = newweights / np.sum(newweights)
    nruter = -np.sum(np.array([
        np.sum(10. * (np.array(json.loads(c[1])) + np.ravel(
            np.dot(
                generate_conf.read_POSCAR("SPOSCAR_" + str(c[3]))["lattvec"],
                generate_conf.read_POSCAR("SPOSCAR_" +
                                          str(c[3]))["positions"]) -
            np.dot(sposcar["lattvec"], sposcar["positions"]))).reshape(-1, 3) *
               (np.array(json.loads(c[2])).reshape(-1, 3)),
               axis=0) for c in config
    ]) * newweights[:, np.newaxis],
                     axis=0)
    return nruter / abs(np.linalg.det(
        sposcar["lattvec"] * 10.)) * codata.e * 1e30 * 1e-8
Ejemplo n.º 3
0
def prepare_fit_3rd_weights(mat_rec_ac, mat_rec_ac_3rd, M, N, enforce_acoustic,
                            iteration_min):
    """
    Prepare the input for the fit for a 2nd and 3rd order effective
    Hamiltonian.
    """

    xdata, ydata, weights = prepare_fit_weights(mat_rec_ac, enforce_acoustic,
                                                iteration_min)
    print("finished preparing 2nd order part of the fit")

    conn = sqlite3.connect("QSCAILD.db")
    cur = conn.cursor()
    cur.execute(
        "SELECT id, displacements, iteration "
        "FROM configurations WHERE iteration >=?", (iteration_min, ))
    config = cur.fetchall()
    conn.commit()
    conn.close()

    sposcar = generate_conf.read_POSCAR("SPOSCAR_CURRENT")

    print("start preparing 3rd order part")
    xdata_3rd = []
    natoms = int(len(json.loads(config[0][1])) / 3)
    for k in range(mat_rec_ac_3rd.shape[0]):
        print("preparing data number " + str(k))
        xdata_int = []
        fcs_3rd_full = mat_rec_ac_3rd[k]
        for c in config:
            sposcar_old = generate_conf.read_POSCAR("SPOSCAR_" + str(c[2]))
            newdisp = np.array(json.loads(c[1])) + np.ravel(
                np.dot(sposcar_old["lattvec"], sposcar_old["positions"]) -
                np.dot(sposcar["lattvec"], sposcar["positions"]))
            xdata_int.append(calc_3rd_forces(fcs_3rd_full, M, N, newdisp))

        if enforce_acoustic:
            for alpha in range(3):
                disp = np.zeros((natoms, 3))
                disp[:, alpha] = 0.01 * np.ones(natoms).T
                xdata_int.append(
                    calc_3rd_forces(fcs_3rd_full, M, N, np.ravel(disp)))

        xdata_3rd.append(np.ravel(xdata_int))
    xdata_3rd = np.concatenate((xdata, np.transpose(np.array(xdata_3rd))),
                               axis=1)

    return [xdata_3rd, ydata, weights]
Ejemplo n.º 4
0
def read_3rd_fcs_asinfile(fcs_file, poscar_file):
    """
    Read a set of anharmonic force constants from a file.
    """
    poscar = generate_conf.read_POSCAR(poscar_file)
    lattvec = poscar["lattvec"] * 10.
    fcs_3rd = []
    atom_info = []
    R_j = []
    R_k = []
    abc = []
    with open(fcs_file, "r") as f:
        nblocks = int(next(f).strip())
        tmp = np.empty((3, 2))
        for iblock in range(nblocks):
            next(f)
            next(f)
            tmp[:, 0] = [float(i) for i in next(f).split()]
            tmp[:, 1] = [float(i) for i in next(f).split()]
            Rj = np.round(sp.linalg.solve(lattvec, tmp[:, 0]))
            Rk = np.round(sp.linalg.solve(lattvec, tmp[:, 1]))
            ijk = [int(i) - 1 for i in next(f).split()]
            for il in range(27):
                fields = next(f).split()
                c1, c2, c3 = [int(i) - 1 for i in fields[:3]]
                atom_info.append(ijk)
                R_j.append(Rj)
                R_k.append(Rk)
                abc.append([c1, c2, c3])
                fcs_3rd.append(float(fields[3]))
    return np.array(fcs_3rd), np.array(atom_info), np.array(R_j), np.array(
        R_k), np.array(abc)
Ejemplo n.º 5
0
def read_FORCE_CONSTANTS(sposcar_file, fcs_file):
    """
    Read and return the information contained in a FORCE_CONSTANTS
    file, which must correspond to the provided sposcar object.
    """

    #in phonopy comments:
    #force_constants[ i, j, a, b ]
    #  i: Atom index of finitely displaced atom.
    #  j: Atom index at which force on the atom is measured.
    #  a, b: Cartesian direction indices = (0, 1, 2) for i and j, respectively

    sposcar = generate_conf.read_POSCAR(sposcar_file)
    with open(fcs_file, "r") as f:
        n = int(next(f).strip())
        nsatoms = len(sposcar["types"])
        if n != nsatoms:
            raise ValueError(
                "file {} does not match the provided SPOSCAR object".format(
                    fcs_file))
        fullmatrix = np.empty((nsatoms, nsatoms, 3, 3))
        for iat1 in range(nsatoms):
            for iat2 in range(nsatoms):
                p1, p2 = [int(i) for i in next(f).split()]
                if p1 != iat1 + 1 or p2 != iat2 + 1:
                    raise ValueError(
                        "invalid index in file {}".format(fcs_file))
                for icoord in range(3):
                    fullmatrix[iat1, iat2, icoord, :] = [
                        float(j) for j in next(f).split()
                    ]
    return fullmatrix
Ejemplo n.º 6
0
def save_symmetry_information_3rd(n3rdorder, third, symm_acoustic=True):
    """
    Computes and saves the 2nd and 3rd order symmetry matrices.
    """
    (natoms, crotations, equivalences, kernels, irreducible,
     todo) = get_symmetry_information("SPOSCAR")
    if (symm_acoustic):
        ker_ac, nirr_ac = acoustic_sum_rule(natoms, crotations, equivalences,
                                            kernels, irreducible, todo)
    else:
        nirr_ac = len(todo)
        ker_ac = np.identity(nirr_ac)
    mat_rec_ac = [
        reconstruct_fc_acoustic(
            natoms, ker_ac, np.array([int(j == k) for j in range(nirr_ac)]),
            crotations, equivalences, kernels, irreducible, symm_acoustic)
        for k in range(nirr_ac)
    ]
    np.save(
        "../mat_rec_ac_2nd_" + str(n3rdorder[0]) + "x" + str(n3rdorder[1]) +
        "x" + str(n3rdorder[2]) + ".npy", mat_rec_ac)
    if not third:
        return
    poscar = generate_conf.read_POSCAR("POSCAR")
    sposcar = thirdorder_common.gen_SPOSCAR(poscar, n3rdorder[0], n3rdorder[1],
                                            n3rdorder[2])
    if (symm_acoustic):
        (ker_ac_3rd, nirr_ac_3rd, wedge, list4, dmin, nequi, shifts,
         frange) = thirdorder_save.save("save_sparse", n3rdorder[0],
                                        n3rdorder[1], n3rdorder[2],
                                        n3rdorder[3])
        with open('out_sym', 'a') as file:
            file.write("3rd order number of irreducible elements after " +
                       "acoustic sum rule: " + str(nirr_ac_3rd) + "\n")
        np.save(
            "../ker_ac_3rd_" + str(n3rdorder[0]) + "x" + str(n3rdorder[1]) +
            "x" + str(n3rdorder[2]) + "_" + str(n3rdorder[3]) + ".npy",
            ker_ac_3rd)
    else:
        wedge, list4, dmin, nequi, shifts, frange = thirdorder_save.save(
            "return", n3rdorder[0], n3rdorder[1], n3rdorder[2], n3rdorder[3])
        nirr_ac_3rd = 0
        for ii in range(wedge.nlist):
            print("nindependentbasis: " + str(wedge.nindependentbasis[ii]))
            nirr_ac_3rd += wedge.nindependentbasis[ii]
        with open('out_sym', 'a') as file:
            file.write("3rd order number of irreducible elements without" +
                       " acoustic sum rule: " + str(nirr_ac_3rd) + "\n")
        ker_ac_3rd = np.identity(nirr_ac_3rd)
    mat_rec_ac_3rd = calc_mat_rec_ac_3rd(poscar, sposcar, ker_ac_3rd,
                                         nirr_ac_3rd, wedge, list4, n3rdorder,
                                         symm_acoustic)
    np.save(
        "../mat_rec_ac_3rd_" + str(n3rdorder[0]) + "x" + str(n3rdorder[1]) +
        "x" + str(n3rdorder[2]) + "_" + str(n3rdorder[3]) + ".npy",
        mat_rec_ac_3rd)
    return
Ejemplo n.º 7
0
def calc_energy_pressure(f_grun, m_grun, T, poscar_file):
    """
    Calculate the energy associated to the pressure estimated from the
    Gruneisen parameters.
    """
    poscar = generate_conf.read_POSCAR(poscar_file)
    nBE = np.array([fBE(f, T) + 0.5 for f in f_grun])
    nmodes = poscar["numbers"].sum() * 3.
    volume = abs(np.linalg.det(poscar["lattvec"] * 10.))
    return nmodes * np.mean(codata.h * m_grun * 1e12 *
                            nBE[:, np.newaxis]) / volume * 1e30 * 1e-8 / 3.
Ejemplo n.º 8
0
def write_displacement_matrix(poscar_file, fcs_file, T, n, use_smalldisp,
                              imaginary_freq, grid):
    """
    Write the displacement matrix depending of T, force constants and
    structure, integrated over the Brillouin zone.
    """

    SYMPREC = 1e-5
    NQ = grid

    if not os.path.isfile(poscar_file):
        sys.exit("The specified POSCAR file does not exist.")
    na, nb, nc = [int(i) for i in n]
    if min(na, nb, nc) < 1:
        sys.exit("All dimensions must be positive integers")

    poscar = generate_conf.read_POSCAR(poscar_file)
    natoms = poscar["numbers"].sum()
    ntot = na * nb * nc * natoms
    nmodes = 3 * natoms
    ncells = na * nb * nc
    matrix = np.zeros((ncells * nmodes, ncells * nmodes), dtype=np.complex128)
    local_matrix = np.zeros((ncells * nmodes, ncells * nmodes),
                            dtype=np.complex128)

    if use_smalldisp:
        for idiag in range(ncells * nmodes):
            matrix[idiag, idiag] = 0.000001
        return matrix

    if not os.path.isfile(fcs_file):
        sys.exit("The specified FORCE_CONSTANTS file does not exist.")

    supercell_matrix = np.diag([na, nb, nc])

    structure = phonopy.interface.read_crystal_structure(poscar_file,
                                                         "vasp")[0]
    fc = phonopy.file_IO.parse_FORCE_CONSTANTS(fcs_file)

    phonon = phonopy.Phonopy(
        structure,
        supercell_matrix,
        primitive_matrix=None,
        factor=phonopy.units.VaspToTHz,
        dynamical_matrix_decimals=None,
        force_constants_decimals=None,
        symprec=SYMPREC,
        is_symmetry=True,
        log_level=0)
    if os.path.isfile("BORN"):
        nac_params = phonopy.file_IO.get_born_parameters(
            open("BORN"), phonon.get_primitive(),
            phonon.get_primitive_symmetry())
        phonon.set_nac_params(nac_params=nac_params)

    phonon.set_force_constants(fc)

    masses = phonon.get_supercell().get_masses(
    ) * codata.physical_constants["atomic mass constant"][0]

    qpoints = create_mesh(NQ)
    nqpoints = qpoints.shape[0]

    # Initializations and preliminaries
    comm = MPI.COMM_WORLD  # get MPI communicator object
    size = comm.size  # total number of processes
    rank = comm.rank  # rank of this process

    full_qlist = list(range(nqpoints))
    qlist = full_qlist[rank::size]

    for qpt in qlist:
        local_matrix += qpoint_worker((qpoints[qpt, :], phonon, T, na, nb, nc,
                                       imaginary_freq, poscar["positions"]))

    # Reduce all qpoints
    comm.Reduce(local_matrix, matrix, op=MPI.SUM, root=0)

    if rank == 0:
        matrix *= codata.hbar / 2. / nqpoints / 2. / np.pi / 1e12  # m**2
        for i, j in itertools.product(
                range(ncells * nmodes), range(ncells * nmodes)):
            matrix[i, j] /= np.sqrt(masses[i // 3] * masses[j // 3])

        matrix = 1e18 * matrix.real  # nm**2
    comm.Barrier()
    return matrix
Ejemplo n.º 9
0
def write_displacement_matrix_gamma(sposcar_file, fcs_file, T, n,
                                    use_smalldisp, imaginary_freq):
    """
    Writes the displacement matrix depending of T, force constants and
    structure, using only the gamma-point of the supercell.
    """

    SYMPREC = 1e-5

    if not os.path.isfile(sposcar_file):
        sys.exit("The specified POSCAR file does not exist.")
    na, nb, nc = [1, 1, 1]

    poscar = generate_conf.read_POSCAR(sposcar_file)
    natoms = poscar["numbers"].sum()
    ntot = na * nb * nc * natoms
    nmodes = 3 * natoms
    ncells = na * nb * nc
    matrix = np.zeros((ncells * nmodes, ncells * nmodes), dtype=np.complex128)

    if use_smalldisp:
        for idiag in range(ncells * nmodes):
            matrix[idiag, idiag] = 0.000001
        return matrix

    if not os.path.isfile(fcs_file):
        sys.exit("The specified FORCE_CONSTANTS file does not exist.")

    supercell_matrix = np.diag([na, nb, nc])

    structure = phonopy.interface.read_crystal_structure(sposcar_file,
                                                         "vasp")[0]
    fc = phonopy.file_IO.parse_FORCE_CONSTANTS(fcs_file)

    phonon = phonopy.Phonopy(
        structure,
        supercell_matrix,
        primitive_matrix=None,
        factor=phonopy.units.VaspToTHz,
        dynamical_matrix_decimals=None,
        force_constants_decimals=None,
        symprec=SYMPREC,
        is_symmetry=True,
        log_level=0)
    if os.path.isfile("BORN"):
        nac_params = phonopy.file_IO.get_born_parameters(
            open("BORN"), phonon.get_primitive(),
            phonon.get_primitive_symmetry())
        phonon.set_nac_params(nac_params=nac_params)

    phonon.set_force_constants(fc)

    masses = phonon.get_supercell().get_masses(
    ) * codata.physical_constants["atomic mass constant"][0]

    nqpoints = 1
    print("nqpoints: " + repr(nqpoints))

    matrix = qpoint_worker(([0., 0., 0.], phonon, T, na, nb, nc,
                            imaginary_freq, poscar["positions"]))

    matrix *= codata.hbar / 2. / nqpoints / 2. / np.pi / 1e12  # m**2
    for i, j in itertools.product(
            range(ncells * nmodes), range(ncells * nmodes)):
        matrix[i, j] /= np.sqrt(masses[i // 3] * masses[j // 3])

    matrix = 1e18 * matrix.real  # nm**2
    return matrix
Ejemplo n.º 10
0
def write_mode_gruneisen_gamma(poscar_file, sposcar_file, n, fcs_file,
                               fcs_3rd_file, imaginary_freq, filename):
    """
    Write the gruneisen parameters depending of T, force constants and
    structure, using only the gamma point of the supercell.
    """

    SYMPREC = 1e-5
    NQ = 1

    if not os.path.isfile(poscar_file):
        sys.exit("Gruneisen: the specified POSCAR file does not exist.")

    poscar = generate_conf.read_POSCAR(poscar_file)
    sposcar = generate_conf.read_POSCAR(sposcar_file)
    corresp = symmetry.calc_corresp(poscar, sposcar, n)
    ncells = n[0] * n[1] * n[2]
    natoms = poscar["numbers"].sum()
    nmodes = 3 * natoms * ncells

    supercell_matrix = np.diag([1, 1, 1])

    if not os.path.isfile(fcs_file):
        sys.exit("The specified FORCE_CONSTANTS file does not exist.")
    if not os.path.isfile(fcs_3rd_file):
        sys.exit("The specified FORCE_CONSTANTS_3RD file does not exist.")

    fcs_3rd, atom_info, R_j, R_k, abc = read_3rd_fcs_asinfile(
        fcs_3rd_file, poscar_file)
    nblocks = len(fcs_3rd)
    poscar_positions = sp.dot(poscar["lattvec"], poscar["positions"]).T * 10.
    cartesian_positions = np.array([
        sp.dot(poscar["lattvec"], R_k[iblock])[abc[iblock, 2]] * 10. +
        poscar_positions[atom_info[iblock, 2], abc[iblock, 2]]
        for iblock in range(nblocks)
    ])

    structure = phonopy.interface.read_crystal_structure(sposcar_file,
                                                         "vasp")[0]
    fc = phonopy.file_IO.parse_FORCE_CONSTANTS(fcs_file)

    phonon = phonopy.Phonopy(structure,
                             supercell_matrix,
                             primitive_matrix=None,
                             factor=phonopy.units.VaspToTHz,
                             dynamical_matrix_decimals=None,
                             force_constants_decimals=None,
                             symprec=SYMPREC,
                             is_symmetry=True,
                             log_level=0)
    if os.path.isfile("BORN"):
        nac_params = phonopy.file_IO.get_born_parameters(
            open("BORN"), phonon.get_primitive(),
            phonon.get_primitive_symmetry())
        phonon.set_nac_params(nac_params=nac_params)

    phonon.set_force_constants(fc)

    masses = phonon.get_unitcell().get_masses()
    massesi = np.array([
        masses[corresp.index([atom_info[iblock, 0], 0, 0, 0])]
        for iblock in range(nblocks)
    ])
    massesj = np.array([
        masses[corresp.index([atom_info[iblock, 1], 0, 0, 0])]
        for iblock in range(nblocks)
    ])

    print("nqpoints: " + str(NQ))
    mesh = [[0., 0., 0.]]

    w_grun = []
    m_grun = []
    f_grun = []
    tot_cv = 0.
    r = range(nmodes)
    for q in mesh:
        f, psi = phonon.get_frequencies_with_eigenvectors(q)
        factorj = 1.0
        for im in r:
            if (f[im] < -1.e-4):
                print("ATTENTION: IMAGINARY FREQUENCIES ->"
                      " CONVERTED TO POSITIVE VALUE")
                if imaginary_freq == -1:
                    f[im] = abs(f[im])
                else:
                    f[im] = imaginary_freq
            if (f[im] > 1.e-4):
                lpsi = psi[:, im].reshape(-1, 3)
                psii = np.conj(
                    np.array([
                        lpsi[corresp.index([atom_info[iblock, 0], 0, 0, 0]),
                             abc[iblock, 0]] for iblock in range(nblocks)
                    ]))
                psij = np.array([
                    lpsi[corresp.index([
                        atom_info[iblock, 1], R_j[iblock, 0] %
                        n[0], R_j[iblock, 1] % n[1], R_j[iblock, 2] % n[2]
                    ]), abc[iblock, 1]] for iblock in range(nblocks)
                ])
                m_gruni = mode_gruneisen(f[im], psii, psij, massesi, massesj,
                                         cartesian_positions, fcs_3rd,
                                         factorj).real * ncells
                m_grun.append(m_gruni)
                f_grun.append(f[im])
            else:
                m_grun.append(np.array([0., 0., 0.]))
                f_grun.append(f[im])

    with open(filename, 'w') as f:
        for i in range(len(f_grun)):
            f.write(
                str(f_grun[i]) + '  ' + str(m_grun[i][0]) + '  ' +
                str(m_grun[i][1]) + '  ' + str(m_grun[i][2]) + '\n')

    m_grun = np.array(m_grun)
    f_grun = np.array(f_grun)
    return f_grun, m_grun
Ejemplo n.º 11
0
def write_mode_gruneisen(poscar_file, n, fcs_file, fcs_3rd_file,
                         imaginary_freq, grid, filename):
    """
    Write the gruneisen parameters depending of T, force constants and
    structure, in the whole Brillouin zone.
    """
    SYMPREC = 1e-5

    if not os.path.isfile(poscar_file):
        sys.exit("Gruneisen: the specified POSCAR file does not exist.")

    poscar = generate_conf.read_POSCAR(poscar_file)
    ncells = n[0] * n[1] * n[2]
    natoms = poscar["numbers"].sum()
    nmodes = 3 * natoms

    supercell_matrix = np.diag([n[0], n[1], n[2]])

    if not os.path.isfile(fcs_file):
        sys.exit("The specified FORCE_CONSTANTS file does not exist.")
    if not os.path.isfile(fcs_3rd_file):
        sys.exit("The specified FORCE_CONSTANTS_3RD file does not exist.")

    fcs_3rd, atom_info, R_j, R_k, abc = read_3rd_fcs_asinfile(
        fcs_3rd_file, poscar_file)
    nblocks = len(fcs_3rd)
    poscar_positions = sp.dot(poscar["lattvec"], poscar["positions"]).T * 10.
    cartesian_positions = np.array([
        sp.dot(poscar["lattvec"], R_k[iblock])[abc[iblock, 2]] * 10. +
        poscar_positions[atom_info[iblock, 2], abc[iblock, 2]]
        for iblock in range(nblocks)
    ])

    structure = phonopy.interface.read_crystal_structure(poscar_file,
                                                         "vasp")[0]
    fc = phonopy.file_IO.parse_FORCE_CONSTANTS(fcs_file)

    phonon = phonopy.Phonopy(structure,
                             supercell_matrix,
                             primitive_matrix=None,
                             factor=phonopy.units.VaspToTHz,
                             dynamical_matrix_decimals=None,
                             force_constants_decimals=None,
                             symprec=SYMPREC,
                             is_symmetry=True,
                             log_level=0)
    if os.path.isfile("BORN"):
        nac_params = phonopy.file_IO.get_born_parameters(
            open("BORN"), phonon.get_primitive(),
            phonon.get_primitive_symmetry())
        phonon.set_nac_params(nac_params=nac_params)

    phonon.set_force_constants(fc)

    masses = phonon.get_unitcell().get_masses()
    massesi = masses[atom_info[:, 0]]
    massesj = masses[atom_info[:, 1]]

    NQ = grid
    mesh = create_mesh(NQ)
    nqpoints = mesh.shape[0]

    m_grun = []
    f_grun = []
    r = range(nmodes)

    # Initializations and preliminaries
    comm = MPI.COMM_WORLD  # get MPI communicator object
    size = comm.size  # total number of processes
    rank = comm.rank  # rank of this process

    # Scatter qpoints across cores.
    full_qlist = list(range(nqpoints))
    qlist = full_qlist[rank::size]

    for qpt in qlist:
        q = mesh[qpt, :]
        f, psi = phonon.get_frequencies_with_eigenvectors(q)
        factor = np.exp(2j * np.pi * np.dot(q, poscar["positions"]))
        factorj = np.exp(2j * np.pi * np.dot(R_j, q))
        for im in r:
            if (f[im] < -1.e-4):
                print("ATTENTION: IMAGINARY FREQUENCIES ->"
                      " CONVERTED TO POSITIVE VALUE")
                if imaginary_freq == -1:
                    f[im] = abs(f[im])
                else:
                    f[im] = imaginary_freq
            if (f[im] > 1.e-4):
                lpsi = psi[:, im].reshape(-1, 3) * factor[:, np.newaxis]
                psii = np.conj(
                    np.array([
                        lpsi[atom_info[iblock, 0], abc[iblock, 0]]
                        for iblock in range(nblocks)
                    ]))
                psij = np.array([
                    lpsi[atom_info[iblock, 1], abc[iblock, 1]]
                    for iblock in range(nblocks)
                ])
                m_gruni = mode_gruneisen(f[im], psii, psij, massesi, massesj,
                                         cartesian_positions, fcs_3rd,
                                         factorj).real
                m_grun.append(m_gruni)
                f_grun.append(f[im])
            else:
                m_grun.append(np.array([0., 0., 0.]))
                f_grun.append(f[im])
    m_grun = np.array(m_grun)
    f_grun = np.array(f_grun)

    # Gather all qpoints
    m_grun = comm.gather(m_grun, root=0)
    f_grun = comm.gather(f_grun, root=0)

    if rank == 0:
        m_grun = np.concatenate(m_grun)
        f_grun = np.concatenate(f_grun)
        with open(filename, 'w') as f:
            for i in range(f_grun.shape[0]):
                f.write(
                    str(f_grun[i]) + '  ' + str(m_grun[i][0]) + '  ' +
                    str(m_grun[i][1]) + '  ' + str(m_grun[i][2]) + '\n')

    m_grun = comm.bcast(m_grun, root=0)
    f_grun = comm.bcast(f_grun, root=0)

    return f_grun, m_grun
Ejemplo n.º 12
0
def fit_force_constants(nconf, nfits, T, n, cutoff, third, use_pressure,
                        pressure, use_smalldisp, calc_symm, symm_acoustic,
                        imaginary_freq, enforce_acoustic, grid, tolerance,
                        pdiff, memory, mixing):
    """
    Main function that monitors the self-consistency loop.
    """

    iteration = 0
    write_gruneisen = False

    if not os.path.isfile("iteration"):
        iteration = 1
        if os.path.isfile("QSCAILD.db"):
            with open("finished", "w") as file:
                file.write(
                    "finished: error\n"
                    "Problem: no previous iteration but database already present,"
                    " remove file QSCAILD.db")
            comm.Abort()
            sys.exit(
                "Problem: no previous iteration but database already present,"
                " remove file QSCAILD.db")
        else:
            if rank == 0:
                shutil.copy("POSCAR", "POSCAR_CURRENT")
                shutil.copy("SPOSCAR", "SPOSCAR_CURRENT")
                print("Create table in database")
                conn = sqlite3.connect("QSCAILD.db")
                cur = conn.cursor()
                cur.execute(
                    "CREATE TABLE configurations (id integer, iteration"
                    " integer, displacements text, probability real,"
                    " current_proba real, forces text, energy real,"
                    " har_forces text, har_energy real)")
                conn.commit()
                conn.close()
                if calc_symm:
                    symmetry.save_symmetry_information_3rd(
                        [n[0], n[1], n[2], cutoff], third, symm_acoustic)
            renew_configurations(nconf, T, n, iteration, "POSCAR", "SPOSCAR",
                                 "FORCE_CONSTANTS", use_smalldisp,
                                 imaginary_freq, grid)
            comm.Barrier()
            if rank == 0:
                with open("iteration", "w") as f:
                    f.write(str(iteration) + "\n")
        return

    if rank == 0:
        with open("iteration", "r") as f:
            iteration = int(f.readline().split()[0])
        if not os.path.isfile("QSCAILD.db"):
            with open("finished", "w") as file:
                file.write(
                    "finished: error\n"
                    "Problem: previous iterations but no database is present,"
                    " remove file iteration")
            comm.Abort()
            sys.exit("Problem: previous iterations but no database is present,"
                     " remove file iteration")
        with open("out_energy", 'a') as file:
            file.write("iteration: " + str(iteration) + "\n")
        with open("out_fit", 'a') as file:
            file.write("iteration: " + str(iteration) + "\n")
        gradient.store_vasp_forces_energy(iteration)

        iteration_min = int(math.floor(iteration * (1.0 - memory)))
        if os.path.isfile("FORCE_CONSTANTS_CURRENT"):
            shutil.copy("FORCE_CONSTANTS_CURRENT", "FORCE_CONSTANTS_PREVIOUS")

        print("Load 2nd order symmetry information")
        mat_rec_ac = np.load("../mat_rec_ac_2nd_" + str(n[0]) + "x" +
                             str(n[1]) + "x" + str(n[2]) + ".npy", allow_pickle = True)
        nirr_ac = len(mat_rec_ac)
        poscar = generate_conf.read_POSCAR("POSCAR")

        natoms = poscar["numbers"].sum() * n[0] * n[1] * n[2]
        if third:
            sposcar = thirdorder_common.gen_SPOSCAR(poscar, n[0], n[1], n[2])
            print("Load 3rd order symmetry information")
            wedge, list4, dmin, nequi, shifts, frange = thirdorder_save.save(
                "return", n[0], n[1], n[2], cutoff)
            mat_rec_ac_3rd = np.load("../mat_rec_ac_3rd_" + str(n[0]) + "x" +
                                     str(n[1]) + "x" + str(n[2]) + "_" +
                                     str(cutoff) + ".npy", allow_pickle = True)[()]
            print(("shape: " + str(mat_rec_ac_3rd.shape)))
            if (symm_acoustic):
                ker_ac_3rd = np.load("../ker_ac_3rd_" + str(n[0]) + "x" +
                                     str(n[1]) + "x" + str(n[2]) + "_" +
                                     str(cutoff) + ".npy", allow_pickle = True)
            else:
                ker_ac_3rd = np.identity(mat_rec_ac_3rd.shape[0])
            M, N = symmetry.calc_cells_dispmats(n)

        if third:
            x_data, y_data, weights = gradient.prepare_fit_3rd_weights(
                mat_rec_ac, mat_rec_ac_3rd, M, N, enforce_acoustic,
                iteration_min)
        else:
            x_data, y_data, weights = gradient.prepare_fit_weights(
                mat_rec_ac, enforce_acoustic, iteration_min)

        clf = linear_model.LinearRegression(fit_intercept=False)
        clf.fit(x_data, y_data, weights)

        if third:
            coef_2nd = clf.coef_[:nirr_ac]
            coef_3rd = clf.coef_[nirr_ac:]
        else:
            coef_2nd = clf.coef_

        with open("out_fit", 'a') as file:
            file.write("fit 2nd: " + str(coef_2nd.tolist()) + "\n")
            if third:
                file.write("fit 3rd: " + str(coef_3rd.tolist()) + "\n")
            file.write("score: "+str(clf.score(x_data,y_data,weights))+"\n")
        force_constants = symmetry.reconstruct_fc_acoustic_frommat(
            mat_rec_ac, np.array(coef_2nd))
        gradient.print_FORCE_CONSTANTS(force_constants,
                                       "FORCE_CONSTANTS_FIT_" + str(iteration))
        if iteration == 1 and not use_smalldisp:
            force_constants = (
                1.0 - mixing
            ) * force_constants + mixing * gradient.read_FORCE_CONSTANTS(
                "SPOSCAR", "FORCE_CONSTANTS")
        elif not use_smalldisp:
            force_constants = (
                1.0 - mixing
            ) * force_constants + mixing * gradient.read_FORCE_CONSTANTS(
                "SPOSCAR_CURRENT", "FORCE_CONSTANTS_CURRENT")
        gradient.print_FORCE_CONSTANTS(force_constants,
                                       "FORCE_CONSTANTS_CURRENT")
        if third:
            phifull = symmetry.reconstruct_3rd_fcs(poscar, sposcar, ker_ac_3rd,
                                                   coef_3rd, wedge, list4,
                                                   symm_acoustic)
            thirdorder_common.write_ifcs(
                phifull, poscar, sposcar, dmin, nequi, shifts, frange,
                "FORCE_CONSTANTS_FIT_3RD_" + str(iteration))
            thirdorder_common.write_ifcs(phifull, poscar, sposcar, dmin, nequi,
                                         shifts, frange,
                                         "FORCE_CONSTANTS_CURRENT_3RD")

        poscar_current = generate_conf.read_POSCAR("POSCAR_CURRENT")
        sposcar_current = generate_conf.read_POSCAR("SPOSCAR_CURRENT")
        factor = np.array([1.0, 1.0, 1.0])

    os.sync()
    comm.Barrier()

    #Compute external pressure and updates lattice parameter if necessary
    if use_pressure in ['cubic', 'tetragonal', 'orthorombic']:

        if os.path.isfile("POSCAR_PARAM") and os.path.isfile(
                "SPOSCAR_PARAM") and rank == 0:
            poscar_param = generate_conf.read_POSCAR("POSCAR_PARAM")
            poscar_param["lattvec"] = poscar_current["lattvec"]
            generate_conf.write_POSCAR(poscar_param, "POSCAR_PARAM")
            sposcar_param = generate_conf.read_POSCAR("SPOSCAR_PARAM")
            sposcar_param["lattvec"] = sposcar_current["lattvec"]
            generate_conf.write_POSCAR(sposcar_param, "SPOSCAR_PARAM")

        if grid > 0 and write_gruneisen and third:
            f_grun, m_grun = gruneisen.write_mode_gruneisen(
                "POSCAR_CURRENT", n, "FORCE_CONSTANTS_CURRENT",
                "FORCE_CONSTANTS_CURRENT_3RD", imaginary_freq, grid,
                "mode_gruneisen")

        if rank == 0:

            if grid == 0 and write_gruneisen and third:
                f_grun, m_grun = gruneisen.write_mode_gruneisen_gamma(
                    "POSCAR_CURRENT", "SPOSCAR_CURRENT", n,
                    "FORCE_CONSTANTS_CURRENT", "FORCE_CONSTANTS_CURRENT_3RD",
                    imaginary_freq, "mode_gruneisen")

            if write_gruneisen and third:
                gruneisen.write_weighted_gruneisen(
                    f_grun, m_grun, [Ti * 100. for Ti in range(1, 16)],
                    "weighted_gruneisen")

            potential_pressure = np.diag(
                gradient.calc_mean_stress_weights(iteration_min, weights))
            kinetic_pressure = gradient.calc_kinetic_term(
                iteration_min, weights)
            mean_pressure = potential_pressure + kinetic_pressure

            for i in range(3):
                if (mean_pressure[i] > pressure[i] + pdiff / 2.):
                    factor[i] = 1. + 0.001 * (min(
                        (mean_pressure[i] - pressure[i]) / 10., 4.))
                elif (mean_pressure[i] < pressure[i] - pdiff / 2.):
                    factor[i] = 1. - 0.001 * (min(
                        (pressure[i] - mean_pressure[i]) / 10., 4.))

            #Symmetrize stress tensor
            if use_pressure == 'cubic':
                factor = np.array(
                    [np.mean(factor),
                     np.mean(factor),
                     np.mean(factor)])
            if use_pressure == 'tetragonal':
                factor = np.array([
                    0.5 * factor[0] + 0.5 * factor[1],
                    0.5 * factor[0] + 0.5 * factor[1], factor[2]
                ])

            if use_pressure == 'cubic':
                sposcar_current[
                    "lattvec"] = sposcar_current["lattvec"] * factor[0]
                poscar_current[
                    "lattvec"] = poscar_current["lattvec"] * factor[0]
            else:
                # Can only handle diagonal lattice vectors if the unit cell
                # is non-cubic
                for i in range(3):
                    sposcar_current["lattvec"][
                        i, i] = sposcar_current["lattvec"][i, i] * factor[i]
                    poscar_current["lattvec"][
                        i, i] = poscar_current["lattvec"][i, i] * factor[i]

            # Make parameter update of the poscar using non-harmonic part
            # of forces
            if os.path.isfile("POSCAR_PARAM") and os.path.isfile(
                    "SPOSCAR_PARAM"):
                param_grad = gradient.calc_delta_Ep_weights(
                    force_constants, sposcar_param, iteration_min, weights)
                with open("out_parameter", 'a') as file:
                    file.write("iteration: " + str(iteration) + "\n")
                    file.write("parameter gradient: " + str(param_grad) + "\n")
                poscar_current[
                    "positions"] -= poscar_param["positions"] * param_grad
                sposcar_current[
                    "positions"] -= sposcar_param["positions"] * param_grad

            generate_conf.write_POSCAR(poscar_current, "POSCAR_CURRENT")
            generate_conf.write_POSCAR(sposcar_current, "SPOSCAR_CURRENT")
            if use_pressure in ['cubic', 'tetragonal', 'orthorombic']:
                with open("out_volume", 'a') as file:
                    file.write("iteration: " + str(iteration) + "\n")
                    file.write("kinetic pressure: " +
                               str(kinetic_pressure.tolist()) + "\n")
                    file.write("potential pressure: " +
                               str(potential_pressure.tolist()) + "\n")
                    file.write("mean pressure: " +
                               str(mean_pressure.tolist()) + "\n")
                    file.write("lattice vectors: " +
                               str(poscar_current["lattvec"].tolist()) + "\n")
        else:
            mean_pressure = None
        mean_pressure = comm.bcast(mean_pressure, root=0)

    os.sync()
    iteration = comm.bcast(iteration, root=0)
    comm.Barrier()

    if iteration >= nfits:
        if rank == 0:
            with open("finished", "w") as file:
                file.write("finished: maximum iteration number\n")
        return

    if test_convergence(iteration, tolerance):
        if not use_pressure in ['cubic', 'tetragonal', 'orthorombic']:
            if rank == 0:
                with open("finished", "w") as file:
                    file.write("finished: obtained convergence\n")
            return
        elif np.amax(np.abs(mean_pressure - pressure)) < pdiff:
            if rank == 0:
                with open("finished", "w") as file:
                    file.write("finished: obtained convergence\n")
            return

    iteration += 1

    renew_configurations(nconf, T, n, iteration, "POSCAR_CURRENT",
                         "SPOSCAR_CURRENT", "FORCE_CONSTANTS_CURRENT",
                         use_smalldisp, imaginary_freq, grid)
    if rank == 0:
        with open("iteration", "w") as f:
            f.write(str(iteration) + "\n")
    return
Ejemplo n.º 13
0
def prepare_fit_weights(mat_rec_ac, enforce_acoustic, iteration_min):
    """
    Prepare the input for the fit for a 2nd order effective Hamiltonian.
    """

    conn = sqlite3.connect("QSCAILD.db")
    cur = conn.cursor()
    cur.execute(
        "SELECT id, displacements, forces, probability, current_proba,"
        " iteration FROM configurations WHERE iteration >=?",
        (iteration_min, ))
    config = cur.fetchall()
    conn.commit()
    conn.close()

    ydata = []
    xdata = []
    weights = []
    natoms = int(len(json.loads(config[0][1])) / 3)

    sposcar = generate_conf.read_POSCAR("SPOSCAR_CURRENT")

    for k in range(len(mat_rec_ac)):
        xdata_int = []
        for c in config:
            sposcar_old = generate_conf.read_POSCAR("SPOSCAR_" + str(c[5]))
            newdisp = np.array(json.loads(c[1])) + np.ravel(
                np.dot(sposcar_old["lattvec"], sposcar_old["positions"]) -
                np.dot(sposcar["lattvec"], sposcar["positions"]))
            disp = 10. * newdisp  ##Put displacements in Angstroms
            xdata_int.append(-mat_rec_ac[k].dot(disp))
        if enforce_acoustic:
            for alpha in range(3):
                disp = np.zeros((natoms, 3))
                disp[:, alpha] = 0.01 * np.ones(natoms).T
                xdata_int.append(-mat_rec_ac[k].dot(np.ravel(disp)))
        xdata.append(np.ravel(xdata_int))
    xdata = np.transpose(np.array(xdata))
    for c in config:
        ydata.append(np.ravel(np.array(json.loads(c[2]))))
        print("weight of config " + str(c[0]) + ": " +
              str(np.exp(c[4] - c[3])))
        weights.append(np.exp(c[4] - c[3]) * np.ones(natoms * 3))
    if enforce_acoustic:
        for alpha in range(3):
            ydata.append(np.zeros(natoms * 3))
            weights.append(10. * np.ones(natoms * 3))

    ydata = np.array(ydata)
    weights = np.array(weights)

    #   remove mean force where it is not zero by symmetry
    if os.path.isfile("POSCAR_PARAM") and os.path.isfile("SPOSCAR_PARAM"):
        sposcar_param = generate_conf.read_POSCAR("SPOSCAR_PARAM")
        cartesian_positions = np.ravel(
            sp.dot(sposcar_param["lattvec"], sposcar_param["positions"]).T *
            10.)
        mean_forces = np.sum(ydata * weights, axis=0) / np.sum(weights, axis=0)
        delta_Ep = np.mean(mean_forces * cartesian_positions)
        with np.errstate(divide='ignore', invalid='ignore'):
            symm_mean_force = np.divide(delta_Ep, cartesian_positions)
            symm_mean_force[~np.isfinite(symm_mean_force)] = 0

        with open("out_fit", "a") as file:
            file.write("mean_forces: " + str(mean_forces.tolist()) + "\n")
            file.write("symm_mean_force: " + str(symm_mean_force.tolist()) +
                       "\n")
        ydata -= symm_mean_force[np.newaxis, :]

    ydata = np.ravel(ydata)
    weights = np.ravel(weights)

    return [xdata, ydata, weights]