def test_default(self): atoms = am.Atoms() assert atoms.natoms == 1 assert atoms.natypes == 1 assert atoms.atype[0] == 1 assert np.allclose(atoms.pos[0], np.zeros(3)) assert len(atoms) == atoms.natoms
def build_example(self): atoms = am.Atoms(pos=[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], atype=[2,1]) atoms.test1 = np.array(['a', 'b']) atoms.prop(key='test2', value=[np.zeros((3,3))]) atoms.view['test3'] = [1, 1] atoms.prop_atype('charge', [-1, 1]) return atoms
def fcc_edge(self): axes = np.array([[1, 0, -1], [1, 1, 1], [1, -2, 1]]) alat = uc.set_in_units(4.0248, 'angstrom') C11 = uc.set_in_units(113.76, 'GPa') C12 = uc.set_in_units(61.71, 'GPa') C44 = uc.set_in_units(31.25, 'GPa') c = am.ElasticConstants(C11=C11, C12=C12, C44=C44) burgers = alat / 2 * np.array([1., 0., -1.]) # initializing a new Stroh object using the data stroh = am.defect.Stroh(c, burgers, axes=axes) pos_test = uc.set_in_units(np.array([12.4, 13.5, -10.6]), 'angstrom') disp = stroh.displacement(pos_test) print("displacement =", uc.get_in_units(disp, 'angstrom'), 'angstrom') # monopole system box = am.Box(a=alat, b=alat, c=alat) atoms = am.Atoms(natoms=4, prop={ 'atype': 1, 'pos': [[0.0, 0.0, 0.0], [0.5, 0.5, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5]] }) ucell = am.System(atoms=atoms, box=box, scale=True) system = am.rotate_cubic(ucell, axes) shift = np.array( [0.12500000000000, 0.50000000000000, 0.00000000000000]) new_pos = system.atoms_prop(key='pos', scale=True) + shift system.atoms_prop(key='pos', value=new_pos, scale=True) system.supersize((-7, 7), (-6, 6), (0, 1)) disp = stroh.displacement(system.atoms_prop(key='pos')) system.atoms_prop(key='pos', value=system.atoms_prop(key='pos') + disp) system.pbc = (False, False, True) system.wrap() pos = system.atoms_prop(key='pos') x = uc.get_in_units(pos[:, 0], 'angstrom') y = uc.get_in_units(pos[:, 1], 'angstrom') plt.figure(figsize=(8, 8)) plt.scatter(x, y, s=30) plt.xlim(min(x), max(x)) plt.ylim(min(y), max(y)) plt.xlabel('x-position (Angstrom)', fontsize='large') plt.ylabel('y-position (Angstrom)', fontsize='large') plt.show()
def test_model(self): atoms = self.build_example() model = atoms.model(prop_unit={'atype':None, 'pos':'scaled', 'test1':None, 'test2':None, 'test3':'J', 'charge':'GPa'}) atoms2 = am.Atoms(model=model) for prop in ['atype', 'pos', 'test2', 'test3', 'charge']: assert np.allclose(atoms.view[prop], atoms2.view[prop]) assert atoms.test1[0] == atoms2.test1[0] assert atoms.test1[1] == atoms2.test1[1]
def load(poscar): """ Reads a poscar-style coordination file for a system. Returns an atomman.System, and a list of elements if the file gives them. """ #Read in all lines of the file with uber_open_rmode(poscar) as f: lines = f.read().split('\n') #Interpret box information box_scale = float(lines[1]) avect = np.array(lines[2].split(), dtype='float64') * box_scale bvect = np.array(lines[3].split(), dtype='float64') * box_scale cvect = np.array(lines[4].split(), dtype='float64') * box_scale box = am.Box(avect=avect, bvect=bvect, cvect=cvect) #Read in elements, number of types, and style info try: typenums = np.array(lines[5].split(), dtype='int32') elements = [None for n in xrange(len(typenums))] style = lines[6] start_i = 7 except: elements = lines[5].split() typenums = np.array(lines[6].split(), dtype='int32') style = lines[7] start_i = 8 #Build atype list atype = np.array([], dtype='int32') for i in xrange(len(typenums)): atype = np.hstack((atype, np.full(typenums[i], i + 1, dtype='int32'))) #Check which coordinate style to use if style[0] in 'cCkK': scale = False else: scale = True #Read in positions natoms = np.sum(typenums) pos = np.empty((natoms, 3), dtype='float64') count = 0 for i in xrange(start_i, len(lines)): terms = lines[i].split() if len(terms) > 0: pos[count, :] = np.array(terms, dtype='float64') count += 1 atoms = am.Atoms(natoms=natoms, prop={'atype': atype, 'pos': pos}) system = am.System(atoms=atoms, box=box, scale=scale) return system, elements
def vacancy(system, pos=None, ptd_id=None, scale=False, atol=None): """ Returns a new System where a vacancy point defect has been inserted. Keyword Arguments: system -- base System that the defect is added to. pos -- position of the atom to be removed. ptd_id -- id of the atom to be removed. Alternative to using pos. scale -- if pos is given, indicates if pos is absolute (False) or box-relative (True). Default is False. Adds atom property old_id if it doesn't already exist that tracks the original atom ids. """ pos_list = system.atoms.view['pos'] #if pos is supplied, use isclose and where to identify the id of the atom at pos if pos is not None: if atol is None: atol = uc.set_in_units(1e-3, 'angstrom') if scale: pos = system.unscale(pos) assert ptd_id is None, 'pos and ptd_id cannot both be supplied' ptd_id = np.where(np.isclose(pos_list, pos, atol=atol).all(axis=1)) assert len(ptd_id) == 1 and len( ptd_id[0]) == 1, 'Unique atom at pos not identified' ptd_id = long(ptd_id[0][0]) #test that ptd_id is a valid entry try: pos = pos_list[ptd_id] except: raise TypeError('Invalid ptd_id') #create new system and copy values over d_system = am.System(box=system.box, pbc=system.pbc, atoms=am.Atoms(natoms=system.natoms - 1)) for prop in system.atoms_prop(): view = system.atoms.view[prop] value = np.asarray(np.vstack((view[:ptd_id], view[ptd_id + 1:])), dtype=system.atoms.dtype[prop]) d_system.atoms_prop(key=prop, value=value) #add property old_id with each atom's original id if d_system.atoms_prop(key='old_id') is None: d_system.atoms_prop(key='old_id', value=np.hstack((np.arange(0, ptd_id), np.arange(ptd_id + 1, system.natoms))), dtype='int32') return d_system
def interstitial(system, atype=None, pos=None, scale=False, atol=None): """ Returns a new System where a positional interstitial point defect has been inserted. Keyword Arguments: system -- base System that the defect is added to. atype -- atom type for the interstitial atom. pos -- position for adding the interstitial atom. scale -- if pos is given, indicates if pos is absolute (False) or box-relative (True). Default is False. Adds atom property old_id if it doesn't already exist that tracks the original atom ids. """ pos_list = system.atoms.view['pos'] if atol is None: atol = uc.set_in_units(1e-3, 'angstrom') if scale: pos = system.unscale(pos) #Use isclose and where to check that no atoms are already at pos ptd_id = np.where(np.isclose(pos_list, pos, atol=atol).all(axis=1)) assert len(ptd_id) == 1 and len(ptd_id[0]) == 0, 'atom already at pos' assert isinstance( atype, (int, long)) and atype > 0, 'atype must be a positive integer' #create new system and copy values over d_system = am.System(box=system.box, pbc=system.pbc, atoms=am.Atoms(natoms=system.natoms + 1)) for prop in system.atoms_prop(): view = system.atoms.view[prop] value = np.asarray(np.vstack((view, np.zeros_like(view[0]))), dtype=system.atoms.dtype[prop]) d_system.atoms_prop(key=prop, value=value) d_system.atoms_prop(a_id=d_system.natoms - 1, key='atype', value=atype) d_system.atoms_prop(a_id=d_system.natoms - 1, key='pos', value=pos) #add property old_id with each atom's original id if d_system.atoms_prop(key='old_id') is None: d_system.atoms_prop(key='old_id', value=np.arange(d_system.natoms), dtype='int32') else: old_id = max(system.atoms_prop(key='old_id')) + 1 d_system.atoms_prop(a_id=d_system.natoms - 1, key='old_id', value=old_id) return d_system
def __init__(self, atoms=Atoms(), box=Box(), pbc=(True, True, True), scale=False, prop={}): """ Initilize a System by joining an am.Atoms and am.Box instance. Keyword Arguments: atoms -- Instance of am.Atoms to include. box -- Instance of am.Box to include. pbc -- Tuple of three booleans where True indicates a given box dimension is periodic. Default is all True. scale -- If True, atoms' pos will be scaled relative to the box. Default is False. prop -- Dictionary of free-form system-wide properties. """ #Check parameter types assert isinstance(box, Box), 'Invalid box entry' assert isinstance(atoms, Atoms), 'Invalid atoms entry' assert isinstance(prop, dict), 'invalid prop dictionary' #Copy box self.__box = deepcopy(box) #Copy atoms data = deepcopy(atoms.data) #Reassign atom views to new data array view = OrderedDict() start = 0 for k in atoms.view: vshape = atoms.view[k].shape view[k] = data[:, start:start + atoms.view[k][0].size] view[k].shape = vshape start = start + view[k][0].size #Save new atoms self.__atoms = am.Atoms(data=data, view=view, prop_dtype=atoms.dtype) #Rescale pos if needed if scale is True: self.atoms.view['pos'][:] = self.unscale(atoms.view['pos']) #Save pbc self.pbc = pbc #Save prop dict self.__prop = prop
def test_displacement(): a = 3.18 c = 5.17 ucell = am.System(atoms=am.Atoms(pos=[[0.0, 0.0, 0.0], [1 / 3, 2 / 3, 0.5]]), box=am.Box.hexagonal(a, c), scale=True) system_0 = ucell.supersize(10, 10, 10) system_1 = deepcopy(system_0) system_1.atoms.pos[:] += 5 system_1.wrap() assert not np.allclose(system_1.atoms.pos - system_0.atoms.pos, 5.0) assert np.allclose(am.displacement(system_0, system_1), 5.0)
def load(ase_atoms): """Convert an ase.Atoms into an atomman.System and list of elements.""" assert has_ase, 'ase not imported' box = am.Box(vects=ase_atoms.get_cell()) atoms = am.Atoms(natoms=len(ase_atoms)) atoms.prop(key='pos', value=ase_atoms.get_positions()) all_elements = np.array(ase_atoms.get_chemical_symbols()) elements, atype = np.unique(all_elements, return_inverse=True) atype += 1 atoms.prop(key='atype', value=atype) return am.System(atoms=atoms, box=box), elements
def test_atomic_no_imageflags(self): box = am.Box(vects=[[1.25694013, 0. , 0. ], [1.17551244, 4.01690452, 0. ], [0.23122344, 0.0768582 , 0.76391945]]) pos = [[0.53342537, 0.70899278, 0.21800393], [0.8766086 , 0.98893671, 0.57889022], [0.78898178, 0.44740662, 0.49997271], [0.78302097, 0.06197394, 0.77049739]] atoms = am.Atoms(pos=pos, atype=1) symbols = 'Al' pbc = (True, True, True) system = am.System(atoms=atoms, box=box, scale=True, symbols=symbols, pbc=pbc) self.load_dump(system, atom_style='atomic', units='metal')
def load(cif): """Reads in a CIF crystal file and returns an atomman.System and list of elements.""" assert has_diffpy, 'diffpy.Structure not imported' dps = diffpy.Structure.structure.Structure() #load from an open file-like object if hasattr(cif, 'read'): dps.readStr(cif.read()) #load using a file name elif os.path.isfile(cif): dps.read(cif) #load from a string else: dps.readStr(cif) all_elements = dps.element elements, all_atype = np.unique(all_elements, return_inverse=True) all_atype += 1 all_pos = dps.xyz atype = [] pos = [] for a1, p1 in zip(all_atype, all_pos): noMatch = True for a2, p2 in zip(atype, pos): if a1 == a2 and np.allclose(p1, p2): noMatch = False break if noMatch: atype.append(a1) pos.append(p1) atoms = am.Atoms(natoms=len(pos), prop={'atype':atype, 'pos':pos}) box = am.Box(a=dps.lattice.a, b=dps.lattice.b, c=dps.lattice.c, alpha=dps.lattice.alpha, beta=dps.lattice.beta, gamma=dps.lattice.gamma) return am.System(atoms=atoms, box=box, pbc=(True,True,True), scale=True), list(elements)
def test_bcc(): # Build bcc test system a = 2.865 ucell = am.System(atoms=am.Atoms(pos=[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]]), box=am.Box.cubic(a), scale=True) system = ucell.supersize(30, 30, 30) cutoff = 0.9 * a # Test all periodic boundaries system.pbc = [True, True, True] neighbors = system.neighborlist(cutoff=cutoff) assert np.isclose(neighbors.coord.mean(), 8.0) # Test no periodic boundaries system.pbc = [False, False, False] neighbors = system.neighborlist(cutoff=cutoff) assert np.isclose(neighbors.coord.mean(), 7.6066)
def test_1(self): atoms = am.Atoms(pos=[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], atype=[2, 1]) assert atoms.natoms == 2 assert atoms.natypes == 2 assert atoms.atypes[0] == 1 assert atoms.atypes[1] == 2 atoms.test1 = np.array(['a', 'b']) assert atoms.prop(key='test1', index=0) == 'a' assert atoms.test1[1] == 'b' atoms.prop(key='test2', value=[np.zeros((3, 3))]) assert np.allclose(atoms.view['test2'][0], np.zeros((3, 3))) assert np.allclose(atoms.test2[1], np.zeros((3, 3))) atoms.view['test3'] = [1, 1] assert atoms.view['test3'][0] == 1 assert atoms.test3[1] == 1 atoms.prop_atype('charge', [-1, 1]) assert atoms.charge[0] == 1 assert atoms.charge[1] == -1 df = atoms.df() assert len(df) == 2 assert 'atype' in df assert 'pos[0]' in df assert 'pos[1]' in df assert 'pos[2]' in df assert 'test1' in df assert 'test2[0][0]' in df assert 'test2[0][1]' in df assert 'test2[0][2]' in df assert 'test2[1][0]' in df assert 'test2[1][1]' in df assert 'test2[1][2]' in df assert 'test2[2][0]' in df assert 'test2[2][1]' in df assert 'test2[2][2]' in df assert 'charge' in df
def test_hcp(): # Build hcp test system a = 3.18 c = 5.17 ucell = am.System(atoms=am.Atoms(pos=[[0.0, 0.0, 0.0], [1 / 3, 2 / 3, 0.5]]), box=am.Box.hexagonal(a, c), scale=True) system = ucell.supersize(30, 30, 30) cutoff = 1.1 * a # Test all periodic boundaries system.pbc = [True, True, True] neighbors = system.neighborlist(cutoff=cutoff) assert np.isclose(neighbors.coord.mean(), 12.0) # Test no periodic boundaries system.pbc = [False, False, False] neighbors = system.neighborlist(cutoff=cutoff) assert np.isclose(neighbors.coord.mean(), 11.4411)
def ucell(self, a_scale, c_scale): """ Generates a bct unit cell for intermediate structures based on the given bcc and fcc lattice constants. For the scaling parameters, values of a_scale = c_scale = 0 corresponds to the given fcc lattice, and values of a_scale = c_scale = 1 corresponds to the given bcc lattice. Parameters ---------- a_scale : float Scaling parameter for the bct structure's a lattice parameter. c_scale : float Scaling parameter for the bct structure's c lattice parameter. Returns ------- ucell : atomman.System The corresponding bct unit cell. """ # Set the ideal constants based on a_fcc and a_bcc a_0 = self.a_fcc * 2**0.5 / 2 c_0 = self.a_fcc a_1 = c_1 = self.a_bcc # Compute the bct lattice constants using the scale parameters a = a_0 * (1 - a_scale) + a_1 * a_scale c = c_0 * (1 - c_scale) + c_1 * c_scale # Generate box, atoms and system for the bct unit cell box = am.Box().tetragonal(a=a, c=c) atoms = am.Atoms(pos=[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]]) ucell = am.System(atoms=atoms, box=box, symbols=self.symbol, scale=True) return ucell
def diatom_scan(lammps_command: str, potential: am.lammps.Potential, symbols: list, mpi_command: Optional[str] = None, rmin: float = uc.set_in_units(0.02, 'angstrom'), rmax: float = uc.set_in_units(6.0, 'angstrom'), rsteps: int = 300) -> dict: """ Performs a diatom energy scan over a range of interatomic spaces, r. Parameters ---------- lammps_command :str Command for running LAMMPS. potential : atomman.lammps.Potential The LAMMPS implemented potential to use. symbols : list The potential symbols associated with the two atoms in the diatom. mpi_command : str, optional The MPI command for running LAMMPS in parallel. If not given, LAMMPS will run serially. rmin : float, optional The minimum r spacing to use (default value is 0.02 angstroms). rmax : float, optional The maximum r spacing to use (default value is 6.0 angstroms). rsteps : int, optional The number of r spacing steps to evaluate (default value is 300). Returns ------- dict Dictionary of results consisting of keys: - **'r_values'** (*numpy.array of float*) - All interatomic spacings, r, explored. - **'energy_values'** (*numpy.array of float*) - The computed potential energies for each r value. """ # Build lists of values r_values = np.linspace(rmin, rmax, rsteps) energy_values = np.empty(rsteps) # Define atype based on symbols symbols = aslist(symbols) if len(symbols) == 1: atype = [1, 1] elif len(symbols) == 2: atype = [1, 2] else: raise ValueError('symbols must have one or two values') # Initialize system (will shift second atom's position later...) box = am.Box.cubic(a=rmax + 1) atoms = am.Atoms(atype=atype, pos=[[0.1, 0.1, 0.1], [0.1, 0.1, 0.1]]) system = am.System(atoms=atoms, box=box, pbc=[False, False, False], symbols=symbols) # Add charges if required if potential.atom_style == 'charge': system.atoms.prop_atype('charge', potential.charges(system.symbols)) # Get lammps units lammps_units = lmp.style.unit(potential.units) # Define lammps variables lammps_variables = {} # Loop over values for i in range(rsteps): # Shift second atom's x position system.atoms.pos[1] = np.array([0.1 + r_values[i], 0.1, 0.1]) # Save configuration system_info = system.dump('atom_data', f='diatom.dat', potential=potential) lammps_variables['atomman_system_pair_info'] = system_info # Write lammps input script lammps_script = 'run0.in' template = read_calc_file('iprPy.calculation.diatom_scan', 'run0.template') with open(lammps_script, 'w') as f: f.write(filltemplate(template, lammps_variables, '<', '>')) # Run lammps and extract data try: output = lmp.run(lammps_command, script_name=lammps_script, mpi_command=mpi_command) except: energy_values[i] = np.nan else: energy = output.simulations[0]['thermo'].PotEng.values[-1] energy_values[i] = uc.set_in_units(energy, lammps_units['energy']) if len(energy_values[np.isfinite(energy_values)]) == 0: raise ValueError( 'All LAMMPS runs failed. Potential likely invalid or incompatible.' ) # Collect results results_dict = {} results_dict['r_values'] = r_values results_dict['energy_values'] = energy_values return results_dict
from DataModelDict import DataModelDict as DM import atomman as am # Load dummy input inputdict = DM('input.json') # Build fcc unit cell box = am.Box.cubic(3.2) atoms = am.Atoms(pos=[[0.0, 0.0, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5], [0.5, 0.5, 0.0]]) ucell = am.System(atoms=atoms, box=box, scale=True) # Modify system system = ucell.supersize(3, 3, 3) # Dump to json system.dump('system_model', f='system.json', format='json')
def isolated_atom(lammps_command: str, potential: am.lammps.Potential, mpi_command: Optional[str] = None) -> dict: """ Evaluates the isolated atom energy for each elemental model of a potential. Parameters ---------- lammps_command :str Command for running LAMMPS. potential : atomman.lammps.Potential The LAMMPS implemented potential to use. mpi_command : str, optional The MPI command for running LAMMPS in parallel. If not given, LAMMPS will run serially. Returns ------- dict Dictionary of results consisting of keys: - **'energy'** (*dict*) - The computed potential energies for each symbol. """ # Initialize dictionary energydict = {} # Initialize single atom system box = am.Box.cubic(a=1) atoms = am.Atoms(atype=1, pos=[[0.5, 0.5, 0.5]]) system = am.System(atoms=atoms, box=box, pbc=[False, False, False]) # Get lammps units lammps_units = lmp.style.unit(potential.units) # Define lammps variables lammps_variables = {} # Loop over symbols for symbol in potential.symbols: system.symbols = symbol # Add charges if required if potential.atom_style == 'charge': system.atoms.prop_atype('charge', potential.charges(system.symbols)) # Save configuration system_info = system.dump('atom_data', f='isolated.dat', potential=potential) lammps_variables['atomman_system_pair_info'] = system_info # Write lammps input script lammps_script = 'run0.in' template = read_calc_file('iprPy.calculation.isolated_atom', 'run0.template') with open(lammps_script, 'w') as f: f.write(filltemplate(template, lammps_variables, '<', '>')) # Run lammps and extract data output = lmp.run(lammps_command, script_name=lammps_script, mpi_command=mpi_command) energy = output.simulations[0]['thermo'].PotEng.values[-1] energydict[symbol] = uc.set_in_units(energy, lammps_units['energy']) # Collect results results_dict = {} results_dict['energy'] = energydict return results_dict
def load(model, key='atomic-system', index=0): """Read in a data model containing a crystal-structure and return a System unit cell.""" if isinstance(model, (str, unicode)) and os.path.isfile(model): with open(model) as f: model = f.read() #Pull system model out of data model using key and index a_sys = DataModelDict(model).finds(key) if len(a_sys) == 0: raise KeyError(key + ' not found in model') try: a_sys = a_sys[index] except: raise IndexError('Invalid index ' + str(index) + ' for model key ' + key) #identify the crystal system c_system = a_sys['cell'].keys()[0] cell = a_sys['cell'][c_system] if c_system == 'cubic': a = b = c = uc.value_unit(cell['a']) alpha = beta = gamma = 90.0 elif c_system == 'hexagonal': a = b = uc.value_unit(cell['a']) c = uc.value_unit(cell['c']) alpha = beta = 90.0 gamma = 120.0 elif c_system == 'tetragonal': a = b = uc.value_unit(cell['a']) c = uc.value_unit(cell['c']) alpha = beta = gamma = 90.0 elif c_system == 'trigonal' or c_system == 'rhombohedral': a = b = c = uc.value_unit(cell['a']) alpha = beta = gamma = cell['alpha'] elif c_system == 'orthorhombic': a = uc.value_unit(cell['a']) b = uc.value_unit(cell['b']) c = uc.value_unit(cell['c']) alpha = beta = gamma = 90.0 elif c_system == 'monoclinic': a = uc.value_unit(cell['a']) b = uc.value_unit(cell['b']) c = uc.value_unit(cell['c']) alpha = gamma = 90.0 beta = cell['beta'] elif c_system == 'triclinic': a = uc.value_unit(cell['a']) b = uc.value_unit(cell['b']) c = uc.value_unit(cell['c']) alpha = cell['alpha'] beta = cell['beta'] gamma = cell['gamma'] box = am.Box(a=a, b=b, c=c, alpha=alpha, beta=beta, gamma=gamma) #create list of atoms and list of elements atoms = [] scale = None prop = DataModelDict() all_atypes = np.array(a_sys.finds('component')) all_symbols = np.array(a_sys.finds('symbol')) all_elements = np.array(a_sys.finds('element')) if len(all_atypes) == 0: if len(all_symbols) != 0: symbols, atypes = np.unique(all_symbols, return_inverse) elif len(all_elements) != 0: symbols, atypes = np.unique(all_elements, return_inverse) else: raise ValueError('No atom components, symbols or elements listed') else: atypes = all_atypes symbols = [None for i in xrange(max(all_atypes))] if len(all_elements) != 0 and len(all_symbols) == 0: all_symbols = all_elements if len(all_symbols) != 0: assert len(all_symbols) == len(atypes) sym_dict = {} for atype, symbol in zip(atypes, all_symbols): if atype not in sym_dict: sym_dict[atype] = symbol else: assert sym_dict[atype] == symbol for atype, symbol in sym_dict.iteritems(): symbols[atype - 1] = symbol prop['atype'] = atypes prop['pos'] = np.zeros((len(prop['atype']), 3), dtype='float64') count = 0 pos_units = [] for atom in a_sys.iteraslist('atom'): #read in pos for atom and unit info prop['pos'][count] = uc.value_unit(atom['position']) pos_units.append(atom['position'].get('unit', None)) #Add per-atom properties for property in atom.iteraslist('property'): if property['name'] not in prop: value = uc.value_unit(property) prop[property['name']] = np.zeros( (len(prop['atype']), len(value)), dtype=value.dtype) prop[property['name']][count] = uc.value_unit(property) count += 1 pos_unit = np.unique(pos_units) assert len(pos_unit) == 1, 'Mixed units for positions' if pos_unit[0] == 'scaled': scale = True else: scale = False atoms = am.Atoms(natoms=len(prop['atype']), prop=prop) system = am.System(box=box, atoms=atoms, scale=scale) return system, symbols
lmpS.create_in(in_data, potential, fix) output = lmp.run(lammps_exe, in_name, return_style='object') status = parseLogs.get_vars2('log.lammps') Lx = status['Lx'] Ly = status['Ly'] Lz = status['Lz'] Vol = Lx * Ly * Lz Atoms = status['Atoms'] PotEng = status['PotEng'] / Atoms print Lx, Ly, Lz, Vol, PotEng avect = [4.050, 0.000, 0.000] bvect = [0.000, 4.050, 0.000] cvect = [0.0000001, 0.000, 4.050] origin = [0.000, 0.000, 0.000] prop = { 'atype': 1, 'pos': [[0.0, 0.0, 0.0], [0.5, 0.5, 0.0], [0.5, 0.0, 0.5], [0.0, 0.5, 0.5]] } atoms = am.Atoms(natoms=4, prop=prop) box = am.Box(avect=avect, bvect=bvect, cvect=cvect, origin=origin) fcc_cell = am.System(box=box, atoms=atoms, scale=True) print(fcc_cell) sys_info = lmp.atom_data.dump(fcc_cell, 'atom.dat')
def rotate_cubic(system, axes): """ Rotate a cubic system according to the specified crystallographic axes. Returns an orthogonal system whose box lengths are: a * sqrt(i^2+j^2+k^2) where a is the original cubic box length, and ijk are the crystallographic indicies for the specific direction. """ # rotate system generically system = rotate(system, axes) # test for cubic a = system.box.a try: assert np.isclose(a, system.box.b), str(a) + ' ' + str(system.box.b) assert np.isclose(a, system.box.c), str(a) + ' ' + str(system.box.c) assert np.isclose(90.0, system.box.alpha), str(system.box.alpha) assert np.isclose(90.0, system.box.beta), str(system.box.beta) assert np.isclose(90.0, system.box.gamma), str(system.box.gamma) except: raise ValueError('Cubic system not given') # Test for integer axes values try: for ax_val in axes.flat: assert np.isclose(ax_val, int(ax_val)) except: raise ValueError('axes values must be integers') # Get magnitudes of the axes mag = np.linalg.norm(axes, axis=1) # compute number of atoms for the new system natoms = system.natoms * mag[0] * mag[1] * mag[2] if np.isclose(int(round(natoms)), natoms): natoms = int(round(natoms)) else: raise ValueError( 'not an integer number of atoms associated with the axes.') # create a new box with scaled lattice parameters box = am.Box(a=a * mag[0], b=a * mag[1], c=a * mag[2], origin=system.box.origin) # supersize the rotated box m = int(ceil(max(mag))) system = am.tools.supersize(system, (-m, m), (-m, m), (-m, m)) # filter atoms for only those in the new box data = system.atoms.data # round x-positions near xlo, xhi and only keep data for atoms where xlo # <= x < xhi data[np.where(np.isclose(data.T[1], box.xlo, atol=1e-8, rtol=0)), 1] = box.xlo data = data[data.T[1] >= box.xlo] data[np.where(np.isclose(data.T[1], box.xhi, atol=1e-8, rtol=0)), 1] = box.xhi data = data[data.T[1] < box.xhi] # round y-positions near ylo, yhi and only keep data for atoms where ylo # <= y < yhi data[np.where(np.isclose(data.T[2], box.ylo, atol=1e-8, rtol=0)), 2] = box.ylo data = data[data.T[2] >= box.ylo] data[np.where(np.isclose(data.T[2], box.yhi, atol=1e-8, rtol=0)), 2] = box.yhi data = data[data.T[2] < box.yhi] # round z-positions near zlo, zhi and only keep data for atoms where zlo # <= z < zhi data[np.where(np.isclose(data.T[3], box.zlo, atol=1e-8, rtol=0)), 3] = box.zlo data = data[data.T[3] >= box.zlo] data[np.where(np.isclose(data.T[3], box.zhi, atol=1e-8, rtol=0)), 3] = box.zhi data = data[data.T[3] < box.zhi] # deepcopy the data array to guarantee that it is new and separate data = deepcopy(data) # rebuild views start = 0 view = OrderedDict() for k in system.atoms.view: vshape = (len(data), ) + system.atoms.view[k].shape[1:] view[k] = data[:, start:start + system.atoms.view[k][0].size] view[k].shape = vshape start = start + system.atoms.view[k][0].size # create atoms from natoms, data, view and dtype atoms = am.Atoms(natoms=natoms, data=data, view=view, prop_dtype=system.atoms.dtype) # return new system return am.System(box=box, atoms=atoms)
def dumbbell(system, atype=None, pos=None, ptd_id=None, db_vect=None, scale=False, atol=None): """ Returns a new System where a dumbbell interstitial point defect has been inserted. Keyword Arguments: system -- base System that the defect is added to. atype -- atom type for the atom in the dumbbell pair being added to the system. pos -- position of the system atom where the dumbbell pair is added. ptd_id -- id of the system atom where the dumbbell pair is added. Alternative to using pos. db_vect -- vector associated with the dumbbell interstitial. scale -- indicates if pos and db_vect are absolute (False) or box-relative (True). Default is False. Adds atom property old_id if it doesn't already exist that tracks the original atom ids. """ pos_list = system.atoms.view['pos'] #if pos is supplied, use isclose and where to identify the id of the atom at pos if pos is not None: if atol is None: atol = uc.set_in_units(1e-3, 'angstrom') if scale: pos = system.unscale(pos) assert ptd_id is None, 'pos and ptd_id cannot both be supplied' ptd_id = np.where(np.isclose(pos_list, pos, atol=atol).all(axis=1)) assert len(ptd_id) == 1 and len( ptd_id[0]) == 1, 'Unique atom at pos not identified' ptd_id = long(ptd_id[0][0]) #test that ptd_id is a valid entry try: pos = pos_list[ptd_id] except: raise TypeError('Invalid ptd_id') assert isinstance( atype, (int, long)) and atype > 0, 'atype must be a positive integer' #unscale db_vect if scale is True if scale: db_vect = system.unscale(db_vect) #create new system and copy values over d_system = am.System(box=system.box, pbc=system.pbc, atoms=am.Atoms(natoms=system.natoms + 1)) for prop in system.atoms_prop(): view = system.atoms.view[prop] value = np.asarray(np.vstack( (view[:ptd_id], view[ptd_id + 1:], view[ptd_id], np.zeros_like(view[0]))), dtype=system.atoms.dtype[prop]) d_system.atoms_prop(key=prop, value=value) d_system.atoms_prop(a_id=d_system.natoms - 1, key='atype', value=atype) d_system.atoms_prop(a_id=d_system.natoms - 2, key='pos', value=pos - db_vect) d_system.atoms_prop(a_id=d_system.natoms - 1, key='pos', value=pos + db_vect) #add property old_id with each atom's original id if d_system.atoms_prop(a_id=0, key='old_id') is None: d_system.atoms_prop(key='old_id', value=np.hstack((np.arange(0, ptd_id), np.arange(ptd_id + 1, system.natoms), ptd_id, system.natoms)), dtype='int32') else: old_id = max(system.atoms_prop(key='old_id')) + 1 d_system.atoms_prop(a_id=d_system.natoms - 1, key='old_id', value=old_id) return d_system
def supersize(system, a_size, b_size, c_size): """ Builds a large system based on a seed system and multipliers. Keyword Arguments: system -- atomman.System to use as the seed. a_size -- int or tuple of 2 ints for multiplying along the avect direction. b_size -- int or tuple of 2 ints for multiplying along the bvect direction. c_size -- int or tuple of 2 ints for multiplying along the cvect direction. The multiplier values *_size are taken to be integer tuples (m, n) where m <= 0 and n >= 0. The system multiplication works such that if n = -m, then the seed system's origin will be at the center of the new system. If only one integer is given, then it is assigned to m or n depending on its sign, and the other value is taken to be 0. """ #initial parameter setup sizes = [a_size, b_size, c_size] mults = np.array([0, 0, 0], dtype=int) vects = system.box.vects origin = system.box.origin spos = system.atoms_prop(key='pos', scale=True) for i in xrange(3): #check values in sizes if isinstance(sizes[i], (int, long)): if sizes[i] > 0: sizes[i] = (0, sizes[i]) elif sizes[i] < 0: sizes[i] = (sizes[i], 0) elif isinstance(sizes[i], tuple): assert len(sizes[i]) == 2, 'Invalid system multipliers' assert isinstance( sizes[i][0], (int, long)) and sizes[i][0] <= 0, 'Invalid system multipliers' assert isinstance( sizes[i][1], (int, long)) and sizes[i][1] >= 0, 'Invalid system multipliers' else: raise TypeError('Invalid system multipliers') #calculate multipliers and scale box and first set of positions accordingly mults[i] = sizes[i][1] - sizes[i][0] assert mults[i] != 0, 'Cannot multiply system dimension by zero' spos[:, i] /= mults[i] origin += vects[i] * sizes[i][0] vects[i] *= mults[i] #initilize new Box and Atoms box = atomman.Box(vects=vects, origin=origin) natoms = system.natoms * mults[0] * mults[1] * mults[2] atoms = atomman.Atoms(natoms=natoms) #Copy over all property values using numpy broadcasting for prop in system.atoms_prop(): o_values = system.atoms_prop(key=prop) n_values = np.empty( (mults[0] * mults[1] * mults[2], ) + o_values.shape, dtype=o_values.dtype) n_values[:] = system.atoms_prop(key=prop) n_shape = n_values.shape n_shape = (n_shape[0] * n_shape[1], ) + n_shape[2:] atoms.prop(key=prop, value=n_values.reshape(n_shape)) #Expand spos using broadcasting n_spos = np.empty((mults[0] * mults[1] * mults[2], ) + spos.shape) n_spos[:] = spos n_shape = n_spos.shape n_shape = (n_shape[0] * n_shape[1], ) + n_shape[2:] n_spos = n_spos.reshape(n_shape) #use broadcasting to create arrays to add to spos test = np.empty(mults[0] * system.natoms) test.shape = (system.natoms, mults[0]) test[:] = np.arange(mults[0]) x = test.T.flatten() test = np.empty(mults[1] * len(x)) test.shape = (len(x), mults[1]) test[:] = np.arange(mults[1]) y = test.T.flatten() test.shape = (mults[1], len(x)) test[:] = x x = test.flatten() test = np.empty(mults[2] * len(x)) test.shape = (len(x), mults[2]) test[:] = np.arange(mults[2]) z = test.T.flatten() test.shape = (mults[2], len(x)) test[:] = x x = test.flatten() test[:] = y y = test.flatten() #xyz is displacement values to add to spos xyz = np.hstack( (x[:, np.newaxis], y[:, np.newaxis], z[:, np.newaxis])) * np.array( [1. / mults[0], 1. / mults[1], 1. / mults[2]]) #save pos values, return new System atoms.prop(key='pos', value=n_spos + xyz) return atomman.System(box=box, atoms=atoms, scale=True)
def load(data, prop_info=None): """ Read a LAMMPS-style dump file and return a System. Argument: data = file name, file-like object or string to read data from. Keyword Argument: prop_info -- DataModelDict for relating the per-atom properties to/from the dump file and the System. Will create a default json instance <data>.json if prop_info is not given and <data>.json doesn't already exist. """ #read in prop_info if supplied if prop_info is not None: if isinstance(prop_info, (str, unicode)) and os.path.isfile(prop_info): with open(prop_info) as f: prop_info = f.read() prop_info = DataModelDict(prop_info) #check for default prop_info file else: try: with open(data + '.json') as fj: prop_info = DataModelDict(fj) except: prop_info = None box_unit = None #read box_unit if specified in prop_info if prop_info is not None: prop_info = prop_info.find('LAMMPS-dump-atoms_prop-relate') box_unit = prop_info['box_prop'].get('unit', None) with uber_open_rmode(data) as f: pbc = None box = None natoms = None system = None readnatoms = False readatoms = False readtimestep = False acount = 0 bcount = 3 #loop over all lines in file for line in f: terms = line.split() if len(terms) > 0: #read atomic values if time to do so if readatoms: #sort values by a_id and save to prop_vals a_id = long(terms[id_index]) - 1 prop_vals[a_id] = terms acount += 1 #save values to sys once all atoms read in if acount == natoms: readatoms = False #cycle over the defined atoms_prop in prop_info for prop, p_keys in prop_info['atoms_prop'].iteritems( ): #set default keys dtype = p_keys.get('dtype', None) shape = p_keys.get('shape', None) shape = (natoms, ) + np.empty(shape).shape value = np.empty(shape) #cycle over the defined LAMMPS-attributes in prop_info for attr, a_keys in prop_info[ 'LAMMPS-attribute'].iteritems(): #cycle over list of relations for each LAMMPS-attribute for relation in a_keys.iteraslist('relation'): #if atoms prop and relation prop match if relation['prop'] == prop: #get unit and scale info unit = relation.get('unit', None) if unit == 'scaled': unit = None scale = True else: scale = False #find index of attribute in name_list a_index = name_list.index(attr) #check if relation has index listed try: index = relation['index'] if isinstance(index, list): index = ( Ellipsis, ) + tuple(index) else: index = (Ellipsis, ) + ( index, ) value[index] = prop_vals[:, a_index] #scalar if no index except: value[:] = prop_vals[:, a_index] #test if values are ints if dtype not specified if dtype is None and np.allclose( np.asarray(value, dtype=int), value): value = np.asarray(value, dtype=int) else: value = np.asarray(value, dtype=dtype) #save prop values to system system.atoms_prop(key=prop, value=uc.set_in_units( value, unit), scale=scale) #read number of atoms if time to do so elif readnatoms: natoms = int(terms[0]) readnatoms = False elif readtimestep: timestep = int(terms[0]) readtimestep = False #read x boundary condition values if time to do so elif bcount == 0: xlo = uc.set_in_units(float(terms[0]), box_unit) xhi = uc.set_in_units(float(terms[1]), box_unit) if len(terms) == 3: xy = uc.set_in_units(float(terms[2]), box_unit) bcount += 1 #read y boundary condition values if time to do so elif bcount == 1: ylo = uc.set_in_units(float(terms[0]), box_unit) yhi = uc.set_in_units(float(terms[1]), box_unit) if len(terms) == 3: xz = uc.set_in_units(float(terms[2]), box_unit) bcount += 1 #read z boundary condition values if time to do so elif bcount == 2: zlo = uc.set_in_units(float(terms[0]), box_unit) zhi = uc.set_in_units(float(terms[1]), box_unit) if len(terms) == 3: yz = uc.set_in_units(float(terms[2]), box_unit) xlo = xlo - min((0.0, xy, xz, xy + xz)) xhi = xhi - max((0.0, xy, xz, xy + xz)) ylo = ylo - min((0.0, yz)) yhi = yhi - max((0.0, yz)) box = am.Box(xlo=xlo, xhi=xhi, ylo=ylo, yhi=yhi, zlo=zlo, zhi=zhi, xy=xy, xz=xz, yz=yz) else: box = am.Box(xlo=xlo, xhi=xhi, ylo=ylo, yhi=yhi, zlo=zlo, zhi=zhi) bcount += 1 #if not time to read value, check the ITEM: header information else: #only consider ITEM: lines if terms[0] == 'ITEM:': #ITEM: TIMESTEP indicates it is time to read the timestep if terms[1] == 'TIMESTEP': readtimestep = True #ITEM: NUMBER indicates it is time to read natoms elif terms[1] == 'NUMBER': readnatoms = True #ITEM: BOX gives pbc and indicates it is time to read box parameters elif terms[1] == 'BOX': pbc = [True, True, True] for i in xrange(3): if terms[i + len(terms) - 3] != 'pp': pbc[i] = False bcount = 0 #ITEM: ATOMS gives list of per-Atom property names and indicates it is time to read atomic values elif terms[1] == 'ATOMS': assert box is not None, 'Box information not found' assert natoms is not None, 'Number of atoms not found' #read list of property names name_list = terms[2:] id_index = name_list.index('id') #create empty array for reading property values prop_vals = np.empty((natoms, len(name_list))) #create and save default prop_info Data Model if needed if prop_info is None: prop_info = __prop_info_default_load(name_list) if isinstance( data, (str, unicode)) and len(data) < 80: with open(data + '.json', 'w') as fj: prop_info.json(fp=fj, indent=4) prop_info = prop_info.find( 'LAMMPS-dump-atoms_prop-relate') #create system and flag that it is time to read data system = am.System(atoms=am.Atoms(natoms=natoms), box=box, pbc=pbc) system.prop['timestep'] = timestep readatoms = True if system is None: raise ValueError('Failed to properly load dump file ' + str(data)[:50]) return system
def make_screw_plate_old(self, size=[40, 60, 3], rad=[100, 115], move=[0., 0., 0.], filename="lmp_init.txt", opt=None): alat = uc.set_in_units(self.pot['lattice'], 'angstrom') C11 = uc.set_in_units(self.pot['c11'], 'GPa') C12 = uc.set_in_units(self.pot['c12'], 'GPa') C44 = uc.set_in_units(self.pot['c44'], 'GPa') axes = np.array([[1, -2, 1], [1, 0, -1], [1, 1, 1]]) unitx = alat * np.sqrt(6) unity = alat * np.sqrt(2) sizex = size[0] sizey = size[1] sizez = size[2] c = am.ElasticConstants(C11=C11, C12=C12, C44=C44) burgers = 0.5 * alat * -np.array([1., 1., 1.]) # initializing a new Stroh object using the data stroh = am.defect.Stroh(c, burgers, axes=axes) # monopole system box = am.Box(a=alat, b=alat, c=alat) atoms = am.Atoms(natoms=2, prop={ 'atype': 2, 'pos': [[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]] }) ucell = am.System(atoms=atoms, box=box, scale=True) system = am.rotate_cubic(ucell, axes) # shftx = 0.5 * alat * np.sqrt(6.) / 3. shftx = 0.0 shfty = -1. / 3. * alat * np.sqrt(2) / 2. # shfty = 2. / 3. * alat * np.sqrt(2) / 2. center = [0.5 * unitx * sizex, 0.5 * unity * sizey] new_pos = system.atoms_prop(key='pos') + np.array([shftx, shfty, 0.0]) system.atoms_prop(key='pos', value=new_pos) system.supersize((0, sizex), (0, sizey), (0, sizez)) # to make a plate # radius2 = rad[0] * rad[0] radiusout2 = rad[1] * rad[1] elements = [] for atom in system.atoms: elements.append('Nb') ase_atoms = am.convert.ase_Atoms.dump(system, elements) pos = ase_atoms.get_positions() delindex = [] for i in range(len(pos)): atom = ase_atoms[i] dx = pos[i, 0] - center[0] dy = pos[i, 1] - center[1] r = dx * dx + dy * dy if r > radiusout2: delindex.append(atom.index) if r < radius2: atom.symbol = 'W' del ase_atoms[delindex] (system, elements) = am.convert.ase_Atoms.load(ase_atoms) # use neb, it's to generate init configuration if opt in ['neb']: system_init = copy.deepcopy(system) shift = np.array([-0.5, -0.5, 0.0]) new_pos = system_init.atoms_prop(key='pos', scale=True) + shift system_init.atoms_prop(key='pos', value=new_pos, scale=True) disp = stroh.displacement(system_init.atoms_prop(key='pos')) system_init.atoms_prop(key='pos', value=system_init.atoms_prop(key='pos') + disp) shift = np.array([0.5, 0.50, 0.0]) new_pos = system_init.atoms_prop(key='pos', scale=True) + shift system_init.atoms_prop(key='pos', value=new_pos, scale=True) # for lammps read structure lmp.atom_data.dump(system_init, "init.txt") # for dd map plot ase.io.write("lmp_perf.cfg", images=ase_atoms, format='cfg') lmp.atom_data.dump(system, "lmp_perf.txt") shift = np.array([-0.5, -0.5, 0.0]) new_pos = system.atoms_prop(key='pos', scale=True) + shift system.atoms_prop(key='pos', value=new_pos, scale=True) new_pos = system.atoms_prop(key='pos') + move system.atoms_prop(key='pos', value=new_pos) disp = stroh.displacement(system.atoms_prop(key='pos')) # pull pull = False if pull is True: core_rows = [disp[:, 2].argsort()[-3:][::-1]] print(disp[core_rows]) exclus = np.arange(len(disp), dtype=int) unitburger = np.mean(disp[core_rows][:, 2]) print(unitburger) exclus = np.delete(exclus, core_rows) disp[core_rows] -= 1. / 3. * unitburger # disp[exclus] -= 1. / 3. * unitburger system.atoms_prop(key='pos', value=system.atoms_prop(key='pos') + disp) new_pos = system.atoms_prop(key='pos') - move system.atoms_prop(key='pos', value=new_pos) shift = np.array([0.500000, 0.500000, 0.000000]) new_pos = system.atoms_prop(key='pos', scale=True) + shift system.atoms_prop(key='pos', value=new_pos, scale=True) new_pos = system.atoms_prop(key='pos', scale=False) # for lammps read structure lmp.atom_data.dump(system, filename) dis_atoms = am.convert.ase_Atoms.dump(system, elements) return (ase_atoms, dis_atoms)
def sys_gen(units = 'metal', atom_style = 'atomic', pbc = (True, True, True), ucell = am.System(atoms = am.Atoms(4, prop = {'atype': [1], 'pos': [[0.0, 0.0, 0.0], [0.5, 0.5, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5]]})), axes = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]), shift = np.array([0.1, 0.1, 0.1]), size = np.array([[-3,3], [-3,3], [-3,3]], dtype=np.int)): """ Generates the LAMMPS input command lines associated with having LAMMPS create a system. Keyword Arguments: units -- LAMMPS units option to use. Default is 'metal'. atom_style -- LAMMPS atom_style option to use. Default is 'atomic'. pbc -- list or tuple of three booleans indicating which directions are periodic. Default is (True, True, True). ucell -- a small system (i.e. crystallographic unit cell) from which the returned system is generated from. Default is an fcc unit cell with cell lengths = 1. axes -- crystallographic axes to rotate the ucell by. For a cubic ucell, the dimensions of the rotated system will increase to ensure that all directions can be periodic. Default is [[1,0,0],[0,1,0],[0,0,1]]. shift -- box-scaled vector to shift all atoms by. Default is [0.1, 0.1, 0.1]. (The LAMMPS algorithm for generating systems sometimes has issues at boundaries.) size -- system multipliers to expand the system by. Default is [[-3,3], [-3,3], [-3,3]], i.e. 6x6x6 supercell of ucell where Cartesian (0,0,0) is in the center of the returned System's Box. """ size = np.asarray(size) shift = np.asarray(shift) axes = np.asarray(axes) boundary = '' for i in xrange(3): if pbc[i]: boundary += 'p ' else: boundary += 'm ' ntypes = ucell.natypes pos_basis = '' type_basis = '' for i in xrange(ucell.natoms): pos = ucell.atoms_prop(a_id=i, key='pos', scale = True) pos_basis += ' basis %f %f %f' %(pos[0], pos[1], pos[2]) if i < ucell.natoms - 1: pos_basis += ' &\n' if ucell.atoms_prop(a_id=i, key='atype') > 1: type_basis += ' &\n basis %i %i'%(i+1, ucell.atoms_prop(a_id=i, key='atype')) vects = ucell.box.vects #Test if box is cubic if vects[1][0] == 0.0 and vects[2][0] == 0.0 and vects[2][1] == 0.0: region_box = 'region box block %i %i %i %i %i %i' % (size[0,0], size[0,1], size[1,0], size[1,1], size[2,0], size[2,1]) ortho = True else: assert np.allclose(axes[0], [1,0,0]) and np.allclose(axes[1], [0,1,0]) and np.allclose(axes[2], [0,0,1]), 'Rotation of non-orthogonal box not suppported' ortho = False size_xy = vects[1][0] * (size[0,1] - size[0,0]) / ucell.box.a size_xz = vects[2][0] * (size[0,1] - size[0,0]) / ucell.box.a size_yz = vects[2][1] * (size[1,1] - size[1,0]) / ucell.box.b region_box = 'region box prism %i %i %i %i %i %i %f %f %f' % (size[0,0], size[0,1], size[1,0], size[1,1], size[2,0], size[2,1], size_xy, size_xz, size_yz) #Adjust crystal spacing for systems to be (nearly) perfectly periodic across boundaries spacing = np.zeros(3) for i in xrange(3): spacing[i] = vects[i][i] * ((axes[i,0]**2+axes[i,1]**2+axes[i,2]**2)**0.5) newline = '\n' script = newline.join(['#Atomic system info generated by AtomMan package', '', 'units ' + units, 'atom_style ' + atom_style, '' 'boundary ' + boundary, '', 'lattice custom 1.0 &', ' a1 %.12f %.12f %.12f &' % (vects[0][0], vects[0][1], vects[0][2]), ' a2 %.12f %.12f %.12f &' % (vects[1][0], vects[1][1], vects[1][2]), ' a3 %.12f %.12f %.12f &' % (vects[2][0], vects[2][1], vects[2][2]), ' origin %f %f %f &' % (shift[0], shift[1], shift[2]), ' spacing %.12f %.12f %.12f &' % (spacing[0], spacing[1], spacing[2]), ' orient x %i %i %i &' % (axes[0,0], axes[0,1], axes[0,2]), ' orient y %i %i %i &' % (axes[1,0], axes[1,1], axes[1,2]), ' orient z %i %i %i &' % (axes[2,0], axes[2,1], axes[2,2]), pos_basis, '', region_box, 'create_box %i box' %(ntypes), 'create_atoms 1 box' + type_basis]) return script