예제 #1
0
def test_orca():
    from ase.optimize import BFGS
    from ase.atoms import Atoms
    from ase.calculators.orca import ORCA

    atoms = Atoms('OHH', positions=[(0, 0, 0), (1, 0, 0), (0, 1, 0)])

    atoms.calc = ORCA(label='water', orcasimpleinput='BLYP def2-SVP')

    opt = BFGS(atoms)
    opt.run(fmax=0.05)

    final_energy = atoms.get_potential_energy()
    print(final_energy)

    assert abs(final_energy + 2077.24420) < 1.0
예제 #2
0
def test_orca_qmmm():
    from ase.calculators.tip4p import TIP4P, epsilon0, sigma0
    from ase.calculators.orca import ORCA
    from ase.calculators.qmmm import EIQMMM, LJInteractions
    from ase.data import s22

    atoms = s22.create_s22_system('Water_dimer')

    qmcalc = ORCA(label='water', orcasimpleinput='BLYP def2-SVP')

    lj = LJInteractions({('O', 'O'): (epsilon0, sigma0)})

    atoms.calc = EIQMMM(selection=[0, 1, 2],
                        qmcalc=qmcalc,
                        mmcalc=TIP4P(),
                        interaction=lj,
                        output='orca_qmmm.log')

    e = atoms.get_potential_energy()

    assert abs(e + 2077.45445852) < 1.0
예제 #3
0
def main():
    """Run main procedure."""
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "commands",
        metavar="input_file",
        nargs="?",
        type=argparse.FileType("r"),
        default="-",
        help="input text file with commands",
    )
    parser.add_argument(
        "-O",
        "--output-file",
        type=argparse.FileType("w"),
        default="-",
        help="output coordinates file",
    )
    parser.add_argument(
        "--no-final-neb",
        dest="final_neb",
        action="store_false",
        help="piecewise nudged-elastic band only",
    )
    parser.add_argument("--no-opt",
                        dest="opt",
                        action="store_false",
                        help="use final states as given")
    args = parser.parse_args()

    n = 0
    auto_n = True
    images = []
    method, theory = "linear", None
    for line in args.commands:
        for command in line.split():
            command = command.strip()
            if command == "linear":
                method, theory = "linear", None
            elif command == "idpp":
                method, theory = "idpp", None
            elif command in {"pm3", "am1", "xtb2"}:
                # method == "idpp"
                theory = command
            elif command == "auto":
                auto_n = True
            else:
                try:
                    structure = io.read(command)
                except FileNotFoundError:
                    try:
                        n = int(command)
                    except ValueError:
                        parser.error(
                            f"could not understand command or find file: '{command}'"
                        )
                    continue

                if len(images) > 0 and (auto_n or n > 0):
                    if auto_n:
                        rmsd = calc_rmsd(images[-1].get_positions(),
                                         structure.get_positions())
                        n = max(1, int(rmsd / 0.3))

                    pieces = [images[-1]]
                    pieces += [images[-1].copy() for _ in range(n)]
                    pieces += [structure]
                    if method == "idpp":
                        neb = NEB(pieces,
                                  remove_rotation_and_translation=False,
                                  **neb_kwargs)
                    else:
                        neb = NEB(pieces,
                                  remove_rotation_and_translation=True,
                                  **neb_kwargs)
                    neb.interpolate(method)
                    if theory is not None:
                        # TODO(schneiderfelipe): avoid repeat the code for NEB
                        orcablocks = ""
                        if theory not in {"pm3", "am1"}:
                            orcablocks = f"%pal nprocs {os.cpu_count()} end"
                        for piece in pieces[1:-1]:
                            piece.calc = ORCA(
                                orcasimpleinput=f"{theory} loosescf nososcf",
                                orcablocks=orcablocks,
                                **calc_kwargs,
                            )
                        if n < 5:
                            # best for 2 and 4 structures
                            opt = FIRE(neb, **opt_kwargs)
                        else:
                            # best for 3 and 10 structures
                            opt = LBFGS(neb, **opt_kwargs)
                        opt.run(**run_kwargs)
                    images = images[:-1] + pieces
                else:
                    images.append(structure)

    run_kwargs.update({"fmax": run_kwargs["fmax"] / 5})
    if args.opt and theory is not None:
        # TODO(schneiderfelipe): avoid repeat the code for NEB
        orcablocks = ""
        if theory not in {"pm3", "am1"}:
            orcablocks = f"%pal nprocs {os.cpu_count()} end"
        images[0].calc = ORCA(
            orcasimpleinput=f"{theory} loosescf nososcf",
            orcablocks=orcablocks,
            **calc_kwargs,
        )
        images[-1].calc = ORCA(
            orcasimpleinput=f"{theory} loosescf nososcf",
            orcablocks=orcablocks,
            **calc_kwargs,
        )

        opt = LBFGS(images[0], **opt_kwargs)
        opt.run(**run_kwargs)

        opt = LBFGS(images[-1], **opt_kwargs)
        opt.run(**run_kwargs)

    if args.final_neb and theory is not None and len(images) > 2:
        neb = NEB(images, remove_rotation_and_translation=True, **neb_kwargs)

        # TODO(schneiderfelipe): avoid repeat the code for NEB
        orcablocks = ""
        if theory not in {"pm3", "am1"}:
            orcablocks = f"%pal nprocs {os.cpu_count()} end"
        for image in images[1:-1]:
            image.calc = ORCA(
                orcasimpleinput=f"{theory} loosescf nososcf",
                orcablocks=orcablocks,
                **calc_kwargs,
            )
        if len(images) < 5:
            # best for 2 and 4 structures
            opt = FIRE(neb, **opt_kwargs)
        else:
            # best for 3 and 10 structures
            opt = LBFGS(neb, **opt_kwargs)

        opt.run(**run_kwargs)

    with redirect_stdout(args.output_file):
        io.write("-", images, format="xyz", plain=True)

    # some programs (e.g., Chemcraft) won't read without a newline at the end
    # but even with this, Chemcraft won't read if there are only 2 strucures
    args.output_file.write("\n")
