def getUnitCell(self): sideLen = self.sideLen edge = Atoms() nAtom = 2 * sideLen + 1 for i in range(nAtom): if i % 2 == 0: label = 'C' y = 0.5 else: label = 'N' if len(self.elements) == 1: label = 'C' y = 1.0 x = (-sideLen + i) * 0.5 * sqrt(3) y -= (sideLen + 1) * 1.5 atom = Atom(label, (x, y, 0.0)) edge.append(atom) unitCell = Atoms() for i in range(6): newEdge = edge.copy() newEdge.rotate('z', i * 2 * pi / 6.0) unitCell.extend(newEdge) #get cell dist = (self.sideLen + 1) * 3.0 #the distance between 2 hole center if self.cubic: newAtoms = unitCell.copy() newAtoms.translate([dist * sqrt(3) / 2, dist / 2.0, 0]) unitCell.extend(newAtoms) unitCell.set_cell([dist * sqrt(3), dist, 10.0]) else: cell = np.diag([dist * sqrt(3) / 2, dist, 10]) cell[0, 1] = dist / 2.0 unitCell.set_cell(cell) return unitCell
def getUnitCell(self): sideLen=self.sideLen edge=Atoms() nAtom=2*sideLen+1 for i in range(nAtom): if i%2==0: label='C' y=0.5 else: label='N' if len(self.elements)==1:label='C' y=1.0 x=(-sideLen+i)*0.5*sqrt(3) y-=(sideLen+1)*1.5 atom=Atom(label,(x,y,0.0)) edge.append(atom) unitCell=Atoms() for i in range(6): newEdge=edge.copy() newEdge.rotate('z',i*2*pi/6.0) unitCell.extend(newEdge) #get cell dist=(self.sideLen+1)*3.0 #the distance between 2 hole center if self.cubic: newAtoms=unitCell.copy() newAtoms.translate([dist*sqrt(3)/2,dist/2.0,0]) unitCell.extend(newAtoms) unitCell.set_cell([dist*sqrt(3),dist,10.0]) else: cell=np.diag([dist*sqrt(3)/2,dist,10]) cell[0,1]=dist/2.0 unitCell.set_cell(cell) return unitCell
def testSingle(molecule): #TEST fragmentation print "Test fragmentation with s22 set" fragment_names = [molecule+'_f1',molecule+'_f2'] test_f = Fragmentation([molecule]) minimize = False #minimize = True print 'Relaxed:', minimize sys = Atoms(s22_sim_data[molecule]['symbols'], s22_sim_data[molecule]['positions']) test_f.molecules = [ReaxFFSystem(molecule,atoms=sys, fragment_list=fragment_names, minimize=minimize)] n = s22_sim_data[molecule]['dimer atoms'] atom_fragments = [ sys.copy()[range(n[0])], sys.copy()[range(n[0],n[0]+n[1])] ] test_f.fragments = [ ReaxFFSystem(name,atoms=a, minimize = minimize) for name,a in zip(fragment_names,atom_fragments)] test_f.fill_data_reference(data_type='s22') test_f.run(write=True) print test_f.data
def test_turbomole_h3o2m(): # http://jcp.aip.org/resource/1/jcpsa6/v97/i10/p7507_s1 doo = 2.74 doht = 0.957 doh = 0.977 angle = radians(104.5) initial = Atoms('HOHOH', positions=[(-sin(angle) * doht, 0., cos(angle) * doht), (0., 0., 0.), (0., 0., doh), (0., 0., doo), (sin(angle) * doht, 0., doo - cos(angle) * doht) ]) if 0: view(initial) final = Atoms('HOHOH', positions=[(-sin(angle) * doht, 0., cos(angle) * doht), (0., 0., 0.), (0., 0., doo - doh), (0., 0., doo), (sin(angle) * doht, 0., doo - cos(angle) * doht)]) if 0: view(final) # Make band: images = [initial.copy()] for i in range(3): images.append(initial.copy()) images.append(final.copy()) neb = NEB(images, climb=True) # Write all commands for the define command in a string define_str = ('\n\na coord\n\n*\nno\nb all 3-21g ' 'hondo\n*\neht\n\n-1\nno\ns\n*\n\ndft\non\nfunc ' 'pwlda\n\n\nscf\niter\n300\n\n*') # Set constraints and calculator: constraint = FixAtoms(indices=[1, 3]) # fix OO BUG No.1: fixes atom 0 and 1 # constraint = FixAtoms(mask=[0,1,0,1,0]) # fix OO #Works without patch for image in images: image.calc = Turbomole(define_str=define_str) image.set_constraint(constraint) # Relax initial and final states: if 1: dyn1 = QuasiNewton(images[0]) dyn1.run(fmax=0.10) dyn2 = QuasiNewton(images[-1]) dyn2.run(fmax=0.10) # Interpolate positions between initial and final states: neb.interpolate() if 1: for image in images: print(image.get_distance(1, 2), image.get_potential_energy()) dyn = BFGS(neb, trajectory='turbomole_h3o2m.traj') dyn.run(fmax=0.10) for image in images: print(image.get_distance(1, 2), image.get_potential_energy())
def test_distance(): import itertools import numpy as np from ase import Atoms, Atom from ase.geometry import distance # artificial structure org = Atoms('COPNS', [[-1.75072, 0.62689, 0.00000], [0.58357, 2.71652, 0.00000], [-5.18268, 1.36522, 0.00000], [-1.86663, -0.77867, 2.18917], [-1.80586, 0.20783, -2.79331]]) maxdist = 3.0e-13 # translate for dx in range(3, 10, 2): new = org.copy() new.translate([dx / np.sqrt(2), -dx / np.sqrt(2), 0]) dist = distance(org, new, True) dist2 = distance(org, new, False) print('translation', dx, '-> distance', dist) assert dist < maxdist assert dist == dist2 # rotate for axis in ['x', '-y', 'z', np.array([1, 1, 1] / np.sqrt(3))]: for rot in [20, 200]: new = org.copy() new.translate(-new.get_center_of_mass()) new.rotate(rot, axis) dist = distance(org, new, True) dist2 = distance(org, new, False) print('rotation', axis, ', angle', rot, '-> distance', dist) assert dist < maxdist assert dist == dist2 if 0: # reflect new = Atoms() cm = org.get_center_of_mass() for a in org: new.append(Atom(a.symbol, -(a.position - cm))) dist = distance(org, new) print('reflected -> distance', dist) # permute for i, a in enumerate(org): if i < 3: a.symbol = 'H' for indxs in itertools.permutations(range(3)): new = org.copy() for c in range(3): new[c].position = org[indxs[c]].position dist = distance(org, new) print('permutation', indxs, '-> distance', dist) assert dist < maxdist
def main(): #TEST atomization print "Test atomization" molecule_names = ['CH4'] test = Fragmentation(molecule_names) test.molecules = [ GPAWSystems(name, h=0.3, vacuum=2.0, xc='PBE') for name in molecule_names ] atom_names = [] for gs in test.molecules: atom_names.extend(gs.system.get_chemical_symbols()) test.fragments = [ GPAWSystems(name, h=0.3, vacuum=2.0, xc='PBE') for name in set(atom_names) ] test.fill_data_reference(data_type='g22') test.run() error = 5.64039227514 - test.mae print 'Test error: {0} eV'.format(error) #TEST fragmentation print "Test fragmentation with s22 set" molecule = 'Ammonia_dimer' fragment_names = [molecule + '_f1', molecule + 'f2'] test_f = Fragmentation([molecule]) sys = Atoms(s22_sim_data[molecule]['symbols'], s22_sim_data[molecule]['positions']) test_f.molecules = [ GPAWSystems(molecule, atoms=sys, h=0.4, vacuum=2.0, fragment_list=fragment_names) ] n = s22_sim_data[molecule]['dimer atoms'] atom_fragments = [ sys.copy()[range(n[0])], sys.copy()[range(n[0], n[0] + n[1])] ] test_f.fragments = [ GPAWSystems(name, atoms=a, h=0.4, vacuum=2.0) for name, a in zip(fragment_names, atom_fragments) ] test_f.fill_data_reference(data_type='s22') test_f.run(write=True) error = 266.704827694 - test_f.mae print 'Test error: {0} eV'.format(error)
def test_h3o2m(): # http://jcp.aip.org/resource/1/jcpsa6/v97/i10/p7507_s1 doo = 2.74 doht = 0.957 doh = 0.977 angle = radians(104.5) initial = Atoms('HOHOH', positions=[(-sin(angle) * doht, 0, cos(angle) * doht), (0., 0., 0.), (0., 0., doh), (0., 0., doo), (sin(angle) * doht, 0., doo - cos(angle) * doht) ]) if 0: view(initial) final = Atoms('HOHOH', positions=[(-sin(angle) * doht, 0., cos(angle) * doht), (0., 0., 0.), (0., 0., doo - doh), (0., 0., doo), (sin(angle) * doht, 0., doo - cos(angle) * doht)]) if 0: view(final) # Make band: images = [initial.copy()] for i in range(3): images.append(initial.copy()) images.append(final.copy()) neb = NEB(images, climb=True) def calculator(): return NWChem(task='gradient', theory='scf', charge=-1) # Set constraints and calculator: constraint = FixAtoms(indices=[1, 3]) # fix OO for image in images: image.calc = calculator() image.set_constraint(constraint) # Relax initial and final states: if 1: dyn1 = QuasiNewton(images[0]) dyn1.run(fmax=0.10) dyn2 = QuasiNewton(images[-1]) dyn2.run(fmax=0.10) # Interpolate positions between initial and final states: neb.interpolate() if 1: for image in images: print(image.get_distance(1, 2), image.get_potential_energy()) dyn = BFGS(neb, trajectory='nwchem_h3o2m.traj') dyn.run( fmax=0.10) # use better basis (e.g. aug-cc-pvdz) for NEB to converge for image in images: print(image.get_distance(1, 2), image.get_potential_energy())
def test_supercell_w_periodic_atom_removed(comparator): s1 = Atoms(['H', 'H', 'He', 'He', 'He'], positions=[[.1, .1, .1], [-.1, -.1, -.1], [.4, .3, .2], [.3, .6, .3], [.8, .5, .6]], cell=[1, 1, 1], pbc=True) s1 *= (2, 1, 1) a0 = s1.copy() del a0[0] a5 = s1.copy() del a5[5] assert comparator.compare(a0, a5) assert comparator.compare(a5, a0) == comparator.compare(a0, a5)
def testSingle(moleculeName = "Methane_dimer"): #TEST fragmentation print "Test fragmentation with s22 set" minimize = False minimize = True print 'Relaxed:', minimize fragTest = Fragmentation([moleculeName]) #atoms = s22.create_s22_system(moleculeName) data = s22.data[moleculeName] atoms = Atoms(data['symbols'], data['positions']) dimer1End = s22.data[moleculeName]['dimer atoms'][0] frag1Atoms = atoms.copy()[:dimer1End] frag2Atoms = atoms.copy()[dimer1End:] calculate_charges(frag1Atoms) calculate_charges(frag2Atoms) atoms.set_charges(np.append(frag1Atoms.get_charges(), frag2Atoms.get_charges())) fragment1 = CHARMMSystem(moleculeName + '_f1', frag1Atoms, minimize = minimize) fragment2 = CHARMMSystem(moleculeName + '_f2', frag2Atoms, minimize = minimize) system = CHARMMSystem(moleculeName, atoms, minimize = minimize, fragment_list = [fragment1.name, fragment2.name]) fragTest.molecules = [system] fragTest.fragments = [fragment1, fragment2] fragTest.fill_data_reference(data_type='s22') fragTest.run(write=True) import ase.io ase.io.write('molecule.xyz', atoms) print fragTest.data
def test_obtain_geometries(self): vibrations = self.vibrational_analysis.parse_vibrations() symbol_dict = { 17: "Cl", 9: "F", 8: "O", 7: "N", 6: "C", 1: "H", } atoms = [] parser = ccread(self.vibrational_analysis.log_file) for atom_num, coords in zip(parser.atomnos, parser.atomcoords[-1]): atoms.append(Atom(symbol=symbol_dict[atom_num], position=coords)) test_pre_geometry = Atoms(atoms) test_post_geometry = test_pre_geometry.copy() for vib, displacement in vibrations: if vib < 0: test_post_geometry.arrays["positions"] -= displacement pre_geometry, post_geometry = self.vibrational_analysis.obtain_geometries( ) for i, positions in enumerate(test_pre_geometry.arrays["positions"]): for j, x in enumerate(positions): self.assertEqual(x, pre_geometry.arrays["positions"][i][j]) for i, positions in enumerate(test_post_geometry.arrays["positions"]): for j, x in enumerate(positions): self.assertEqual(x, post_geometry.arrays["positions"][i][j])
def __init__(self, structure: Atoms, sublattices: Sublattices) -> None: self._structure = structure.copy() self._occupations = self._structure.numbers self._sublattices = sublattices self._sites_by_species = self._get_sites_by_species()
def test_harmonic_vibrations(self, testdir): """Check the numerics with a trivial case: one atom in harmonic well""" rng = np.random.RandomState(42) k = rng.rand() ref_atoms = Atoms('H', positions=np.zeros([1, 3])) atoms = ref_atoms.copy() mass = atoms.get_masses()[0] atoms.calc = ForceConstantCalculator(D=np.eye(3) * k, ref=ref_atoms, f0=np.zeros((1, 3))) vib = Vibrations(atoms, name='harmonic') vib.run() vib.read() expected_energy = ( units._hbar # In J/s * np.sqrt(k # In eV/A^2 * units._e # eV -> J * units.m**2 # A^-2 -> m^-2 / mass # in amu / units._amu # amu^-1 -> kg^-1 )) / units._e # J/s -> eV/s assert np.allclose(vib.get_energies(), expected_energy)
class TestSlab(): "Adsorption of N2 on Ag slab - vibration with frozen molecules" def setup(self): # To reproduce n2_on_ag_data: # from ase.build import fcc111, add_adsorbate # ag_slab = fcc111('Ag', (4, 4, 2), a=2.031776) # ag_slab.calc = EMT() # n2 = Atoms('N2', # positions=[(0, 0, 0), (0, 0, 1.1)], # calculator=EMT()) # QuasiNewton(n2).run(fmax=0.01) # add_adsorbate(ag_slab, n2, height=0.1, position='fcc') # QuasiNewton(ag_slab).run(fmax=1e-3) self.n2_on_ag = Atoms(**n2_on_ag_data) def test_vibrations_on_surface(self, testdir): atoms = self.n2_on_ag.copy() atoms.calc = EMT() vibs = Vibrations(atoms, indices=[-2, -1]) vibs.run() freqs = vibs.get_frequencies() vib_data = vibs.get_vibrations() assert_array_almost_equal(freqs, vib_data.get_frequencies())
def add(self, _=None): """Add atoms.""" atoms = self.structure.copy() selection = self.selection if self.ligand.value == 0: initial_ligand = Atoms([Atom(self.element.value, [0, 0, 0])]) rad = SYMBOL_RADIUS[self.element.value] else: initial_ligand = self.ligand.rotate(align_to=self.action_vector) rad = SYMBOL_RADIUS[self.ligand.anchoring_atom] for idx in self.selection: # It is important to copy, otherwise the initial structure will be modified position = self.structure.positions[idx].copy() lgnd = initial_ligand.copy() if self.bond_length.disabled: lgnd.translate( position + self.action_vector * (SYMBOL_RADIUS[self.structure.symbols[idx]] + rad)) else: lgnd.translate(position + self.action_vector * self.bond_length.value) atoms += lgnd self.structure = atoms self.selection = selection
def test_info(): from ase import Atoms from ase.io import Trajectory # Create a molecule with an info attribute info = dict( creation_date='2011-06-27', chemical_name='Hydrogen', # custom classes also works provided that it is # imported and pickleable... foo={'seven': 7}) molecule = Atoms('H2', positions=[(0., 0., 0.), (0., 0., 1.1)], info=info) assert molecule.info == info # Copy molecule atoms = molecule.copy() assert atoms.info == info # Save molecule to trajectory traj = Trajectory('info.traj', 'w', atoms=molecule) traj.write() del traj # Load molecule from trajectory t = Trajectory('info.traj') atoms = t[-1] print(atoms.info) assert atoms.info == info
def evaluate_energy(angles: Union[List[float], np.ndarray], atoms: Atoms, dihedrals: List[DihedralInfo], calc: Calculator, relax: bool = True) -> float: """Compute the energy of a cysteine molecule given dihedral angles Args: angles: List of dihedral angles atoms: Structure to optimize dihedrals: Description of the dihedral angles calc: Calculator used to compute energy/gradients relax: Whether to relax the non-dihedral degrees of freedom Returns: - (float) energy of the structure """ # Make a copy of the input atoms = atoms.copy() # Set the dihedral angles to desired settings dih_cnsts = [] for a, di in zip(angles, dihedrals): atoms.set_dihedral(*di.chain, a, indices=di.group) # Define the constraints dih_cnsts.append((a, di.chain)) # If not relaxed, just compute the energy if not relax: return calc.get_potential_energy(atoms) atoms.set_constraint() atoms.set_constraint(FixInternals(dihedrals_deg=dih_cnsts)) return relax_structure(atoms, calc)[0]
def initialize_subsystem(self, info): """Initializes a SubsystemInternal from the given Subsystem. Parameters: info: SubSystem """ name = info.name real_indices = self.generate_subsystem_indices(name) # Create a copy of the subsystem temp_atoms = Atoms() index_map = {} reverse_index_map = {} counter = 0 for index in real_indices: atom = self.atoms[index] temp_atoms.append(atom) index_map[index] = counter reverse_index_map[counter] = index counter += 1 atoms = temp_atoms.copy() atoms.set_pbc(self.atoms.get_pbc()) atoms.set_cell(self.atoms.get_cell()) # Create the SubSystem subsystem = SubSystemInternal( atoms, info, index_map, reverse_index_map, len(self.atoms)) self.subsystems[name] = subsystem
def matrix_of_equivalent_positions_from_structure(structure: Atoms, cutoff: float, position_tolerance: float, symprec: float, find_primitive: bool = True) \ -> Tuple[np.ndarray, Structure, List]: """Sets up a list of permutation maps from an Atoms object. Parameters ---------- structure input structure cutoff cutoff radius find_primitive if True the symmetries of the primitive structure will be employed symprec tolerance imposed when analyzing the symmetry using spglib position_tolerance tolerance applied when comparing positions in Cartesian coordinates Returns ------- The tuple that is returned comprises the permutation matrix, the primitive structure, and the neighbor list. """ structure = structure.copy() structure_prim = structure if find_primitive: structure_prim = get_primitive_structure(structure, symprec=symprec) logger.debug('Size of primitive structure: {}'.format(len(structure_prim))) # get symmetry information structure_as_tuple = ase_atoms_to_spglib_cell(structure_prim) symmetry = spglib.get_symmetry(structure_as_tuple, symprec=symprec) translations = symmetry['translations'] rotations = symmetry['rotations'] # set up a permutation map object matrix_of_equivalent_positions = MatrixOfEquivalentPositions( translations, rotations) # create neighbor_lists from the different cutoffs prim_icet_structure = Structure.from_atoms(structure_prim) neighbor_list = get_neighbor_lists( prim_icet_structure, [cutoff], position_tolerance=position_tolerance)[0] # get fractional positions for neighbor_list frac_positions = get_fractional_positions_from_neighbor_list( prim_icet_structure, neighbor_list) logger.debug('Number of fractional positions: {}'.format( len(frac_positions))) if frac_positions is not None: matrix_of_equivalent_positions.build(frac_positions) return matrix_of_equivalent_positions, prim_icet_structure, neighbor_list
def test_s22(): fragTest = Fragmentation(s22.s22) minimize = False #minimize = True print 'Relaxed:', minimize fragTest.molecules = [] fragTest.fragments = [] for moleculeName in s22.s22: data = s22.data[moleculeName] atoms = Atoms(data['symbols'], data['positions']) dimer1End = data['dimer atoms'][0] frag1Atoms = atoms.copy()[:dimer1End] frag2Atoms = atoms.copy()[dimer1End:] fragment1 = ReaxFFSystem(moleculeName + '_f1', frag1Atoms, minimize = minimize) fragment2 = ReaxFFSystem(moleculeName + '_f2', frag2Atoms, minimize = minimize) system = ReaxFFSystem(moleculeName, atoms, minimize = minimize, fragment_list = [fragment1.name, fragment2.name]) fragTest.molecules.append(system) fragTest.fragments += [fragment1, fragment2] fragTest.fill_data_reference(data_type='s22') fragTest.run(write=True)
def test_Ag_Cu100(): from math import sqrt from ase import Atom, Atoms from ase.neb import NEB from ase.constraints import FixAtoms from ase.vibrations import Vibrations from ase.calculators.emt import EMT from ase.optimize import QuasiNewton, BFGS # Distance between Cu atoms on a (100) surface: d = 3.6 / sqrt(2) initial = Atoms('Cu', positions=[(0, 0, 0)], cell=(d, d, 1.0), pbc=(True, True, False)) initial *= (2, 2, 1) # 2x2 (100) surface-cell # Approximate height of Ag atom on Cu(100) surfece: h0 = 2.0 initial += Atom('Ag', (d / 2, d / 2, h0)) # Make band: images = [initial.copy() for i in range(6)] neb = NEB(images, climb=True) # Set constraints and calculator: constraint = FixAtoms(range(len(initial) - 1)) for image in images: image.calc = EMT() image.set_constraint(constraint) # Displace last image: images[-1].positions[-1] += (d, 0, 0) # Relax height of Ag atom for initial and final states: dyn1 = QuasiNewton(images[0]) dyn1.run(fmax=0.01) dyn2 = QuasiNewton(images[-1]) dyn2.run(fmax=0.01) # Interpolate positions between initial and final states: neb.interpolate() for image in images: print(image.positions[-1], image.get_potential_energy()) dyn = BFGS(neb, trajectory='mep.traj') dyn.run(fmax=0.05) for image in images: print(image.positions[-1], image.get_potential_energy()) a = images[0] vib = Vibrations(a, [4]) vib.run() print(vib.get_frequencies()) vib.summary() print(vib.get_mode(-1)) vib.write_mode(-1, nimages=20)
def copy(self): cluster = Atoms.copy(self) cluster.symmetry = self.symmetry cluster.surfaces = self.surfaces.copy() cluster.lattice_basis = self.lattice_basis.copy() cluster.atomic_basis = self.atomic_basis.copy() cluster.resiproc_basis = self.resiproc_basis.copy() return cluster
def main(): #TEST atomization print "Test atomization" molecule_names = ['CH4'] test = Fragmentation(molecule_names) test.molecules = [GPAWSystems(name,h=0.3,vacuum=2.0,xc='PBE') for name in molecule_names] atom_names = [] for gs in test.molecules: atom_names.extend(gs.system.get_chemical_symbols()) test.fragments = [GPAWSystems(name,h=0.3,vacuum=2.0,xc='PBE') for name in set(atom_names)] test.fill_data_reference(data_type='g22') test.run() error = 5.64039227514 - test.mae print 'Test error: {0} eV'.format(error) #TEST fragmentation print "Test fragmentation with s22 set" molecule = 'Ammonia_dimer' fragment_names = [molecule+'_f1',molecule+'f2'] test_f = Fragmentation([molecule]) sys = Atoms(s22_sim_data[molecule]['symbols'], s22_sim_data[molecule]['positions']) test_f.molecules = [GPAWSystems(molecule,atoms=sys, h=0.4, vacuum=2.0, fragment_list=fragment_names)] n = s22_sim_data[molecule]['dimer atoms'] atom_fragments = [ sys.copy()[range(n[0])], sys.copy()[range(n[0],n[0]+n[1])] ] test_f.fragments = [ GPAWSystems(name,atoms=a,h=0.4, vacuum=2.0) for name,a in zip(fragment_names,atom_fragments)] test_f.fill_data_reference(data_type='s22') test_f.run(write=True) error = 266.704827694 - test_f.mae print 'Test error: {0} eV'.format(error)
def test_one_vs_many(): s1 = Atoms('H3', positions=[[0.5, 0.5, 0], [0.5, 1.5, 0], [1.5, 1.5, 0]], cell=[2, 2, 2], pbc=True) # Get the unit used for position comparison u = (s1.get_volume() / len(s1))**(1 / 3) comp = SymmetryEquivalenceCheck(stol=.095 / u, scale_volume=True) s2 = s1.copy() assert comp.compare(s1, s2) s2_list = [] s3 = Atoms('H3', positions=[[0.5, 0.5, 0], [0.5, 1.5, 0], [1.5, 1.5, 0]], cell=[3, 3, 3], pbc=True) s2_list.append(s3) for d in np.linspace(0.1, 1.0, 5): s2 = s1.copy() s2.positions[0] += [d, 0, 0] s2_list.append(s2) assert not comp.compare(s1, s2_list[:-1]) assert comp.compare(s1, s2_list)
def test_s22(): fragTest = Fragmentation(s22.s22) minimize = False minimize = True print 'Relaxed:', minimize fragTest.molecules = [] fragTest.fragments = [] testSet = [ #'Ammonia_dimer', #'Water_dimer', #'Formic_acid_dimer', #'Formamide_dimer', #'Uracil_dimer_h-bonded', #'2-pyridoxine_2-aminopyridine_complex', #'Adenine-thymine_Watson-Crick_complex', 'Methane_dimer', #'Ethene_dimer', 'Benzene-methane_complex', #'Benzene_dimer_parallel_displaced', #'Pyrazine_dimer', #'Uracil_dimer_stack', #'Indole-benzene_complex_stack', #'Adenine-thymine_complex_stack', #'Ethene-ethyne_complex', #'Benzene-water_complex', #'Benzene-ammonia_complex', #'Benzene-HCN_complex', #'Benzene_dimer_T-shaped', #'Indole-benzene_T-shape_complex', 'Phenol_dimer' ] for moleculeName in testSet: data = s22.data[moleculeName] atoms = Atoms(data['symbols'], data['positions']) dimer1End = data['dimer atoms'][0] frag1Atoms = atoms.copy()[:dimer1End] frag2Atoms = atoms.copy()[dimer1End:] fragment1 = COMPASSSystem(moleculeName + '_f1', frag1Atoms, minimize=minimize) fragment2 = COMPASSSystem(moleculeName + '_f2', frag2Atoms, minimize=minimize) system = COMPASSSystem(moleculeName, atoms, minimize=minimize, fragment_list=[fragment1.name, fragment2.name]) fragTest.molecules.append(system) fragTest.fragments += [fragment1, fragment2] fragTest.fill_data_reference(data_type='s22') fragTest.run(write=True)
def __init__(self, structure: Atoms, cutoffs: List[float], chemical_symbols: Union[List[str], List[List[str]]], symprec: float = 1e-5, position_tolerance: float = None) -> None: if not isinstance(structure, Atoms): raise TypeError('Input configuration must be an ASE Atoms object' ', not type {}'.format(type(structure))) if not all(structure.pbc): raise ValueError('Input structure must have periodic boundary conditions') if symprec <= 0: raise ValueError('symprec must be a positive number') self._config = {'symprec': symprec} self._cutoffs = cutoffs.copy() self._input_structure = structure.copy() self._input_chemical_symbols = copy.deepcopy(chemical_symbols) chemical_symbols = self._get_chemical_symbols() self._pruning_history = [] # set up primitive occupied_primitive, primitive_chemical_symbols = get_occupied_primitive_structure( self._input_structure, chemical_symbols, symprec=self.symprec) self._primitive_chemical_symbols = primitive_chemical_symbols assert len(occupied_primitive) == len(primitive_chemical_symbols) # derived tolerances if position_tolerance is None: self._config['position_tolerance'] = symprec else: if position_tolerance <= 0: raise ValueError('position_tolerance must be a positive number') self._config['position_tolerance'] = position_tolerance effective_box_size = abs(np.linalg.det(occupied_primitive.cell)) ** (1 / 3) tol = self.position_tolerance / effective_box_size tol = min(tol, self._config['position_tolerance'] / 5) self._config['fractional_position_tolerance'] = round(tol, -int(floor(log10(abs(tol))))) # set up orbit list self._orbit_list = OrbitList( structure=occupied_primitive, cutoffs=self._cutoffs, symprec=self.symprec, position_tolerance=self.position_tolerance, fractional_position_tolerance=self.fractional_position_tolerance) self._orbit_list.remove_inactive_orbits(primitive_chemical_symbols) # call (base) C++ constructor _ClusterSpace.__init__(self, chemical_symbols=primitive_chemical_symbols, orbit_list=self._orbit_list, position_tolerance=self.position_tolerance, fractional_position_tolerance=self.fractional_position_tolerance)
def pad_atoms(atoms: Atoms, margin: float, directions='xy', in_place=False): """ Repeat the atoms in x and y, retaining only the repeated atoms within the margin distance from the cell boundary. Parameters ---------- atoms: ASE Atoms object The atoms that should be padded. margin: float The padding margin. Returns ------- ASE Atoms object Padded atoms. """ if not is_cell_orthogonal(atoms): raise RuntimeError('The cell of the atoms must be orthogonal.') if not in_place: atoms = atoms.copy() old_cell = atoms.cell.copy() axes = [{'x': 0, 'y': 1, 'z': 2}[direction] for direction in directions] reps = [1, 1, 1] for axis in axes: reps[axis] = int(1 + 2 * np.ceil(margin / atoms.cell[axis, axis])) if any([rep > 1 for rep in reps]): atoms *= reps atoms.positions[:] -= np.diag(old_cell) * [rep // 2 for rep in reps] atoms.cell = old_cell # import matplotlib.pyplot as plt # from abtem import show_atoms # show_atoms(atoms, plane='xz') # plt.show() to_keep = np.ones(len(atoms), dtype=bool) for axis in axes: to_keep *= (atoms.positions[:, axis] > -margin) * ( atoms.positions[:, axis] < atoms.cell[axis, axis] + margin) atoms = atoms[to_keep] # for axis in axes: # left = atoms[atoms.positions[:, axis] < margin] # left.positions[:, axis] += atoms.cell[axis, axis] # right = atoms[(atoms.positions[:, axis] > atoms.cell[axis, axis] - margin) & # (atoms.positions[:, axis] < atoms.cell[axis, axis])] # right.positions[:, axis] -= atoms.cell[axis, axis] # atoms += left + right return atoms
def cut_rectangle(atoms: Atoms, origin: Sequence[float], extent: Sequence[float], margin: float = 0.): """ Cuts out a cell starting at the origin to a given extent from a sufficiently repeated copy of atoms. Parameters ---------- atoms : ASE atoms object This should correspond to a repeatable unit cell. origin : two float Origin of the new cell. Units of Angstrom. extent : two float xy-extent of the new cell. Units of Angstrom. margin : float Atoms within margin from the border of the new cell will be included. Units of Angstrom. Default is 0. Returns ------- ASE atoms object """ # TODO : check that this works in edge cases atoms = atoms.copy() cell = atoms.cell.copy() extent = ( extent[0], extent[1], atoms.cell[2, 2], ) atoms.positions[:, :2] -= np.array(origin) a = atoms.cell.scaled_positions(np.array((extent[0] + 2 * margin, 0, 0))) b = atoms.cell.scaled_positions(np.array((0, extent[1] + 2 * margin, 0))) repetitions = (int(np.ceil(abs(a[0])) + np.ceil(abs(b[0]))), int(np.ceil(abs(a[1])) + np.ceil(abs(b[1]))), 1) shift = (-np.floor(min(a[0], 0)) - np.floor(min(b[0], 0)), -np.floor(min(a[1], 0)) - np.floor(min(b[1], 0)), 0) atoms.set_scaled_positions(atoms.get_scaled_positions() - shift) atoms *= repetitions atoms.positions[:, :2] -= margin atoms.set_cell([extent[0], extent[1], cell[2, 2]]) atoms = atoms[((atoms.positions[:, 0] >= -margin) & (atoms.positions[:, 1] >= -margin) & (atoms.positions[:, 0] < extent[0] + margin) & (atoms.positions[:, 1] < extent[1] + margin))] return atoms
def setup_atomic_square(): """ Setup squares of 4 gold atoms with known positions :return: """ atoms1 = Atoms('Au4', [[0, 0, 0], [3, 0, 0], [0, 3, 0], [3, 3, 0]]) atoms1.center() atoms2 = atoms1.copy() scale = .75 atoms2.positions *= scale return atoms1, atoms2
def __init__(self, formulas: List[FormulaType], initial_structure: Atoms, num_refills: int, *args, **kwargs): super().__init__(*args, **kwargs) self.formulas = formulas self.atoms = initial_structure.copy() self.num_refills = num_refills self.formulas_cycle = itertools.cycle(self.formulas) self.current_refill_counter = 0 self.reset()
def ring(self): #armchair ring atoms=Atoms() atom=Atoms('C',[(1.0,0.0,0.0)]) for i in range(6): atom.rotate('z',pi/3*i) atoms.extend(atom.copy()) atoms.set_cell([3.0,sqrt(3),self.az]) return atoms
def testget_unique_atoms(self): unit = Atoms("C4", positions=[(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0)]) unit1 = unit.copy() unit1.translate([1, 0, 0]) atoms = Atoms() atoms.extend(unit) atoms.extend(unit1) self.assertEqual(len(atoms), 8) atoms = get_unique_atoms(atoms) self.assertEqual(len(atoms), 6)
def unitcell(self, latx, laty): unit = Atoms('C2', [(0.5, 0.5, 0.0), (0.5 + sqrt(2) / 2, 0.5 + sqrt(2) / 2, 0)]) atoms = Atoms() for i in range(4): a = unit.copy() a.rotate('z', pi / 2 * i) atoms.extend(a) atoms.set_cell([2 + sqrt(2), 2 + sqrt(2), 10.0]) col = unit.repeat((latx, laty, 1)) return col
def ring(self): # armchair ring atoms = Atoms() atom = Atoms('C', positions=[(1.0, 0.0, 0.0)]) for i in range(6): unit = atom.copy() unit.rotate('z', pi / 3 * i) atoms.extend(unit) atoms.set_cell([3.0, sqrt(3), self.az]) atoms.center() wrap(atoms) return atoms
def perovskite(symbols, a): # perovskite ABX3 # http://cst-www.nrl.navy.mil/lattice/struk/e2_1.html u = 0.01 scaled_positions = [(0.00 , 0.00 , 0.00), (0.50+u, 0.50-u, 0.50+u), (0.00 , 0.50-u, 0.50+u), (0.50-u, 0.00 , 0.50+u), (0.50-u, 0.50+u, 0.00)] atoms = Atoms(symbols, cell=(a, a, a), pbc=True) atoms.set_scaled_positions(scaled_positions) return atoms.copy()
def testget_unique_atoms(self): unit = Atoms( "C4", positions=[ (0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0)]) unit1 = unit.copy() unit1.translate([1, 0, 0]) atoms = Atoms() atoms.extend(unit) atoms.extend(unit1) self.assertEqual(len(atoms), 8) atoms = get_unique_atoms(atoms) self.assertEqual(len(atoms), 6)
def ring(self): #armchair ring b=3.134/self.bond/2 atoms=Atoms() atom=Atoms('MoS2',[(1.0,0.0,0.0),(-1.0,0,b),(-1.0,0,-b)]) for i in range(3): atom.rotate('z',pi*2.0/3*i) atoms.extend(atom.copy()) atoms.set_cell([3.0,sqrt(3),10.0]) return atoms
def unitcell(self,latx,laty): unit=Atoms('C2',[(0.5,0.5,0.0),(0.5+sqrt(2)/2,0.5+sqrt(2)/2,0)]) atoms=Atoms() for i in range(4): a=unit.copy() a.rotate('z',pi/2*i) atoms.extend(a) atoms.set_cell([2+sqrt(2),2+sqrt(2),10.0]) col=unit.repeat((latx,laty,1)) return col
def encode_to_atoms(encode, out_file='input.traj'): """ Dump the encoding to a local traj file. """ # First, decode the trajectory data = json.loads(encode, encoding='utf-8') # Construct the initial atoms object atoms = Atoms( data['numbers'], data['trajectory']['0']['positions'], cell=data['trajectory']['0']['cell'], pbc=data['pbc']) atoms.info = data['calculator_parameters'] atoms.set_constraint([dict2constraint(_) for _ in data['constraints']]) # Attach the calculator calc = SPC( atoms=atoms, energy=data['trajectory']['0'].get('energy'), forces=data['trajectory']['0'].get('forces'), stress=data['trajectory']['0'].get('stress')) atoms.set_calculator(calc) # Collect the rest of the trajectory information images = [atoms] for i in range(len(data['trajectory']))[1:]: atoms = atoms.copy() if data['trajectory'][str(i)]['cell']: atoms.set_cell(data['trajectory'][str(i)]['cell']) if data['trajectory'][str(i)]['positions']: atoms.set_positions(data['trajectory'][str(i)]['positions']) calc = SPC( atoms=atoms, energy=data['trajectory'][str(i)].get('energy'), forces=data['trajectory'][str(i)].get('forces'), stress=data['trajectory'][str(i)].get('stress')) atoms.set_calculator(calc) images += [atoms] # Write the traj file if out_file: write(out_file, images) return images
def atoms2lammps(input_atoms): """ Converts an atoms object to a lammps input file""" atoms = Atoms.copy(input_atoms) with open("data.atoms", "w") as f: f.write("# file produced by jb-function\n") # First line is for comment f.write("{0} atoms\n".format(len(atoms))) # Identify number of atoms atom_index = {} for i, atom in enumerate(atoms): sym = atom.symbol if sym not in atom_index.keys(): atom_index[sym] = [i + 1, atom.mass] f.write("{0} atom types\n".format(len(atom_index))) # Number of atom types a, b, c = atoms.get_cell() # Transform input vectors a_x = np.linalg.norm(a) b_x = np.linalg.norm(b) * np.cos(cell_angle(a, b)) b_y = np.linalg.norm(b) * np.sin(cell_angle(a, b)) c_x = np.linalg.norm(c) * np.cos(cell_angle(c, a)) c_y = (np.dot(b, c) - b_x * c_x) / b_y c_z = np.sqrt(np.linalg.norm(c) ** 2 - c_x ** 2 - c_y ** 2) cell = [[a_x, 0.0, 0.0], [b_x, b_y, 0.0], [c_x, c_y, c_z]] # Command used to scale atoms to new cell atoms.set_cell(cell, scale_atoms=True) f.write("0 {0} xlo xhi\n".format(cell[0][0])) f.write("0 {0} ylo yhi\n".format(cell[1][1])) f.write("0 {0} zlo zhi\n".format(cell[2][2])) f.write("{0} {1} {2} xy xz yz\n".format(cell[1][0], cell[2][0], cell[2][1])) f.write("Masses\n\n") for sym, ind in atom_index.iteritems(): f.write("{0} {1} # {2}\n".format(ind[0], ind[1], sym)) f.write("\n") f.write("Atoms\n\n") for i, atom in enumerate(atoms): sym = atom.symbol p = atom.position f.write("{0} {1} {2} {3} {4} {5}\n".format(i + 1, atom_index[sym][0], 0.0, p[0], p[1], p[2]))
def unitcell(self,latx,laty): unit=Atoms('C2N',[(1/2*sqrt(3),0.5,0.0), (1/2*sqrt(3),-0.5,0), (1/2*sqrt(3),1.5,0)]) atoms=Atoms() for i in range(3): a=unit.copy() a.rotate('z',pi*2/3*i) atoms.extend(a) if self.centerN: atoms.append(Atom('N',(0,0,0))) atoms.set_cell([6*sqrt(3)/2,6,10.0]) col=unit.repeat((latx,laty,1)) return col
def create_PVA(units): start_group = Atoms('H') start_bonds = np.matrix('1 1; 1 1') unit = Atoms('CH2CHOH') unit_bonds = np.matrix(""" 1 1 1 1 0 0 0 0 ; 1 1 0 0 0 0 0 0 ; 1 0 1 0 0 0 0 0 ; 1 0 0 1 1 1 0 1 ; 0 0 0 1 1 0 0 0 ; 0 0 0 1 0 1 1 0 ; 0 0 0 0 0 1 1 0 ; 0 0 0 1 0 0 0 0 """) unit_carbons = np.array([0, 3]) end_group = Atoms('CH3') end_bonds = np.matrix(""" 1 1 1 1 ; 1 1 0 0 ; 1 0 1 0 ; 1 0 0 1 """) N = len(start_group) + units*len(unit) + len(end_group) atoms = start_group.copy() bonds = np.zeros((N,N), dtype=int) bonds[:2,:2] = start_bonds for i in range(units): n = len(atoms) atoms.extend(unit) bonds[n:n+len(unit)+1, n:n+len(unit)+1] = unit_bonds n = len(atoms) atoms.extend(end_group) bonds[n:n+len(end_group), n:n+len(end_group)] = end_bonds unit_indices = slice(len(start_group), None, len(unit)) return atoms, bonds, unit_indices
def eval_energy(input): """Function to evaluate energy of an individual Inputs: input = [Optimizer class object with parameters, Individual class structure to be evaluated] Outputs: energy, bul, individ, signal energy = energy of Individual evaluated bul = bulk structure of Individual if simulation structure is Defect individ = Individual class structure evaluated signal = string of information about evaluation """ if input[0]==None: energy=0 bul=0 individ=0 rank = MPI.COMM_WORLD.Get_rank() signal='Evaluated none individual on '+repr(rank)+'\n' else: [Optimizer, individ]=input if Optimizer.calc_method=='MAST': energy = individ.energy bul = individ.energy signal = 'Recieved MAST structure\n' else: if Optimizer.parallel: rank = MPI.COMM_WORLD.Get_rank() if not Optimizer.genealogy: STR='----Individual ' + str(individ.index)+ ' Optimization----\n' else: STR='----Individual ' + str(individ.history_index)+ ' Optimization----\n' indiv=individ[0] if 'EE' in Optimizer.debug: debug = True else: debug = False if debug: write_xyz(Optimizer.debugfile,indiv,'Recieved by eval_energy') Optimizer.debugfile.flush() if Optimizer.structure=='Defect': indi=indiv.copy() if Optimizer.alloy==True: bulk=individ.bulki else: bulk=individ.bulko nat=indi.get_number_of_atoms() csize=bulk.get_cell() totalsol=Atoms(cell=csize, pbc=True) totalsol.extend(indi) totalsol.extend(bulk) for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in totalsol if atm.symbol==sym]) STR+='Defect configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n' elif Optimizer.structure=='Surface': totalsol=Atoms() totalsol.extend(indiv) nat=indiv.get_number_of_atoms() totalsol.extend(individ.bulki) for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in totalsol if atm.symbol==sym]) STR+='Surface-Bulk configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n' cell=numpy.maximum.reduce(indiv.get_cell()) totalsol.set_cell([cell[0],cell[1],500]) totalsol.set_pbc([True,True,False]) if Optimizer.constrain_position: ts = totalsol.copy() indc,indb,vacant,swap,stro = find_defects(ts,Optimizer.solidbulk,0) sbulk = Optimizer.solidbulk.copy() bcom = sbulk.get_center_of_mass() #totalsol.translate(-bulkcom) #indc.translate(-bulkcom) #totalsol.append(Atom(position=[0,0,0])) # for one in indc: # index = [atm.index for atm in totalsol if atm.position[0]==one.position[0] and atm.position[1]==one.position[1] and atm.position[2]==one.position[2]][0] # if totalsol.get_distance(-1,index) > Optimizer.sf: # r = random.random() # totalsol.set_distance(-1,index,Optimizer.sf*r,fix=0) # totalsol.pop() # totalsol.translate(bulkcom) com = indc.get_center_of_mass() dist = (sum((bcom[i] - com[i])**2 for i in range(3)))**0.5 if dist > Optimizer.sf: STR+='Shifting structure to within region\n' r = random.random()*Optimizer.sf comv = numpy.linalg.norm(com) ncom = [one*r/comv for one in com] trans = [ncom[i]-com[i] for i in range(3)] indices = [] for one in indc: id = [atm.index for atm in totalsol if atm.position[0]==one.position[0] and atm.position[1]==one.position[1] and atm.position[2]==one.position[2]][0] totalsol[id].position += trans # Check for atoms that are too close min_len=0.7 #pdb.set_trace() if not Optimizer.fixed_region: if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': cutoffs=[2.0 for one in totalsol] nl=NeighborList(cutoffs,bothways=True,self_interaction=False) nl.update(totalsol) for one in totalsol[0:nat]: nbatoms=Atoms() nbatoms.append(one) indices, offsets=nl.get_neighbors(one.index) for index, d in zip(indices,offsets): index = int(index) sym=totalsol[index].symbol pos=totalsol[index].position + numpy.dot(d,totalsol.get_cell()) at=Atom(symbol=sym,position=pos) nbatoms.append(at) while True: dflag=False for i in range(1,len(nbatoms)): d=nbatoms.get_distance(0,i) if d < min_len: nbatoms.set_distance(0,i,min_len+.01,fix=0.5) STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n' dflag=True if dflag==False: break for i in range(len(indices)): totalsol[indices[i]].position=nbatoms[i+1].position totalsol[one.index].position=nbatoms[0].position nl.update(totalsol) if debug: write_xyz(Optimizer.debugfile,totalsol,'After minlength check') Optimizer.debugfile.flush() else: for i in range(len(indiv)): for j in range(len(indiv)): if i != j: d=indiv.get_distance(i,j) if d < min_len: indiv.set_distance(i,j,min_len,fix=0.5) STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n' if debug: write_xyz(Optimizer.debugfile,indiv,'After minlength check') Optimizer.debugfile.flush() # Set calculator to use to get forces/energies if Optimizer.parallel: calc = setup_calculator(Optimizer) if Optimizer.fixed_region: pms=copy.deepcopy(calc.parameters) try: pms['mass'][len(pms['mass'])-1] += '\ngroup RO id >= '+repr(nat)+'\nfix freeze RO setforce 0.0 0.0 0.0\n' except KeyError: pms['pair_coeff'][0] += '\ngroup RO id >= '+repr(nat)+'\nfix freeze RO setforce 0.0 0.0 0.0\n' calc = LAMMPS(parameters=pms, files=calc.files, keep_tmp_files=calc.keep_tmp_files, tmp_dir=calc.tmp_dir) lmin = copy.copy(Optimizer.lammps_min) Optimizer.lammps_min = None Optimizer.static_calc = setup_calculator(Optimizer) Optimizer.lammps_min = lmin else: calc=Optimizer.calc if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': totalsol.set_calculator(calc) totalsol.set_pbc(True) else: indiv.set_calculator(calc) indiv.set_pbc(True) #Current bug in ASE optimizer-Lammps prevents pbc=false if Optimizer.structure=='Cluster': indiv.set_cell([500,500,500]) indiv.translate([250,250,250]) cwd=os.getcwd() # Perform Energy Minimization if not Optimizer.parallel: Optimizer.output.flush() if Optimizer.ase_min == True: try: if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': dyn=BFGS(totalsol) else: dyn=BFGS(indiv) dyn.run(fmax=Optimizer.ase_min_fmax, steps=Optimizer.ase_min_maxsteps) except OverflowError: STR+='--- Error: Infinite Energy Calculated - Implement Random ---\n' box=Atoms() indiv=gen_pop_box(Optimizer.natoms, Optimizer.atomlist, Optimizer.size) indiv.set_calculator(calc) dyn=BFGS(indiv) dyn.run(fmax=fmax, steps=steps) except numpy.linalg.linalg.LinAlgError: STR+='--- Error: Singular Matrix - Implement Random ---\n' indiv=gen_pop_box(Optimizer.natoms, Optimizer.atomlist, Optimizer.size) indiv.set_calculator(calc) dyn=BFGS(indiv) dyn.run(fmax=fmax, steps=steps) # Get Energy of Minimized Structure if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': en=totalsol.get_potential_energy() #force=numpy.maximum.reduce(abs(totalsol.get_forces())) if Optimizer.fitness_scheme == 'enthalpyfit': pressure=totalsol.get_isotropic_pressure(totalsol.get_stress()) cell_max=numpy.maximum.reduce(totalsol.get_positions()) cell_min=numpy.minimum.reduce(totalsol.get_positions()) cell=cell_max-cell_min volume=cell[0]*cell[1]*cell[2] else: pressure=0 volume=0 na=totalsol.get_number_of_atoms() ena=en/na energy=en individ[0]=totalsol[0:nat] bul=totalsol[(nat):len(totalsol)] STR+='Number of positions = '+repr(len(bul)+len(individ[0]))+'\n' individ[0].set_cell(csize) indiv=individ[0] else: en=indiv.get_potential_energy() if Optimizer.fitness_scheme == 'enthalpyfit': pressure=indiv.get_isotropic_pressure(indiv.get_stress()) cell_max=numpy.maximum.reduce(indiv.get_positions()) cell_min=numpy.minimum.reduce(indiv.get_positions()) cell=cell_max-cell_min volume=cell[0]*cell[1]*cell[2] else: pressure=0 volume=0 na=indiv.get_number_of_atoms() ena=en/na energy=ena individ[0]=indiv bul=0 else: if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': if Optimizer.calc_method=='VASP': en=totalsol.get_potential_energy() calcb=Vasp(restart=True) totalsol=calcb.get_atoms() stress=calcb.read_stress() else: try: totcop=totalsol.copy() if debug: write_xyz(Optimizer.debugfile,totcop,'Individual sent to lammps') OUT=totalsol.calc.calculate(totalsol) totalsol=OUT['atoms'] totalsol.set_pbc(True) if Optimizer.fixed_region: if debug: print 'Energy of fixed region calc = ', OUT['thermo'][-1]['pe'] totalsol.set_calculator(Optimizer.static_calc) OUT=totalsol.calc.calculate(totalsol) totalsol=OUT['atoms'] totalsol.set_pbc(True) if debug: print 'Energy of static calc = ', OUT['thermo'][-1]['pe'] en=OUT['thermo'][-1]['pe'] stress=numpy.array([OUT['thermo'][-1][i] for i in ('pxx','pyy','pzz','pyz','pxz','pxy')])*(-1e-4*GPa) #force=numpy.maximum.reduce(abs(totalsol.get_forces())) if debug: write_xyz(Optimizer.debugfile,totalsol,'After Lammps Minimization') Optimizer.debugfile.flush() except Exception, e: os.chdir(cwd) STR+='WARNING: Exception during energy eval:\n'+repr(e)+'\n' f=open('problem-structures.xyz','a') write_xyz(f,totcop,data='Starting structure hindex='+individ.history_index) write_xyz(f,totalsol,data='Lammps Min structure') en=10 stress=0 f.close() if Optimizer.fitness_scheme == 'enthalpyfit': pressure=totalsol.get_isotropic_pressure(stress) cell_max=numpy.maximum.reduce(totalsol.get_positions()) cell_min=numpy.minimum.reduce(totalsol.get_positions()) cell=cell_max-cell_min volume=cell[0]*cell[1]*cell[2] else: pressure=totalsol.get_isotropic_pressure(stress) volume=0 na=totalsol.get_number_of_atoms() ena=en/na energy=en if Optimizer.structure=='Defect': if Optimizer.fixed_region==True or Optimizer.finddefects==False: individ[0]=totalsol[0:nat] bul=totalsol[(nat):len(totalsol)] individ[0].set_cell(csize) else: if 'FI' in Optimizer.debug: outt=find_defects(totalsol,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=Optimizer.debugfile) else: outt=find_defects(totalsol,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=False) individ[0]=outt[0] bul=outt[1] individ.vacancies = outt[2] individ.swaps = outt[3] STR += outt[4] indiv=individ[0] else: top,bul=find_top_layer(totalsol,Optimizer.surftopthick) indiv=top.copy() individ[0]=top.copy() else:
def rotct_rand(ind1, ind2, Optimizer): """Rotate atoms cut and splice Rotates atoms randomly around center of mass and cuts with xy plane Maintains number of atoms Maintains concentration of atoms Returns individuals to standard positions at end (un-rotates) """ if 'CX' in Optimizer.debug: debug = True else: debug = False Optimizer.output.write('Random Rotate Cut/Splice Cx between individual '+repr(ind1.index)+' and individual '+repr(ind2.index)+'\n') #Perserve starting conditions of individual indi1 = ind1[0].copy() indi2 =ind2[0].copy() #Translate individuals so COM is at (0,0,0) com1 = indi1.get_center_of_mass() indi1.translate(-1*com1) com2 = indi2.get_center_of_mass() indi2.translate(-1*com2) #Select random axis, random angle, and random position and rotate individuals cmax = [min(numpy.maximum.reduce(indi1.get_positions())[i],numpy.maximum.reduce(indi2.get_positions())[i]) for i in range(3)] cmin = [min(numpy.minimum.reduce(indi1.get_positions())[i],numpy.minimum.reduce(indi2.get_positions())[i]) for i in range(3)] n=0 while n<10: rax = random.choice(['x', '-x','y','-y','z','-z']) rang = random.random()*90 rpos = [random.uniform(cmin[i]*0.8,cmax[i]*0.8) for i in range(3)] indi1.rotate(rax,a=rang,center=rpos,rotate_cell=False) #Search for atoms in individual 1 that are above the xy plane group1 = Atoms(cell=ind1[0].get_cell(),pbc=ind1[0].get_pbc()) indices1=[] for one in indi1: if one.position[2] >= 0: group1.append(one) indices1.append(one.index) if len(group1) > 2 and len(group1) < len(indi1): break else: n+=1 indi1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) indi2.rotate(rax,a=rang,center=rpos,rotate_cell=False) if debug: print 'Group1 size = ', len(group1) print 'Position = ', rpos print 'Angle = ', rang print 'Axis = ', rax print 'Number of tries = ', n if len(group1) != 0: #Apply concentration forcing if needed group2 = Atoms(cell=ind2[0].get_cell(),pbc=ind2[0].get_pbc()) indices2 = [] dellist = [] for one in indi2: if one.position[2] >= 0: group2.append(one) indices2.append(one.index) if Optimizer.forcing=='Concentration': symlist = list(set(indi1.get_chemical_symbols())) seplist = [[atm for atm in group2 if atm.symbol == sym] for sym in symlist] group2n=Atoms(cell=group2.get_cell(),pbc=group2.get_pbc()) indices2n = [] dellist = [] for one in group1: sym1=one.symbol listpos=[i for i,s in enumerate(symlist) if s==sym1][0] if len(seplist[listpos]) > 0: pos = random.choice(range(len(seplist[listpos]))) group2n.append(seplist[listpos][pos]) indices2n.append(indices2[seplist[listpos][pos].index]) del seplist[listpos][pos] else: dellist.append(one.index) if len(dellist) != 0: dellist.sort(reverse=True) for one in dellist: del group1[one] del indices1[one] indices2=indices2n group2=group2n.copy() else: dellist = [] while len(group2) < len(group1)-len(dellist): #Too many atoms in group 1 dellist.append(random.choice(group1).index) if len(dellist) != 0: dellist.sort(reverse=True) for one in dellist: del group1[one] del indices1[one] dellist = [] while len(group1) < len(group2)-len(dellist): #Too many atoms in group 2 dellist.append(random.choice(group2).index) if len(dellist) != 0: dellist.sort(reverse=True) for one in dellist: del group2[one] del indices2[one] other2 = Atoms(cell=ind2[0].get_cell(),pbc=ind2[0].get_pbc()) for one in indi2: if one.index not in indices2: other2.append(one) other1 = Atoms(cell=ind1[0].get_cell(),pbc=ind1[0].get_pbc()) for one in indi1: if one.index not in indices1: other1.append(one) indi1 = group2.copy() indi1.extend(other1) indi2 = group1.copy() indi2.extend(other2) #DEBUG: Write crossover to file if debug: write_xyz(Optimizer.debugfile, group1,'group1') write_xyz(Optimizer.debugfile, other1,'other1') write_xyz(Optimizer.debugfile, group2,'group2') write_xyz(Optimizer.debugfile, other2,'other2') print 'Length of group1 = ',len(group1),'Length of group2',len(group2) #DEBUG: Check structure of atoms exchanged for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in indi1 if atm.symbol==sym]) Optimizer.output.write('CX RANDROTCT: Individual 1 contains '+repr(nc)+' '+repr(sym)+' atoms\n') nc=len([atm for atm in indi2 if atm.symbol==sym]) Optimizer.output.write('CX RANDROTCT: Individual 2 contains '+repr(nc)+' '+repr(sym)+' atoms\n') if Optimizer.forcing !='Concentration': for i in range(len(Optimizer.atomlist)): atms1=[inds for inds in indi1 if inds.symbol==Optimizer.atomlist[i][0]] atms2=[inds for inds in indi2 if inds.symbol==Optimizer.atomlist[i][0]] if len(atms1)==0: if len(atms2)==0: indi1[random.randint(0,len(indi1)-1)].symbol==Optimizer.atomlist[i][0] indi2[random.randint(0,len(indi2)-1)].symbol==Optimizer.atomlist[i][0] else: indi1.append(atms2[random.randint(0,len(atms2)-1)]) indi1.pop(random.randint(0,len(indi1)-2)) else: if len(atms2)==0: indi2.append(atms1[random.randint(0,len(atms1)-1)]) indi2.pop(random.randint(0,len(indi2)-2)) indi1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) indi2.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) indi1.translate(com1) indi2.translate(com2) #DEBUG: Check structure and number of atoms in crystal if Optimizer.structure=='Defect': solid1=Atoms() solid1.extend(indi1) solid1.extend(ind1.bulki) solid2=Atoms() solid2.extend(indi2) solid2.extend(ind2.bulki) for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in solid1 if atm.symbol==sym]) Optimizer.output.write('CX RANDROTCT: Defect 1 configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n') nc=len([atm for atm in solid2 if atm.symbol==sym]) Optimizer.output.write('CX RANDROTCT: Defect 2 configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n') if debug: Optimizer.output.flush() #pdb.set_trace() ind1[0]=indi1 ind2[0]=indi2 return ind1, ind2
from gpaw.pes.dos import DOSPES from gpaw.pes.tddft import TDDFTPES atoms = Atoms([Atom('C', (7.666263598984184, 7.637780850431168, 8.289450797111844)), Atom('O', (8.333644370007132, 8.362384430165646, 7.710230973847514))]) atoms.center(vacuum=8) h = 0.15 N_c = np.round(atoms.get_cell().diagonal() / h / 16) * 16 m_c = GPAW(gpts=N_c, nbands=6, mixer=MixerDif(0.1, 5, weight=100.0), #convergence={'bands':10}, parallel={'domain': mpi.size}, xc='PBE', txt='CO-m.txt', spinpol=True) m = atoms.copy() m.set_initial_magnetic_moments([-1,1]) m.set_calculator(m_c) m.get_potential_energy() d_c = GPAW(gpts=N_c, nbands=16, mixer=MixerDif(0.1, 5, weight=100.0), convergence={'bands':10}, parallel={'domain': mpi.size}, xc='PBE', txt='CO-d.txt', spinpol=True) d = atoms.copy() d.set_initial_magnetic_moments([-1,1]) d_c.set(charge=1) d.set_calculator(d_c) d.get_potential_energy()
# GPAW calculations a = 0.75 # Bond length cell = np.diag([5, 5, 12 * a]) atoms = Atoms('H12', pbc=(1, 1, 1), cell=cell) atoms.positions[:, 2] = [i * a for i in range(12)] calc = GPAW(h=0.2, occupations=FermiDirac(width=0.1), mode='lcao', basis='sz', usesymm=False) # Lead calculation lead = atoms.copy() del lead[4:] cell_lead = cell.copy() cell_lead[2, 2] = a * len(lead) lead.set_cell(cell_lead) calc.set(kpts=(1, 1, 14)) lead.set_calculator(calc) e1 = lead.get_potential_energy() niter1 = calc.get_number_of_iterations() calc.write('lead.gpw') dump_lead_hs(calc, 'lead') # Tip calculation tip = atoms.copy() tip.positions[:] += (atoms.cell / 2.0)[0, :] + (atoms.cell / 2.0)[1, :] del tip[:4]
atoms = Atoms(FaceCenteredCubic('Au', [[1, 0, 0], [1, 1, 0], [1, 1, 1]], (4, 6, 4))) atoms.center() s = ElasticScatter({'qmin': 3., 'rmax': 20.}) displacement = atoms.get_positions() - atoms.get_center_of_mass() distance = np.sqrt(np.sum(displacement**2, axis=1)) print(np.max(distance)) norm_displacement = (displacement.T / distance).T adp_tensor = norm_displacement * .01 print(np.max(adp_tensor)) adp_tensor_target = adp_tensor.copy() target_atoms = atoms.copy() target_adps = ADP(atoms, adps=adp_tensor_target) target_atoms.info['adps'] = target_adps target_pdf = s.get_pdf(target_atoms) adp_calc = Calc1D(target_data=target_pdf, exp_grad_function=s.get_grad_adp_pdf, exp_function=s.get_pdf, conv=100) calc = Calc1D(target_data=target_pdf, exp_grad_function=null_func, exp_function=s.get_pdf, conv=100)
import numpy as np from ase import Atoms from ase.io import write, read from ase.test import NotAvailable a = 5.0 d = 1.9 c = a / 2 atoms = Atoms('AuH', positions=[(c, c, 0), (c, c, d)], cell=(a, a, 2 * d), pbc=(0, 0, 1)) extra = np.array([ 2.3, 4.2 ]) atoms.set_array('extra', extra) atoms *= (1, 1, 2) images = [atoms.copy(), atoms.copy()] r = ['xyz', 'traj', 'cube', 'pdb', 'cfg', 'struct', 'cif', 'gen'] try: import Scientific version = Scientific.__version__.split('.') print 'Found ScientificPython version: ',Scientific.__version__ if map(int,version) < [2,8]: print 'ScientificPython 2.8 or greater required for numpy support in NetCDF' #raise NotAvailable('ScientificPython version 2.8 or greater is required') except (ImportError, NotAvailable): print 'No Scientific python found. Check your PYTHONPATH' #raise NotAvailable('ScientificPython version 2.8 or greater is required') else: r += ['etsf'] w = r + ['xsf', 'findsym'] try:
def find_defects(solid, bulko, rcutoff, atomlistcheck = False, trackvacs = False, trackswaps = False, debug = False, dcheck = 0.6): """Function to find interstitials, vacancies, and substitutional atoms (swaps) in a defected structure. Identifies species by comparison to perfect structure. Inputs: solid = ASE atoms class for defected structure bulko = ASE atoms class for perfect structure rcutoff = float value of distance to surrounding atoms to include atomlistcheck = False/list of atom types and concentrations according to atomlist format trackvacs = True/False whether or not to identify vacancies in defect trackswaps = True/False whether or not to identify substitutional defects debug = False/file object to write debug structures""" # Combine perfect and defect structures together b = bulko.copy() b.extend(solid) b.set_pbc(True) # Debug: Write solid and bulko to file if debug: print len(bulko) write_xyz(debug, b, 'Find Ints: Solid and Bulko') # Identify nearest neighbor atoms for each atom in perfect structure ntot = len(bulko) ctoff1 = [1.2 for one in b] nl = NeighborList(ctoff1, bothways = True, self_interaction = False) nl.update(b) slist = [] blist = [] wlist = [] # Loop over each atom in perfect structure for one in range(ntot): indices, offsets = nl.get_neighbors(one) for index, d in zip(indices, offsets): index = int(index) if index >= ntot: pos = b[index].position + numpy.dot(d, bulko.get_cell()) natm1 = Atom(position = pos) dist, dx, dy, dz = calc_dist(b[one], natm1) if dist <= dcheck: # Assume atoms closer than 0.6 Angstroms to be equivalent slist.append(index-ntot) blist.append(one) if b[one].symbol == b[index].symbol: wlist.append(index-ntot) # Identify those atoms corresponding to interstitials, vacancies, and substitutions oslist = [atm.index for atm in solid if atm.index not in slist] vlist = [atm.index for atm in bulko if atm.index not in blist] swlist = [atm.index for atm in solid if atm.index not in wlist and atm.index not in oslist] # Create Atoms objects for each identified defect ntot = len(solid) cluster = Atoms() for one in oslist: cluster.append(solid[one]) vacant = Atoms() if trackvacs == True: for one in vlist: vacant.append(Atom(symbol = bulko[one].symbol, position = bulko[one].position)) solid.append(Atom(symbol = 'X', position = bulko[one].position)) oslist.append(len(solid)-1) stro = 'Cluster Identified with length = {0}\nIdentified {1} vacancies\n'.format(len(cluster), len(vlist)) swaps = Atoms() if trackswaps == True: for one in swlist: swaps.append(solid[one]) oslist.append(one) stro = 'Cluster Identified with length = {0}\nIdentified {1} swaps\n'.format(len(cluster), len(swlist)) else: stro = 'Cluster Identified with length = {0}\n'.format(len(cluster)) # Debug: write cluster to file if debug: b = cluster.copy() write_xyz(debug, b, 'Find Ints: Cluster') debug.flush() print('Found cluster size = ', len(b)) # Identify atoms surrounding the identified defects in the defected structure box = Atoms() bulki = Atoms() if rcutoff != 0: if rcutoff > 2.0: cutoffs = [rcutoff for one in solid] else: cutoffs = [2.0 for one in solid] solid.set_pbc(True) nl = NeighborList(cutoffs, bothways = True, self_interaction = False) nl.update(solid) nbatmsd = [] repinds = [] for one in oslist: if one not in repinds: if one < ntot: nbatmsd.append((0, one)) repinds.append(one) for one in oslist: indices, offsets = nl.get_neighbors(one) for index, d in zip(indices, offsets): index = int(index) if index not in repinds and index < ntot: opos = copy.copy(solid[index].position) solid[index].position = solid[index].position + numpy.dot(d, solid.get_cell()) dist = solid.get_distance(one, index) solid[index].position = opos if dist <= rcutoff: nbatmsd.append((dist, index)) repinds.append(index) else: nbatmsd = [] repinds = [] for one in oslist: if one not in repinds: if one < ntot: nbatmsd.append((0, one)) repinds.append(one) nbatmsd = sorted(nbatmsd, key = lambda one:one[0], reverse = True) indices = [] natomsbox = 0 # Select only atoms closest to defects that satisfy concentrations specified by atomlist given in atomlistcheck if atomlistcheck: for sym, c, m, u in atomlistcheck: i = 0 nbsym = [one for one in nbatmsd if solid[one[1]].symbol == sym] if len(nbsym) > c: while i < c: a = nbsym.pop() box.append(solid[a[1]]) indices.append(a[1]) i += 1 else: for a in nbsym: box.append(solid[a[1]]) indices.append(a[1]) i += 1 if len(box)-natomsbox < c: try: while True: for n in range(len(nbatmsd)-1, -1, -1): inds, offsets = nl.get_neighbors(nbatmsd[n][1]) for one, d in zip(inds, offsets): if len(box)-natomsbox < c: if one not in indices and one < ntot and solid[one].symbol == sym: opos = copy.copy(solid[one].position) solid[one].position = solid[one].position + numpy.dot(d, solid.get_cell()) dist = solid.get_distance(nbatmsd[n][1], one) solid[one].position = opos if dist <= rcutoff*5.0: box.append(solid[one]) indices.append(one) else: raise StopIteration() for one, d in zip(inds, offsets): if len(box)-natomsbox < c: if one not in indices and one < ntot and solid[one].symbol == sym: opos = copy.copy(solid[one].position) solid[one].position = solid[one].position + numpy.dot(d, solid.get_cell()) dist = solid.get_distance(nbatmsd[n][1], one) solid[one].position = opos box.append(solid[one]) indices.append(one) else: raise StopIteration() except StopIteration: pass natomsbox = len(box) # Double check for sanity for sym, c, m, u in atomlistcheck: symsbox = [one for one in box if one.symbol == sym] if len(symsbox) != c: stro += 'WARNING!!!! : FAILURE IN FIND_DEFECTS TO MATCH PROVIDED ATOMLIST. DEBUG!!!!\n' # If atomlistcheck is False then use all the atoms in the given cutoff distance else: for a in nbatmsd: box.append(solid[a[1]]) indices.append(a[1]) # Add remaining atoms in defect to defected bulk atoms object for one in range(len(solid)): if one not in indices and one < ntot: bulki.append(solid[one]) # Check for accidental vacancy admissions #checklist = [atm for atm in box if atm.symbol == 'X'] #checklist.extend([atm for atm in bulki if atm.symbol == 'X']) # Set up new individual indiv = box.copy() bulki.set_cell(bulko.get_cell()) indiv.set_cell(bulko.get_cell()) bulki.set_pbc(True) indiv.set_pbc(True) stro += 'Atomlist check = {0}\n'.format(atomlistcheck) stro += 'Bulko = {0}\n'.format(bulko) stro += 'New individual ({0} atoms) : {1}\n'.format(len(indiv), indiv) stro += 'New bulki ({0} atoms) : {1}\n'.format(len(bulki), bulki) # Debug: write new indiv to file if debug: b = indiv.copy() write_xyz(debug, b, 'Find Ints: New Individual') # Debug: write new bulki to file b = bulki.copy() write_xyz(debug, b, 'Find Ints: New Bulki') debug.flush() print(len(bulko)) return indiv, bulki, vacant, swaps, stro
# this only runs in the main script, not in processes on other cores if __name__ == '__main__': NCORES = 6 # number of cores to run processes on # setup an atoms object a = 3.6 atoms = Atoms([Atom('Cu',(0, 0, 0))], cell=0.5 * a*np.array([[1.0, 1.0, 0.0], [0.0, 1.0, 1.0], [1.0, 0.0, 1.0]])) v0 = atoms.get_volume() # Step 1 COUNTER = 0 calculators = [] # list of calculators to be run factors = [-0.1, 0.05, 0.0, 0.05, 0.1] for f in factors: newatoms = atoms.copy() newatoms.set_volume(v0*(1 + f)) label = 'bulk/cu-mp/step1-{0}'.format(COUNTER) COUNTER += 1 calc = jasp(label, xc='PBE', encut=350, kpts=(6,6,6), isym=2, atoms=newatoms) calculators.append(calc) # now we set up the Pool of processes pool = multiprocessing.Pool(processes=NCORES) # get the output from running each calculation out = pool.map(do_calculation, calculators) pool.close()
constraint = FixAtoms(mask=[atom.position[2] < 3 for atom in atoms]) atoms.set_constraint(constraint) atoms.cell[2][2] = 25 atoms = sortz(atoms) #### ads = Atoms('CO') ads[0].position = atoms[-1].position ads[1].position = atoms[-1].position ads[0].z = ads[0].z + 1.80 ads[1].z = ads[0].z + 1.16 # top_o co = ads.copy() atoms_top = atoms + co atoms_top = atoms_top*[2, 2, 1] atoms_top = sortz(atoms_top) atoms_top.write('datas/224_atoms_top.in') # bri co = ads.copy() co.positions += atoms.cell[0]/4.0 + atoms.cell[1]/4.0 atoms_bri = atoms + co atoms_bri = atoms_bri*[2, 2, 1] atoms_bri = sortz(atoms_bri) atoms_bri.write('datas/224_atoms_bri.in') # tri_a co = ads.copy() co.positions += atoms.cell[0]*2/6.0 + atoms.cell[1]/6.0
from ase.utils.distance import distance # artificial structure org = Atoms('COPNS', [[-1.75072, 0.62689, 0.00000], [0.58357, 2.71652, 0.00000], [-5.18268, 1.36522, 0.00000], [-1.86663, -0.77867, 2.18917], [-1.80586, 0.20783, -2.79331]]) #visualize.view(org) maxdist = 3.0e-13 # translate for dx in range(3, 10, 2): new = org.copy() new.translate([dx / np.sqrt(2), -dx / np.sqrt(2), 0]) dist = distance(org, new, True) dist2 = distance(org, new, False) print('translation', dx, '-> distance', dist) assert dist < maxdist assert dist == dist2 # rotate for axis in ['x', '-y', 'z', np.array([1, 1, 1] / np.sqrt(3))]: for rot in [20, 200]: new = org.copy() new.translate(-new.get_center_of_mass()) new.rotate(axis, np.pi * rot / 180) dist = distance(org, new, True) dist2 = distance(org, new, False)
def read_vasp_xml(filename='vasprun.xml', index=-1): """Parse vasprun.xml file. Reads unit cell, atom positions, energies, forces, and constraints from vasprun.xml file """ import numpy as np import xml.etree.ElementTree as ET from ase import Atoms from ase.constraints import FixAtoms, FixScaled from ase.calculators.singlepoint import (SinglePointDFTCalculator, SinglePointKPoint) from ase.units import GPa from collections import OrderedDict tree = ET.iterparse(filename, events=['start', 'end']) atoms_init = None calculation = [] ibz_kpts = None parameters = OrderedDict() try: for event, elem in tree: if event == 'end': if elem.tag == 'kpoints': for subelem in elem.iter(tag='generation'): kpts_params = OrderedDict() parameters['kpoints_generation'] = kpts_params for par in subelem.iter(): if par.tag in ['v', 'i']: parname = par.attrib['name'].lower() kpts_params[parname] = __get_xml_parameter(par) kpts = elem.findall("varray[@name='kpointlist']/v") ibz_kpts = np.zeros((len(kpts), 3)) for i, kpt in enumerate(kpts): ibz_kpts[i] = [float(val) for val in kpt.text.split()] elif elem.tag == 'parameters': for par in elem.iter(): if par.tag in ['v', 'i']: parname = par.attrib['name'].lower() parameters[parname] = __get_xml_parameter(par) elif elem.tag == 'atominfo': species = [] for entry in elem.find("array[@name='atoms']/set"): species.append(entry[0].text.strip()) natoms = len(species) elif (elem.tag == 'structure' and elem.attrib.get('name') == 'initialpos'): cell_init = np.zeros((3, 3), dtype=float) for i, v in enumerate(elem.find( "crystal/varray[@name='basis']")): cell_init[i] = np.array([ float(val) for val in v.text.split()]) scpos_init = np.zeros((natoms, 3), dtype=float) for i, v in enumerate(elem.find( "varray[@name='positions']")): scpos_init[i] = np.array([ float(val) for val in v.text.split()]) constraints = [] fixed_indices = [] for i, entry in enumerate(elem.findall( "varray[@name='selective']/v")): flags = (np.array(entry.text.split() == np.array(['F', 'F', 'F']))) if flags.all(): fixed_indices.append(i) elif flags.any(): constraints.append(FixScaled(cell_init, i, flags)) if fixed_indices: constraints.append(FixAtoms(fixed_indices)) atoms_init = Atoms(species, cell=cell_init, scaled_positions=scpos_init, constraint=constraints, pbc=True) elif elem.tag=='dipole': dblock = elem.find('v[@name="dipole"]') if dblock is not None: dipole = np.array([float(val) for val in dblock.text.split()]) elif event == 'start' and elem.tag == 'calculation': calculation.append(elem) except ET.ParseError as parse_error: if atoms_init is None: raise parse_error if calculation[-1].find('energy') is None: calculation = calculation[:-1] if not calculation: yield atoms_init if calculation: if isinstance(index, int): steps = [calculation[index]] else: steps = calculation[index] else: steps = [] for step in steps: # Workaround for VASP bug, e_0_energy contains the wrong value # in calculation/energy, but calculation/scstep/energy does not # include classical VDW corrections. So, first calculate # e_0_energy - e_fr_energy from calculation/scstep/energy, then # apply that correction to e_fr_energy from calculation/energy. lastscf = step.findall('scstep/energy')[-1] try: lastdipole = step.findall('scstep/dipole')[-1] except: lastdipole = None de = (float(lastscf.find('i[@name="e_0_energy"]').text) - float(lastscf.find('i[@name="e_fr_energy"]').text)) free_energy = float(step.find('energy/i[@name="e_fr_energy"]').text) energy = free_energy + de cell = np.zeros((3, 3), dtype=float) for i, vector in enumerate(step.find( 'structure/crystal/varray[@name="basis"]')): cell[i] = np.array([float(val) for val in vector.text.split()]) scpos = np.zeros((natoms, 3), dtype=float) for i, vector in enumerate(step.find( 'structure/varray[@name="positions"]')): scpos[i] = np.array([float(val) for val in vector.text.split()]) forces = None fblocks = step.find('varray[@name="forces"]') if fblocks is not None: forces = np.zeros((natoms, 3), dtype=float) for i, vector in enumerate(fblocks): forces[i] = np.array([float(val) for val in vector.text.split()]) stress = None sblocks = step.find('varray[@name="stress"]') if sblocks is not None: stress = np.zeros((3, 3), dtype=float) for i, vector in enumerate(sblocks): stress[i] = np.array([float(val) for val in vector.text.split()]) stress *= -0.1 * GPa stress = stress.reshape(9)[[0, 4, 8, 5, 2, 1]] dipole = None if lastdipole is not None: dblock = lastdipole.find('v[@name="dipole"]') if dblock is not None: dipole = np.zeros((1,3), dtype=float) dipole = np.array([float(val) for val in dblock.text.split()]) dblock = step.find('dipole/v[@name="dipole"]') if dblock is not None: dipole = np.zeros((1,3), dtype=float) dipole = np.array([float(val) for val in dblock.text.split()]) efermi = step.find('dos/i[@name="efermi"]') if efermi is not None: efermi = float(efermi.text) kpoints = [] for ikpt in range(1, len(ibz_kpts) + 1): kblocks = step.findall( 'eigenvalues/array/set/set/set[@comment="kpoint %d"]' % ikpt) if kblocks is not None: for i, kpoint in enumerate(kblocks): eigenvals = kpoint.findall('r') eps_n = np.zeros(len(eigenvals)) f_n = np.zeros(len(eigenvals)) for j, val in enumerate(eigenvals): val = val.text.split() eps_n[j] = float(val[0]) f_n[j] = float(val[1]) if len(kblocks) == 1: f_n *= 2 kpoints.append(SinglePointKPoint(1, 0, ikpt, eps_n, f_n)) if len(kpoints) == 0: kpoints = None atoms = atoms_init.copy() atoms.set_cell(cell) atoms.set_scaled_positions(scpos) atoms.set_calculator( SinglePointDFTCalculator(atoms, energy=energy, forces=forces, stress=stress, free_energy=free_energy, ibzkpts=ibz_kpts, efermi=efermi, dipole=dipole)) atoms.calc.name = 'vasp' atoms.calc.kpts = kpoints atoms.calc.parameters = parameters yield atoms
(0., 0., doo), (sin(angle) * doht, 0., doo - cos(angle) * doht)]) if 0: view(initial) final = Atoms('HOHOH', positions=[(-sin(angle) * doht, 0., cos(angle) * doht), (0., 0., 0.), (0., 0., doo - doh), (0., 0., doo), (sin(angle) * doht, 0., doo - cos(angle) * doht)]) if 0: view(final) # Make band: images = [initial.copy()] for i in range(3): images.append(initial.copy()) images.append(final.copy()) neb = NEB(images, climb=True) # Set constraints and calculator: constraint = FixAtoms(indices=[1, 3]) # fix OO for image in images: image.set_calculator(EMT()) image.set_constraint(constraint) for image in images: # O-H(shared) distance print(image.get_distance(1, 2), image.get_potential_energy()) # Relax initial and final states:
from ase.neb import NEB from ase.calculators.emt import EMT a = 4.0614 b = a / sqrt(2) h = b / 2 initial = Atoms('Al2', positions=[(0, 0, 0), (a / 2, b / 2, -h)], cell=(a, b, 2 * h), pbc=(1, 1, 0)) initial *= (2, 2, 2) initial.append(Atom('Al', (a / 2, b / 2, 3 * h))) initial.center(vacuum=4.0, axis=2) final = initial.copy() final.positions[-1, 0] += a view([initial, final]) # Construct a list of images: images = [initial] for i in range(5): images.append(initial.copy()) images.append(final) # Make a mask of zeros and ones that select fixed atoms (the # two bottom layers): mask = initial.positions[:, 2] - min(initial.positions[:, 2]) < 1.5 * h constraint = FixAtoms(mask=mask) print(mask)