예제 #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
예제 #2
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
예제 #3
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