예제 #4
0
def main():
    """Run main procedure."""
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("logfile")
    # TODO(schneiderfelipe): set charge and multiplicity
    parser.add_argument(
        "-a",
        "--acc",
        help="accuracy for SCC calculation, lower is better",
        type=float,
        default=1.0,
    )
    parser.add_argument(
        "--iterations",
        help="number of iterations in SCC",
        type=int,
        default=250,
    )
    parser.add_argument(
        "--gfn", help="specify parametrisation of GFN-xTB", type=int
    )
    parser.add_argument(
        "--etemp", help="electronic temperature", type=float, default=300.0
    )
    parser.add_argument(
        "-s",
        "--solvent",
        help=("solvent (SMD/GBSA implicit solvation models)"),
        default="none",
    )
    parser.add_argument(
        "--do-not-cache-api",
        dest="cache_api",
        help="Do not reuse generate API objects (not recommended)",
        action="store_false",
    )

    parser.add_argument(
        "--pm3", help="use PM3", action="store_true",
    )
    parser.add_argument(
        "--b97-3c", help="use B97-3c", action="store_true",
    )
    parser.add_argument(
        "--minimize", action="store_true",
    )
    parser.add_argument(
        "--transition-state", action="store_true",
    )
    parser.add_argument("--max-omega", type=float, default=1.0)
    parser.add_argument("--tol", type=float, default=1e-3)
    parser.add_argument("--nprocs", type=int, default=4)
    args = parser.parse_args()
    print(args)

    data = ccopen(args.logfile).parse()
    initial_positions = data.atomcoords[-1]
    atoms = Atoms(numbers=data.atomnos, positions=initial_positions)

    if args.gfn:
        method = f"GFN{args.gfn}-xTB"
        solvent = smd2gbsa[args.solvent.lower()]

        calc = XTB(
            method=method,
            accuracy=args.acc,
            electronic_temperature=args.etemp,
            max_iterations=args.iterations,
            solvent=solvent,
            cache_api=args.cache_api,
        )
    else:

        if args.b97_3c:
            method = "B97-3c D3BJ def2-SV(P)"
        elif args.pm3:
            method = "PM3"
        else:

            def allow_keyword(keyword):
                for forbidden in {"freq", "opt", "irc", "print"}:
                    if forbidden in keyword.lower():
                        return False
                return True

            keywords = [
                keyword
                for keyword in data.metadata["keywords"]
                if allow_keyword(keyword)
            ]

            method = " ".join(keywords)

        solvent = args.solvent
        blocks = f"%pal\n nprocs {args.nprocs}\nend\n%scf\n maxiter {args.iterations}\nend"
        if solvent != "none" and not args.pm3:
            blocks += f'\n%cpcm\n smd true\n smdsolvent "{solvent}"\nend'

        if "ORCA_COMMAND" not in os.environ:
            # For parallel runs ORCA has to be called with full pathname
            os.environ["ORCA_COMMAND"] = shutil.which("orca")

        calc = ORCA(
            label="012345_swing", orcasimpleinput=method, orcablocks=blocks
        )

    print(f"*** {method} ***")
    print(f"    : solvent:              {solvent}")

    atoms.set_calculator(calc)
    potential_min = atoms.get_potential_energy()
    print(f"@ potential energy:        {potential_min} eV")

    indices = np.where(data.vibfreqs < 0)[0]
    n_indices = len(indices)
    print(f"@ imaginary frequencies:   {data.vibfreqs[indices]}")
    if not n_indices:
        print("    : nothing to be done, bye")
        return

    ignoring = None
    if args.transition_state:
        ignoring = 0
        print("    : transition state:    ignoring first imaginary frequency")

    omegas = []
    potentials = []

    def f(omega):
        atoms.set_positions(
            initial_positions
            + np.einsum("i,ijk->jk", omega, data.vibdisps[indices])
        )

        potential = 1e3 * (atoms.get_potential_energy() - potential_min)

        omegas.append(omega)
        potentials.append(potential)
        print(f"    : omega:               {omega}")
        print(f"    : potential:           {potential} meV")

        return potential

    if args.minimize:
        guesses = [np.zeros_like(indices, dtype=float)]

    for i in indices:
        if ignoring is not None and i == ignoring:
            continue

        print(f"@ searching in direction   #{i}")

        def g(w):
            z = np.zeros_like(indices, dtype=float)
            z[i] = w
            return f(z)

        if args.minimize:
            res = minimize_scalar(
                g,
                method="bounded",
                bounds=(-args.max_omega, args.max_omega),
                tol=args.tol,
            )
            print(res)

            guess = np.zeros_like(indices, dtype=float)
            guess[i] = res.x
            guesses.append(guess)
        else:
            dx = args.max_omega / 100
            x = [-dx, 0.0, dx]
            y = [g(-dx), 0.0, g(dx)]

            # p[0] * x**2 + p[1] * x + p[2] == k * (x - x0)**2 == k * x**2 - 2 * x0 * k * x + k * x0**2
            p = np.polyfit(x, y, 2)
            print(p)
            print(np.roots(p))

            dp = np.polyder(p)
            print(dp)
            r = np.roots(dp)
            print(r)

            # k = p[0]
            # x0 = np.sqrt(p[2] / k)
            # print(k, x0)
            # print(root(lambda z: [p[0] - z[0], p[1] + 2 * z[0] * z[1], p[2] - z[0] * z[1] ** 2], [k, x0]))

            best_positions = initial_positions + np.einsum(
                "i,ijk->jk", r, data.vibdisps[indices]
            )

    if args.minimize:
        print("@ choosing initial guess for global search")
        if n_indices > 1:
            guesses.append(np.sum(guesses, axis=0))
        x0 = guesses[np.argmin([f(guess) for guess in guesses])]

        print("@ searching in all directions")
        constraints = ()
        if args.transition_state and ignoring is not None:
            constraints = (
                {"type": "eq", "fun": lambda omega: omega[ignoring]},
            )
        res = minimize(
            f,
            x0=x0,
            bounds=n_indices * [(-args.max_omega, args.max_omega)],
            constraints=constraints,
            tol=args.tol,
        )
        print(res)
        best_positions = initial_positions + np.einsum(
            "i,ijk->jk", res.x, data.vibdisps[indices]
        )

        # TODO(schneiderfelipe): correct for when using --transition-state
        omegas = np.array(omegas)
        fig, ax = plt.subplots(n_indices, 1)
        if n_indices == 1:
            ax = [ax]
        xlim = (-args.max_omega - 0.05, args.max_omega + 0.05)
        ylim = (np.min(potentials) - 2.0, 40.0)
        for i in indices:
            if ignoring is not None and i == ignoring:
                continue

            ax[i].plot(omegas[:, i], potentials, "o")
            ax[i].set_title(f"view of normal mode #{i}")
            ax[i].set_ylabel(r"potential energy (meV)")
            ax[i].set_xlabel(rf"$\omega_{i}$")
            ax[i].set_ylim(ylim)
            ax[i].set_xlim(xlim)
        plt.tight_layout()
        plt.show()

    print("@ writing best geometry to swinged.xyz")
    # TODO(schneiderfelipe): print a RMSD between initial and final structures
    atoms.set_positions(best_positions)
    atoms.write("swinged.xyz", format="xyz", plain=True)
