Beispiel #1
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
Beispiel #2
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())
 def set_calc(self):
     keywords_ = ['conp full nosymm linmin']
     keywords_.append(self.name)
     if len(self.keywords):
         self.keywords = keywords_ + self.keywords
     self.keywords = ' '.join(self.keywords)
     calc = GULP(keywords=self.keywords,
                 options=self.options,
                 library=self.library)
     self.atoms.set_calculator(calc)
def main(directory, seedname):
    '''
  Read an extended .xyz file, run it through Gulp, and produce an
     electronic_structure.dat file.
  N.B. this requires ASE 3.19 or later, as earlier versions have problems
     reading forces from Gulp.
  N.B. the environment variable GULP_LIB must point to the Libraries directory
     in Gulp.
  '''

    # Set up the calculator.
    # This can be replaced with any other ASE calculator.
    # N.B. this reads from Caesar's root working directory,
    #   so only one settings file is needed.
    keywords, library, options, has_forces, has_stress = read_gulp_file(
        '{0}.gin'.format(seedname))
    calculator = GULP(keywords=keywords, library=library, options=options)

    # Change to the directory where calculations should be run.
    os.chdir(directory)

    # Read the atomic positions and lattice from the extended .xyz file.
    atoms = ase.io.read('{0}.xyz'.format(seedname))

    # Run the calculation and get the results.
    atoms.set_calculator(calculator)

    energy = atoms.get_potential_energy()

    if has_forces:
        forces = atoms.get_forces()
    else:
        forces = None

    if has_stress:
        stress = atoms.get_stress()
    else:
        stress = None

    # Construct the electronic_structrue.dat file.
    write_electronic_structure('electronic_structure.dat',
                               energy,
                               forces=forces,
                               stress=stress)
Beispiel #5
0
def test_gulp_opt():
    import numpy as np
    from ase.calculators.gulp import GULP
    from ase.optimize import BFGS
    from ase.build import molecule, bulk
    from ase.constraints import ExpCellFilter

    # GULP optmization test
    atoms = molecule('H2O')
    atoms1 = atoms.copy()
    atoms1.calc = GULP(library='reaxff.lib')
    with BFGS(atoms1) as opt1:
        opt1.run(fmax=0.005)

    atoms2 = atoms.copy()
    calc2 = GULP(keywords='opti conp', library='reaxff.lib')
    with calc2.get_optimizer(atoms2) as opt2:
        opt2.run()

    print(np.abs(opt1.atoms.positions - opt2.atoms.positions))
    assert np.abs(opt1.atoms.positions - opt2.atoms.positions).max() < 1e-5

    # GULP optimization test using stress
    atoms = bulk('Au', 'bcc', a=2.7, cubic=True)
    atoms1 = atoms.copy()
    atoms1.calc = GULP(keywords='conp gradient stress_out',
                       library='reaxff_general.lib')
    atoms1f = ExpCellFilter(atoms1)
    with BFGS(atoms1f) as opt1:
        opt1.run(fmax=0.005)

    atoms2 = atoms.copy()
    calc2 = GULP(keywords='opti conp', library='reaxff_general.lib')
    with calc2.get_optimizer(atoms2) as opt2:
        opt2.run()

    print(np.abs(opt1.atoms.positions - opt2.atoms.positions))
    assert np.abs(opt1.atoms.positions - opt2.atoms.positions).max() < 1e-5
