root / ase / optimize / test / __init__.py @ 7
Historique | Voir | Annoter | Télécharger (4,33 ko)
| 1 | 1 | tkerber | """Define a helper function for running tests
|
|---|---|---|---|
| 2 | 1 | tkerber |
|
| 3 | 1 | tkerber | The skeleton for making a new setup is as follows:
|
| 4 | 1 | tkerber |
|
| 5 | 1 | tkerber | from ase.optimize.test import run_test
|
| 6 | 1 | tkerber |
|
| 7 | 1 | tkerber | def get_atoms():
|
| 8 | 1 | tkerber | return Atoms('H')
|
| 9 | 1 | tkerber |
|
| 10 | 1 | tkerber | def get_calculator():
|
| 11 | 1 | tkerber | return EMT()
|
| 12 | 1 | tkerber |
|
| 13 | 1 | tkerber | run_test(get_atoms, get_calculator, 'Hydrogen')
|
| 14 | 1 | tkerber | """
|
| 15 | 1 | tkerber | import matplotlib |
| 16 | 1 | tkerber | matplotlib.rcParams['backend']="Agg" |
| 17 | 1 | tkerber | |
| 18 | 1 | tkerber | from ase.optimize.bfgs import BFGS |
| 19 | 1 | tkerber | from ase.optimize.lbfgs import LBFGS, LBFGSLineSearch |
| 20 | 1 | tkerber | from ase.optimize.fire import FIRE |
| 21 | 1 | tkerber | from ase.optimize.mdmin import MDMin |
| 22 | 1 | tkerber | from ase.optimize.sciopt import SciPyFminCG |
| 23 | 1 | tkerber | from ase.optimize.sciopt import SciPyFminBFGS |
| 24 | 1 | tkerber | from ase.optimize.bfgslinesearch import BFGSLineSearch |
| 25 | 1 | tkerber | |
| 26 | 1 | tkerber | from ase.parallel import rank, paropen |
| 27 | 1 | tkerber | |
| 28 | 1 | tkerber | import matplotlib.pyplot as pl |
| 29 | 1 | tkerber | import numpy as np |
| 30 | 1 | tkerber | |
| 31 | 1 | tkerber | import traceback |
| 32 | 1 | tkerber | |
| 33 | 1 | tkerber | optimizers = [ |
| 34 | 1 | tkerber | 'BFGS',
|
| 35 | 1 | tkerber | 'LBFGS',
|
| 36 | 1 | tkerber | 'LBFGSLineSearch',
|
| 37 | 1 | tkerber | 'FIRE',
|
| 38 | 1 | tkerber | 'MDMin',
|
| 39 | 1 | tkerber | 'SciPyFminCG',
|
| 40 | 1 | tkerber | 'SciPyFminBFGS',
|
| 41 | 1 | tkerber | 'BFGSLineSearch'
|
| 42 | 1 | tkerber | ] |
| 43 | 1 | tkerber | |
| 44 | 1 | tkerber | def get_optimizer(optimizer): |
| 45 | 1 | tkerber | if optimizer == 'BFGS': return BFGS |
| 46 | 1 | tkerber | elif optimizer == 'LBFGS': return LBFGS |
| 47 | 1 | tkerber | elif optimizer == 'LBFGSLineSearch': return LBFGSLineSearch |
| 48 | 1 | tkerber | elif optimizer == 'FIRE': return FIRE |
| 49 | 1 | tkerber | elif optimizer == 'MDMin': return MDMin |
| 50 | 1 | tkerber | elif optimizer == 'SciPyFminCG': return SciPyFminCG |
| 51 | 1 | tkerber | elif optimizer == 'SciPyFminBFGS': return SciPyFminBFGS |
| 52 | 1 | tkerber | elif optimizer == 'BFGSLineSearch': return BFGSLineSearch |
| 53 | 1 | tkerber | |
| 54 | 1 | tkerber | def run_test(get_atoms, get_calculator, name, |
| 55 | 1 | tkerber | fmax=0.05, steps=100, plot=True): |
| 56 | 1 | tkerber | |
| 57 | 1 | tkerber | plotter = Plotter(name, fmax) |
| 58 | 1 | tkerber | csvwriter = CSVWriter(name) |
| 59 | 1 | tkerber | for optimizer in optimizers: |
| 60 | 1 | tkerber | note = ''
|
| 61 | 1 | tkerber | logname = name + '-' + optimizer
|
| 62 | 1 | tkerber | |
| 63 | 1 | tkerber | atoms = get_atoms() |
| 64 | 1 | tkerber | atoms.set_calculator(get_calculator()) |
| 65 | 1 | tkerber | opt = get_optimizer(optimizer) |
| 66 | 1 | tkerber | relax = opt(atoms, logfile=None)
|
| 67 | 1 | tkerber | #logfile = logname + '.log',
|
| 68 | 1 | tkerber | #trajectory = logname + '.traj')
|
| 69 | 1 | tkerber | |
| 70 | 1 | tkerber | obs = DataObserver(atoms) |
| 71 | 1 | tkerber | relax.attach(obs) |
| 72 | 1 | tkerber | try:
|
| 73 | 1 | tkerber | relax.run(fmax = fmax, steps = steps) |
| 74 | 1 | tkerber | E = atoms.get_potential_energy() |
| 75 | 1 | tkerber | |
| 76 | 1 | tkerber | if relax.get_number_of_steps() == steps:
|
| 77 | 1 | tkerber | note = 'Not converged in %i steps' % steps
|
| 78 | 1 | tkerber | except Exception: |
| 79 | 1 | tkerber | traceback.print_exc() |
| 80 | 1 | tkerber | note = 'An exception occurred'
|
| 81 | 1 | tkerber | E = np.nan |
| 82 | 1 | tkerber | |
| 83 | 1 | tkerber | nsteps = relax.get_number_of_steps() |
| 84 | 1 | tkerber | if hasattr(relax, 'force_calls'): |
| 85 | 1 | tkerber | fc = relax.force_calls |
| 86 | 1 | tkerber | if rank == 0: |
| 87 | 1 | tkerber | print '%-15s %-15s %3i %8.3f (%3i) %s' % (name, optimizer, nsteps, E, fc, note) |
| 88 | 1 | tkerber | else:
|
| 89 | 1 | tkerber | fc = nsteps |
| 90 | 1 | tkerber | if rank == 0: |
| 91 | 1 | tkerber | print '%-15s %-15s %3i %8.3f %s' % (name, optimizer, nsteps, E, note) |
| 92 | 1 | tkerber | |
| 93 | 1 | tkerber | plotter.plot(optimizer, obs.get_E(), obs.get_fmax()) |
| 94 | 1 | tkerber | csvwriter.write(optimizer, nsteps, E, fc, note) |
| 95 | 1 | tkerber | |
| 96 | 1 | tkerber | plotter.save() |
| 97 | 1 | tkerber | csvwriter.finalize() |
| 98 | 1 | tkerber | |
| 99 | 1 | tkerber | class Plotter: |
| 100 | 1 | tkerber | def __init__(self, name, fmax): |
| 101 | 1 | tkerber | self.name = name
|
| 102 | 1 | tkerber | self.fmax = fmax
|
| 103 | 1 | tkerber | if rank == 0: |
| 104 | 1 | tkerber | self.fig = pl.figure(figsize=[12.0, 9.0]) |
| 105 | 1 | tkerber | self.axes0 = self.fig.add_subplot(2, 1, 1) |
| 106 | 1 | tkerber | self.axes1 = self.fig.add_subplot(2, 1, 2) |
| 107 | 1 | tkerber | |
| 108 | 1 | tkerber | def plot(self, optimizer, E, fmax): |
| 109 | 1 | tkerber | if rank == 0: |
| 110 | 1 | tkerber | self.axes0.plot(E, label = optimizer)
|
| 111 | 1 | tkerber | self.axes1.plot(fmax)
|
| 112 | 1 | tkerber | |
| 113 | 1 | tkerber | def save(self, format='png'): |
| 114 | 1 | tkerber | if rank == 0: |
| 115 | 1 | tkerber | self.axes0.legend()
|
| 116 | 1 | tkerber | self.axes0.set_title(self.name) |
| 117 | 1 | tkerber | self.axes0.set_ylabel('E [eV]') |
| 118 | 1 | tkerber | #self.axes0.set_yscale('log')
|
| 119 | 1 | tkerber | |
| 120 | 1 | tkerber | self.axes1.set_xlabel('steps') |
| 121 | 1 | tkerber | self.axes1.set_ylabel('fmax [eV/A]') |
| 122 | 1 | tkerber | self.axes1.set_yscale('log') |
| 123 | 1 | tkerber | self.axes1.axhline(self.fmax, color='k', linestyle='--') |
| 124 | 1 | tkerber | self.fig.savefig(self.name + '.' + format) |
| 125 | 1 | tkerber | |
| 126 | 1 | tkerber | class CSVWriter: |
| 127 | 1 | tkerber | def __init__(self, name): |
| 128 | 1 | tkerber | self.f = paropen(name + '.csv', 'w') |
| 129 | 1 | tkerber | |
| 130 | 1 | tkerber | def write(self, optimizer, nsteps, E, fc, note=''): |
| 131 | 1 | tkerber | self.f.write(
|
| 132 | 1 | tkerber | '%s,%i,%i,%f,%s\n' % (optimizer, nsteps, fc, E, note)
|
| 133 | 1 | tkerber | ) |
| 134 | 1 | tkerber | |
| 135 | 1 | tkerber | def finalize(self): |
| 136 | 1 | tkerber | self.f.close()
|
| 137 | 1 | tkerber | |
| 138 | 1 | tkerber | class DataObserver: |
| 139 | 1 | tkerber | def __init__(self, atoms): |
| 140 | 1 | tkerber | self.atoms = atoms
|
| 141 | 1 | tkerber | self.E = []
|
| 142 | 1 | tkerber | self.fmax = []
|
| 143 | 1 | tkerber | |
| 144 | 1 | tkerber | def __call__(self): |
| 145 | 1 | tkerber | self.E.append(self.atoms.get_potential_energy()) |
| 146 | 1 | tkerber | self.fmax.append(np.sqrt((self.atoms.get_forces()**2).sum(axis=1)).max()) |
| 147 | 1 | tkerber | |
| 148 | 1 | tkerber | def get_E(self): |
| 149 | 1 | tkerber | return np.array(self.E) |
| 150 | 1 | tkerber | |
| 151 | 1 | tkerber | def get_fmax(self): |
| 152 | 1 | tkerber | return np.array(self.fmax) |