예제 #5
0
def get_ase_calc(embedder):
    '''
    Attach the correct ASE calculator
    to the ASE Atoms object.
    embedder: either a TSCoDe embedder object or
        a 4-element strings tuple containing
        (calculator, method, procs, solvent)
    '''
    if isinstance(embedder, tuple):
        calculator, method, procs, solvent = embedder

    else:
        calculator = embedder.options.calculator
        method = embedder.options.theory_level
        procs = embedder.options.procs
        solvent = embedder.options.solvent

    if calculator == 'XTB':
        try:
            from xtb.ase.calculator import XTB
        except ImportError:
            raise Exception(
                ('Cannot import xtb python bindings. Install them with:\n'
                 '>>> conda install -c conda-forge xtb-python\n'
                 '(See https://github.com/grimme-lab/xtb-python)'))

        from tscode.solvents import (solvent_synonyms, xtb_solvents,
                                     xtb_supported)

        solvent = solvent_synonyms[
            solvent] if solvent in solvent_synonyms else solvent
        solvent = 'none' if solvent is None else solvent

        if solvent not in xtb_solvents:
            raise Exception(
                f'Solvent \'{solvent}\' not supported by XTB. Supported solvents are:\n{xtb_supported}'
            )

        return XTB(method=method, solvent=solvent)

    command = COMMANDS[calculator]

    if calculator == 'MOPAC':

        if solvent is not None:
            method = method + ' ' + get_solvent_line(solvent, calculator,
                                                     method)

        return MOPAC(label='temp',
                     command=f'{command} temp.mop > temp.cmdlog 2>&1',
                     method=method + ' GEO-OK')

    if calculator == 'ORCA':

        orcablocks = ''

        if procs > 1:
            orcablocks += f'%pal nprocs {procs} end'

        if solvent is not None:
            orcablocks += get_solvent_line(solvent, calculator, method)

        return ORCA(label='temp',
                    command=f'{command} temp.inp > temp.out 2>&1',
                    orcasimpleinput=method,
                    orcablocks=orcablocks)

    if calculator == 'GAUSSIAN':

        if solvent is not None:
            method = method + ' ' + get_solvent_line(solvent, calculator,
                                                     method)

        mem = str(MEM_GB) + 'GB' if MEM_GB >= 1 else str(int(1000 *
                                                             MEM_GB)) + 'MB'

        calc = Gaussian(
            label='temp',
            command=f'{command} temp.com',
            method=method,
            nprocshared=procs,
            mem=mem,
        )

        if 'g09' in command:

            from ase.io import read

            def g09_read_results(self=calc):
                output = read(self.label + '.out', format='gaussian-out')
                self.calc = output.calc
                self.results = output.calc.results

            calc.read_results = g09_read_results

            # Adapting for g09 outputting .out files instead of g16 .log files.
            # This is a bad fix and the issue should be corrected in the ASE
            # source code: merge request on GitHub pending to be written

            return calc