Beispiel #6
0
def test_run_gulp_exception(STO_atoms, gulp_keywords, gulp_options,
                            gulp_shells, gulp_library, gulp_conditions,
                            expected_output, monkeypatch):
    """
    GIVEN a structure and a set of gulp options, including shells

    WHEN we run a gulp calculation, but do not have a restart file

    THEN we raise an exception.

    Parameters
    ----------
    STO_atoms : ASE atoms
        An ASE atoms object containing SrTiO_{3} and five vacancies.
    gulp_keywords : list, optional
        List of GULP keywords.
    gulp_options : list, optional
        List of GULP options.
    gulp_shells : list, optional
        List of 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_setups : list, optional
        A list of symbols for each atom if they are not wanted to be the same as in the original atoms object

    ---------------------------------------------------------------------------
    Paul Sharp 18/01/2018
    """

    # Make sure we follow path where the restart file does not exist
    monkeypatch.setattr(os.path, 'isfile', lambda x: False)

    STO_atoms.set_calculator(GULP())

    with pytest.raises(RuntimeError):
        chemdash.gulp_calc.run_gulp(STO_atoms, "gulp", "", gulp_keywords,
                                    gulp_options, gulp_shells, gulp_library,
                                    gulp_conditions)
Beispiel #7
0
def run_gulp(atoms='',
             shel=None,
             kwds='',
             opts='',
             lib='',
             produce_steps='',
             gulp_command='gulp < gulp.gin > gulp.got'):
    iat = len(atoms)
    converged = False
    if os.path.isfile("temp.res"):
        os.remove("temp.res")
    if produce_steps == True:
        try:
            files = glob.glob("atoms*.cif")
            for z in range(len(files)):
                os.remove(files[z])
        except:
            pass
    for i in range(len(kwds)):
        if i == 0:
            if not 'dump temp.res\n' in opts[i]:
                opts[i].append('dump temp.res\n')
            if shel == None:
                calc = GULP(keywords=kwds[i], options=opts[i], library=lib)
            else:
                calc = GULP(keywords=kwds[i],
                            options=opts[i],
                            library=lib,
                            shel=shel)
            atoms.set_calculator(calc)
            atoms.get_calculator().optimized = False
            try:
                energy = atoms.get_potential_energy()
                if len(atoms) != iat:
                    converged = False
                    break
                try:
                    if glob.glob("gulptmp*") != []:
                        if platform.system() == 'Windows':
                            files = glob.glob("gulptmp*")
                            for z in range(len(files)):
                                os.remove(files[z])
                        if platform.system() == 'Linux':
                            os.system("rm gulptmp*")
                except:
                    pass
            except:
                f = open("gulp.gin", 'r')
                f2 = f.readlines()
                cell = re.findall("\d+\.\d+", f2[6])
                for i in range(len(cell)):
                    cell[i] = cell[i][:10]

                f.close()
                f3 = open("gulp.gin", 'w')
                f2[6] = str(
                    str(cell[0]) + " " + str(cell[1]) + " " + str(cell[2]) +
                    " " + str(cell[3]) + " " + str(cell[4]) + " " +
                    str(cell[5]) + "\n")
                for i in range(len(f2)):
                    f3.write(f2[i])
                f3.close()
                atoms = read_gulp("gulp.gin")
                atoms.set_calculator(calc)
                try:
                    energy = atoms.get_potential_energy()
                    if len(atoms) != iat:
                        converged = False
                        break
                    if glob.glob("gulptmp*") != []:
                        if platform.system() == 'Windows':
                            os.system("del gulptmp*")
                        if platform.system() == 'Linux':
                            os.system("rm gulptmp*")
                except:
                    #except(ValueError):
                    energy = 1.0e20
                #	break
            if atoms.get_calculator().optimized == True:
                if atoms.calc.Gnorm <= 0.01:
                    #converged = True
                    #try:
                    #	atoms = read_gulp("temp.res")
                    #except:
                    #	converged = False
                    #	pass

                    ### add in extra check to see if the calculation has REALLY converged
                    f4 = open("gulp.got", 'r').readlines()
                    if 'opti' in kwds[i]:
                        if '  **** Optimisation achieved ****' in f4:
                            converged = True
                        else:
                            converged = False

            if 'sing' in kwds[i]:
                converged = True
            if produce_steps == True:
                label = str("atoms" + str(i + 1) + ".cif")
                write(label, atoms)
            #os.remove("gulp.got")
            #os.remove("gulp.gin")

        if i > 0:
            try:
                f = open("temp.res", 'r').readlines()
                new_file = open("gulp.gin", 'w')
                for j in f:
                    if "title" in j:
                        start = f.index(j) - 1
                    if "totalenergy" in j:
                        end = f.index(j)

                new_file.write(kwds[i])
                new_file.write("\n")
                for j in opts[i]:
                    new_file.write(j)
                    new_file.write("\n")
                new_file.write(str("library " + str(lib)))
                new_file.write("\n")
                cp = f[start:end]

                for j in cp:
                    new_file.write(j)
                new_file.close()

                os.system(gulp_command)
                output = open("gulp.got", 'r').readlines()
                if 'opti' in kwds[i]:
                    converged = '  **** Optimisation achieved ****\n' in output

                if 'sing' in kwds[i]:
                    converged = True
                    for j in output:
                        if "Total lattice energy" in j:
                            if "eV" in j:
                                e_line = j
                    energy = float(
                        e_line[e_line.index('-'):e_line.index('eV') - 1])
                    atoms = read_gulp("temp.res")

                if 'sing' not in kwds[i]:
                    try:
                        for j in output:
                            if "Final energy" in j:
                                e_line = j
                                break

                        energy = float(
                            e_line[e_line.index('-'):e_line.index('eV') - 1])

                        atoms = read_gulp("temp.res")

                    except:
                        converged = False
                        energy = 1.0e20
            except:
                converged = False
                energy = 1.0e20

    if converged == True:
        try:
            atoms = read_gulp("temp.res")
        except:
            pass
    else:
        converged = False
        energy = 1.0e20

    #view(atoms)
    return atoms, energy, converged
