def step1(): """ get substrate bulk structures from materialsproject for Pt, Ag, Cu, Ni, Al, Au, Pd, Ir and do 3d relaxation(ISIF=3) get 2d structures from the provided poscars(just poscar_graphene) and relax in x and y only(vasp_noz bin) - POSCAR_graphene must be made available in the directory - creates required input files and submits the jobs to the que - 8 + 1 jobs - returns: step1_sub.json step1_2d.json """ #job directory for the runs job_dir_sub = 'step1_sub' job_dir_2d = 'step1_2d' # create list of all substrate poscars poscars_sub = [] poscars_2d = [] # substrate structures for sub in substrates: struct_sub = get_struct_from_mp(sub) sa_sub = SpacegroupAnalyzer(struct_sub) struct_sub = sa_sub.get_conventional_standard_structure() poscars_sub.append(Poscar(struct_sub)) # 2d structures for td in mat2ds: poscars_2d.append(Poscar.from_file(td)) # setup calibrate and run'em turn_knobs_sub = OrderedDict( [ ('POSCAR', poscars_sub) ]) turn_knobs_2d = OrderedDict( [ ('POSCAR', poscars_2d) ]) # normal binary qadapter_sub, job_cmd_sub = get_run_cmmnd(nnodes=nnodes, nprocs=nprocs, walltime=walltime, job_bin=bin_sub, mem=mem) # binary with z constraint qadapter_2d, job_cmd_2d = get_run_cmmnd(nnodes=nnodes, nprocs=nprocs, walltime=walltime, job_bin=bin_2d, mem=mem) run_cal(turn_knobs_sub, qadapter_sub, job_cmd_sub, job_dir_sub, 'step1_sub', incar=incar_sub, kpoints=kpoints_sub) run_cal(turn_knobs_2d, qadapter_2d, job_cmd_2d, job_dir_2d, 'step1_2d', incar=incar_2d, kpoints=kpoints_2d) return ['step1_sub.json', 'step1_2d.json']
#----------------------------------- #nanopartcle specifications #----------------------------------- #max radius in angstroms rmax = 15 #surface families to be chopped off hkl_family = [(1, 0, 0), (1, 1, 1)] #surfac energies could be in any units, will be normalized surface_energies = [28, 25] #----------------------------------- #intial structure #----------------------------------- #caution: set the structure wrt which the the miller indices are #specified. use your own key structure = get_struct_from_mp('PbS', MAPI_KEY="") #primitve ---> conventional cell sa = SpacegroupAnalyzer(structure) structure_conventional = sa.get_conventional_standard_structure() #----------------------------------- # create nanoparticle #----------------------------------- nanoparticle = Nanoparticle(structure_conventional, rmax=rmax, hkl_family=hkl_family, surface_energies=surface_energies) nanoparticle.create() nanoparticle.to(fmt='xyz', filename='nanoparticle.xyz')
from mpinterfaces.nanoparticle import Nanoparticle # ----------------------------------- # nanoparticle specifications # ----------------------------------- # max radius in angstroms rmax = 15 # surface families to be chopped off hkl_family = [(1, 0, 0), (1, 1, 1)] # surfac energies could be in any units, will be normalized surface_energies = [28, 25] # ----------------------------------- # initial structure # ----------------------------------- # caution: set the structure wrt which the the miller indices are # specified. use your own key structure = get_struct_from_mp('PbS', MAPI_KEY="") # primitive ---> conventional cell sa = SpacegroupAnalyzer(structure) structure_conventional = sa.get_conventional_standard_structure() # ----------------------------------- # create nanoparticle # ----------------------------------- nanoparticle = Nanoparticle(structure_conventional, rmax=rmax, hkl_family=hkl_family, surface_energies=surface_energies) nanoparticle.create() nanoparticle.to(fmt='xyz', filename='nanoparticle.xyz')
def get_structures(): for species in structures: struct_species = get_struct_from_mp(species) poscar_list.append(Poscar(struct_species)) return None
# coding: utf-8 # Copyright (c) Henniggroup. # Distributed under the terms of the MIT License. from __future__ import division, unicode_literals, print_function import os import sys from collections import OrderedDict from mpinterfaces import get_struct_from_mp from mpinterfaces.lammps import CalibrateLammps from mpinterfaces.utils import get_run_cmmnd # list of structures from materialsproject structures = get_struct_from_mp('ZnO', all_structs=True) # scale the structures scell_size = 12 for s in structures: a, b, c = s.lattice.abc s.make_supercell([int(scell_size / a), int(scell_size / b), int(scell_size / c)]) # lammps input paramaters parameters = {'atom_style': 'charge', 'charges': {'Zn': 2, 'O': -2}, 'minimize': '1.0e-13 1.0e-20 1000 10000', 'fix': ['fix_nve all nve', '1 all box/relax aniso 0.0 vmax 0.001', '1a all qeq/comb 1 0.0001 file fq.out']} # list of pair styles
matplotlib.use('Agg') from pymatgen.core.composition import Composition from pymatgen.phasediagram.entries import PDEntry from pymatgen.phasediagram.pdmaker import PhaseDiagram from pymatgen.phasediagram.plotter import PDPlotter from mpinterfaces import get_struct_from_mp from mpinterfaces.lammps import CalibrateLammps from mpinterfaces.utils import * # all the info/warnings/outputs redirected to the log file: # lammps_Al_O.log logger = get_logger('lammps_Al_O') # list of structures from materialsproject structures = get_struct_from_mp('Al-O', all_structs=True) # scale the structures scell_size = 12 for s in structures: a, b, c = s.lattice.abc s.make_supercell( [ceil(scell_size / a), ceil(scell_size / b), ceil(scell_size / c)]) # lammps input paramaters parameters = { 'atom_style': 'charge', 'charges': { 'Al': 0, 'O': 0
import sys from math import sqrt from collections import OrderedDict import numpy as np from pymatgen.io.vasp.inputs import Incar, Poscar from pymatgen.io.vasp.inputs import Potcar, Kpoints from pymatgen.symmetry.analyzer import SpacegroupAnalyzer from mpinterfaces import get_struct_from_mp, Interface from mpinterfaces.calibrate import Calibrate, CalibrateSlab from mpinterfaces.utils import get_run_cmmnd MAPI_KEY = os.environ.get("MAPI_KEY", "") #get structure from materialsproject, use your own key strt = get_struct_from_mp('PbS', MAPI_KEY=MAPI_KEY) #convert from fcc primitive to conventional cell #the conventional unit cell is used to create the slab #this is important becasue the hkl specification for the required slab #is wrt the provided unit cell sa = SpacegroupAnalyzer(strt) structure_conventional = sa.get_conventional_standard_structure() strt = structure_conventional.copy() #create slab iface = Interface(strt, hkl=[1,1,1], min_thick=10, min_vac=10, supercell=[1,1,1]) # sort structure into groups of elements atoms for Potcar mapping iface.sort() # vasp input incar_dict = {
from __future__ import division, unicode_literals, print_function import os import sys from collections import OrderedDict from mpinterfaces import get_struct_from_mp from mpinterfaces.lammps import CalibrateLammps from mpinterfaces.utils import get_run_cmmnd # list of structures from materialsproject structures = get_struct_from_mp("ZnO", all_structs=True) # scale the structures scell_size = 12 for s in structures: a, b, c = s.lattice.abc s.make_supercell([int(scell_size / a), int(scell_size / b), int(scell_size / c)]) # lammps input paramaters parameters = { "atom_style": "charge", "charges": {"Zn": 2, "O": -2}, "minimize": "1.0e-13 1.0e-20 1000 10000", "fix": ["fix_nve all nve", "1 all box/relax aniso 0.0 vmax 0.001", "1a all qeq/comb 1 0.0001 file fq.out"], } # list of pair styles pair_styles = ["comb3 polar_off"] # list of pair coefficient files pair_coeff_files = [os.path.join(os.getcwd(), "ffield.comb3")] # parameters tuned: structures, pair styles and pair coefficients turn_knobs = OrderedDict([("STRUCTURES", structures), ("PAIR_STYLES", pair_styles), ("PAIR_COEFFS", pair_coeff_files)]) # job directory and run settings
def get_grain_boundary_interface(structure=None, hkl_pair= {'hkl': [[1,0,0],[1,1,0]],\ 'thickness':[10,10]}, twist = 0, tilt = 0, separation=0): """ Args: structure: pymatgen structure to create grain boundary in hkl_pair: dict of {'hkl':thickness} twist: twist in degrees tilt: tilt in degrees """ structure = get_struct_from_mp(structure, MAPI_KEY="") sa = SpacegroupAnalyzer(structure) structure_conventional = sa.get_conventional_standard_structure() structure = structure_conventional.copy() structure.sort() #creation of lower part of grain boundary lower= Interface(structure,\ hkl = hkl_pair['hkl'][0], min_thick = hkl_pair['thickness'][0], min_vac = separation+hkl_pair['thickness'][1], primitive = False, from_ase = True, center_slab=False) lower.to(fmt="poscar", filename="POSCAR_lower.vasp") #creation of upper part of grain boundary upper= Interface(structure,\ hkl = hkl_pair['hkl'][1], min_thick = hkl_pair['thickness'][1], min_vac = 0, primitive = False, from_ase = True) #find top atoms reference of lower part of gb substrate_top_z = np.max(np.array([site.coords for site in lower])[:, 2]) # define twist and tilt vectors twist_shift_normal = lower.lattice.matrix[2,:]/\ np.linalg.norm(lower.lattice.matrix[2,:]) tilt_normal = upper.lattice.matrix[1,:]/\ np.linalg.norm(upper.lattice.matrix[2,:]) #define twist operation SymmOp object twist_op = SymmOp.from_axis_angle_and_translation(axis= twist_shift_normal,\ angle=twist, angle_in_radians=False,translation_vec=(0, 0, 0)) #define tilt operation SymmOp object tilt_op = SymmOp.from_axis_angle_and_translation(axis= tilt_normal,\ angle=tilt, angle_in_radians=False,translation_vec=(0, 0, 0)) upper.apply_operation(twist_op) upper.to(fmt="poscar", filename="POSCAR_upper.vasp") upper.apply_operation(tilt_op) #define shift separation along twist vector normal to upper plane shift = -1 * twist_shift_normal / np.linalg.norm( twist_shift_normal) * separation #define origin to shift w.r.t top of the lower grain origin = np.array([0, 0, substrate_top_z]) #shift sites in upper for site in upper: new_coords = site.coords - origin + shift lower.append(site.specie, new_coords, coords_are_cartesian=True) return lower
# new_sites = [site for k, site in enumerate(mol) if k not in remove_sites] # return Molecule.from_sites(new_sites) if __name__ == '__main__': # nanopartcle settings # max radius in angstroms rmax = 15 # surface families to be chopped off surface_families = [(1, 0, 0), (1, 1, 1)] # could be in any units, will be normalized surface_energies = [28, 25] # caution: set the structure wrt which the the miller indices are specified # use your own API key structure = get_struct_from_mp('PbS') # primitve ---> conventional cell sa = SpacegroupAnalyzer(structure) structure_conventional = sa.get_conventional_standard_structure() nanoparticle = Nanoparticle(structure_conventional, rmax=rmax, hkl_family=surface_families, surface_energies=surface_energies) nanoparticle.create() nanoparticle.to(fmt='xyz', filename='nanoparticle.xyz') """ Wulff construction using the ASE package works only for cubic systems and doesn't support multiatom basis from ase.cluster import wulff_construction
import sys from math import sqrt from collections import OrderedDict import numpy as np from pymatgen.io.vasp.inputs import Incar, Poscar from pymatgen.io.vasp.inputs import Potcar, Kpoints from pymatgen.symmetry.analyzer import SpacegroupAnalyzer from mpinterfaces import get_struct_from_mp, Interface from mpinterfaces.calibrate import Calibrate, CalibrateSlab from mpinterfaces.utils import get_run_cmmnd MAPI_KEY = os.environ.get("MAPI_KEY", "") #get structure from materialsproject, use your own key strt = get_struct_from_mp('PbS', MAPI_KEY=MAPI_KEY) #convert from fcc primitive to conventional cell #the conventional unit cell is used to create the slab #this is important becasue the hkl specification for the required slab #is wrt the provided unit cell sa = SpacegroupAnalyzer(strt) structure_conventional = sa.get_conventional_standard_structure() strt = structure_conventional.copy() #create slab iface = Interface(strt, hkl=[1, 1, 1], min_thick=10, min_vac=10, supercell=[1, 1, 1]) # sort structure into groups of elements atoms for Potcar mapping iface.sort()
def makePoscars(M_elements, X_elements, monolayer_path, bulk_path, getCompeting=True): """ function that writes out poscars of chem-substituted M-X monolayers Args: M_elements : (list) M X_elements : (list) X ratio : (float?) monolayers : (str) path to poscar files of monolayers bulks : (str) path to poscar files of bulk Returns: List of Poscar file objects for twod monolayers and their competitors """ # checing the existence of the monolayer # and bulk directories # these direcotries can simply contain the motifs at # the top most level monosDir = os.listdir(monolayer_path) bulksDir = os.listdir(bulk_path) # if bulks in os.listdir('inputs'): # bulksDir = os.listdir('inputs/bulks') # else: # bulks = [] twod = [] competitors = [] monos = {} bulks = {} results = {} # making direcotries of types of chem sub directories results['onRatio'] = [] results['hull'] = [] # read in monolayer and bulk motifs for mon in monosDir: monos[mon] = Structure.from_file(monolayer_path + '/' + mon) results[mon] = [] for bulk in bulksDir: bulks[bulk] = Structure.from_file(bulk_path + '/' + bulk) results[bulk + '_bulk'] = [] # perform the chem sub based on the input X and M lists for base_name, mono in monos.items(): # os.mkdir(monolayer) # os.chdir(monolayer) for M in M_elements: for X in X_elements: coreElements = [M, X] # naming the files .. can be set as poscar.comment sub_spec = np.unique(mono.species) if len(sub_spec) != len(coreElements): print(base_name + ' DOES NOT HAVE ' + len(coreElements) + ' ELEMENTS. ENDING LOOP') break else: substitutionDict = {} counter = 0 for element in sub_spec: substitutionDict[element] = coreElements[counter] counter += 1 substitutedStruct = mono substitutedStruct.replace_species(substitutionDict) results[base_name].append(substitutedStruct) if getCompeting: competing = get_competing_phases_new( mono ) # argument taken is the POSCAR in the current directory. # Modify get_competing_phases code to allow input structure # object? if len(competing) == 1: # ONRATIO newStruct = get_struct_from_mp( competing[0][1]) # assume the # lowest hull distance results['onRatio'].append(newStruct) # chem sub ## how about more than 2 ? this would just be the case in ternaries, etc. elif len(competing) == 2: # HULL newStruct1 = get_struct_from_mp(competing[0][1]) newStruct2 = get_struct_from_mp(competing[1][1]) results['hull'].append(newStruct1) results['hull'].append(newStruct2) # write_potcar(pathToPOTCAR) # relax(submit=False) # same for bulks for base_name, bulk in bulks.items(): for M in M_elements: for X in X_elements: coreElements = [M, X] sub_spec = np.unique(bulk.species) if len(sub_spec) != len(coreElements): print(base_name + ' DOES NOT HAVE ' + len(coreElements) + ' ELEMENTS. ENDING LOOP') break else: substitutionDict = {} counter = 0 for element in sub_spec: substitutionDict[element] = coreElements[counter] counter += 1 substitutedStruct = bulk substitutedStruct.replace_species(substitutionDict) results[base_name + '_bulk'].append(substitutedStruct) return results
def get_grain_boundary_interface(structure=None, hkl_pair= {'hkl': [[1,0,0],[1,1,0]],\ 'thickness':[10,10]}, twist = 0, tilt = 0, separation=0): """ Args: structure: pymatgen structure to create grain boundary in hkl_pair: dict of {'hkl':thickness} twist: twist in degrees tilt: tilt in degrees """ structure = get_struct_from_mp(structure, MAPI_KEY="") sa = SpacegroupAnalyzer(structure) structure_conventional = sa.get_conventional_standard_structure() structure = structure_conventional.copy() structure.sort() #creation of lower part of grain boundary lower= Interface(structure,\ hkl = hkl_pair['hkl'][0], min_thick = hkl_pair['thickness'][0], min_vac = separation+hkl_pair['thickness'][1], primitive = False, from_ase = True, center_slab=False) lower.to(fmt="poscar", filename="POSCAR_lower.vasp") #creation of upper part of grain boundary upper= Interface(structure,\ hkl = hkl_pair['hkl'][1], min_thick = hkl_pair['thickness'][1], min_vac = 0, primitive = False, from_ase = True) #find top atoms reference of lower part of gb substrate_top_z = np.max(np.array([site.coords for site in lower])[:,2]) # define twist and tilt vectors twist_shift_normal = lower.lattice.matrix[2,:]/\ np.linalg.norm(lower.lattice.matrix[2,:]) tilt_normal = upper.lattice.matrix[1,:]/\ np.linalg.norm(upper.lattice.matrix[2,:]) #define twist operation SymmOp object twist_op = SymmOp.from_axis_angle_and_translation(axis= twist_shift_normal,\ angle=twist, angle_in_radians=False,translation_vec=(0, 0, 0)) #define tilt operation SymmOp object tilt_op = SymmOp.from_axis_angle_and_translation(axis= tilt_normal,\ angle=tilt, angle_in_radians=False,translation_vec=(0, 0, 0)) upper.apply_operation(twist_op) upper.to(fmt="poscar", filename="POSCAR_upper.vasp") upper.apply_operation(tilt_op) #define shift separation along twist vector normal to upper plane shift = -1*twist_shift_normal/np.linalg.norm(twist_shift_normal) * separation #define origin to shift w.r.t top of the lower grain origin = np.array([0,0, substrate_top_z]) #shift sites in upper for site in upper: new_coords = site.coords - origin + shift lower.append(site.specie, new_coords, coords_are_cartesian=True) return lower