예제 #6
0
from ase import io
from ase.calculators.orca import ORCA
from ase.optimize.fire import FIRE
from ase.optimize.bfgs import BFGS

#Optimise molecule
ethan = io.read('xyz_files/ethan.xyz')
orca_calc= ORCA(
    label="orca",
    maxiter=200,
    task="gradient",
    orcasimpleinput="HF-3c"
)
ethan.set_calculator(orca_calc)

#opt = FIRE(ethan, trajectory='ethan.traj')
#opt.run(fmax=0.00241)
opt = BFGS(ethan, trajectory='ethan.traj')
opt.run(fmax=0.0005)
예제 #7
0
파일: ionize.py 프로젝트: fuulish/fuase
frgchg = np.zeros(len(fragments), dtype='int')
frgmlt = np.ones(len(fragments), dtype='int')

frgchg[0] = 1
frgmlt[0] = 2

cutoff = 0.0

neu_label = 'large-cut_neutral_'

for basis in ['STO-3G', '6-31G*']:
    for xc in ['PBE', 'BHandHLYP']:
        #### neutral #####

        calc = ORCA(xc=xc, basis=basis, charges=charges, raw=raw)

        gebf = GEBF(atoms,
                    molecules=True,
                    fragments=fragments,
                    subsyscalc=calc,
                    cutoff=cutoff,
                    label=neu_label,
                    printlevel=1,
                    econv=1.e-4,
                    qconv=1.e-2,
                    around_solute=around_solute)

        atoms.set_calculator(gebf)

        neutral = atoms.get_potential_energy()