예제 #1
0
def test_gulp():
    # flake8: noqa
    from ase.calculators.gulp import GULP, Conditions
    from ase import Atoms
    import numpy as np

    cluster = Atoms(symbols='O4SiOSiO2SiO2SiO2SiOSiO2SiO3SiO3H8',
              pbc=np.array([False, False, False], dtype=bool),
              cell=np.array(
          [[ 0.,  0.,  0.],
           [ 0.,  0.,  0.],
           [ 0.,  0.,  0.]]),
              positions=np.array(
          [[-1.444348, -0.43209 , -2.054785],
           [-0.236947,  2.98731 ,  1.200025],
           [ 3.060238, -1.05911 ,  0.579909],
           [ 2.958277, -3.289076,  2.027579],
           [-0.522747,  0.847624, -2.47521 ],
           [-2.830486, -2.7236  , -2.020633],
           [-0.764328, -1.251141,  1.402431],
           [ 3.334801,  0.041643, -4.168601],
           [-1.35204 , -2.009562,  0.075892],
           [-1.454655, -1.985635, -1.554533],
           [ 0.85504 ,  0.298129, -3.159972],
           [ 1.75833 ,  1.256026,  0.690171],
           [ 2.376446, -0.239522, -2.881245],
           [ 1.806515, -4.484208, -2.686456],
           [-0.144193, -2.74503 , -2.177778],
           [ 0.167583,  1.582976,  0.47998 ],
           [-1.30716 ,  1.796853, -3.542121],
           [ 1.441364, -3.072993, -1.958788],
           [-1.694171, -1.558913,  2.704219],
           [ 4.417516,  1.263796,  0.563573],
           [ 3.066366,  0.49743 ,  0.071898],
           [-0.704497,  0.351869,  1.102318],
           [ 2.958884,  0.51505 , -1.556651],
           [ 1.73983 , -3.161794, -0.356577],
           [ 2.131519, -2.336982,  0.996026],
           [ 0.752313, -1.788039,  1.687183],
           [-0.142347,  1.685301, -1.12086 ],
           [ 2.32407 , -1.845905, -2.588202],
           [-2.571557, -1.937877,  2.604727],
           [ 2.556369, -4.551103, -3.2836  ],
           [ 3.032586,  0.591698, -4.896276],
           [-1.67818 ,  2.640745, -3.27092 ],
           [ 5.145483,  0.775188,  0.95687 ],
           [-2.81059 , -3.4492  , -2.650319],
           [ 2.558023, -3.594544,  2.845928],
           [ 0.400993,  3.469148,  1.733289]]))


    c = Conditions(cluster)
    c.min_distance_rule('O', 'H', 'O2', 'H', 'O1')
    cluster.calc = GULP(
        keywords='opti conp phon noden distance molq compare angle nono',
        shel=['O1','O2'],
        conditions=c)
    print(cluster.get_potential_energy())
예제 #2
0
def GULPRelaxation(inputStr):
    ##for gulp to work. gulp folder must be in the same folder as the script
    environ["GULP_LIB"] = "\"" + getcwd() + "/Gulp_40/Libraries/\""
    environ["ASE_GULP_COMMAND"] = "\"" + getcwd(
    ) + "/Gulp_40/Exe/gulp.exe\" < PREFIX.gin > PREFIX.got"

    ##takes string inputStr and turns it into stepNb, shouldRestartFromScratch listOfAtoms
    if len(inputStr) % 4 != 2:
        print("Args nb " + str(len(inputStr)))
        print(inputStr)
        print(
            "Not enough args. Args order : stepNb, shouldRestartFromScratch (0 or 1), \n atom list formatted as Name Xpos Ypos Zpos for each atom (example CO2 would be C 0 0 0 O 0 1 1 O 0 1 -1)"
        )
        return "", False

    atomNames = []
    atomXYZ = []

    stepNb = int(inputStr[0])
    shouldRestartFromScratch = int(inputStr[1])

    #if restart from scratch, destroy previously known trajectory
    if (shouldRestartFromScratch == 1):
        my_file = Path('tmp.pckl')
        if my_file.is_file():
            remove('tmp.pckl')

    #create Atoms object to optimize
    for i in range(0, math.floor(len(inputStr) / 4)):
        atomNames.append(inputStr[4 * i + 2])
        atomXYZ.append((float(inputStr[4 * i + 3]), float(inputStr[4 * i + 4]),
                        float(inputStr[4 * i + 5])))

    atoms = Atoms(atomNames, positions=atomXYZ)
    c = Conditions(atoms)

    #attach calculator
    calc = GULP(keywords='conp', library="./Gulp_40/Libraries/reaxff.lib")
    atoms.calc = calc
    calc.set(keywords='conp opti')

    #optimize
    opt = calc.get_optimizer(atoms)
    opt.run(fmax=0.05)

    #io.write('../MoleculeLibrary/tmp.xyz', atoms, format='xyz')

    pos = atoms.get_positions()
    outStr = ""

    for i in range(0, len(atomNames)):
        outStr += atomNames[i] + " "
        outStr += str(pos[i][0]) + " "
        outStr += str(pos[i][1]) + " "
        outStr += str(pos[i][2]) + " "

    return outStr, True
