Commit d9d36c43 authored by Jens Jørgen Mortensen's avatar Jens Jørgen Mortensen

Merge branch 'opttest-docs' into 'master'

Update optimizer-test docs

See merge request !354
parents a04ba2d5 d2e88c37
Pipeline #21494950 passed with stage
in 3 minutes and 5 seconds
# Creates: systems.db
def workflow():
from myqueue.job import Job
return [Job('agts.py'),
Job('run_tests_emt.py', deps='agts.py'),
Job('run_tests.py+1@8x1d', deps='agts.py'),
Job('run_tests.py+2@8x1d', deps='agts.py'),
Job('analyze.py',
deps=['run_tests_emt.py', 'run_tests.py+1', 'run_tests.py+2'])]
if __name__ == '__main__':
from ase.optimize.test.systems import create_database
create_database() # creates systems.db
# Creates: emt-iteration.csv, lcao-time.csv, systems.csv
import ase.db
from ase.optimize.test.analyze import analyze
analyze('results-emt.db', 'emt')
analyze('results-lcao.db', 'lcao')
db1 = ase.db.connect('systems.db')
with open('systems.csv', 'w') as f:
print('test-name,description', file=f)
for row in db1.select():
print('{},{}'.format(row.formula, row.description), file=f)
......@@ -3,7 +3,9 @@
===============
Optimizer tests
===============
This page shows benchmarks of optimizations done with our different optimizers.
This page shows benchmarks of optimizations done with ASE's different
:mod:`optimizers <ase.optimize>`.
Note that the iteration number (steps) is not the same as the number of force
evaluations. This is because some of the optimizers uses internal line searches
or similar.
......@@ -14,107 +16,38 @@ Different optimizers may perform the same number of steps, but along a different
path, so the time spent on calculation of energy/forces may be different
due to different convergence of the self-consistent field.
G2
==
PBE relaxation of molecules from the G2 set.
On the plots: the number of optimizer force calls (stats), the total run time,
the systems with the largest number of optimizer force calls, and the number of
systems for which optimization failed.
In the corresponding tables: the most common value of the total energy
("relaxed energy"), and the differences (optimizer - "relaxed energy").
The dot sign denotes the above difference below a threshold
(same as the printed precision of "relaxed energy" in eV),
and "N/A" denotes an optimization failure.
Only the systems that fail to converge or converge to a
total energy above the threshold are given in the tables.
Calculator used: GPAW mode='lcao' (see :git:`~doc/devel/ase_optimize/g2_dzp.py`)
Limit of optimizer steps: 25
.. csv-table::
:file: g2_dzp.csv
:header: optimizer, failed, time, steps
N2Cu
====
Relaxation of Cu surface.
Calculator used: EMT
.. csv-table::
:file: N2Cu-surf.csv
N2 adsorption on relaxed Ru surface
Calculator used: EMT
.. csv-table::
:file: N2Cu-N2.csv
Cu_bulk
=======
Bulk relaxation of Cu where atoms has been rattled.
Calculator used: EMT
.. csv-table::
:file: Cu_bulk.csv
CO_Au111
========
CO adsorption on Au
Calculator used: EMT
.. csv-table::
:file: CO_Au111.csv
H2
==
Geometry optimization of gas-phase molecule.
Test systems
============
Calculator used: EMT
These are the test systems (:download:`systems.db`):
.. csv-table::
:file: H2-emt.csv
Calculator used: GPAW
:file: systems.csv
:header-rows: 1
.. csv-table::
:file: H2-gpaw.csv
C5H12
=====
Geometry optimization of gas-phase molecule.
EMT calculations
================
Calculator used: GPAW (lcao)
Calculation done with :class:`~ase.calculators.emt.EMT`. Number of steps:
.. csv-table::
:file: C5H12-gpaw.csv
nanoparticle
============
Adsorption of a NH on a Pd nanoparticle.
Calculator used: GPAW (lcao)
:file: emt-iterations.csv
:header-rows: 1
.. csv-table::
:file: nanoparticle.csv
NEB
=======
Diffusion of gold atom on Al(100) surface.
GPAW-LCAO calculations
======================
Calculator used: EMT
Parameters::
.. csv-table::
:file: neb-emt.csv
GPAW(mode='lcao',
basis='dzp',
kpts={'density': 2.0})
Calculator used: GPAW (lcao)
Absolute time relative to fastest optimizer:
.. csv-table::
:file: neb-gpaw.csv
:file: lcao-time.csv
:header-rows: 1
from myqueue.job import Job
def workflow():
jobs = [Job('g2_dzp.py+{}@4x13h'.format(i)) for i in range(10)]
return jobs + [Job('g2_dzp_csv.py', deps=jobs)]
import time
import ase.db
import ase.optimize
from ase.collections import g2
from gpaw import GPAW, Mixer
optimizers = ['BFGS', 'BFGSLineSearch',
'FIRE', 'GoodOldQuasiNewton',
'LBFGS', 'LBFGSLineSearch']
con = ase.db.connect('g2_dzp.db')
for name, atoms in zip(g2.names, g2):
if len(atoms) == 1:
continue
atoms.center(vacuum=3.5)
for optimizer in optimizers:
id = con.reserve(name=name, optimizer=optimizer)
if id is None:
continue
mol = atoms.copy()
mol.calc = GPAW(mode='lcao',
basis='dzp',
h=0.17,
xc='PBE',
mixer=Mixer(0.05, 2),
txt='{0}-{1}.txt'.format(name, optimizer))
Optimizer = getattr(ase.optimize, optimizer)
opt = Optimizer(mol)
t = time.time()
try:
opt.run(fmax=0.05, steps=50)
except Exception as ex:
print(name, optimizer, ex)
continue
con.write(mol, name=name, optimizer=optimizer,
steps=opt.nsteps, time=time.time() - t)
del con[id]
# Creates: g2_dzp.csv
from __future__ import print_function
import numpy as np
import ase.db
con = ase.db.connect('g2_dzp.db')
N = 6 # number of optimizers
M = len(con) // N # number of molecules
data = []
for row in con.select():
data.append((row.optimizer,
row.name,
row.get('time', 42),
row.get('steps', 42),
row.get('energy', 42),
row.get('fmax', 42)))
data.sort()
optimizers = [x[0] for x in data[::M]]
data = np.array([x[2:] for x in data]).reshape((N, M, 4))
e0 = data[:, :, 2].min(0)
results = []
for opt, d in zip(optimizers, data):
ok = (d[:, 3] < 0.05) & (d[:, 2] < e0 + 0.1)
failed = M - sum(ok)
time, niter = d[ok, :2].mean(0)
results.append((failed, time, niter, opt))
with open('g2_dzp.csv', 'w') as f:
for failed, time, niter, opt in sorted(results):
print('{0}, {1}, {2:.1f}, {3:.1f}'.format(opt, failed, time, niter),
file=f)
import ase.db
from ase.optimize.test.test import (test_optimizer, all_optimizers,
get_optimizer)
from gpaw import GPAW
db1 = ase.db.connect('systems.db')
db = ase.db.connect('results-lcao.db')
def lcao(txt):
return GPAW(mode='lcao',
basis='dzp',
kpts={'density': 2.0},
txt=txt)
systems = [row.toatoms() for row in db1.select()]
for opt in all_optimizers:
optimizer = get_optimizer(opt)
test_optimizer(systems, optimizer, lcao, 'lcao-', db)
import ase.db
from ase.calculators.emt import EMT
from ase.optimize.test.test import (test_optimizer, all_optimizers,
get_optimizer)
db1 = ase.db.connect('systems.db')
db = ase.db.connect('results-emt.db', serial=True)
systems = [row.toatoms() for row in db1.select() if row.formula != 'C5H12']
for opt in all_optimizers:
optimizer = get_optimizer(opt)
test_optimizer(systems, optimizer, EMT, 'emt-', db)
from ase.db import connect
from ase.optimize.test.systems import create_database
from gpaw import GPAW, PW
def create_database_gpaw():
create_database()
db = connect('systems.db')
systems = [row.toatoms() for row in db.select()]
db = connect('systems-gpaw.db')
for atoms in systems:
if atoms.number_of_lattice_vectors != 3:
atoms.center(vacuum=3.5)
atoms.calc = GPAW(mode=PW(500), # 'lcao',
# basis='dzp',
kpts={'density': 2.0},
txt=None)
db.write(atoms)
if __name__ == '__main__':
create_database_gpaw()
This diff is collapsed.
......@@ -17,6 +17,8 @@ except ImportError:
from urllib.request import urlopen
from urllib.error import HTTPError
import os
from pathlib import Path
srcpath = 'http://wiki.fysik.dtu.dk/gpaw-files'
agtspath = 'http://wiki.fysik.dtu.dk'
......@@ -148,16 +150,15 @@ get('static', ['NOMAD_Logo_supported_by.png'])
def setup(app):
# Get png files and other stuff from the AGTS scripts that run
# Get png and csv files and other stuff from the AGTS scripts that run
# every weekend:
from gpaw.test.big.agts import AGTSQueue
queue = AGTSQueue()
queue.collect()
names = set()
for job in queue.jobs:
if not job.creates:
for path in Path().glob('**/*agts.py'):
line1 = path.read_text().split('\n', 1)[0]
if not line1.startswith('# Creates:'):
continue
for name in job.creates:
for name in line1.split(':')[1].split(','):
name = name.strip()
if name in names:
raise RuntimeError(
'The name {0!r} is used in more than one place!'
......@@ -165,8 +166,8 @@ def setup(app):
names.add(name)
# the files are saved by the weekly tests under agtspath/agts-files
# now we are copying them back to their original run directories
path = os.path.join(job.dir, name)
if os.path.isfile(path):
file = path.with_name(name)
if file.is_file():
continue
print(path, 'copied from', agtspath)
get('agts-files', [name], job.dir, source=agtspath)
print(file, 'copied from', agtspath)
get('agts-files', [name], str(file.parent), source=agtspath)
# Creates: Al_conv_ecut.png, Al_conv_k.png
from myqueue.job import Job
def workflow():
return [
Job('al.py@8x12h'),
Job('al.agts.py', deps=['al.py'])]
if __name__ == '__main__':
import pylab as plt
from ase.eos import EquationOfState
from ase.io import read
def fit(filename):
configs = read(filename + '@:')
volumes = [a.get_volume() for a in configs]
energies = [a.get_potential_energy() for a in configs]
eos = EquationOfState(volumes, energies)
v0, e0, B = eos.fit()
return (4 * v0)**(1 / 3.0)
cutoffs = range(200, 501, 50)
a = [fit('Al-%d.txt' % ecut) for ecut in cutoffs]
plt.figure(figsize=(6, 4))
plt.plot(cutoffs, a, 'o-')
plt.axis(ymin=4.03, ymax=4.05)
plt.xlabel('Plane-wave cutoff energy [eV]')
plt.ylabel('lattice constant [Ang]')
plt.savefig('Al_conv_ecut.png')
kpoints = range(4, 17)
plt.figure(figsize=(6, 4))
a = [fit('Al-%02d.txt' % k) for k in kpoints]
plt.plot(kpoints, a, '-')
plt.xlabel('number of k-points')
plt.ylabel('lattice constant [Ang]')
plt.savefig('Al_conv_k.png')
return [Job('al.py@8x12h'),
Job('al_analysis.py', deps=['al.py'])]
# Creates: Al_conv_ecut.png, Al_conv_k.png
import matplotlib.pyplot as plt
from ase.eos import EquationOfState
from ase.io import read
def fit(filename):
configs = read(filename + '@:')
volumes = [a.get_volume() for a in configs]
energies = [a.get_potential_energy() for a in configs]
eos = EquationOfState(volumes, energies)
v0, e0, B = eos.fit()
return (4 * v0)**(1 / 3.0)
cutoffs = range(200, 501, 50)
a = [fit('Al-%d.txt' % ecut) for ecut in cutoffs]
plt.figure(figsize=(6, 4))
plt.plot(cutoffs, a, 'o-')
plt.axis(ymin=4.03, ymax=4.05)
plt.xlabel('Plane-wave cutoff energy [eV]')
plt.ylabel('lattice constant [Ang]')
plt.savefig('Al_conv_ecut.png')
kpoints = range(4, 17)
plt.figure(figsize=(6, 4))
a = [fit('Al-%02d.txt' % k) for k in kpoints]
plt.plot(kpoints, a, '-')
plt.xlabel('number of k-points')
plt.ylabel('lattice constant [Ang]')
plt.savefig('Al_conv_k.png')
......@@ -34,4 +34,4 @@ with respect to number of **k**-points:
.. image:: Al_conv_k.png
(see also :download:`analysis script <al.agts.py>`).
(see also :download:`analysis script <al_analysis.py>`).
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment