def __getitem__(self, i=-1): b = self.backend[i] atoms = Atoms(positions=b.positions, numbers=self.numbers, cell=b.cell, masses=self.masses, pbc=self.pbc, celldisp=self.celldisp, info=b.get('info'), constraint=[dict2constraint(d) for d in decode(self.constraints)], momenta=b.get('momenta'), magmoms=b.get('magmoms'), charges=b.get('charges'), tags=b.get('tags')) atoms._readTags(self.new_tags) if 'calculator' in b: results = {} c = b.calculator for prop in all_properties: if prop in c: results[prop] = c.get(prop) calc = SinglePointCalculator(atoms, **results) calc.name = b.calculator.name atoms.set_calculator(calc) return atoms
def __getitem__(self, i=-1): if isinstance(i, slice): return SlicedTrajectory(self, i) b = self.backend[i] if 'numbers' in b: # numbers and other header info was written alongside the image: atoms = read_atoms(b, traj=self) else: # header info was not written because they are the same: atoms = read_atoms( b, header=[self.pbc, self.numbers, self.masses, self.constraints], traj=self) if 'calculator' in b: results = {} implemented_properties = [] c = b.calculator for prop in all_properties: if prop in c: results[prop] = c.get(prop) implemented_properties.append(prop) calc = SinglePointCalculator(atoms, **results) calc.name = b.calculator.name calc.implemented_properties = implemented_properties if 'parameters' in c: calc.parameters.update(c.parameters) atoms.calc = calc return atoms
def write(self, at, **kwargs): import ase.db from ase.calculators.singlepoint import SinglePointCalculator all_kwargs = self.kwargs.copy() all_kwargs.update(kwargs) all_kwargs.update(at.params) energy = at.params.get('energy', None) forces = getattr(at, 'force', None) if forces is not None: forces = forces.T stress = at.params.get('virial', None) if stress is not None: stress = -stress.view(np.ndarray) / at.get_volume() orig_calc = at.get_calculator() params = {} data = {} skip_params = ['energy', 'virial', 'calculator', 'id', 'unique_id'] # filter out duplicate data for (key, value) in all_kwargs.items(): key = key.lower() if key in skip_params: continue if (isinstance(value, int) or isinstance(value, basestring) or isinstance(value, float) or isinstance(value, bool)): # scalar key/value pairs params[key] = value else: # more complicated data structures data[key] = value skip_arrays = ['numbers', 'positions', 'species'] for (key, value) in at.arrays.items(): if key in skip_arrays: continue key = key.lower() data[key] = value try: calc = SinglePointCalculator(atoms=at, energy=energy, forces=forces, stress=stress) if orig_calc is not None: calc.name = orig_calc.name else: calc.name = all_kwargs.get('calculator', '(unknown)') at.set_calculator(calc) database = ase.db.connect(self.dbfile) database.write(at, key_value_pairs=params, data=data) finally: at.set_calculator(orig_calc)
def irc(minmode, maxiter, ftol, dx=0.01, direction='both', **kwargs): d = minmode.d if direction not in ['forward', 'reverse', 'both']: raise ValueError("Don't understand direction='{}'".format(direction)) x = minmode.x_m.copy() conf = minmode.atoms.copy() calc = SinglePointCalculator(conf, **minmode.atoms.calc.results) conf.set_calculator(conf) path = [conf] f1, g1, _ = minmode.kick(np.zeros_like(x)) minmode.f_minmode(**kwargs) if np.linalg.norm(g1) > ftol: warnings.warn('Initial forces are greater than convergence tolerance! ' 'Are you sure this is a transition state?') if direction == 'both': x0 = minmode.x.copy() H = minmode.H.copy() last = minmode.last.copy() fpath = irc(minmode, maxiter, ftol, dx, 'forward', **kwargs) minmode.x = x0 minmode.H = H minmode.last = last rpath = irc(minmode, maxiter, ftol, dx, 'reverse', **kwargs) return list(reversed(fpath)) + rpath[1:] d1 = minmode.vecs[:, 0] d1 *= dx / np.linalg.norm(d1) if direction == 'reverse': d1 *= -1 xi = 1. # Outer loop finds all points along the MEP while True: f1, g1, _ = minmode.kick(d1) # Inner loop optimizes each individual point along the MEP while True: eps, xi = rs_newton_irc(minmode, g1, d1, dx, xi) epsnorm = np.linalg.norm(eps) print('Epsnorm is {}'.format(epsnorm)) if epsnorm < 1e-4: break f1, g1, _ = minmode.kick(eps) d1 += eps conf = minmode.atoms.copy() calc = SinglePointCalculator(conf, **minmode.atoms.calc.results) conf.set_calculator(calc) path.append(conf) if np.all(minmode.lams > 0) and minmode.converged(ftol): return path
def test_standardcomparator(): from ase.ga.standard_comparators import (InteratomicDistanceComparator, EnergyComparator, RawScoreComparator, SequentialComparator) from ase import Atoms from ase.calculators.singlepoint import SinglePointCalculator from ase.ga import set_raw_score a1 = Atoms('AgAgAg', positions=[[0, 0, 0], [1.5, 0, 0], [1.5, 1.5, 0]]) a2 = Atoms('AgAgAg', positions=[[0, 0, 0], [1.4, 0, 0], [1.5, 1.5, 0]]) e1 = 1.0 e2 = 0.8 a1.set_calculator(SinglePointCalculator(a1, energy=e1)) a2.set_calculator(SinglePointCalculator(a2, energy=e2)) comp1 = InteratomicDistanceComparator(n_top=3, pair_cor_cum_diff=0.03, pair_cor_max=0.7, dE=0.3) assert comp1.looks_like(a1, a2) comp2 = InteratomicDistanceComparator(n_top=3, pair_cor_cum_diff=0.03, pair_cor_max=0.7, dE=0.15) assert not comp2.looks_like(a1, a2) comp3 = InteratomicDistanceComparator(n_top=3, pair_cor_cum_diff=0.02, pair_cor_max=0.7, dE=0.3) assert not comp3.looks_like(a1, a2) hard_E_comp = EnergyComparator(dE=1.0) assert hard_E_comp.looks_like(a1, a2) soft_E_comp = EnergyComparator(dE=.01) assert not soft_E_comp.looks_like(a1, a2) set_raw_score(a1, .1) set_raw_score(a2, .27) rs_comp = RawScoreComparator(0.15) assert not rs_comp.looks_like(a1, a2) comp1 = SequentialComparator([hard_E_comp, rs_comp], [0, 0]) assert not comp1.looks_like(a1, a2) comp2 = SequentialComparator([hard_E_comp, rs_comp], [0, 1]) assert comp2.looks_like(a1, a2)
def __getitem__(self, i=-1): b = self.backend[i] atoms = read_atoms(b, header=[self.pbc, self.numbers, self.masses, self.constraints]) if 'calculator' in b: results = {} c = b.calculator for prop in all_properties: if prop in c: results[prop] = c.get(prop) calc = SinglePointCalculator(atoms, **results) calc.name = b.calculator.name atoms.set_calculator(calc) return atoms
def convert(self): lines = open(self.xdatcar).readlines() if len(lines[7].split()) == 0: del (lines[0:8]) elif len(lines[5].split()) == 0: del (lines[0:6]) elif len(lines[4].split()) == 0: del (lines[0:5]) elif lines[7].split()[0] == 'Direct': del (lines[0:8]) step = 0 iatom = 0 scaled_pos = [] for line in lines: if iatom == len(self.atoms): if step == 0: self.out.write_header(self.atoms[self.calc.resort]) scaled_pos = np.array(scaled_pos) # Now resort the positions to match self.atoms self.atoms.set_scaled_positions(scaled_pos[self.calc.resort]) calc = SinglePointCalculator(self.atoms, energy=self.energies[step], forces=self.forces[step]) self.atoms.calc = calc self.out.write(self.atoms) scaled_pos = [] iatom = 0 step += 1 else: if not line.split()[0] == 'Direct': iatom += 1 scaled_pos.append( [float(line.split()[n]) for n in range(3)]) # Write also the last image # I'm sure there is also more clever fix... if step == 0: self.out.write_header(self.atoms[self.calc.resort]) scaled_pos = np.array(scaled_pos)[self.calc.resort] self.atoms.set_scaled_positions(scaled_pos) calc = SinglePointCalculator(self.atoms, energy=self.energies[step], forces=self.forces[step]) self.atoms.calc = calc self.out.write(self.atoms) self.out.close()
def load_castep(file_name): """Load the results of a CASTEP calculation Args: file_name (str): name of the `*-out.cell` file to load. Returns: atoms (ase.Atoms): the loaded ase atoms object with a CASTEP single point calculator containing thr results of the computation attached. """ atoms = io.read(file_name) try: # Create a calculator to store the energy & forces atoms_cast = io.read(file_name.replace('-out.cell', '.castep')) energy = atoms_cast.get_potential_energy() forces = atoms_cast.get_forces() spcalc = SinglePointCalculator(atoms, energy=energy, forces=forces) atoms.set_calculator(spcalc) except: # Something is wrong. The run didn't finish executing or failed to # converge print("Failed to load -out.cell file") atoms.set_tags(tag_muon(atoms)) atoms.info['original_file'] = file_name.replace('-out.cell', '.cell') return atoms
def main(): db_name = "data/almgsicu.db" traj = TrajectoryWriter("data/almgsicu_data.traj") db = connect(db_name) groups = set() for row in db.select(): g = row.get('group', None) if g is not None and g not in exclude_groups: groups.add(g) structures = [] for g in groups: row = db.get(group=g, struct_type='initial') init = row.toatoms() if init.get_chemical_formula() in ignore_formulas: continue try: final = db.get(group=g, struct_type='relaxed') except: continue energy = 0.0 if final is not None: energy = final.energy calc = SinglePointCalculator(init, energy=energy) init.calc = calc structures.append(init) for idx in sorted(equiv_from_atat, reverse=True): del structures[idx] for s in structures: traj.write(s)
def new_db(kwargs, new_db_name): db_name = "almgsi_newconfig.db" kwargs["db_name"] = new_db_name bc = BulkCrystal(**kwargs) names = [] db = connect(db_name) for row in db.select(converged=1): names.append(row.name) ns = GenerateStructures(bc, struct_per_gen=10) for name in names: print(name) init_struct = None final_struct = None energy = 0.0 for row in db.select(name=name): if row["calculator"] == "unknown": energy = row.energy init_struct = row.toatoms() else: final_struct = row.toatoms() calc = SinglePointCalculator(final_struct, energy=energy) final_struct.set_calculator(calc) try: ns.insert_structure(init_struct=init_struct, final_struct=final_struct, generate_template=True) except Exception as exc: print(str(exc))
def get_traj(self): self.uc= np.linalg.inv(self.cell) images = [] his = TrajectoryWriter(self.structure+'.traj',mode='w') indexs = np.array(self.indexs) ind = indexs.argsort() batch_ = self.batch if self.nframe>self.batch else self.nframe for i in range(batch_): ii = ind[i] xf = np.dot(self.x[ii],self.uc) xf = np.mod(xf,1.0) self.x[ii] = np.dot(xf,self.cell) if self.qs is None: c = None else: c = self.qs[i] A = Atoms(self.atom_name,self.x[ii], charges=c, cell=self.cells[ii],pbc=[True,True,True]) if self.checkMol: A = press_mol(A) calc = SinglePointCalculator(A,energy=float(self.energy_nw[ii])) A.set_calculator(calc) his.write(atoms=A) images.append(A) his.close() return images
def save_current_status(self): # save current atoms t = self.atoms.copy() t.info = self.atoms.info.copy() e = self.atoms.get_potential_energy() f = self.atoms.get_forces() spc = SinglePointCalculator(t, energy=e, forces=f) t.set_calculator(spc) write(self.fn_current_atoms, t) accept_digits = "" for ii in self.accept_history: accept_digits += str(ii) accept_digits += "," accept_digits = accept_digits[:-1] # save the current status of the basin hopping info = { "nsteps": self.nsteps, "no_improvement_step": self.no_improvement_step, 'Temperature': self.T, "free_energy_min": self.free_energy_min, "energy_min": self.energy_min, 'history': accept_digits, 'on_optimization': self.on_optimization } with open(self.fn_status_file, "w") as fp: json.dump(info, fp, sort_keys=True, indent=4, separators=(',', ': '))
def extract_cluster(atoms): max_dist = 3.0 mg_indx = [atom.index for atom in atoms if atom.symbol == "Mg"] indices = deepcopy(mg_indx) for indx in mg_indx: indx_dist = list(range(len(atoms))) del indx_dist[indx] indx_dist = np.array(indx_dist) dists = atoms.get_distances(indx, indx_dist, mic=True) dists = np.array(dists) new_indx = indx_dist[dists<max_dist] indices += list(new_indx) indices = list(set(indices)) cluster = atoms[indices] cell = cluster.get_cell() diag = 0.5*(cell[0, :] + cell[1, :] + cell[2, :]) indices = list(range(1, len(cluster))) dist = cluster.get_distances(0, indices, mic=True, vector=True) com = np.mean(dist, axis=0) + cluster[0].position cluster.translate(diag-com) cluster.wrap() energy = atoms.get_potential_energy() calc = SinglePointCalculator(cluster, energy=energy) cluster.set_calculator(calc) return cluster
def amp_data(lab='amp', dft='siesta', dic='/home/gfeng/siesta/train/ethane', batch=800,sort=False): ''' prepare data for AMP ''' md = MDtoData(dft=dft,direc=dic, batch=batch,sort=sort) if len(md.energy_nw)<batch: batch = len(md.energy_nw) box = [md.cell[0][0],md.cell[1][1],md.cell[2][2]] his = TrajectoryWriter(lab+'.traj',mode='w') for i in range(batch): md.energy_nw[i] x = np.mod(md.x[i],box) A = Atoms(md.atom_name,x,cell=md.cell,pbc=[True,True,True]) e = float(md.energy_nw[i]) calc = SinglePointCalculator(A,energy=e, free_energy=float(md.max_e), forces=md.forces[i]) A.set_calculator(calc) his.write(atoms=A) del A his.close()
def read_positions_qe(qe_output_name): """ Input a QE logfile name and it extracts the postions and cells to build a trajectory file. May only work for pw? """ # initialize arrays and atoms object steps = extract_coordinates(qe_output_name) energies = get_total_energies(qe_output_name) nsteps = max(steps.keys()) + 1 forces = get_forces(qe_output_name) images = [] for istep in range(nsteps): symbols = [ ''.join(i for i in s if not i.isdigit()) for s in [i[0] for i in steps[istep]['positions']] ] positions = [i[1] for i in steps[istep]['positions']] mask = [len(i) != 3 for i in positions] posclean = [i[:3] for i in positions] cell = steps[istep]['cell'] atoms = Atoms(symbols, posclean, cell=cell, pbc=(1, 1, 1)) atoms.set_constraint(FixAtoms(mask=mask)) calc = SinglePointCalculator(atoms=atoms, energy=energies[istep], forces=forces[istep], stress=None, magmoms=None) atoms.set_calculator(calc) images.append(atoms) return images
def decompostion(gen='rdx.gen', ncpu=12): ''' decompostion energy of N-NO2 ''' traj = TrajectoryWriter('stretch.traj', mode='w') ncfg = 20 A = read(gen) s = stretch(A, shrink=0.8, enlarge=2.6, fix_end=3, move_end=18, move_atoms=[18, 19, 20], nconfig=ncfg) for i in range(ncfg): atoms = s.move(i) write_nwchem_inp(atoms, struc=gen.split('.')[0], task='dft gradient', xc='b3lyp', basis='6-311G*') system('mpirun -n %d nwchem inp-nw > nw.out' % (ncpu)) e, grad_ = get_nw_gradient(out='nw.out') system('cp nw.out nw_%s.out' % str(i)) system('rm QMD-*') print('- energy(NWchem):', e) calc = SinglePointCalculator(atoms, energy=e) atoms.set_calculator(calc) traj.write(atoms=atoms) traj.close()
def main(rowNum): conc = get_conc(rowNum) print(conc) if conc is None: return settings = settings_from_json(settings_file) atoms = bulk('Al', a=4.05, crystalstructure='fcc', cubic=True) * (N, N, N) atoms = attach_calculator(settings, atoms, get_eci()) cu = ['Cu'] * int(conc['Cu'] * len(atoms)) si = ['Si'] * int(conc['Si'] * len(atoms)) mg = ['Mg'] * int(conc['Mg'] * len(atoms)) al = ['Al'] * (len(atoms) - len(cu) - len(mg) - len(si)) symbols = al + mg + si + cu shuffle(symbols) atoms.symbols = symbols # Trigger a calculation atoms.get_potential_energy() temperatures = list(range(1000, 1, -50)) obs = LowestEnergyStructure(atoms) for T in temperatures: print(f"Temperature {T}") mc = Montecarlo(atoms, T) mc.attach(obs) mc.run(steps=20 * len(atoms)) db = connect(db_name) calc = SinglePointCalculator(obs.emin_atoms, energy=obs.lowest_energy) obs.emin_atoms.set_calculator(calc) db.write(obs.emin_atoms)
def load_dftb_calculator(directory, atoms): """ Set the tag for a muon in an atoms object Args: directory (str): path to a directory to load DFTB+ results Returns: calculator (ase.calculator.SinglePointCalculator): a single point calculator for the results of the DFTB+ calculation """ results_file = os.path.join(directory, "results.tag") temp_file = os.path.join(directory, "results.tag.bak") # We need to backup the results file here because # .read_results() will remove the results file with BackupFile(results_file, temp_file): calc = Dftb(atoms=atoms) calc.atoms_input = atoms calc.directory = directory calc.read_results() return SinglePointCalculator(atoms, energy=calc.get_potential_energy(), forces=calc.get_forces(), charges=calc.get_charges(atoms), stress=calc.get_stress(atoms))
def to_ase(self): arrays_keys = set(self.arrays_keys) info_keys = set(self.info_keys) cell = self.pop('cell', None) pbc = self.pop('pbc', None) numbers = self.pop('numbers', None) positions = self.pop('positions', None) results_keys = self.derived['results_keys'] info_keys -= {'cell', 'pbc'} arrays_keys -= {'numbers', 'positions'} atoms = Atoms(cell=cell, pbc=pbc, numbers=numbers, positions=positions) if 'calculator_name' in self: # calculator_name = self['info'].pop('calculator_name') # atoms.calc = get_calculator(data['results']['calculator_name'])(**params) params = self.pop('calculator_parameters', {}) atoms.calc = SinglePointCalculator(atoms, **params) atoms.calc.results.update((key, self[key]) for key in results_keys) atoms.arrays.update((key, np.array(self[key])) for key in arrays_keys) atoms.info.update((key, self[key]) for key in info_keys) return atoms
def load_dftb_precon(file_name): """Load the results of a DFTB+ calculation that was run with the ASE preconditioned optimizer Args: file_name (str): name of the `results.json` file to load. Returns: atoms (ase.Atoms): the loaded ase atoms object with a DFTB+ single point calculator containing the results of the computation attached. """ def load_file(file_name): atoms = io.read(file_name) atoms_orig = io.read(file_name.replace(".xyz", ".gen")) atoms.cell = atoms_orig.cell return atoms results = json.load(open(file_name, 'r')) atoms_file = 'geo_end.xyz' atoms = load_file(os.path.join(os.path.dirname(file_name), atoms_file)) calc = SinglePointCalculator(atoms, energy=results['energy'], forces=results['forces']) atoms.set_calculator(calc) atoms.set_tags(tag_muon(atoms)) return atoms
def read_lammps_dump(fdump, nequil=None, iframes=None): from ovito.io import import_file pl = import_file(fdump) # pipe line nframe = pl.source.num_frames traj = [] if iframes is None: iframes = range(nframe) if nequil is not None: iframes = iframes[nequil:] for iframe in iframes: dc = pl.compute(iframe) # data collection atoms = dc.to_ase_atoms() atoms.info['Timestep'] = dc.attributes['Timestep'] keys_to_delete = [key for key in atoms.arrays.keys() if key not in ['numbers', 'positions']] for key in keys_to_delete: del atoms.arrays[key] # any results to add? results = get_particle_results(dc) if 'Charge' in results: # add charges atoms.set_initial_charges(results['Charge']) add_results = {} lmp_names = ['Force', 'Dipole Orientation'] ase_names = ['forces', 'dipole'] for lmp_name, ase_name in zip(lmp_names, ase_names): if lmp_name in results: add_results[ase_name] = results[lmp_name] traj.append(atoms) if len(add_results) > 0: from ase.calculators.singlepoint import SinglePointCalculator calc = SinglePointCalculator(atoms) calc.results.update(add_results) atoms.set_calculator(calc) return traj
def __init__(self, atoms): """ | It wraps :obj:`ase.Atoms` object to define additional methods and attributes. | Before wrapping, it sorts atoms by element alphabetically. | It stores calculated neighbor information such as distance, indices. Args: atoms (~ase.Atoms): an object to wrap. """ tags = atoms.get_chemical_symbols() deco = sorted([(tag, i) for i, tag in enumerate(tags)]) indices = [i for tag, i in deco] self._atoms = atoms[indices] results = {} calculator = atoms.get_calculator() if calculator: for key, value in calculator.results.items(): if key in atoms.arrays: results[key] = value[indices] else: results[key] = value self._atoms.set_calculator( SinglePointCalculator(self._atoms, **results)) self._cache = {}
def calc(id): db = connect(db_name) atoms_orig = db.get_atoms(id=id) kvp = db.get(id=id).key_value_pairs atoms = atoms_orig.copy() # Do linear interpolation of the cell size a_au = 4.0782 a_cu = 3.6149 symbs = atoms.get_chemical_symbols() count = {"Au": 0, "Cu": 0} for s in symbs: count[s] += 1 c_au = float(count["Au"]) / len(atoms) a = a_au * c_au + a_cu * (1.0 - c_au) a_orig = 3.9 cell = atoms.get_cell() atoms.set_cell(cell * a / a_orig, scale_atoms=True) calc = EMT() atoms.set_calculator(calc) relaxer = BFGS(atoms) relaxer.run(fmax=0.025) res = minimize(relax_cell, a, args=(atoms, cell)) print(res["x"]) relaxer = BFGS(atoms) relaxer.run(fmax=0.025) energy = atoms.get_potential_energy() del db[id] calc = SinglePointCalculator(atoms_orig, energy=energy) atoms_orig.set_calculator(calc) kvp["converged"] = True db.write(atoms_orig, key_value_pairs=kvp)
def dict2atoms(dct, attach_calculator=False): constraint_dicts = dct.get('constraints') if constraint_dicts: constraints = [] for c in constraint_dicts: assert c.pop('__name__') == 'ase.constraints.FixAtoms' constraints.append(FixAtoms(**c)) else: constraints = None atoms = Atoms(dct['numbers'], dct['positions'], cell=dct['cell'], pbc=dct['pbc'], magmoms=dct.get('magmoms'), charges=dct.get('charges'), tags=dct.get('tags'), masses=dct.get('masses'), momenta=dct.get('momenta'), constraint=constraints) results = dct.get('results') if attach_calculator: atoms.calc = get_calculator( dct['calculator_name'])(**dct['calculator_parameters']) elif results: atoms.calc = SinglePointCalculator(atoms, **results) return atoms
def convert_to_cubic(setting_prim): conc_args = { "conc_ratio_min_1":[[64,0,0]], "conc_ratio_max_1":[[24,40,0]], "conc_ratio_min_2":[[64,0,0]], "conc_ratio_max_2":[[22,21,21]] } setting_cubic = BulkCrystal( crystalstructure="fcc", a=4.05, size=[3,3,3], basis_elements=[["Mg","Si","Al",]], \ conc_args=conc_args, db_name=db_name_cubic, max_cluster_size=4, cubic=True ) view(setting_cubic.atoms) atoms = setting_prim.atoms.copy() a = 4.05 atoms.set_cell([[4*a,0,0],[0,4*a,0],[0,0,4*a]]) atoms.wrap() view(atoms) print (setting_prim.atoms.get_cell()) exit() out_file = "data/temp_out.xyz" target_cell = setting_cubic.atoms.get_cell() cubic_str_gen = struc_generator = GenerateStructures( setting_cubic, struct_per_gen=10 ) db = connect(db_name) for row in db.select(converged=1): energy = row.energy atoms = row.toatoms() atoms.set_cell(target_cell) atoms.wrap() write(out_file,atoms) calc = SinglePointCalculator(atoms,energy=energy) atoms.set_calculator(calc) cubic_str_gen.insert_structure(init_struct=out_file,final_struct=atoms)
def to_labeled_system(self, data, *args, **kwargs): '''Convert System to ASE Atoms object.''' from ase import Atoms from ase.calculators.singlepoint import SinglePointCalculator structures = [] species = [data['atom_names'][tt] for tt in data['atom_types']] for ii in range(data['coords'].shape[0]): structure = Atoms(symbols=species, positions=data['coords'][ii], pbc=not data.get('nopbc', False), cell=data['cells'][ii]) results = { 'energy': data["energies"][ii], 'forces': data["forces"][ii] } if "virials" in data: # convert to GPa as this is ase convention v_pref = 1 * 1e4 / 1.602176621e6 vol = structure.get_volume() results['stress'] = data["virials"][ii] / (v_pref * vol) structure.calc = SinglePointCalculator(structure, **results) structures.append(structure) return structures
def singlePoint(self, anew): a = anew.copy() # Save structure with ML-energy if self.master: self.writer_spPredict.write(a) # broadcast structure, so all cores have the same pos = a.positions if self.master: pos = a.positions self.comm.broadcast(pos, 0) a.positions = pos self.comm.barrier() # Perform single-point label = self.traj_namebase + '{}'.format(self.traj_counter) E, F = singleGPAW(a, label, calc=self.calc) self.comm.barrier() # save structure for training results = {'energy': E, 'forces': F} calc_sp = SinglePointCalculator(a, **results) a.set_calculator(calc_sp) self.a_add.append(a) # Save to spTrain-trajectory self.writer_spTrain.write(a, energy=E, forces=F) self.ksaved += 1 return E, F
def read_dacapo(filename): from ase.io.pupynere import NetCDFFile nc = NetCDFFile(filename) vars = nc.variables cell = vars['UnitCell'][-1] try: magmoms = vars['InitialAtomicMagneticMoment'][:] except KeyError: magmoms = None try: tags = vars['AtomTags'][:] except KeyError: tags = None atoms = Atoms(scaled_positions=vars['DynamicAtomPositions'][-1], symbols=[(a + b).strip() for a, b in vars['DynamicAtomSpecies'][:]], cell=cell, magmoms=magmoms, tags=tags, pbc=True) try: energy = vars['TotalEnergy'][-1] force = vars['DynamicAtomForces'][-1] except KeyError: energy = None force = None calc = SinglePointCalculator(atoms, energy=energy, forces=force) ### Fixme magmoms atoms.set_calculator(calc) return atoms
def test_struc_from_ase(): from ase import Atoms from ase.calculators.singlepoint import SinglePointCalculator results = { "forces": np.random.randn(20, 3), "energy": np.random.rand(), "stress": np.random.randn(6), } uc = Atoms( ["Pd" for i in range(10)] + ["Ag" for i in range(10)], positions=np.random.rand(20, 3), cell=np.random.rand(3, 3), ) calculator = SinglePointCalculator(uc, **results) uc.set_calculator(calculator) new_struc = Structure.from_ase_atoms(uc) assert np.all(new_struc.species_labels == uc.get_chemical_symbols()) assert np.all(new_struc.positions == uc.get_positions()) assert np.all(new_struc.cell == uc.get_cell()) assert np.all(new_struc.forces == results["forces"]) assert np.all(new_struc.energy == results["energy"]) assert np.all(new_struc.stress == results["stress"])
def read_castep_geom(fd, index=None, units=units_CODATA2002): """Reads a .geom file produced by the CASTEP GeometryOptimization task and returns an atoms object. The information about total free energy and forces of each atom for every relaxation step will be stored for further analysis especially in a single-point calculator. Note that everything in the .geom file is in atomic units, which has been conversed to commonly used unit angstrom(length) and eV (energy). Note that the index argument has no effect as of now. Contribution by Wei-Bing Zhang. Thanks! Routine now accepts a filedescriptor in order to out-source the *.gz and *.bz2 handling to formats.py. Note that there is a fallback routine read_geom() that behaves like previous versions did. """ from ase.calculators.singlepoint import SinglePointCalculator # fd is closed by embracing read() routine txt = fd.readlines() traj = [] Hartree = units['Eh'] Bohr = units['a0'] # Yeah, we know that... # print('N.B.: Energy in .geom file is not 0K extrapolated.') for i, line in enumerate(txt): if line.find('<-- E') > 0: start_found = True energy = float(line.split()[0]) * Hartree cell = [x.split()[0:3] for x in txt[i + 1:i + 4]] cell = np.array([[float(col) * Bohr for col in row] for row in cell]) if line.find('<-- R') > 0 and start_found: start_found = False geom_start = i for i, line in enumerate(txt[geom_start:]): if line.find('<-- F') > 0: geom_stop = i + geom_start break species = [line.split()[0] for line in txt[geom_start:geom_stop]] geom = np.array([[float(col) * Bohr for col in line.split()[2:5]] for line in txt[geom_start:geom_stop]]) forces = np.array([[ float(col) * Hartree / Bohr for col in line.split()[2:5] ] for line in txt[geom_stop:geom_stop + (geom_stop - geom_start)]]) image = ase.Atoms(species, geom, cell=cell, pbc=True) image.set_calculator( SinglePointCalculator(atoms=image, energy=energy, forces=forces)) traj.append(image) if index is None: return traj else: return traj[index]
def store_E_and_F_in_spc(self): """Collect the energies and forces on all nodes and store as single point calculators""" # Make sure energies and forces are known on all nodes self.get_forces() images = self.images if self.parallel: energy = np.empty(1) forces = np.empty((self.natoms, 3)) for i in range(1, self.nimages - 1): # Determine which node is the leading for image i root = (i - 1) * self.world.size // (self.nimages - 2) # If on this node, extract the calculated numbers if self.world.rank == root: energy[0] = images[i].get_potential_energy() forces = images[i].get_forces() # Distribute these numbers to other nodes self.world.broadcast(energy, root) self.world.broadcast(forces, root) # On all nodes, remove the calculator, keep only energy # and force in single point calculator self.images[i].calc = SinglePointCalculator(self.images[i], energy=energy[0], forces=forces)
def dict2atoms(dct, attach_calculator=False): constraint_dicts = dct.get('constraints') if constraint_dicts: constraints = [dict2constraint(c) for c in constraint_dicts] else: constraints = None atoms = Atoms(dct['numbers'], dct['positions'], cell=dct['cell'], pbc=dct['pbc'], magmoms=dct.get('initial_magmoms'), charges=dct.get('initial_charges'), tags=dct.get('tags'), masses=dct.get('masses'), momenta=dct.get('momenta'), constraint=constraints) if attach_calculator: atoms.calc = get_calculator( dct['calculator'])(**dct['calculator_parameters']) else: results = {} for prop in all_properties: if prop in dct: results[prop] = dct[prop] if results: atoms.calc = SinglePointCalculator(atoms, **results) return atoms
def __getitem__(self, i=-1): b = self.backend[i] if 'numbers' in b: # numbers and other header info was written alongside the image: atoms = read_atoms(b) else: # header info was not written because they are the same: atoms = read_atoms(b, header=[self.pbc, self.numbers, self.masses, self.constraints]) if 'calculator' in b: results = {} c = b.calculator for prop in all_properties: if prop in c: results[prop] = c.get(prop) calc = SinglePointCalculator(atoms, **results) calc.name = b.calculator.name atoms.set_calculator(calc) return atoms
def write(self, atoms=None, **kwargs): """Write the atoms to the file. If the atoms argument is not given, the atoms object specified when creating the trajectory object is used. Use keyword arguments to add extra properties:: writer.write(atoms, energy=117, dipole=[0, 0, 1.0]) """ b = self.backend if atoms is None: atoms = self.atoms if hasattr(atoms, 'interpolate'): # seems to be a NEB neb = atoms assert not neb.parallel or world.size == 1 for image in neb.images: self.write(image) return while hasattr(atoms, 'atoms_for_saving'): # Seems to be a Filter or similar, instructing us to # save the original atoms. atoms = atoms.atoms_for_saving if self.header_data is None: b.write(version=1, ase_version=__version__) if self.description: b.write(description=self.description) # Atomic numbers and periodic boundary conditions are written # in the header in the beginning. # # If an image later on has other numbers/pbc, we write a new # header. All subsequent images will then have their own header # whether or not their numbers/pbc change. self.header_data = get_header_data(atoms) write_header = True else: if not self.multiple_headers: header_data = get_header_data(atoms) self.multiple_headers = not headers_equal(self.header_data, header_data) write_header = self.multiple_headers write_atoms(b, atoms, write_header=write_header) calc = atoms.get_calculator() if calc is None and len(kwargs) > 0: calc = SinglePointCalculator(atoms) if calc is not None: if not hasattr(calc, 'get_property'): calc = OldCalculatorWrapper(calc) c = b.child('calculator') c.write(name=calc.name) if hasattr(calc, 'todict'): d = calc.todict() if d: c.write(parameters=d) for prop in all_properties: if prop in kwargs: x = kwargs[prop] else: if self.properties is not None: if prop in self.properties: x = calc.get_property(prop, atoms) else: x = None else: try: x = calc.get_property(prop, atoms, allow_calculation=False) except (PropertyNotImplementedError, KeyError): # KeyError is needed for Jacapo. x = None if x is not None: if prop in ['stress', 'dipole']: x = x.tolist() c.write(prop, x) info = {} for key, value in atoms.info.items(): try: encode(value) except TypeError: warnings.warn('Skipping "{0}" info.'.format(key)) else: info[key] = value if info: b.write(info=info) b.sync()
def write(self, atoms=None, **kwargs): """Write the atoms to the file. If the atoms argument is not given, the atoms object specified when creating the trajectory object is used. Use keyword arguments to add extra properties:: writer.write(atoms, energy=117, dipole=[0, 0, 1.0]) """ b = self.backend if atoms is None: atoms = self.atoms if hasattr(atoms, 'interpolate'): # seems to be a NEB neb = atoms assert not neb.parallel or world.size == 1 for image in neb.images: self.write(image) return while hasattr(atoms, 'atoms_for_saving'): # Seems to be a Filter or similar, instructing us to # save the original atoms. atoms = atoms.atoms_for_saving if len(b) == 0: b.write(version=1, ase_version=__version__) if self.description: b.write(description=self.description) # Atomic numbers and periodic boundary conditions are only # written once - in the header. Store them here so that we can # check that they are the same for all images: self.numbers = atoms.get_atomic_numbers() self.pbc = atoms.get_pbc() else: if (atoms.pbc != self.pbc).any(): raise ValueError('Bad periodic boundary conditions!') elif len(atoms) != len(self.numbers): raise ValueError('Bad number of atoms!') elif (atoms.numbers != self.numbers).any(): raise ValueError('Bad atomic numbers!') write_atoms(b, atoms, write_header=(len(b) == 0)) calc = atoms.get_calculator() if calc is None and len(kwargs) > 0: calc = SinglePointCalculator(atoms) if calc is not None: if not hasattr(calc, 'get_property'): calc = OldCalculatorWrapper(calc) c = b.child('calculator') c.write(name=calc.name) if hasattr(calc, 'todict'): d = calc.todict() if d: c.write(parameters=d) for prop in all_properties: if prop in kwargs: x = kwargs[prop] else: if self.properties is not None: if prop in self.properties: x = calc.get_property(prop, atoms) else: x = None else: try: x = calc.get_property(prop, atoms, allow_calculation=False) except (PropertyNotImplementedError, KeyError): # KeyError is needed for Jacapo. x = None if x is not None: if prop in ['stress', 'dipole']: x = x.tolist() c.write(prop, x) info = {} for key, value in atoms.info.items(): try: encode(value) except TypeError: warnings.warn('Skipping "{0}" info.'.format(key)) else: info[key] = value if info: b.write(info=info) b.sync()
def read_gaussian_out(filename, index=-1, quantity='atoms', quantities=None): """"Interface to GaussianReader and returns various quantities""" energy = 0.0 try: data = GR(filename)[index] except IndexError: return {} positions = np.array(data['Positions']) numbers = np.array(data['Atomic_numbers']) method = data['Method'] version = data['Version'] if method.lower()[1:] in allowed_methods: method = 'HF' atoms = Atoms(positions=positions, numbers=numbers) for key, value in data.items(): if key in method: #covers case where calculation is a scan and hence energy is a list of values not a single one try: energy = value[-1] except TypeError: energy = value if energy: energy_set = True else: energy_set = False try: # Re-read in the log file f = open(filename, 'r') lines = f.readlines() f.close() forces = list() for n, line in enumerate(lines): if 'oniom' in method.lower() and 'extrapolated energy' in line: energy = float(line.split()[4]) elif not energy_set and 'SCF Done' in line: energy = float(line.split()[4]) if ('Forces (Hartrees/Bohr)' in line): for j in range(len(atoms)): forces += [[float(lines[n + j + 3].split()[2]), float(lines[n + j + 3].split()[3]), float(lines[n + j + 3].split()[4])]] #convert = ase.units.Hartree / ase.units.Bohr convert = utils.convertor(1, 'hartree', 'eV') / utils.convertor(1, 'bohr', 'Angstrom') forces = np.array(forces) * convert except: forces = None #energy *= ase.units.Hartree # Convert the energy from a.u. to eV energy = utils.convertor(energy, 'hartree', 'eV') calc = SinglePointCalculator(atoms, energy=energy, forces=forces) calc.path = os.path.split(filename)[0] calc.label = os.path.split(filename)[1].replace('.log', '') calc.data = data atoms.set_calculator(calc) data_dict = {'energy': energy, 'forces': forces, 'dipole': data.get('Dipole'), 'atoms': atoms, 'version': version} if quantities: return [data_dict[q] for q in quantities] elif quantity in data_dict: return data_dict[quantity] else: return None
def write(self, atoms=None, **kwargs): """Write the atoms to the file. If the atoms argument is not given, the atoms object specified when creating the trajectory object is used. Use keyword arguments to add extra properties:: writer.write(atoms, energy=117, dipole=[0, 0, 1.0]) """ b = self.backend if atoms is None: atoms = self.atoms if hasattr(atoms, 'interpolate'): # seems to be a NEB neb = atoms assert not neb.parallel or world.size == 1 for image in neb.images: self.write(image) return if len(b) == 0: self.write_header(atoms) else: if (atoms.pbc != self.pbc).any(): raise ValueError('Bad periodic boundary conditions!') elif len(atoms) != len(self.numbers): raise ValueError('Bad number of atoms!') elif (atoms.numbers != self.numbers).any(): raise ValueError('Bad atomic numbers!') b.write(positions=atoms.get_positions(), cell=atoms.get_cell().tolist()) if atoms.has('tags'): b.write(tags=atoms.get_tags()) if atoms.has('momenta'): b.write(momenta=atoms.get_momenta()) if atoms.has('magmoms'): b.write(magmoms=atoms.get_initial_magnetic_moments()) if atoms.has('charges'): b.write(charges=atoms.get_initial_charges()) calc = atoms.get_calculator() if calc is None and len(kwargs) > 0: calc = SinglePointCalculator(atoms) if calc is not None: if not isinstance(calc, Calculator): calc = OldCalculatorWrapper(calc) c = b.child('calculator') c.write(name=calc.name) for prop in all_properties: if prop in kwargs: x = kwargs[prop] else: if self.properties is not None: if prop in self.properties: x = calc.get_property(prop, atoms) else: x = None else: try: x = calc.get_property(prop, atoms, allow_calculation=False) except (NotImplementedError, KeyError): # KeyError is needed for Jacapo. x = None if x is not None: if prop in ['stress', 'dipole']: x = x.tolist() c.write(prop, x) info = {} for key, value in atoms.info.items(): try: encode(value) except TypeError: warnings.warn('Skipping "{0}" info.'.format(key)) else: info[key] = value if info: b.write(info=info) b.sync()