예제 #3
0
파일: gulp.py 프로젝트: shuchingou/ase
                                    [-0.144193, -2.74503, -2.177778],
                                    [0.167583, 1.582976, 0.47998],
                                    [-1.30716, 1.796853, -3.542121],
                                    [1.441364, -3.072993, -1.958788],
                                    [-1.694171, -1.558913, 2.704219],
                                    [4.417516, 1.263796, 0.563573],
                                    [3.066366, 0.49743, 0.071898],
                                    [-0.704497, 0.351869, 1.102318],
                                    [2.958884, 0.51505, -1.556651],
                                    [1.73983, -3.161794, -0.356577],
                                    [2.131519, -2.336982, 0.996026],
                                    [0.752313, -1.788039, 1.687183],
                                    [-0.142347, 1.685301, -1.12086],
                                    [2.32407, -1.845905, -2.588202],
                                    [-2.571557, -1.937877, 2.604727],
                                    [2.556369, -4.551103, -3.2836],
                                    [3.032586, 0.591698, -4.896276],
                                    [-1.67818, 2.640745, -3.27092],
                                    [5.145483, 0.775188, 0.95687],
                                    [-2.81059, -3.4492, -2.650319],
                                    [2.558023, -3.594544, 2.845928],
                                    [0.400993, 3.469148, 1.733289]]))

c = Conditions(cluster)
c.min_distance_rule('O', 'H', 'O2', 'H', 'O1')
cluster.set_calculator(
    GULP(keywords='opti conp phon noden distance molq compare angle nono',
         shel=['O1', 'O2'],
         conditions=c))