Beispiel #8
0
                                    [-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())
Beispiel #9
0
def run_gulp(structure,
             gulp_file,
             previous_restart_file="",
             gulp_keywords=["conp gradients"],
             gulp_options=[],
             gulp_shells=[],
             gulp_library="",
             gulp_conditions=None):
    """
    Run GULP in order to perform any stage of a split calculation.
    The calculation is run either by using an ASE calculator or as a system
    command depending on whether or not we have shells present -- if so, the
    system approach is required in order to preserve the positions of atomic
    shells.

    Parts of this routine are based on the "restart_gulp" routine,
    written by Chris Collins, and the section that runs GULP as a system command
    is taken from ASE-GULP.

    Parameters
    ----------
    structure : ASE atoms
        The structure used in the GULP calculation
    gulp_file : string
        Used to construct input and output files for GULP
    previous_restart_file : string, optional
        Restart file for previous GULP calculation -- used to construct new input file.
    gulp_keywords : list, optional
        List of GULP keywords. Default is "sing" for a single point energy calculation.
    gulp_options : list, optional
        List of GULP options. Default is None.
    gulp_shells : dictionary, optional
        List of 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
    -------
    structure : ase atoms
        The structure after performing this calculation.
    energy : float
        Energy of the structure in eV/atom.
    result : string
        The result of the GULP calculation,
        either "converged", "unconverged", "gulp failure", or "timed out"
    calc_files : dict
        The input, output and restart files for this GULP calculation.

    ---------------------------------------------------------------------------
    Paul Sharp 02/08/2018
    """

    # Set files for calculation
    calc_files = {
        "input": gulp_file + ".gin",
        "output": gulp_file + ".got",
        "restart": gulp_file + ".res",
    }

    energy = ""
    gnorm = ""
    result = ""
    timeout_outcome = "CPU limit has been exceeded - restart optimisation "

    # Determine how to do the second calculation depending on whether or not we have shells present
    if (gulp_shells == []) or (structure.get_calculator() is None):

        # Use ASE calculator -- set keywords and options for this calculation
        calc = (GULP(label=gulp_file,
                     keywords=gulp_keywords,
                     options=gulp_options,
                     shel=gulp_shells,
                     library=gulp_library,
                     conditions=gulp_conditions))

        structure.set_calculator(calc)

        # Run calculation
        try:
            energy = structure.get_potential_energy()

        except:
            pass

        else:
            gnorm = structure.calc.get_Gnorm()

    else:

        # Run as system command -- need to construct the GULP input file from the ".res" file of the previous calculation
        if os.path.isfile(previous_restart_file):

            create_input_file_from_restart_file(calc_files["input"],
                                                previous_restart_file,
                                                structure.get_cell(),
                                                gulp_keywords, gulp_options,
                                                gulp_library)

            execute_gulp_command_or_script(gulp_file, calc_files["output"])

            # Read energy from output file
            if os.path.isfile(calc_files["output"]):

                energy = read_energy(calc_files["output"])
                gnorm = read_gnorm(calc_files["output"])

        else:

            raise RuntimeError(
                'ERROR in "gulp_calc.run_gulp()" -- shells are used in this GULP calculation, but a ".res" file was not generated in the previous stage of the calculation.\n'
                'This means that the positions of the shells cannot be tracked accurately. Please specify "dump <restart>.res" in the "gulp_options".'
            )

    if not os.path.isfile(calc_files["output"]):
        result = "gulp failure"

    # The calculation can timeout either within GULP or via the bash timeout command
    elif read_outcome(
            calc_files["output"]) == timeout_outcome or check_timed_out(
                calc_files["output"]):
        result = "timed out"

    # Convert energy to units of eV/atom
    try:
        energy /= float(len(strip_vacancies(structure.copy())))
    except (TypeError, ValueError):
        pass

    return structure, energy, gnorm, result, calc_files
