def write_lammps_data(structure=None, file=''): """ write lammps structure data from ase with custom modifications """ structure.sort() structure.to(fmt= "poscar", filename= "new_pymatgen_slab.vasp") atoms = AseAtomsAdaptor().get_atoms(structure) f=open(file,"w") f.write( 'datafile (written by JARVIS-FF) \n\n') symbols = atoms.get_chemical_symbols() import ase.io.vasp n_atoms = len(symbols) f.write('%d \t atoms \n' % n_atoms) species = [tos for tos in Poscar(structure).site_symbols] n_atom_types = len(species) #print ("species",species) f.write('%d atom types\n' % n_atom_types) p = Prism(atoms.get_cell()) xhi, yhi, zhi, xy, xz, yz = p.get_lammps_prism_str() f.write('0.0 %s xlo xhi\n' % xhi) f.write('0.0 %s ylo yhi\n' % yhi) f.write('0.0 %s zlo zhi\n' % zhi) f.write('%s %s %s xy xz yz\n' % (xy, xz, yz)) f.write('\n\n') f.write('Atoms \n\n') for i, r in enumerate(map(p.pos_to_lammps_str, atoms.get_positions())): c = 0.0 s = species.index(symbols[i]) + 1 f.write('%6d %3d %6f %s %s %s\n' % ((i+1, s, c)+tuple(r)) ) f.close()
def _create_surface(self): ''' This method will create the surface structure to relax Returns: surface_atoms_constrained `ase.Atoms` object of the surface to submit to Fireworks for relaxation ''' # Get the bulk and convert to `pymatgen.Structure` object with open(self.input().path, 'rb') as file_handle: bulk_doc = pickle.load(file_handle) bulk_atoms = make_atoms_from_doc(bulk_doc) bulk_structure = AseAtomsAdaptor.get_structure(bulk_atoms) # Use pymatgen to turn the bulk into a surface sga = SpacegroupAnalyzer(bulk_structure, symprec=0.1) bulk_structure = sga.get_conventional_standard_structure() gen = SlabGenerator(initial_structure=bulk_structure, miller_index=self.miller_indices, min_slab_size=self.min_height, **self.slab_generator_settings) surface_structure = gen.get_slab(self.shift, tol=self.get_slab_settings['tol']) # Convert the surface back to an `ase.Atoms` object and constrain # subsurface atoms surface_atoms = AseAtomsAdaptor.get_atoms(surface_structure) surface_atoms_constrained = self.__constrain_surface(surface_atoms) return surface_atoms_constrained
def layers_match(layers, ltol=0.2, stol=0.3, angle_tol=5.0): """ Compares all layers in the material layers:: list of ASE structures corresponding to layers ltol:: tolerance on cell length stol:: tolerance on atomic site positions angle_tol:: tolerance on cell angles """ # instance of the adaptor to convert ASE structures to pymatgen format adaptor = AseAtomsAdaptor() # Create an instance of Structure Matcher with the given tolerances sm = StructureMatcher(ltol, stol, angle_tol) # Translate the refence layer (first) from ASE to pymatgen format # We enforce the third vector to be orthogonal to the planes, and we extend by # a small factor the third direction length (not too much as the thresholds are # in relative units) to avoid to still have some periodicity (e.g. for systems with # 1 layer only) ase_reflayer = layers[0].copy() ase_reflayer.cell[2] = np.array([0, 0, 2 * ase_reflayer.cell[2, 2]]) ref_layer = adaptor.get_structure(ase_reflayer) # Initialize to true the variable saying if all layers are identical all_match = True for this_layer in layers[1:]: aselayer = this_layer.copy() aselayer.cell[2] = np.array([0, 0, 2 * aselayer.cell[2, 2]]) # Translate layer from ASE to pymatgen format layer = adaptor.get_structure(aselayer) # If the layer does not match the refence one set to false all_match if not sm.fit(ref_layer, layer): all_match = False # else: # str1, str2, fu, s1_supercell = sm._preprocess(ref_layer,layer) # print (sm._strict_match(str1,str2,fu,s1_supercell,break_on_match=False)) return all_match
def ase_input_generator(ase_S, nbnd): """ Using ASE write functions for generate input Args: (ASE Structure) Returns: Input files for Quantum Espresso first SCFU calculations """ SCF_input = qe_input.scfu() pymat_S = AseAtomsAdaptor.get_structure(ase_S) hubbard_u_list = initialize_hubbard(pymat_S) #--update the SYSTEM card SCF_input['SYSTEM']['nbnd'] = nbnd SCF_input['SYSTEM'].update(insert_hubbard_block(hubbard_u_list)) converted_pymat_S = reorder(pymat_S, hubbard_u_list) pseudos = Pseudos(converted_pymat_S) converted_ase_S = AseAtomsAdaptor.get_atoms(converted_pymat_S) write("dftu.in", converted_ase_S, format = "espresso-in", \ pseudopotentials=pseudos, input_data = SCF_input, kspacing=0.04)
def fit_gap(atoms: List[Atoms], energies: List[float], forces: Optional[np.ndarray] = None, **kwargs) -> Potential: """Fit a GAP potential using MAL and return a ready-to-use QUIPPy object Args: atoms: List of molecules to use for training energies: List of energies for each structure forces: If available, forces acting on each atom output_dir: Directory in which to store potential kwargs: Passed to the :meth:`GAPotential.train` method Returns: ase Potential object instantiated with a model fit to the data """ # Convert all of the structures to periodic atoms = [make_periodic(a.copy()) for a in atoms] # Conver them to PyMatgen objects conv = AseAtomsAdaptor() strcs = [conv.get_structure(a) for a in atoms] # Fit using maml gap = GAPotential() gap.train(strcs, energies, forces, **kwargs) # Save to disk and return the QUIPy object gap.write_param() return Potential(param_filename="gap.xml")
def surfer(mpid='', vacuum=15, layers=2, mat=None, max_index=1, write_file=True): """ ASE surface bulder Args: vacuum: vacuum region mat: Structure object max_index: maximum miller index min_slab_size: minimum slab size Returns: structures: list of surface Structure objects """ if mat == None: with MPRester() as mp: mat = mp.get_structure_by_material_id(mpid) if mpid == '': print('Provide structure') sg_mat = SpacegroupAnalyzer(mat) mat_cvn = sg_mat.get_conventional_standard_structure() mat_cvn.sort() indices = get_symmetrically_distinct_miller_indices(mat_cvn, max_index) ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn) structures = [] pos = Poscar(mat_cvn) try: pos.comment = str('sbulk') + str('@') + str('vac') + str(vacuum) + str( '@') + str('layers') + str(layers) except: pass structures.append(pos) if write_file == True: mat_cvn.to(fmt='poscar', filename=str('POSCAR-') + str('cvn') + str('.vasp')) for i in indices: ase_slab = surface(ase_atoms, i, layers) ase_slab.center(vacuum=vacuum, axis=2) slab_pymatgen = AseAtomsAdaptor().get_structure(ase_slab) slab_pymatgen.sort() surf_name = '_'.join(map(str, i)) pos = Poscar(slab_pymatgen) try: pos.comment = str("Surf-") + str(surf_name) + str('@') + str( 'vac') + str(vacuum) + str('@') + str('layers') + str(layers) except: pass if write_file == True: pos.write_file(filename=str('POSCAR-') + str("Surf-") + str(surf_name) + str('.vasp')) structures.append(pos) return structures
def getInterstitials(ase_in,inter,spinpol): pmg_init = AseAtomsAdaptor.get_structure(ase_in) pmg_init2 = SpacegroupAnalyzer(pmg_init).get_conventional_standard_structure() interstitial = Interstitial(pmg_init2,None,covalent_radii) #accuracy=high breaks... os.system('cls' if os.name == 'nt' else 'clear') output = [] for i,site in enumerate(interstitial.enumerate_defectsites()): coordination = int(round(interstitial.get_defectsite_coordination_number(i))) mult = 0 # interstitial.get_defectsite_multiplicity(i) -- broken ??? insert = InsertSitesTransformation([inter],[site.coords],coords_are_cartesian=True) try: pmg_new = insert.apply_transformation(pmg_init2.copy()) ase_new = AseAtomsAdaptor.get_atoms(pmg_new) if coordination == 4: siteName='T' elif coordination == 6: siteName='O' else: siteName = '%d-fold'%coordination strname = '_%s-%s'%(inter,siteName) if spinpol: new_magmoms = [3 if e in misc.magElems else 0 for e in ase_new.get_chemical_symbols()] ase_new.set_initial_magnetic_moments(new_magmoms) output.append((ase_new,strname)) except ValueError: pass #ValueError: New site is too close to an existing site! return output
def _featurize(self, struct: PymatgenStructure) -> np.ndarray: """Calculate SOAP descriptor from pymatgen structure. Parameters ---------- struct: pymatgen.Structure A periodic crystal composed of a lattice and a sequence of atomic sites with 3D coordinates and elements. Returns ------- features: np.ndarray soap descriptor """ soap = SOAP( periodic=self.periodic, species=self.species, rcut=self.rcut, nmax=self.nmax, lmax=self.lmax, rbf=self.rbf, sigma=self.sigma, average=self.average, ) if self.convert: adaptor = AseAtomsAdaptor() struct = adaptor.get_atoms(struct) features = soap.create(struct) features = np.asarray(features) return features
def get_ase_slab(pmg_struct, hkl=(1, 1, 1), min_thick=10, min_vac=10): """ takes in the intial structure as pymatgen Structure object uses ase to generate the slab returns pymatgen Slab object Args: pmg_struct: pymatgen structure object hkl: hkl index of surface of slab to be created min_thick: minimum thickness of slab in Angstroms min_vac: minimum vacuum spacing """ ase_atoms = AseAtomsAdaptor().get_atoms(pmg_struct) pmg_slab_gen = SlabGenerator(pmg_struct, hkl, min_thick, min_vac) h = pmg_slab_gen._proj_height nlayers = int(math.ceil(pmg_slab_gen.min_slab_size / h)) ase_slab = surface(ase_atoms, hkl, nlayers) ase_slab.center(vacuum=min_vac / 2, axis=2) pmg_slab_structure = AseAtomsAdaptor().get_structure(ase_slab) return Slab(lattice=pmg_slab_structure.lattice, species=pmg_slab_structure.species_and_occu, coords=pmg_slab_structure.frac_coords, site_properties=pmg_slab_structure.site_properties, miller_index=hkl, oriented_unit_cell=pmg_slab_structure, shift=0., scale_factor=None, energy=None)
def __init__(self, atoms, parameters={}, name='SPARC SCF', sparc_command=None, psuedo_potentials_path=None, db_file=None, parents=None, to_db=False, identifier=None, **kwargs): t = [] try: translator = AseAtomsAdaptor() atoms = translator.get_atoms(atoms) except: pass t.append( OptimizeLattice(atoms=atoms, parameter_dict=parameters, sparc_command=sparc_command, psuedo_potentials_path=psuedo_potentials_path, identifier=identifier, to_db=to_db)) super(OptimizeLatticeSPARC, self).__init__(t, parents=parents, name="{}-{}".format( dict_atoms(atoms).get_chemical_formula(), name), **kwargs)
def update_soap_analysis(struct, all_kwargs): if not struct: raise PreventUpdate struct = self.from_data(struct) kwargs = self.reconstruct_kwargs_from_state( callback_context.inputs) # TODO: make sure is_int kwarg information is enforced so that int() conversion is unnecessary desc = SOAP( species=[e.number for e in struct.composition.elements], sigma=kwargs["sigma"], rcut=kwargs["rcut"], nmax=int(kwargs["nmax"]), lmax=int(kwargs["lmax"]), periodic=True, crossover=kwargs["crossover"], sparse=False, average=kwargs["average"], ) adaptor = AseAtomsAdaptor() atoms = adaptor.get_atoms(struct) feature = normalize(desc.create(atoms, n_jobs=cpu_count())) return _get_soap_graph(feature, "SOAP vector for this material")
def smart_vac(strt=None,tol=0.1): """ Umbrell function for vacancy formation energies with convergence Args: strt: Structure object tol: defect energy convergence tolerance in eV Returns: def_list: list of defect energies def_header_list: list of defect names """ vac_arr=[] sg_mat = SpacegroupAnalyzer(strt) mat_cvn = sg_mat.get_conventional_standard_structure() mat_cvn.sort() cellmax=1 #int(mat_cvn.composition.num_atoms)+int(mat_cvn.ntypesp)#5 ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn) ase_atoms=ase_atoms*(cellmax,cellmax,cellmax) #if len(ase_atoms) >200: # cellmax=1 #else: # cellmax=2 #cellmax=int(mat_cvn.composition.num_atoms)+int(mat_cvn.ntypesp)#5 print ("type of trt is= celmmax",type(strt),cellmax) try: print ("int(strt.composition.num_atoms)",int(strt.composition.num_atoms)) print (int(strt.ntypesp)) except: pass #cellmax=int(strt.composition.num_atoms)+int(strt.ntypesp) vac_done=0 vac=vac_antisite_def_struct_gen(cellmax=cellmax,struct=strt) def_list=[100000 for y in range(len(vac)-1)] while vac_done !=1: vac=vac_antisite_def_struct_gen(cellmax=cellmax,struct=strt) if vac not in vac_arr: vac_arr.append(vac) print ("in smart_vac(strt=None), cellmax,vac,vac_done=",cellmax,vac,vac_done) def_list2,header_list=def_energy(vac=vac) diff=matrix(def_list)-matrix(def_list2) diff_arr=np.array(diff).flatten() print ("in smart_vac(strt=None diff_arr=",diff_arr) if any(diff_arr)>tol: # for el in diff_arr: # if abs(el)>tol : # print ("in smart_vac(strt=None abs_el=",abs(el)) vac_done=0 cellmax=cellmax+1 ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn) ase_atoms=ase_atoms*(cellmax,cellmax,cellmax) if len(ase_atoms) >100: vac_done=1 def_list=def_list2 else: vac_done=1 # cellmax=cellmax+1 return def_list,header_list
def __init__(self, atoms, parameters={}, calculator='VASP', name='ASE Optimize', db_file=None, parents=None, to_db=False, identifier=None, optimizer='QuasiNewton', fmax=0.05, calculator_module='ase.calculators', **kwargs): """ Runs an SCF calculation in SPARC on the given structure Args: atoms (Atoms Object or Pymatgen Structure): Input structure name (str): Name for the Firework parameters (Dict): the input parameters for SPARC sparc_command (str): optional, a command used by ase to run SPARC. This can also be set with the $ASE_SPARC_COMMAND environment variable. psuedo_potentials_path (str): optional, a path to the pseudopotentials you'd like used. This can also be set using the $PSP_PATH environment Variable. db_file (str): Not implemented parents ([Firework]): Parents of this Firework """ t = [] try: translator = AseAtomsAdaptor() atoms = translator.get_atoms(atoms) except: pass t.append( OptimizeASE(atoms=atoms, parameter_dict=parameters, calculator=calculator, to_db=to_db, db_file=db_file, identifier=identifier, optimizer=optimizer, fmax=fmax, calculator_module=calculator_module)) super(ASE_Optimize_FW, self).__init__(t, parents=parents, name="{}-{}".format( dict_atoms(atoms).get_chemical_formula(), name), **kwargs)
def smart_surf(strt=None, tol=0.1): """ Umbrell function for surface energies with convergence Args: strt: Structure object tol: surface energy convergence tolerance in eV Returns: surf_list: list of surface energies surf_header_list: list of surface names """ sg_mat = SpacegroupAnalyzer(strt) mat_cvn = sg_mat.get_conventional_standard_structure() mat_cvn.sort() layers = 2 indices = get_symmetrically_distinct_miller_indices(mat_cvn, 1) ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn) for i in indices: ase_slab = surface(ase_atoms, i, layers) ase_slab.center(vacuum=15, axis=2) if len(ase_slab) < 50: layers = 3 surf_arr = [] surf_done = 0 surf = surfer(mat=strt, layers=layers) surf_list = [100000 for y in range(len(surf) - 1)] print("in smart_surf :surf,surf_list=", surf, surf_list) while surf_done != 1: layers = layers + 1 indices = get_symmetrically_distinct_miller_indices(mat_cvn, 1) ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn) for i in indices: ase_slab = surface(ase_atoms, i, layers) ase_slab.center(vacuum=15, axis=2) if len(ase_slab) > 100: surf_done = 1 if (ase_slab.get_cell()[2][2]) > 40: surf_done = 1 surf = surfer(mat=strt, layers=layers) if surf not in surf_arr: surf_arr.append(surf) surf_list2, surf_header_list = surf_energy(surf=surf) print("in smart_surf :surf2,surf_list2=", surf_list2, surf_header_list) diff = matrix(surf_list) - matrix(surf_list2) print("in smart_surf :surf3,surf_list3=", matrix(surf_list), matrix(surf_list2)) diff_arr = np.array(diff).flatten() if any(diff_arr) > tol: #for el in diff_arr: # if abs(el)>tol : # print ("in smart_surf :abs el=",abs(el)) surf_done = 0 surf_list = surf_list2 else: surf_done = 1 return surf_list, surf_header_list
def new_struc(db, s, eng): s_pmg = AseAtomsAdaptor().get_structure(s) for row in db.select(): ref = db.get_atoms(id=row.id) if abs(eng-row.ff_energy) < 1e-2: ref_pmg = AseAtomsAdaptor().get_structure(ref) if sm.StructureMatcher().fit(s_pmg, ref_pmg): return False return True
def smart_vac(strt=None,parameters=None): parameters['control_file']='/users/knc6/inelast_nobox.mod' vac_arr=[] sg_mat = SpacegroupAnalyzer(strt) mat_cvn = sg_mat.get_conventional_standard_structure() mat_cvn.sort() cellmax=2 #int(mat_cvn.composition.num_atoms)+int(mat_cvn.ntypesp)#5 ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn) ase_atoms=ase_atoms*(cellmax,cellmax,cellmax) #print ("type of trt is= celmmax",type(strt),cellmax) try: print ("int(strt.composition.num_atoms)",int(strt.composition.num_atoms)) print (int(strt.ntypesp)) except: pass vac_done=0 tol=0.01 #change 0.1 try: vac=vac_antisite_def_struct_gen(cellmax=cellmax,struct=strt) except: print ("Failed for v_1",os.getcwd()) pass def_list=[100000 for y in range(len(vac)-1)] while vac_done !=1: try: vac=vac_antisite_def_struct_gen(cellmax=cellmax,struct=strt) except: print ("Failed for v_2",os.getcwd()) pass if vac not in vac_arr: try: vac_arr.append(vac) print ("in smart_vac(strt=None), cellmax,vac,vac_done=",cellmax,vac,vac_done) def_list2,header_list=def_energy(vac=vac,parameters=parameters) diff=matrix(def_list)-matrix(def_list2) diff_arr=np.array(diff).flatten() print ("in smart_vac(strt=None diff_arr=",diff_arr) print ("sleepig for 5") except: print ("Failed for v_3",os.getcwd()) pass if any(diff_arr)>tol: # for el in diff_arr: # if abs(el)>tol : # print ("in smart_vac(strt=None abs_el=",abs(el)) vac_done=0 cellmax=cellmax+1 ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn) ase_atoms=ase_atoms*(cellmax,cellmax,cellmax) if len(ase_atoms) >50: vac_done=1 break def_list=def_list2 else: vac_done=1 return def_list,header_list
def get_ion_geoms(argv): """""" #------------------------------------------------------------------------------- # Argument parser #------------------------------------------------------------------------------- parser = argparse.ArgumentParser(description=__doc__) # Positional arguments parser.add_argument('filename', default="vasprun.xml", type=str, nargs='?', help='set input xml file. Default vasprun.xml;') # Optional args parser.add_argument('--debug', action='store_true', dest='debug', help='show debug informations.') #------------------------------------------------------------------------------- # Initialize and check variables #------------------------------------------------------------------------------- args = parser.parse_args(argv) # Set up LOGGER c_log = logging.getLogger(__name__) # Adopted format: level - current function name - mess. Width is fixed as visual aid std_format = '[%(levelname)5s - %(funcName)10s] %(message)s' logging.basicConfig(format=std_format) c_log.setLevel(logging.INFO) # Set debug option if args.debug: c_log.setLevel(logging.DEBUG) c_log.debug(args) #------------------------------------------------------------------------------- # Load geometry and print in cartesian #------------------------------------------------------------------------------- # Quickly load the xml, skip big parts to go faster vasprun = Vasprun(args.filename, parse_projected_eigen=False, parse_eigen=False, parse_dos=False, exception_on_bad_xml=False, parse_potcar_file=False) # Conver between PyMatGen Strcutre and ASE # Just because we are more familiar with the latter ase_bridge = AseAtomsAdaptor() # For each structure, save a POSCAR with the ion step in front (easier to read in right order from bash) for i, structure in enumerate(vasprun.structures): ase_bridge.get_atoms(structure).write("%i-ion_step.vasp" % i, vasp5=True) return Vasprun.structures
def get_structures_from_protosearch(formulas, source='icsd', db_interface=None): """ Calls protosearch to get the hypothetical structures. Args: formulas ([str]): list of chemical formulas from which to generate candidate structures source (str): project name in OQMD to be used as source. Defaults to ICSD. db_interface (DbInterface): interface to OQMD database by default uses the one pulled from data.matr.io Returns: (pandas.DataFrame) hypothetical pymatgen structures generated and their unique ids from protosearch TODO: - For efficiency, n_max_atoms can be handled within OqmdInterface """ if db_interface is None: cache_matrio_data("oqmd_ver3.db") oqmd_db_path = os.path.join(CAMD_CACHE, "oqmd_ver3.db") db_interface = OqmdInterface(oqmd_db_path) dataframes = [ db_interface.create_proto_data_set(source=source, chemical_formula=formula) for formula in formulas ] _structures = pd.concat(dataframes) # Drop bad structures _structures.dropna(axis=0, how='any', inplace=True) # conversion to pymatgen structures ase_adap = AseAtomsAdaptor() pmg_structures = [ ase_adap.get_structure(_structures.iloc[i]['atoms']) for i in range(len(_structures)) ] _structures['pmg_structures'] = pmg_structures # The uuid below is probably an overkill. But want the strings # to be unique. Sometimes in spaces with similar stoichiometries # they may clash e.g. IrSb2O2 and Ir2SbO2 may end up producing # the same string, despite different substitutions on same structure. # We should figure out a way to get the right order from protosearch. structure_uids = [ _structures.iloc[i]['proto_name'].replace('_', '-') + '-' + '-'.join(pmg_structures[i].symbol_set) + '-' + str(uuid.uuid4()).replace('-', '')[:6] for i in range(len(_structures)) ] _structures.index = structure_uids return _structures
def constructSuperCell(QEinputPath, fineGrid): # ase has some problem in its super cell constructing function # here switch to pymatgen structure = read(QEinputPath) structure.set_pbc((True, True, True)) pymatgenObject = AseAtomsAdaptor() pymatgenStruct = pymatgenObject.get_structure(structure) pymatgenStruct.make_supercell(fineGrid) # pymatgenStruct.to(filename='pymatgenSuperCell.cif') return pymatgenStruct
def get_conventionalstructure(ase_structure): from pymatgen.io.ase import AseAtomsAdaptor from pymatgen.symmetry.analyzer import SpacegroupAnalyzer mg_structure = AseAtomsAdaptor.get_structure(ase_structure) sga = SpacegroupAnalyzer(mg_structure) standard_structure = sga.get_conventional_standard_structure() standard_ase = AseAtomsAdaptor.get_atoms(standard_structure) return standard_ase
def surfer(vacuum=15, layers=2, mat=None, max_index=1, write_file=True): """ ASE surface bulder Args: vacuum: vacuum region mat: Structure object max_index: maximum miller index min_slab_size: minimum slab size Returns: structures: list of surface Structure objects """ if mat == None: print("Provide structure") sg_mat = SpacegroupAnalyzer(mat) mat_cvn = sg_mat.get_conventional_standard_structure() mat_cvn.sort() indices = get_symmetrically_distinct_miller_indices(mat_cvn, max_index) ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn) structures = [] pos = Poscar(mat_cvn) try: pos.comment = (str("sbulk") + str("@") + str("vac") + str(vacuum) + str("@") + str("layers") + str(layers)) except: pass structures.append(pos) if write_file == True: mat_cvn.to(fmt="poscar", filename=str("POSCAR-") + str("cvn") + str(".vasp")) for i in indices: ase_slab = surface(ase_atoms, i, layers) ase_slab.center(vacuum=vacuum, axis=2) slab_pymatgen = AseAtomsAdaptor().get_structure(ase_slab) slab_pymatgen.sort() surf_name = "_".join(map(str, i)) pos = Poscar(slab_pymatgen) try: pos.comment = (str("Surf-") + str(surf_name) + str("@") + str("vac") + str(vacuum) + str("@") + str("layers") + str(layers)) except: pass if write_file == True: pos.write_file(filename=str("POSCAR-") + str("Surf-") + str(surf_name) + str(".vasp")) structures.append(pos) return structures
def ase2pmg(atoms): ''' convert ase Atoms. obj. to pymatgen Structure obj. Args: atoms: Atoms obj. Returns: structure: Structure obj. ''' aaa=AseAtomsAdaptor() return aaa.get_structure(atoms)
def pmg2ase(structure): ''' convert Structure obj. to ase Atoms. obj. Args: structure: Structure obj. Returns: atoms: Atoms obj. ''' aaa=AseAtomsAdaptor() return aaa.get_atoms(structure)
def calculate(self, structure, show=False): c = XRDCalculator(wavelength=self.wavelength) xrd_pattern = c.get_xrd_pattern(AseAtomsAdaptor.get_structure(structure)) if show: c.show_xrd_plot(AseAtomsAdaptor.get_structure(structure)) descriptor_data = dict(descriptor_name=self.name, descriptor_info=str(self), xrd_pattern=xrd_pattern) structure.info['descriptor'] = descriptor_data return structure
def run_oximachine(self, _=None): """Call the oxiMACHINE and save prediction to self.oxidation_states it possible""" self.output.value = """<i class="fa fa-spinner fa-pulse" style="color:red;" ></i>""" try: atoms_adaptor = AseAtomsAdaptor() structure = atoms_adaptor.get_structure(self.structure) X, metal_indices, _ = _featurize_single(structure) # pylint:disable=invalid-name predictions = _make_predictions(X) except Exception: # pylint:disable=broad-except self.output.value = 'Could not determine the oxidation states' else: self.output.value = '' results = dict(zip(metal_indices, predictions)) self.oxidation_states = results
def random_structure_group(symbols, composition, thickness, tol_factor, model_file, dmin=2.0, Natt=RANDOM_ATTEMPTS): # returns pyxtal generated structure (ase Atoms) with lowest e_tot according to megnet model tol_m_1 = Tol_matrix(prototype="atomic", factor=tol_factor) adapt = AseAtomsAdaptor() model = MEGNetModel.from_file(model_file) e_tot_min = 0. for i in range(Natt): group_id = randrange(80) + 1 my_crystal = random_crystal_2D(group_id, symbols, composition, 1.0, thickness=thickness, tm=tol_m_1) flag = 0 if my_crystal.valid == True: struct = crystal_to_atoms(my_crystal) Nat = len(struct.get_chemical_symbols()) struct_pymatgen = adapt.get_structure(struct) try: e_tot = model.predict_structure(struct_pymatgen) except: e_tot = 0. print("isolated molecule exception handled") struct2x2x1 = struct * (2, 2, 1) positions = struct2x2x1.get_positions() # positions = struct.get_positions() # print(struct) flag = check_dist(Nat * 2 * 2, positions, dmin) # print(flag) if (e_tot < e_tot_min) and flag == 1: struct_out = struct e_tot_min = e_tot print("e_tot/atom: " + str(e_tot_min)) # write(filename="POSCAR.best.in", images=struct_out, format="espresso-in") # write(filename="POSCAR.best", images=struct_out, format="vasp") del model return struct_out
def random_structure_on_substrate(symbols, amin, amax, dmin, model_file, Natt=RANDOM_ATTEMPTS): # returns random structure (ase Atoms) on substrate with lowest e_tot according to Megnet model substrate = read_vasp("POSCAR.substrate") adapt = AseAtomsAdaptor() model = MEGNetModel.from_file(model_file) e_tot_min = 1000. for i in range(Natt): s = surface(substrate, (0, 0, 1), 1, vacuum=0., tol=1e-10) cell = s.get_cell() cell[2][2] = CELL_Z s.set_cell(cell) amin = cell[0][0] amax = cell[0][0] struct = random_structure(symbols, amin, amax, dmin, iwrite=0) j = 0 atoms = struct.get_chemical_symbols() positions = struct.get_positions() for atom in atoms: at = Atom(atom) positions[j][2] = positions[j][2] + SURF_DIST pos = positions[j] at.position = pos s.append(at) j = j + 1 struct_pymatgen = adapt.get_structure(s) try: e_tot = model.predict_structure(struct_pymatgen) # print(e_tot) except: e_tot = 0. print("isolated molecule exception handled") if e_tot < e_tot_min: struct_out = s e_tot_min = e_tot print("e_tot min: ", e_tot_min) write(filename='best.in', images=struct_out, format="espresso-in") del model return struct_out
def parse_periodic_case(file_1, file_2, try_supercell: bool = True, pymatgen: bool = False, get_reduced_structure: bool = True): """ Parser for periodic structures, handles two possible cases: (1) Structures are supercells (within tolerance), then one cell is multiplied by the scaling factors (2) Structures are not supercells of each other, then we rescale on cell to the volume of the other cell to make sure we have meaningful comparisons. Args: file_1 (str/pymatgen structure object): path to first file, in on format that ASE can parse, pymatgen structure object in case pymatgen=True file_2 (str/pymatgen structure object): path to second file, pymatgen structure object in case pymatgen=True try_supercell (bool): if true, we attempt to build a supercell, default: True pymatgen (bool): if true, then file_1 and file_2 take pymatgen structure objects get_reduced_structure (bool): if true (default) it gets the Niggli reduced cell. Returns: atomic symbols (list), cartesian positions (list) of structure 1, atomic symbols (list), cartesian positions (list) of structure 2 """ if pymatgen: atoms1 = AseAtomsAdaptor.get_atoms(file_1) atoms2 = AseAtomsAdaptor.get_atoms(file_2) else: atoms1 = read(file_1) atoms2 = read(file_2) if get_reduced_structure: niggli_reduce(atoms1) niggli_reduce(atoms2) if try_supercell: a1, a2 = attempt_supercell(atoms1, atoms2) else: a1, a2 = rescale_periodic_system(atoms1, atoms2) atomic_symbols_1 = a1.get_chemical_symbols() positions_1 = a1.get_positions() atomic_symbols_2 = a2.get_chemical_symbols() positions_2 = a2.get_positions() return np.array(atomic_symbols_1), np.array(positions_1), np.array( atomic_symbols_2), np.array(positions_2)
def dict_to(dictionary): x = 0 for key in dictionary.keys(): y = dictionary[key]['surface'] if (isinstance(y, dict) == False): w = AseAtomsAdaptor.get_atoms(y) z = atoms_to_dict(w) atom_hash = get_hash(w) add_everything_to_dict(key, dictionary[key], z, atom_hash) else: y = dictionary[key]['surface'] w = AseAtomsAdaptor.get_atoms(Structure.from_dict(y)) z = atoms_to_dict(w) atom_hash = get_hash(w) add_everything_to_dict(key, dictionary[key], z, atom_hash)
def __init__(self, n_jobs: int, on_errors: str = 'raise', return_type: str = 'any', batch_calculate: bool = False, batch_size: int = 30): super().__init__(n_jobs=n_jobs, on_errors=on_errors, return_type=return_type, batch_calculate=batch_calculate, batch_size=batch_size) self.adaptor_dict = {} # Dynamic assignment self.adaptor = AseAtomsAdaptor() self.pbc = True self.cutoff = 5.0
def get_distance_from_plane(structure : Structure, i, x,y,z): """ Get distance of atom i from the plane formed by atoms x, y, and z :param structure: :param i: :param x: :param y: :param z: :return: """ atoms = AseAtomsAdaptor.get_atoms(structure) atoms.wrap(atoms.get_scaled_positions()[i]) positions = atoms.get_positions() x = positions[x] y = positions[y] z = positions[z] p = positions[i] # get Normal Vector v1 = y - x v2 = z - x # Get equation of plane ax+by+cz+d = 0 normal = np.cross(v1, v2) / np.linalg.norm(np.cross(v1, v2)) d = np.dot(normal, x) a = normal[0] b = normal[1] c = normal[2] # Get closest point on plane return abs((a * p[0] + b * p[1] + c * p[2] - d) / (a ** 2 + b ** 2 + c ** 2)) # distance between point and plane
def get_angle_from_plane(structure : Structure, i, i1, i2, x, y, z): """ Get distance of atom i from the plane formed by atoms x, y, and z :param structure: :param i: :param x: :param y: :param z: :return: """ atoms = AseAtomsAdaptor.get_atoms(structure) atoms.wrap(atoms.get_scaled_positions()[i]) positions = atoms.get_positions() x = positions[x] y = positions[y] z = positions[z] v = positions[i1] - positions[i2] # get Normal Vector v1 = y - x v2 = z - x # Get equation of plane ax+by+cz+d = 0 normal = np.cross(v1, v2) / np.linalg.norm(np.cross(v1, v2)) a = normal[0] b = normal[1] c = normal[2] plane = np.array([a,b,c]) return np.arcsin(abs(np.dot(v, plane)) / (np.linalg.norm(v)*np.linalg.norm(plane))) * 180/np.pi
def __init__(self, vrun_obj=None): if vrun_obj: self.kpoints = np.array(vrun_obj.actual_kpoints) self.structure = vrun_obj.final_structure self.atoms = AseAtomsAdaptor.get_atoms(self.structure) self.proj = None if len(vrun_obj.eigenvalues) == 1: e = list(vrun_obj.eigenvalues.values())[0] self.ebands = e[:, :, 0].transpose() * units.eV self.dosweight = 2.0 if vrun_obj.projected_eigenvalues: self.proj = list(vrun_obj.projected_eigenvalues.values())[0] elif len(vrun_obj.eigenvalues) == 2: raise BoltztrapError("spin bs case not implemented") self.lattvec = self.atoms.get_cell().T * units.Angstrom # TODO: read mommat from vasprun self.mommat = None self.magmom = None self.spin = None self.fermi = vrun_obj.efermi * units.eV self.nelect = vrun_obj.parameters['NELECT'] self.UCvol = self.structure.volume * units.Angstrom ** 3
def __init__(self, bs_obj, structure=None, nelect=None): """Structure and nelect is needed to be provide""" self.kpoints = np.array([kp.frac_coords for kp in bs_obj.kpoints]) if structure is None: try: self.structure = bs_obj.structure except: BaseException('No structure found in the bs obj.') else: self.structure = structure self.atoms = AseAtomsAdaptor.get_atoms(self.structure) if len(bs_obj.bands) == 1: e = list(bs_obj.bands.values())[0] self.ebands = e * units.eV self.dosweight = 2.0 elif len(bs_obj.bands) == 2: raise BaseException("spin bs case not implemented") self.lattvec = self.atoms.get_cell().T * units.Angstrom self.mommat = None self.magmom = None self.fermi = bs_obj.efermi * units.eV self.nelect = nelect self.UCvol = self.structure.volume * units.Angstrom ** 3 self.vbm_idx = list(bs_obj.get_vbm()['band_index'].values())[0][-1] self.cbm_idx = list(bs_obj.get_cbm()['band_index'].values())[0][0]
def __init__(self, bs_obj, structure=None, nelect=None, spin=None): """ Structure and nelect is needed to be provide. spin must be select if bs is spin-polarized. """ self.kpoints = np.array([kp.frac_coords for kp in bs_obj.kpoints]) if structure is None: try: self.structure = bs_obj.structure except: BaseException('No structure found in the bs obj.') else: self.structure = structure self.atoms = AseAtomsAdaptor.get_atoms(self.structure) self.proj = None if len(bs_obj.bands) == 1: e = list(bs_obj.bands.values())[0] self.ebands = e * units.eV self.dosweight = 2.0 if bs_obj.projections: self.proj = bs_obj.projections[Spin.up].transpose((1,0,3,2)) elif len(bs_obj.bands) == 2: if not spin: raise BaseException("spin-polarized bs, you need to select a spin") elif spin in (-1,1): e = bs_obj.bands[Spin(spin)] self.ebands = e * units.eV self.dosweight = 1.0 if bs_obj.projections: self.proj = bs_obj.projections[Spin(spin)].transpose((1,0,3,2)) self.lattvec = self.atoms.get_cell().T * units.Angstrom self.mommat = None self.magmom = None self.fermi = bs_obj.efermi * units.eV self.nelect = nelect self.UCvol = self.structure.volume * units.Angstrom ** 3 self.spin = spin if not bs_obj.is_metal() and not spin: self.vbm_idx = list(bs_obj.get_vbm()['band_index'].values())[0][-1] self.cbm_idx = list(bs_obj.get_cbm()['band_index'].values())[0][0]
def __init__(self, structure, parameters={}, label='mpintlmp', specorder=None, always_triclinic=False, no_data_file=False): LAMMPS.__init__(self, label=label, parameters=parameters, specorder=specorder, files=[], always_triclinic=always_triclinic, no_data_file=no_data_file) self.structure = structure self.atoms = AseAtomsAdaptor().get_atoms(structure) self.label = label self.parameters = parameters self.specorder = specorder self.always_triclinic = always_triclinic self.no_data_file = no_data_file self.charges = None if 'charges' in self.parameters: self.charges = self.parameters['charges']
class MPINTLammps(LAMMPS, PMGSONable): """ setup LAMMPS for given structure and parameters extends ase.calculators.lammpsrun.LAMMPS """ def __init__(self, structure, parameters={}, label='mpintlmp', specorder=None, always_triclinic=False, no_data_file=False): LAMMPS.__init__(self, label=label, parameters=parameters, specorder=specorder, files=[], always_triclinic=always_triclinic, no_data_file=no_data_file) self.structure = structure self.atoms = AseAtomsAdaptor().get_atoms(structure) self.label = label self.parameters = parameters self.specorder = specorder self.always_triclinic = always_triclinic self.no_data_file = no_data_file self.charges = None if 'charges' in self.parameters: self.charges = self.parameters['charges'] def write_lammps_data(self, f): """ write lammps structure data from ase with custom modifications """ f.write(f.name + ' (written by mpinterfaces) \n\n') symbols = self.atoms.get_chemical_symbols() n_atoms = len(symbols) f.write('%d \t atoms \n' % n_atoms) if self.specorder is None: species = [tos.symbol for tos in self.structure.types_of_specie] else: species = self.specorder n_atom_types = len(species) f.write('%d atom types\n' % n_atom_types) p = prism(self.atoms.get_cell()) xhi, yhi, zhi, xy, xz, yz = p.get_lammps_prism_str() f.write('0.0 %s xlo xhi\n' % xhi) f.write('0.0 %s ylo yhi\n' % yhi) f.write('0.0 %s zlo zhi\n' % zhi) if self.always_triclinic or p.is_skewed(): f.write('%s %s %s xy xz yz\n' % (xy, xz, yz)) f.write('\n\n') f.write('Atoms \n\n') for i, r in enumerate(map(p.pos_to_lammps_str, self.atoms.get_positions())): c = 0.0 if self.charges: c = self.charges[symbols[i]] s = species.index(symbols[i]) + 1 if 'atom_style' in self.parameters: if self.parameters['atom_style'] == 'charge': f.write('%6d %3d %6f %s %s %s\n' % ((i+1, s, c)+tuple(r)) ) else: f.write('%6d %3d %s %s %s\n' % ((i+1, s)+tuple(r))) if self.atoms.get_velocities() is not None: f.write('\n\nVelocities \n\n') for i, v in enumerate(self.atoms.get_velocities()): f.write('%6d %s %s %s\n' % ((i+1,)+tuple(v))) f.close() def write_lammps_in(self, lammps_in=None, lammps_trj=None, lammps_data=None): """ write lammps input file from ase with custom modifications """ f = lammps_in f.write('clear\n' + ('variable dump_file string "%s"\n' % lammps_trj) + ('variable data_file string "%s"\n' % lammps_data)) parameters = self.parameters pbc = self.atoms.get_pbc() f.write('units metal \n') if 'atom_style' in parameters: f.write('atom_style %s \n' % parameters['atom_style']) else: f.write('atom_style atomic \n') if 'boundary' in parameters: f.write('boundary %s \n' % parameters['boundary']) else: f.write('boundary %c %c %c \n' % tuple('sp'[x] for x in pbc)) f.write('atom_modify sort 0 0.0 \n') for key in ('neighbor' ,'newton'): if key in parameters: f.write('%s %s \n' % (key, parameters[key])) f.write('\n') # If no_data_file, # write the simulation box and the atoms if self.no_data_file: p = self.prism f.write('lattice sc 1.0\n') xhi, yhi, zhi, xy, xz, yz = p.get_lammps_prism_str() if self.always_triclinic or p.is_skewed(): f.write('region asecell prism 0.0 %s 0.0 %s 0.0 %s ' % (xhi, yhi, zhi)) f.write('%s %s %s side in units box\n' % (xy, xz, yz)) else: f.write(('region asecell block 0.0 %s 0.0 %s 0.0 %s ' 'side in units box\n') % (xhi, yhi, zhi)) symbols = self.atoms.get_chemical_symbols() if self.specorder is None: species = [tos.symbol for tos in self.structure.types_of_specie] else: species = self.specorder n_atom_types = len(species) species_i = dict([(s,i+1) for i,s in enumerate(species)]) f.write('create_box %i asecell\n' % n_atom_types) for s, pos in zip(symbols, self.atoms.get_positions()): f.write('create_atoms %i single %s %s %s units box\n'% ((species_i[s],)+p.pos_to_lammps_fold_str(pos))) else: f.write('read_data %s\n' % lammps_data) # interaction f.write('\n### interactions \n') if ( ('pair_style' in parameters) and ('pair_coeff' in parameters) ): pair_style = parameters['pair_style'] f.write('pair_style %s \n' % pair_style) for pair_coeff in parameters['pair_coeff']: f.write('pair_coeff %s \n' % pair_coeff) if 'mass' in parameters: for mass in parameters['mass']: f.write('mass %s \n' % mass) else: # default interaction f.write('pair_style lj/cut 2.5 \n' + 'pair_coeff * * 1 1 \n' + 'mass * 1.0 \n') f.write('\n### run\n') if 'fix' in parameters: if parameters['fix']: for i in parameters['fix']: f.write('fix %s\n' % i) else: f.write('fix fix_nve all nve\n') if 'thermo_style' in parameters: f.write('thermo_style %s\n' % parameters['thermo_style']) else: f.write(('thermo_style custom %s\n') % (' '.join(self._custom_thermo_args))) if 'thermo_modify' in parameters: f.write('thermo_modify %s\n' % parameters['thermo_modify']) else: f.write('thermo_modify flush yes\n') if 'thermo' in parameters: f.write('thermo %s\n' % parameters['thermo']) else: f.write('thermo 1\n') if 'minimize' in parameters: f.write('minimize %s\n' % parameters['minimize']) if 'run' in parameters: f.write('run %s\n' % parameters['run']) if not (('minimize' in parameters) or ('run' in parameters)): f.write('run 0\n') if 'dump' in parameters: f.write('dump %s\n' % parameters['dump']) else: f.write('dump dump_all all custom 1 %s id type x y z vx vy vz fx fy fz\n' % lammps_trj) f.write('print __end_of_ase_invoked_calculation__\n') f.write('log /dev/stdout\n') # Force LAMMPS to flush log f.close() def as_dict(self): d = dict(structure=self.structure.as_dict(), parameters=self.parameters, label=self.label, specorder=self.specorder, always_triclinic=self.always_triclinic, no_data_file=self.no_data_file) d["@module"] = self.__class__.__module__ d["@class"] = self.__class__.__name__ return d @classmethod def from_dict(cls, d): structure = Structure.from_dict(d["structure"]) return MPINTLammps(structure, parameters=d["parameters"], label=d["label"], specorder=d["specorder"], always_triclinic=d["always_triclinic"], no_data_file=d["no_data_file"])
class MPINTLammps(LAMMPS, MSONable): """ setup LAMMPS for given structure and parameters extends ase.calculators.lammpsrun.LAMMPS """ def __init__( self, structure, parameters={}, label="mpintlmp", specorder=None, always_triclinic=True, no_data_file=False ): LAMMPS.__init__( self, label=label, parameters=parameters, specorder=specorder, files=[], always_triclinic=always_triclinic, no_data_file=no_data_file, ) self.structure = structure self.atoms = AseAtomsAdaptor().get_atoms(structure) self.label = label self.parameters = parameters self.specorder = specorder self.always_triclinic = always_triclinic self.no_data_file = no_data_file self.charges = None if "charges" in self.parameters: self.charges = self.parameters["charges"] def write_lammps_data(self, f): """ write lammps structure data from ase with custom modifications """ f.write(f.name + " (written by mpinterfaces) \n\n") symbols = self.atoms.get_chemical_symbols() n_atoms = len(symbols) f.write("%d \t atoms \n" % n_atoms) if self.specorder is None: species = [tos.symbol for tos in self.structure.types_of_specie] else: species = self.specorder n_atom_types = len(species) f.write("%d atom types\n" % n_atom_types) p = prism(self.atoms.get_cell()) xhi, yhi, zhi, xy, xz, yz = p.get_lammps_prism_str() f.write("0.0 %s xlo xhi\n" % xhi) f.write("0.0 %s ylo yhi\n" % yhi) f.write("0.0 %s zlo zhi\n" % zhi) if self.always_triclinic or p.is_skewed(): f.write("%s %s %s xy xz yz\n" % (xy, xz, yz)) f.write("\n\n") f.write("Atoms \n\n") for i, r in enumerate(map(p.pos_to_lammps_str, self.atoms.get_positions())): c = 0.0 if self.charges: c = self.charges[symbols[i]] s = species.index(symbols[i]) + 1 if "atom_style" in self.parameters: if self.parameters["atom_style"] == "charge": f.write("%6d %3d %6f %s %s %s\n" % ((i + 1, s, c) + tuple(r))) else: f.write("%6d %3d %s %s %s\n" % ((i + 1, s) + tuple(r))) if self.atoms.get_velocities() is not None: f.write("\n\nVelocities \n\n") for i, v in enumerate(self.atoms.get_velocities()): f.write("%6d %s %s %s\n" % ((i + 1,) + tuple(v))) f.close() # self.mplmp.write_lammps_in(lammps_in=lmp_in_fd,lammps_in1=lmp_in_fd1,lammps_in2=lmp_in_fd2, # lammps_trj=lmp_trj_name, # lammps_data=lmp_data_name) # self.mplmp.write_lammps_in(lammps_in=lmp_in_fd,lammps_in1=lmp_in_fd1, # lammps_trj=lmp_trj_name, # lammps_data=lmp_data_name) def write_lammps_in(self, lammps_in=None, lammps_in1=None, lammps_in2=None, lammps_trj=None, lammps_data=None): """ write lammps input file from ase with custom modifications """ f = lammps_in f1 = lammps_in1 # potential.mod f2 = lammps_in2 parameters = self.parameters if "units" in parameters: if parameters["units"] == "real": f.write( ('variable dump_file string "%s"\n' % lammps_trj) + ("variable up equal 1.0e-8\n") + ("variable cfac equal 1.01325e-4\n") + ("variable cunits string GPa\n") + ("variable etol equal 0\n") + ("variable ftol equal 1.0e-10\n") + ("variable maxiter equal 1000\n") + ("variable maxeval equal 10000\n") + ("variable dmax equal 1.0e-2\n") + ('variable data_file string "%s"\n' % lammps_data) ) else: f.write( ('variable dump_file string "%s"\n' % lammps_trj) + ("variable up equal 1.0e-8\n") + ("variable cfac equal 1.0e-4\n") + ("variable cunits string GPa\n") + ("variable etol equal 0\n") + ("variable ftol equal 1.0e-10\n") + ("variable maxiter equal 1000\n") + ("variable maxeval equal 10000\n") + ("variable dmax equal 1.0e-2\n") + ('variable data_file string "%s"\n' % lammps_data) ) pbc = self.atoms.get_pbc() if "control_file" in parameters: f2.write("include %s \n" % parameters["control_file"]) # f2.write('include /home/kamal/inelast.mod \n') if "units" in parameters: f.write("units %s \n" % parameters["units"]) else: f.write("units metal \n") # f.write('units metal \n') if "atom_style" in parameters: f.write("atom_style %s \n" % parameters["atom_style"]) else: f.write("atom_style atomic \n") if "boundary" in parameters: f.write("boundary %s \n" % parameters["boundary"]) else: f.write("boundary %c %c %c \n" % tuple("sp"[x] for x in pbc)) f.write("atom_modify sort 0 0.0 \n") for key in ("neighbor", "newton"): if key in parameters: f.write("%s %s \n" % (key, parameters[key])) f.write("\n") # If no_data_file, # write the simulation box and the atoms if self.no_data_file: p = self.prism f.write("lattice sc 1.0\n") xhi, yhi, zhi, xy, xz, yz = p.get_lammps_prism_str() if self.always_triclinic or p.is_skewed(): f.write("region asecell prism 0.0 %s 0.0 %s 0.0 %s " % (xhi, yhi, zhi)) f.write("%s %s %s side in units box\n" % (xy, xz, yz)) else: f.write(("region asecell block 0.0 %s 0.0 %s 0.0 %s " "side in units box\n") % (xhi, yhi, zhi)) symbols = self.atoms.get_chemical_symbols() ############KAMAL########################################### # species = [tos.symbol for tos in self.structure.types_of_specie] # # for i, r in enumerate(map(p.pos_to_lammps_str, # self.atoms.get_positions())): # s = species.index(symbols[i]) + 1 ################################################ if self.specorder is None: species = [tos.symbol for tos in self.structure.types_of_specie] else: species = self.specorder n_atom_types = len(species) species_i = dict([(s, i + 1) for i, s in enumerate(species)]) f.write("create_box %i asecell\n" % n_atom_types) for s, pos in zip(symbols, self.atoms.get_positions()): f.write( "create_atoms %i single %s %s %s units box\n" % ((species_i[s],) + p.pos_to_lammps_fold_str(pos)) ) else: f.write("read_data %s\n" % lammps_data) # interaction f.write("\n### interactions \n") if "lib" in parameters: lib = parameters["lib"] f1.write("%s \n" % lib) if ("pair_style" in parameters) and ("pair_coeff" in parameters): pair_style = parameters["pair_style"] f1.write("pair_style %s \n" % pair_style) symbols = self.atoms.get_chemical_symbols() species = set(symbols) # species = [tos.symbol.replace("Mo","M") for tos in self.structure.types_of_specie] species = [tos.symbol for tos in self.structure.types_of_specie] tag = "" for i in species: tag = tag + " " + i pair_coef = "* * " + str(parameters["pair_coeff"]) + " " + tag f1.write("pair_coeff %s \n" % pair_coef) # for pair_coeff in parameters['pair_coeff']: # f.write('pair_coeff %s \n' % pair_coeff) # # if 'mass' in parameters: # for mass in parameters['mass']: # f.write('mass %s \n' % mass) masses = set(self.atoms.get_masses()) count = 0 for i in masses: count = count + 1 f.write("mass" + " " + str(count) + " " + str(i) + "\n") else: # default interaction f.write("pair_style lj/cut 2.5 \n" + "pair_coeff * * 1 1 \n" + "mass * 1.0 \n") # f.write('\n### run\n') # if 'fix' in parameters: # if parameters['fix']: # for i in parameters['fix']: # f.write('fix %s\n' % i) # else: # f.write('fix fix_nve all nve\n') f1.write("neighbor 1.0 nsq\n") f1.write("neigh_modify once no every 1 delay 0 check yes\n") f1.write("min_style cg\n") f1.write("min_modify dmax ${dmax} line quadratic\n") f1.write("thermo 1\n") f1.write("thermo_style custom step temp press cpu pxx pyy pzz pxy pxz pyz ke pe etotal vol lx ly lz atoms\n") # f1.write('thermo_style custom step temp pe press pxx pyy pzz pxy pxz pyz lx ly lz vol\n' ) f1.write("thermo_modify norm no\n") # if 'thermo_style' in parameters: # f.write('thermo_style %s\n' % parameters['thermo_style']) # else: # f.write(('thermo_style custom %s\n') % # (' '.join(self._custom_thermo_args))) # if 'thermo_modify' in parameters: # f.write('thermo_modify %s\n' % parameters['thermo_modify']) # else: # f.write('thermo_modify flush yes\n') # if 'thermo' in parameters: # f.write('thermo %s\n' % parameters['thermo']) # else: # f.write('thermo 1\n') # if 'minimize' in parameters: # f.write('minimize %s\n' % parameters['minimize']) # if 'run' in parameters: # f.write('run %s\n' % parameters['run']) # if not (('minimize' in parameters) or ('run' in parameters)): # f.write('run 0\n') # if 'dump' in parameters: # f.write('dump %s\n' % parameters['dump']) # else: # f.write('dump dump_all all custom 1 %s id type x y z vx vy vz fx fy fz\n' % lammps_trj) # f.write('print __end_of_ase_invoked_calculation__\n') # f.write('log /dev/stdout\n') if "fix" in parameters: if parameters["fix"]: for i in parameters["fix"]: f1.write("fix %s\n" % i) f.close() def as_dict(self): d = dict( structure=self.structure.as_dict(), parameters=self.parameters, label=self.label, specorder=self.specorder, always_triclinic=self.always_triclinic, no_data_file=self.no_data_file, ) d["@module"] = self.__class__.__module__ d["@class"] = self.__class__.__name__ return d @classmethod def from_dict(cls, d): structure = Structure.from_dict(d["structure"]) return MPINTLammps( structure, parameters=d["parameters"], label=d["label"], specorder=d["specorder"], always_triclinic=d["always_triclinic"], no_data_file=d["no_data_file"], )
def nebmake(directory, start, final, images, tolerance=0, ci=False, poscar_override=[], linear=False, write=True): if type(start) == str: start_POSCAR = os.path.join(start, 'CONTCAR') if os.path.exists(os.path.join(start, 'CONTCAR')) and os.path.getsize(os.path.join(start, 'CONTCAR')) > 0 else os.path.join(start, 'POSCAR') final_POSCAR = os.path.join(final, 'CONTCAR') if os.path.exists(os.path.join(final, 'CONTCAR')) and os.path.getsize(os.path.join(final, 'CONTCAR')) > 0 else os.path.join(final, 'POSCAR') p1 = Poscar.from_file(start_POSCAR) p2 = Poscar.from_file(final_POSCAR) s1 = p1.structure s2 = p2.structure else: s1 = start s2 = final # s1.sort() # s2.sort() atoms = [] if poscar_override: for i in range(int(len(poscar_override)/2)): atoms.append( (poscar_override[i*2], poscar_override[i*2+1]) ) (s1, s2) = reorganize_structures(s1, s2, atoms=atoms, autosort_tol=tolerance) tolerance=0 try: structures = s1.interpolate(s2, images, autosort_tol=tolerance) except Exception as e: a=input('Failed. Type y to sort --> ') if a=='y': s1.sort() s2.sort() else: raise e structures = s1.interpolate(s2, images, autosort_tol=tolerance) if not linear: from pymatgen.io.ase import AseAtomsAdaptor from ase.neb import NEB structures_ase = [ AseAtomsAdaptor.get_atoms(struc) for struc in structures ] neb = NEB(structures_ase) neb.interpolate('idpp') # type: NEB structures = [ AseAtomsAdaptor.get_structure(atoms) for atoms in neb.images ] if write: start_OUTCAR = os.path.join(start, 'OUTCAR') final_OUTCAR = os.path.join(final, 'OUTCAR') incar = Incar.from_file(os.path.join(start, 'INCAR')) kpoints = Kpoints.from_file(os.path.join(start, 'KPOINTS')) potcar = Potcar.from_file(os.path.join(start, 'POTCAR')) incar['ICHAIN'] = 0 incar['IMAGES'] = images-1 incar['LCLIMB'] = ci for i, s in enumerate(structures): folder = os.path.join(directory, str(i).zfill(2)) os.mkdir(folder) Poscar(s, selective_dynamics=p1.selective_dynamics).write_file(os.path.join(folder, 'POSCAR')) if i == 0: shutil.copy(start_OUTCAR, os.path.join(folder, 'OUTCAR')) if i == images: shutil.copy(final_OUTCAR, os.path.join(folder, 'OUTCAR')) i += 1 incar.write_file(os.path.join(directory, 'INCAR')) kpoints.write_file(os.path.join(directory, 'KPOINTS')) potcar.write_file(os.path.join(directory, 'POTCAR')) return structures