print(cluster.get_potential_energy())
예제 #4
0
def multi_stage_gulp_calc(structure,
                          num_calcs,
                          gulp_files,
                          main_keywords,
                          additional_keywords,
                          main_options,
                          additional_options,
                          max_gnorms,
                          gulp_shells=[],
                          gulp_library="",
                          gulp_conditions=None,
                          remove_vacancies=True):
    """
    Run a GULP calculation that consists of many stages, which can involve
    different keywords and options.

    Parameters
    ----------
    structure : ChemDASH structure
        The structure class containing ASE atoms object and properties.
    num_calcs : integer
        The number of GULP calculations to run
    gulp_files : string
        Name used for input and output files for each GULP calculation
    main_keywords : list
        List of GULP keywords. Default is "sing" for a single point energy
        calculation.
    additional_keywords : list
        List of extra GULP keywords for each calculation. Default is None
    main_options : list
        List of GULP options. Default is None
    additional_options : list
        List of extra GULP options for each calculation. Default is None
    max_gnorms : list
        List of maximum values of the final gnorm for each calculation.
    gulp_shells : dictionary, optional
        A dictionary with atom labels as keys and charges as values for each
        atomic species to have a shell attached.
    gulp_library : string, optional
        The library file containing the forcefield to be used in the calculation.
    gulp_conditions : ASE Conditions, optional
        The conditions used to determine the label given to particular atoms if
        the forcefield has different atom types.

    Returns
    -------
    atoms : ase atoms
        The structure after the split calculation.
    result : string
        The result of the GULP calculation,
        either "converged", "unconverged", "gulp failure", or "timed out"
    energy : float
        Energy of the structure in eV/atom.
    outcome : string
        GULP outcome of the final stage of this calculation.
    calc_time : float
        Time taken for this GULP calculation.
    potentials : float
        Site potentials for each atom.
    derivs : float
        Magnitude of the derivatives of the potential for each atom.

    ---------------------------------------------------------------------------
    Paul Sharp 28/01/2021
    """

    assert len(
        gulp_files
    ) >= num_calcs, 'ERROR in gulp_calc.multi_stage_gulp_calc() -- number of GULP calculations is set to {0:d}, but only {1:d} filenames are provided.'.format(
        num_calcs, len(gulp_files))
    assert len(
        additional_keywords
    ) >= num_calcs, 'ERROR in gulp_calc.multi_stage_gulp_calc() -- number of GULP calculations is set to {0:d}, but only {1:d} sets of additional keywords are provided.'.format(
        num_calcs, len(additional_keywords))
    assert len(
        additional_options
    ) >= num_calcs, 'ERROR in gulp_calc.multi_stage_gulp_calc() -- number of GULP calculations is set to {0:d}, but only {1:d} sets of additional options are provided.'.format(
        num_calcs, len(additional_options))

    gulp_start_time = time.time()

    failed_outcome = "Too many failed attempts to optimise "
    calc_files = {
        "input": "",
        "output": "",
        "restart": "",
    }

    structure.potentials = []
    structure.derivs = []

    # Strip out vacancies from the structure
    if remove_vacancies:
        vacancy_positions = determine_vacancy_positions(structure.atoms.copy())
        del structure.atoms[[
            atom.index for atom in structure.atoms if atom.symbol == "X"
        ]]

    if structure.labels is not None:
        gulp_conditions = Conditions(structure.atoms)
        gulp_conditions.atoms_labels = structure.labels

    for i in range(0, num_calcs):

        composite_keys = (main_keywords + " " + additional_keywords[i]).split()
        gulp_keywords = " ".join(
            sorted(set(composite_keys), key=composite_keys.index))

        composite_options = main_options + additional_options[i]
        composite_options.append("dump " + gulp_files[i] + ".res")
        gulp_options = list(
            sorted(set(composite_options), key=composite_options.index))

        structure.atoms, structure.energy, gnorm, result, calc_files = run_gulp(
            structure.atoms, gulp_files[i], calc_files["restart"],
            gulp_keywords, gulp_options, gulp_shells, gulp_library,
            gulp_conditions)

        # Continue only if the calculation was successfully performed without timing out
        if result == "timed out" or result == "gulp failure":

            outcome = result
            if os.path.isfile(calc_files["output"]):
                outcome = read_outcome(calc_files["output"])

            if outcome == "":
                outcome = "Bash timeout"

            break

        outcome = read_outcome(calc_files["output"])

        # We abandon the calculation if the outcome "Too many failed attempts to optimise" occurs,
        # the energy and gradient norm have blown up such that they are not representable as floats,
        # or the max gnorm for this calculation, if provided, is exceeded.

        # if (outcome == failed_outcome) or (not check_float(structureenergy)) or (not check_float(gnorm)):
        if (not check_float(structure.energy)) or (not check_float(gnorm)):
            result = "unconverged"
            break

        if isinstance(max_gnorms[i], float) and isinstance(gnorm, float):
            if gnorm > max_gnorms[i]:
                result = "unconverged"
                break

        # Update atoms object before continuing
        # This is necessary because of a bug in ASE, where it only updates atomic positions if they are given in cartesian coordinates
        try:
            structure.atoms, structure.energy = update_atoms_from_restart_file(
                structure.atoms, structure.energy, calc_files["restart"])
        except ValueError:
            result = "unconverged"
            break

    else:

        if os.path.isfile(calc_files["output"]):

            if any(pot_keyword in gulp_keywords
                   for pot_keyword in ["pot", "potential"]):
                structure.potentials, structure.derivs = read_potentials(
                    calc_files["output"])

            if check_convergence(calc_files["output"], gulp_keywords):
                result = "converged"
            else:
                result = "unconverged"

        else:
            outcome = ""
            result = "unconverged"

    # Replace the vacancies in the atoms object
    if remove_vacancies:
        structure.atoms = populate_points_with_vacancies(
            structure.atoms, vacancy_positions)

    structure.volume = structure.atoms.get_volume()
    calc_time = time.time() - gulp_start_time

    return structure, result, outcome, calc_time