def parse(self, opts, args): OptimizeTask.parse(self, opts, args) if opts.srelax: if len(opts.srelax.split(',')) > 1: self.sfmax, self.soptimizer = opts.srelax.split(',') else: self.sfmax = opts.srelax self.soptimizer = 'BFGS' self.sfmax = float(self.sfmax) if opts.srelaxsteps is not None: self.ssteps = int(opts.srelaxsteps) else: # yes, the default number of ASE optimizer steps # ase/optimize/optimize.py self.ssteps = 100000000 if opts.fit: points, strain = opts.fit.split(',') if float(strain) > 0: self.fit = (int(points), float(strain) * 0.01) else: self.fit = (int(points), float(strain)) self.eos = opts.eos self.crystal_structure = opts.crystal_structure self.lattice_constant = opts.lattice_constant self.c_over_a = opts.c_over_a self.orthorhombic = opts.orthorhombic self.cubic = opts.cubic self.repeat = opts.repeat
def __init__(self, crystal_structure=None, lattice_constant=None, c_over_a=None, cubic=False, orthorhombic=False, fit=None, eos=None, sfmax=None, soptimizer='BFGS', ssteps=100000000, **kwargs): """Bulk task.""" self.crystal_structure = crystal_structure self.lattice_constant = lattice_constant self.c_over_a = c_over_a self.cubic = cubic self.orthorhombic = orthorhombic self.eos = eos self.fit = fit self.sfmax = sfmax self.soptimizer = soptimizer self.ssteps = ssteps self.repeat = None OptimizeTask.__init__(self, **kwargs) self.summary_keys = ['energy', 'fitted energy', 'volume', 'B']
def add_options(self, parser): OptimizeTask.add_options(self, parser) mol = optparse.OptionGroup(parser, 'Molecule') mol.add_option('-v', '--vacuum', type='float', default=3.0, help='Amount of vacuum to add around isolated systems ' '(in Angstrom).') mol.add_option('--unit-cell', help='Unit cell. Examples: "10.0" or "9,10,11" ' + '(in Angstrom).') mol.add_option('--bond-length', type='float', help='Bond length of dimer in Angstrom.') mol.add_option('-F', '--fit', metavar='N,x', help='Find optimal bondlength and vibration ' + 'frequency using N points and displacements from ' + '-x % to +x %.') mol.add_option('--atomize', action='store_true', help='Calculate Atomization energies.') parser.add_option_group(mol)
def add_options(self, parser): OptimizeTask.add_options(self, parser) bulk = optparse.OptionGroup(parser, 'Bulk') bulk.add_option('-F', '--fit', metavar='N,x', help='Find optimal volume and bulk modulus ' + 'using N points and variations of the lattice ' + 'constants from -x % to +x %.') bulk.add_option('-x', '--crystal-structure', help='Crystal structure.', choices=[ 'sc', 'fcc', 'bcc', 'diamond', 'hcp', 'rocksalt', 'zincblende' ]) bulk.add_option('-a', '--lattice-constant', type='float', help='Lattice constant in Angstrom.') bulk.add_option('--c-over-a', type='float', help='c/a ratio.') bulk.add_option('-O', '--orthorhombic', action='store_true', help='Use orthorhombic unit cell.') bulk.add_option('-C', '--cubic', action='store_true', help='Use cubic unit cell.') bulk.add_option('-r', '--repeat', help='Repeat unit cell. Use "-r 2" or "-r 2,3,1".') parser.add_option_group(bulk)
def analyse(self): OptimizeTask.analyse(self) for name, data in self.data.items(): if 'distances' in data: distances = data['distances'] energies = data['energies'] fit0 = np.poly1d(np.polyfit(1 / distances, energies, 3)) fit1 = np.polyder(fit0, 1) fit2 = np.polyder(fit1, 1) dmin = None for t in np.roots(fit1): if t > 0 and fit2(t) > 0: dmin = 1 / t break if dmin is None: raise ValueError('No minimum!') if abs(dmin) < min(distances) or abs(dmin) > max(distances): raise ValueError('Fit outside of range! ' + \ str(abs(dmin)) + ' not in ' + \ str(distances)) emin = fit0(t) k = fit2(t) * t**4 m1, m2 = self.create_system(name).get_masses() m = m1 * m2 / (m1 + m2) hnu = units._hbar * 1e10 * sqrt(k / units._e / units._amu / m) data['minimum energy'] = emin self.results[name][1:] = [energies[2] - emin, dmin, 1000 * hnu] else: self.results[name].extend([None, None]) for name, data in self.data.items(): atoms = self.create_system(name) if len(atoms) == 1: self.results[name].extend([None, None]) continue eatoms = 0.0 for symbol in atoms.get_chemical_symbols(): if symbol in self.data and symbol != name: eatoms += self.data[symbol]['energy'] else: eatoms = None break ea = None ea0 = None if eatoms is not None: ea = eatoms - data['energy'] if 'minimum energy' in data: ea0 = eatoms - data['minimum energy'] self.results[name].extend([ea, ea0])
def add_options(self, parser): OptimizeTask.add_options(self, parser) bulk = optparse.OptionGroup(parser, 'Bulk') bulk.add_option( '-F', '--fit', metavar='N,x', help='Find optimal volume and bulk modulus ' + 'using odd N points and variations of the lattice ' + 'constant a from -x % to +x %, i.e. in the interval ' '<a - a * x * 100, ..., a, ..., a + a * x * 100>. ' + 'This method gives non-equidistant sampling of volume. ' + 'With x negative (in Angstrom**3) the sampling of ' + 'the cell volume (v) in the interval ' + '<(1 + x /v), ..., 1, ..., (1 - x /v)> is used. ' + 'This method gives equidistant sampling of volume.') bulk.add_option('--eos', type='str', metavar='eos', help='Selects the type of eos.') bulk.add_option( '--srelax', metavar='SFMAX[,SOPTIMIZER]', help='Relax cell by minimizing stress using StranFilter ' 'with SOPTIMIZER algorithm. The SOPTIMIZER keyword is ' 'optional, and if omitted BFGS is used by default.') bulk.add_option('--srelaxsteps', type='int', metavar='ssteps', help='Limit the number of SF optimizer steps.') bulk.add_option('-x', '--crystal-structure', help='Crystal structure.', choices=[ 'sc', 'fcc', 'bcc', 'hcp', 'diamond', 'zincblende', 'rocksalt', 'cesiumchloride', 'fluorite' ]) bulk.add_option('-a', '--lattice-constant', type='float', help='Lattice constant in Angstrom.') bulk.add_option('--c-over-a', type='float', help='c/a ratio.') bulk.add_option('-O', '--orthorhombic', action='store_true', help='Use orthorhombic unit cell.') bulk.add_option('-C', '--cubic', action='store_true', help='Use cubic unit cell.') bulk.add_option('-r', '--repeat', help='Repeat unit cell. Use "-r 2" or "-r 2,3,1".') parser.add_option_group(bulk)
def parse(self, opts, args): OptimizeTask.parse(self, opts, args) if opts.fit: points, strain = opts.fit.split(',') self.fit = (int(points), float(strain) * 0.01) self.crystal_structure = opts.crystal_structure self.lattice_constant = opts.lattice_constant self.c_over_a = opts.c_over_a self.orthorhombic = opts.orthorhombic self.cubic = opts.cubic self.repeat = opts.repeat
def calculate(self, name, atoms): if self.fit and len(atoms) == 2: return self.fit_bond_length(name, atoms) else: data = OptimizeTask.calculate(self, name, atoms) self.check_occupation_numbers(atoms) return data
def parse(self, opts, args): OptimizeTask.parse(self, opts, args) self.vacuum = opts.vacuum self.bond_length = opts.bond_length self.atomize = opts.atomize if opts.fit: points, strain = opts.fit.split(',') self.fit = (int(points), float(strain) * 0.01) if opts.unit_cell: if ',' in opts.unit_cell: self.unit_cell = [float(x) for x in opts.unit_cell.split(',')] else: self.unit_cell = [float(opts.unit_cell)] * 3
def run(self, names1): names = [] atoms = set() for name in names1: if name.lower() == 'g2': from ase.data.g2 import molecule_names names.extend(molecule_names) from ase.data.g2 import atom_names if self.atomize: atoms.update(atom_names) elif name.lower() == 'g2-1': from ase.data.g2_1 import molecule_names names.extend(molecule_names) from ase.data.g2_1 import atom_names if self.atomize: atoms.update(atom_names) else: names.append(name) if self.atomize: atoms.update( self.build_system(name).get_chemical_symbols()) if self.atomize: names.extend(atoms) return OptimizeTask.run(self, names)
def calculate(self, name, atoms): data = OptimizeTask.calculate(self, name, atoms) if self.fmax is not None and len(atoms) == 2: data['distance'] = atoms.get_distance(0, 1) self.check_occupation_numbers(atoms) if self.fit and len(atoms) == 2: self.fit_bond_length(name, atoms, data) return data
def __init__(self, crystal_structure=None, lattice_constant=None, c_over_a=None, cubic=False, orthorhombic=False, fit=None, **kwargs): """Bulk task.""" self.crystal_structure = crystal_structure self.lattice_constant = lattice_constant self.c_over_a = c_over_a self.cubic = cubic self.orthorhombic = orthorhombic self.fit = fit self.repeat = None OptimizeTask.__init__(self, **kwargs) self.summary_keys = ['energy', 'fitted energy', 'volume', 'B']
def analyse(self): OptimizeTask.analyse(self) for name, data in self.data.items(): if 'strains' in data: atoms = self.create_system(name) volumes = data['strains']**3 * atoms.get_volume() energies = data['energies'] eos = EquationOfState(volumes, energies) try: v, e, B = eos.fit() except ValueError: self.results[name].extend([None, None]) else: self.results[name][1:] = [energies[2] - e, v, B * 1e24 / units.kJ] else: self.results[name].extend([None, None])
def __init__(self, vacuum=3.0, cell=None, atomize=False, bond_length=None, fit=None, **kwargs): """Molecule task. This task can calculate bond lengths and vibration frequencies of dimer molecules.""" self.vacuum = vacuum self.unit_cell = cell self.atomize = atomize self.bond_length = bond_length self.fit = fit OptimizeTask.__init__(self, **kwargs) self.summary_keys = ['energy', 'relaxed energy', 'distance', 'frequency', 'atomic energy']
def analyse(self): OptimizeTask.analyse(self) for name, data in self.data.items(): if 'strains' in data: atoms = self.create_system(name) volumes = data['strains']**3 * atoms.get_volume() energies = data['energies'] eos = EquationOfState(volumes, energies) try: v, e, B = eos.fit() except ValueError: self.results[name].extend([None, None]) else: self.results[name][1:] = [ energies[2] - e, v, B * 1e24 / units.kJ ] else: self.results[name].extend([None, None])
def __init__(self, crystal_structure=None, lattice_constant=None, c_over_a=None, cubic=False, orthorhombic=False, fit=None, **kwargs): """Bulk task.""" self.crystal_structure = crystal_structure self.lattice_constant = lattice_constant self.c_over_a = c_over_a self.cubic = cubic self.orthorhombic = orthorhombic self.fit = fit self.repeat = None OptimizeTask.__init__(self, **kwargs) self.summary_header += [('V0', 'Ang^3'), ('B', 'GPa')]
def calculate(self, name, atoms): if self.fmax is not None: # this performs relaxation of internal degrees of freedom data = OptimizeTask.calculate(self, name, atoms) data['distance'] = atoms.get_distance(0, -1) else: # no optimization if self.fit is None or len(atoms) != 2: # for dimers: only calculate single-point energy if no fit follows data = OptimizeTask.calculate(self, name, atoms) if self.fit is not None and len(atoms) == 2: if self.fmax is not None: # fit after optimization self.fit_bond_length(name, atoms, data) else: # fit is the only task performed data = self.fit_bond_length(name, atoms) self.check_occupation_numbers(atoms) return data
def __init__(self, vacuum=3.0, cell=None, atomize=False, bond_length=None, fit=None, **kwargs): """Molecule task. This task can calculate bond lengths and vibration frequencies of dimer molecules.""" self.vacuum = vacuum self.unit_cell = cell self.atomize = atomize self.bond_length = bond_length self.fit = fit OptimizeTask.__init__(self, **kwargs) self.summary_header += [('d0', 'Ang'), ('hnu', 'meV'), ('Ea', 'eV'), ('Ea0', 'eV')]
def add_options(self, parser): OptimizeTask.add_options(self, parser) bulk = optparse.OptionGroup(parser, 'Bulk') bulk.add_option('-F', '--fit', metavar='N,x', help='Find optimal volume and bulk modulus ' + 'using odd N points and variations of the lattice ' + 'constant a from -x % to +x %, i.e. in the interval ' '<a - a * x * 100, ..., a, ..., a + a * x * 100>. ' + 'This method gives non-equidistant sampling of volume. ' + 'With x negative (in Angstrom**3) the sampling of ' + 'the cell volume (v) in the interval ' + '<(1 + x /v), ..., 1, ..., (1 - x /v)> is used. ' + 'This method gives equidistant sampling of volume.') bulk.add_option('--eos', type='str', metavar='eos', help='Selects the type of eos.') bulk.add_option('--srelax', metavar='SFMAX[,SOPTIMIZER]', help='Relax cell by minimizing stress using StranFilter ' 'with SOPTIMIZER algorithm. The SOPTIMIZER keyword is ' 'optional, and if omitted BFGS is used by default.') bulk.add_option('--srelaxsteps', type='int', metavar='ssteps', help='Limit the number of SF optimizer steps.') bulk.add_option('-x', '--crystal-structure', help='Crystal structure.', choices=['sc', 'fcc', 'bcc', 'hcp', 'diamond', 'zincblende', 'rocksalt', 'cesiumchloride', 'fluorite']) bulk.add_option('-a', '--lattice-constant', type='float', help='Lattice constant in Angstrom.') bulk.add_option('--c-over-a', type='float', help='c/a ratio.') bulk.add_option('-O', '--orthorhombic', action='store_true', help='Use orthorhombic unit cell.') bulk.add_option('-C', '--cubic', action='store_true', help='Use cubic unit cell.') bulk.add_option('-r', '--repeat', help='Repeat unit cell. Use "-r 2" or "-r 2,3,1".') parser.add_option_group(bulk)
def add_options(self, parser): OptimizeTask.add_options(self, parser) bulk = optparse.OptionGroup(parser, 'Bulk') bulk.add_option('-F', '--fit', metavar='N,x', help='Find optimal volume and bulk modulus ' + 'using N points and variations of the lattice ' + 'constants from -x % to +x %.') bulk.add_option('-x', '--crystal-structure', help='Crystal structure.', choices=['sc', 'fcc', 'bcc', 'diamond', 'hcp', 'rocksalt', 'zincblende']) bulk.add_option('-a', '--lattice-constant', type='float', help='Lattice constant in Angstrom.') bulk.add_option('--c-over-a', type='float', help='c/a ratio.') bulk.add_option('-O', '--orthorhombic', action='store_true', help='Use orthorhombic unit cell.') bulk.add_option('-C', '--cubic', action='store_true', help='Use cubic unit cell.') bulk.add_option('-r', '--repeat', help='Repeat unit cell. Use "-r 2" or "-r 2,3,1".') parser.add_option_group(bulk)
def expand(self, names): """Expand fcc, bcc, hcp and diamond. The name fcc will be expanded to all the elements with the fcc stucture and so on.""" names = OptimizeTask.expand(self, names) newnames = [] for name in names: if name in ['fcc', 'bcc', 'hcp', 'diamond']: for Z in range(1, 95): x = reference_states[Z] if x is not None and x['symmetry'] == name: newnames.append(chemical_symbols[Z]) else: newnames.append(name) return newnames
def run(self, names1): names = [] atoms = set() for name in names1: if name.lower() == 'g2': from ase.data.g2 import molecule_names names.extend(molecule_names) from ase.data.g2 import atom_names if self.atomize: atoms.update(atom_names) elif name.lower() == 'g2-1': from ase.data.g2_1 import molecule_names names.extend(molecule_names) from ase.data.g2_1 import atom_names if self.atomize: atoms.update(atom_names) else: names.append(name) if self.atomize: atoms.update(self.build_system(name).get_chemical_symbols()) if self.atomize: names.extend(atoms) return OptimizeTask.run(self, names)
def calculate(self, name, atoms): #???? if self.sfmax is not None and self.fmax is not None: # this performs first relaxation of internal degrees of freedom data = OptimizeTask.calculate(self, name, atoms) # writing traj from optimizer does not work for StrainFilter! traj = PickleTrajectory(self.get_filename(name, 'traj'), 'a', atoms) sf = StrainFilter(atoms) while not self.converged(atoms, sfmax=self.sfmax, fmax=self.fmax): # take a step on the cell self.soptimize(name, sf, data, trajectory=traj) # relax internal degrees of freedom OptimizeTask.optimize(self, name, atoms, data, trajectory=traj) data['relaxed energy'] = atoms.get_potential_energy() data['relaxed volume'] = atoms.get_volume() elif self.sfmax is not None: # this performs single-point energy calculation data = OptimizeTask.calculate(self, name, atoms) sf = StrainFilter(atoms) # writing traj from optimizer does not work for StrainFilter! traj = PickleTrajectory(self.get_filename(name, 'traj'), 'w', atoms) self.soptimize(name, sf, data, trajectory=traj) data['relaxed energy'] = atoms.get_potential_energy() data['relaxed volume'] = atoms.get_volume() elif self.fmax is not None: data = OptimizeTask.calculate(self, name, atoms) else: # no optimization if self.fit is None: # only calculate single-point energy if no fit follows data = OptimizeTask.calculate(self, name, atoms) if self.fit is not None: if self.sfmax is not None or self.fmax is not None: # fit after optimization self.fit_volume(name, atoms, data) else: # fit is the only task performed data = self.fit_volume(name, atoms) return data
def calculate(self, name, atoms): #???? if self.sfmax is not None and self.fmax is not None: # this performs first relaxation of internal degrees of freedom data = OptimizeTask.calculate(self, name, atoms) # writing traj from optimizer does not work for StrainFilter! traj = Trajectory(self.get_filename(name, 'traj'), 'a', atoms) sf = StrainFilter(atoms) while not self.converged(atoms, sfmax=self.sfmax, fmax=self.fmax): # take a step on the cell self.soptimize(name, sf, data, trajectory=traj) # relax internal degrees of freedom OptimizeTask.optimize(self, name, atoms, data, trajectory=traj) data['relaxed energy'] = atoms.get_potential_energy() data['relaxed volume'] = atoms.get_volume() elif self.sfmax is not None: # this performs single-point energy calculation data = OptimizeTask.calculate(self, name, atoms) sf = StrainFilter(atoms) # writing traj from optimizer does not work for StrainFilter! traj = Trajectory(self.get_filename(name, 'traj'), 'w', atoms) self.soptimize(name, sf, data, trajectory=traj) data['relaxed energy'] = atoms.get_potential_energy() data['relaxed volume'] = atoms.get_volume() elif self.fmax is not None: data = OptimizeTask.calculate(self, name, atoms) else: # no optimization if self.fit is None: # only calculate single-point energy if no fit follows data = OptimizeTask.calculate(self, name, atoms) if self.fit is not None: if self.sfmax is not None or self.fmax is not None: # fit after optimization self.fit_volume(name, atoms, data) else: # fit is the only task performed data = self.fit_volume(name, atoms) return data
def calculate(self, name, atoms): #???? if self.fit: return self.fit_volume(name, atoms) else: return OptimizeTask.calculate(self, name, atoms)