Beispiel #10
0
import numpy as np
from ase.calculators.gulp import GULP
from ase.optimize import BFGS
from ase.build import molecule

atoms = molecule('H2O')
atoms1 = atoms.copy()
atoms1.calc = GULP(library='reaxff.lib')
opt1 = BFGS(atoms1,trajectory='bfgs.traj')
opt1.run(fmax=0.005)

atoms2 = atoms.copy()
calc2 = GULP(keywords='opti conp', library='reaxff.lib')
opt2 = calc2.get_optimizer(atoms2)
opt2.run()

print(np.abs(opt1.atoms.positions - opt2.atoms.positions))
assert np.abs(opt1.atoms.positions - opt2.atoms.positions).max() < 1e-5
Beispiel #11
0
       [ 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', ifcloselabel1='O2',
                    ifcloselabel2='H', elselabel1='O1')
calc = GULP(keywords='conp', shel=['O1', 'O2'], conditions=c)

# Single point calculation
cluster.calc = calc
print(cluster.get_potential_energy())

# Optimization using the internal optimizer of GULP
calc.set(keywords='conp opti')
opt = calc.get_optimizer(cluster)
opt.run(fmax=0.05)
print(cluster.get_potential_energy())
Beispiel #12
0
import numpy as np
from ase.calculators.gulp import GULP
from ase.optimize import BFGS
from ase.build import molecule, bulk
from ase.constraints import ExpCellFilter

# GULP optmization test
atoms = molecule('H2O')
atoms1 = atoms.copy()
atoms1.calc = GULP(library='reaxff.lib')
opt1 = BFGS(atoms1, trajectory='bfgs.traj')
opt1.run(fmax=0.005)

atoms2 = atoms.copy()
calc2 = GULP(keywords='opti conp', library='reaxff.lib')
opt2 = calc2.get_optimizer(atoms2)
opt2.run()

print(np.abs(opt1.atoms.positions - opt2.atoms.positions))
assert np.abs(opt1.atoms.positions - opt2.atoms.positions).max() < 1e-5

# GULP optimization test using stress
atoms = bulk('Au', 'bcc', a=2.7, cubic=True)
atoms1 = atoms.copy()
atoms1.calc = GULP(keywords='conp gradient stress_out',
                   library='reaxff_general.lib')
atoms1f = ExpCellFilter(atoms1)
opt1 = BFGS(atoms1f, trajectory='bfgs.traj')
opt1.run(fmax=0.005)

atoms2 = atoms.copy()