def read_structures_from_files(fnames): ''' read structures according to filename list Args: fnames: (list) input filename list Returns: structure: Structure obj. list and filename list ''' structures = [] final_fnames = [] assert isinstance(fnames, list) for fname in fnames: structure = read_structures_from_file(fname) mlog.debug(structure) if structure is not None: structures.append(structure) if '/' in fname: fname = fname.replace('/', '_') if '.' in fname: fname = fname.replace('.', '_') final_fnames.append(fname) return structures, final_fnames
def __init__(self, local_root, work_profile, job_uuid=None): """ work_profile: local_root: """ assert (type(local_root) == str) self.local_root = os.path.abspath(local_root) if job_uuid: self.job_uuid = job_uuid else: self.job_uuid = str(uuid.uuid4()) self.remote_root = os.path.join(work_profile.get_work_root(), self.job_uuid) mlog.debug("local_root is %s" % local_root) mlog.debug("remote_root is %s" % self.remote_root) os.makedirs(self.remote_root, exist_ok=True)
def constrain(structs, fnames, atom_index, in_str=" "): #len(structs)==1 mlog.debug("len(structs): {} ".format(len(structs))) mlog.debug("fnames: {} ".format(fnames[0])) for struct, fname in zip(structs, fnames): mlog.debug(fname) mlog.debug(struct) natom = struct.num_sites selective_dynamics = [[True for col in range(3)] for row in range(natom)] for i in range(natom): if i in atom_index: selective_dynamics[i] = [False, False, False] tmp_struct = Structure( struct.lattice, struct.species, struct.frac_coords, site_properties={'selective_dynamics': selective_dynamics}) poscar = Poscar(tmp_struct) poscar.comment = poscar.comment + ' |--> ' + in_str filename = 'Fixed_' + fname + '.vasp' poscar.write_file(filename)
def all_finished(self, job_handler, mark_failure): task_chunks = job_handler['task_chunks'] task_chunks_str = ['+'.join(ii) for ii in task_chunks] task_hashes = [sha1(ii.encode('utf-8')).hexdigest() for ii in task_chunks_str] job_list = job_handler['job_list'] job_record = job_handler['job_record'] command = job_handler['command'] tag_failure_list = ['tag_failure_%d' % ii for ii in range(len(command))] resources = job_handler['resources'] outlog = job_handler['outlog'] errlog = job_handler['errlog'] backward_task_files = job_handler['backward_task_files'] mlog.debug('checking jobs') nchunks = len(task_chunks) for idx in range(nchunks) : cur_hash = task_hashes[idx] rjob = job_list[idx] if not job_record.check_finished(cur_hash) : # chunk not finished according to record status = rjob['batch'].check_status() job_uuid = rjob['context'].job_uuid mlog.debug('checked job %s' % job_uuid) if status == JobStatus.terminated : job_record.increase_nfail(cur_hash) if job_record.check_nfail(cur_hash) > 3: raise RuntimeError('Job %s failed for more than 3 times' % job_uuid) mlog.info('job %s terminated, submit again'% job_uuid) mlog.debug('try %s times for %s'% (job_record.check_nfail(cur_hash), job_uuid)) rjob['batch'].submit(task_chunks[idx], command, res = resources, outlog=outlog, errlog=errlog,restart=True) elif status == JobStatus.finished : mlog.info('job %s finished' % job_uuid) if mark_failure: rjob['context'].download(task_chunks[idx], tag_failure_list, check_exists = True, mark_failure = False) rjob['context'].download(task_chunks[idx], backward_task_files, check_exists = True) else: rjob['context'].download(task_chunks[idx], backward_task_files) rjob['context'].clean() job_record.record_finish(cur_hash) job_record.dump() job_record.dump() return job_record.check_all_finished()
def twod_operation(choice): assert choice in ["1", "2", "3", "4", "5", "6", "7"] if choice == "1": structs, fnames = read_structures() multi_structs(structs, fnames) print("input the supercell supercell factor") print('for x direction can be: 10 1 1') print('for y direction can be: 1 10 1') wait_sep() scale_str = wait() supercell = [int(x) for x in scale_str.split()] if (len(supercell) != 3): print('Unknown format') os._exit(0) if supercell[0] >= supercell[1]: direction = 0 # for x direction else: direction = 1 # for y direction print("input the strain range") print("example: 0.02:0.1:10 ") wait_sep() strain_str = wait() tmp = [float(x) for x in strain_str.split(":")] strain = [] if len(tmp) == 3: strain_range = np.linspace(tmp[0], tmp[1], int(tmp[2])) else: print("Unknown format") os._exit(0) print("input the index of atom need to be fixed") print("example: 1 10 11 20 ") print("0 means fix the atom automatically") wait_sep() atom_index_str = wait() if len(atom_index_str.split()) > 1: atom_index = [int(x) for x in atom_index_str.split("")] auto_fix = False else: atom_index = [int(atom_index_str)] auto_fix = True ripple(structs, fnames, supercell, direction, strain_range, atom_index, auto_fix) return True elif choice == "2": structs, fnames = read_structures() multi_structs(structs, fnames) print("Input the number of layers") wait_sep() in_str = wait() layer_number = int(in_str) print("Input the layer distance") wait_sep() in_str = wait() layer_distance = float(in_str) multi_layers(structs, fnames, layer_number, layer_distance) return True elif choice == "3": """ splitting sep .... . . . . . """ structs, fnames = read_structures() if len(structs) > 1: print("Splitting dont support multi-structures!!!") os._exit(0) atom_index, in_str = atom_selection(structs[0]) print("Input the splitting distance, 10 Ang is enough!") wait_sep() in_str = wait() SplitDistance = float(in_str) print("Numbers of splitting site, 50 sites are enough!") wait_sep() in_str = wait() NumberSplitSite = int(in_str) split(structs, fnames, atom_index, in_str, SplitDistance, NumberSplitSite, ProperDist=3.5, DenseFrac=0.75) return True elif choice == "4": structs, fnames = read_structures() multi_structs(structs, fnames) print("Input the new value of vacuum layer thickness") wait_sep() in_str = wait() wait_sep() nvac_layer_thickness = float(in_str) resize_vacuum(structs, fnames, nvac_layer_thickness) return True elif choice == "5": structs, fnames = read_structures() multi_structs(structs, fnames) for struct, fname in zip(structs, fnames): new_struct = move_to_zcenter(struct) new_struct.to(filename='z-center_' + fname + '.vasp', fmt='poscar') return True elif choice == 6: structs, fnames = read_structures() multi_structs(structs, fnames) try: import sympy except ImportError: print("You have to install sympy module") os._exit(0) print("Input the elastic of material by order : C11 C12 C22 C66") wait_sep() in_str = "" while in_str == "": in_str = input().strip().split() elastic_constant = [float(x) for x in in_str] if len(elastic_constant) != 4: print("You have to input C11 C12 C22 C66") return None C11 = elastic_constant[0] C12 = elastic_constant[1] C22 = elastic_constant[2] C66 = elastic_constant[3] print("Input applied force: e.x. 1.0 GPa nm") wait_sep() in_str = wait() sigma = float(in_str) circle_strain(structs, fnames, C11, C12, C22, C66, sigma) return True elif choice == "7": structs, fnames = read_structures() if len(structs) > 1: print("Constrain doesnot support multi-structures!!!") os._exit(0) atom_index, in_str = atom_selection(structs[0]) mlog.debug("constrained atom index") mlog.debug(' '.join(map(str, atom_index))) constrain(structs, fnames, atom_index, in_str) return True elif choice == "8": print('your choice ?') print('{} >>> {}'.format('1', 'input 2D structure from local disk')) print('{} >>> {}'.format('2', 'get 2D structure online')) wait_sep() in_str = wait() _choice = int(in_str) if _choice == "1": mpid = None structs, fnames = read_structures() if len(structs) > 1: print("Matching dont support multi-structures!!!") os._exit(0) else: print("Input the mp-id for your structure") wait_sep() in_str = wait() mpid = in_str struct = None film, substrates = get_mp_film_substrate(mpid=mpid, struct=struct) df = match_substrate(film, substrates) dumpfn(df.to_dict(), 'substrate_' + fnames[0] + '.json', indent=4) #df.to_csv('substrate.csv', sep=',', header=True, index=True) return True else: print("Unkonw choice") return None
def generate_incar(struct, dirname='.', encut=1.5): """ Generate INCAR according to user's choice. Now these templates are available: a >>> Optimization calculation b >>> SCF calculation c >>> BAND structure calculation d >>> DOS calculation e >>> ELF calculation f >>> Bader charge calculation g >>> AIMD NPT calculation h >>> AIMD NVT calculation i >>> Potential calculation j >>> Partial charge calculation k >>> STM image calculation l >>> optical properties calculation m >>> Mechanical properties calculation n >>> Frequency calculation o >>> Transition state calculation p >>> Phonopy + vasp DFPT calculation q >>> Phonopy + vasp finite difference calculation """ try: pots = Potcar.from_file(os.path.join(dirname, "POTCAR")) pot_elems = [] max_encut_elems = [] for pot in pots: pot_elems.append(pot.element) max_encut_elems.append(pot.PSCTR['ENMAX']) struct_elems = [x.value for x in struct.types_of_specie] mlog.debug('Element order in POSCAR %s' % (struct_elems)) mlog.debug('Element order in POTCAR %s' % (pot_elems)) if struct_elems == pot_elems: pass else: print("The element order in POTCAR conflicts with POSCAR ") os._exit() except: warn_tip(0, '\nPOTCAR file not found\n') max_encut_elems = [500] prop_encut = max(max_encut_elems) * encut elec_relax1['ENCUT'] = prop_encut tip='\n'+\ 'for every letter you can append another letters for extra parameters\n'+\ 'The corresponding list are: \n'+\ 'a: SPIN \n'+\ 'b: SOC \n'+\ 'c: HSE \n'+\ 'd: DIPOLE correction \n'+\ 'e: Electric filed \n'+\ 'f: Add grid \n'+\ 'g: Add Pressure \n'+\ 'h: DFT-D2 \n'+\ 'i: DFT-D3 \n'+\ 'j: VDW-DF \n'+\ 'k: opt-B86 \n'+\ 'l: opt-B88 \n'+\ 'm: LDA+U \n'+\ '\nFor exmaple: aai means one optimization by condsidering SPIN and \n'+\ 'DFT-D3 correction. \n' warn_tip(1, tip) #add tips sepline(ch=' generate INCAR file ', sp='-') print("your choice?") print('''\ a >>> Optimization calculation b >>> SCF calculation c >>> BAND structure calculation d >>> DOS calculation e >>> ELF calculation f >>> Bader charge calculation g >>> AIMD NPT calculation h >>> AIMD NVT calculation i >>> Potential calculation j >>> Partial charge calculation k >>> STM image calculation l >>> optical properties calculation m >>> Mechanical properties calculation n >>> Frequency calculation o >>> Transition state calculation p >>> Phonopy + vasp DFPT calculation q >>> Phonopy + vasp finite difference calculation ''') wait_sep() in_str = wait() choice = in_str[0] in_str = ''.join(in_str.split()) # assert choice in range(1,19) ref_incar = MITRelaxSet(struct).incar #print(ref_incar) ref_incar_cite = {} spin_paras['MAGMOM'] = ref_incar['MAGMOM'] try: LDAU_paras['LDAUJ'] = ref_incar['LDAUJ'] LDAU_paras['LDAUL'] = ref_incar['LDAUL'] except: LDAU_paras['LDAUJ'] = None LDAU_paras['LDAUL'] = None elec_relax1['LREAL'] = ref_incar['LREAL'] def parse_extra_incar(in_str, modify_val=None): incar_str = '' for i in range(1, len(in_str)): if in_str[i] != ' ': incar, comment = Incar.from_dict(eval(extra_params[in_str[i]])) incar_str += incar.get_string(pretty=True, comment=comment) return incar_str incar_str = '' if choice == 'a': # Opt calculation for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'b': # SCF calculation ion_relax['NSW'] = 0 elec_relax1['EDIFF'] = ediff_oth output_paras['LCHGARG'] = True output_paras['LWAVE'] = True for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'c': # band structure calculation ion_relax['NSW'] = 0 elec_relax1['EDIFF'] = ediff_oth start_paras['ICHARG'] = 11 for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'd': # DOS calculation ion_relax['NSW'] = 0 elec_relax1['EDIFF'] = ediff_oth start_paras['ICHARG'] = 11 for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'e': # ELF calculatio ion_relax['NSW'] = 0 elec_relax1['EDIFF'] = ediff_oth output_paras['LCHGARG'] = True output_paras['LELF'] = True for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'f': # Bader charge calculation ion_relax['NSW'] = 0 elec_relax1['EDIFF'] = ediff_oth output_paras['LCHGARG'] = True output_paras['LAECHG'] = True for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'g': # AIMD NPT calculation basic_paras.append('md_NPT_paras') ion_relax['NSW'] = md_step ion_relax['IBRION'] = 0 ion_relax['POTIM'] = 1 ion_relax['ISYM'] = 0 for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'h': # AIMD NVT calculation basic_paras.append('md_NVT_paras') ion_relax['NSW'] = md_step ion_relax['IBRION'] = 0 ion_relax['POTIM'] = 1 ion_relax['ISYM'] = 0 ion_relax['ISIF'] = 2 for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'i': # Potential calculation ion_relax['NSW'] = 0 elec_relax1['EDIFF'] = ediff_oth output_paras['LCHGARG'] = True output_paras['LVTOT'] = True for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'j': # Partial charge calculation basic_paras.append('partial_paras') ion_relax['NSW'] = 0 start_paras['ISTART'] = 1 elec_relax1['EDIFF'] = ediff_oth output_paras['LCHGARG'] = True for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'k': # STM image calculation basic_paras.append('stm_paras') ion_relax['NSW'] = 0 start_paras['ISTART'] = 1 elec_relax1['EDIFF'] = ediff_oth output_paras['LCHGARG'] = True for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'l': # optical properties calculation basic_paras.append('optics_paras') ion_relax['NSW'] = 0 start_paras['ISTART'] = 1 elec_relax1['EDIFF'] = ediff_oth for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'm': # Mechanical properties calculation basic_paras.append('stm_paras') ion_relax['NSW'] = 1 ion_relax['NFREE'] = 4 ion_relax['IBRION'] = 6 ion_relax['POTIM'] = 0.015 elec_relax1['EDIFF'] = ediff_oth for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'n': # Frequency calculation ion_relax['NSW'] = 1 ion_relax['NFREE'] = 4 ion_relax['IBRION'] = 5 ion_relax['POTIM'] = 0.015 elec_relax1['EDIFF'] = ediff_oth for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'o': # Transition state calculation basic_paras.append('neb_paras') ion_relax['POTIM'] = 0 ion_relax['EDIFFG'] = ediffg_neb elec_relax1['EDIFF'] = ediff_opt for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif choice == 'p': # Phonopy + vasp DFPT calculation ion_relax['IBRION'] = 8 elec_relax1['EDIFF'] = ediff_phon basic_paras.append(grid_paras) for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) elif 'q' == choice: # Phonopy + vasp finite difference calculation ion_relax['NSW'] = 0 ion_relax['IBRION'] = -1 elec_relax1['EDIFF'] = ediff_phon basic_paras.append(grid_paras) for dict_paras in basic_paras: incar, comment = Incar.from_dict(eval(dict_paras)) incar_str += incar.get_string(pretty=True, comment=comment) if len(in_str) > 1: incar_str += parse_extra_incar(in_str) else: # left empty for extend raise Exception(f"choice '{choice}' not valid!") write_file(os.path.join(dirname, "INCAR"), incar_str)
def submit_jobs(self, resources, command, work_path, tasks, group_size, forward_common_files, forward_task_files, backward_task_files, forward_task_deference = True, outlog = 'log', errlog = 'err') : self.backward_task_files = backward_task_files # task_chunks = [ # [os.path.basename(j) for j in tasks[i:i + group_size]] \ # for i in range(0, len(tasks), group_size) # ] task_chunks = _split_tasks(tasks, group_size) task_chunks_str = ['+'.join(ii) for ii in task_chunks] task_hashes = [sha1(ii.encode('utf-8')).hexdigest() for ii in task_chunks_str] job_record = JobRecord(work_path, task_chunks, fname = self.jrname) nchunks = len(task_chunks) job_list = [] for ii in range(nchunks) : cur_chunk = task_chunks[ii] cur_hash = task_hashes[ii] if not job_record.check_finished(cur_hash): # chunk is not finished # check if chunk is submitted submitted = job_record.check_submitted(cur_hash) if not submitted: job_uuid = None else : job_uuid = job_record.get_uuid(cur_hash) mlog.debug("load uuid %s for chunk %s" % (job_uuid, cur_hash)) # communication context, bach system context = self.context(work_path, self.session, job_uuid) batch = self.batch(context, uuid_names = self.uuid_names) rjob = {'context':context, 'batch':batch} # upload files tag_upload = '%s_tag_upload' % rjob['context'].job_uuid if not rjob['context'].check_file_exists(tag_upload): rjob['context'].upload('.', forward_common_files) rjob['context'].upload(cur_chunk, forward_task_files, dereference = forward_task_deference) rjob['context'].write_file(tag_upload, '') mlog.debug('uploaded files for %s' % task_chunks_str[ii]) # submit new or recover old submission if not submitted: rjob['batch'].submit(cur_chunk, command, res = resources, outlog=outlog, errlog=errlog) job_uuid = rjob['context'].job_uuid mlog.debug('assigned uuid %s for %s ' % (job_uuid, task_chunks_str[ii])) mlog.info('new submission of %s for chunk %s' % (job_uuid, cur_hash)) else: rjob['batch'].submit(cur_chunk, command, res = resources, outlog=outlog, errlog=errlog, restart = True) mlog.info('restart from old submission %s for chunk %s' % (job_uuid, cur_hash)) # record job and its remote context job_list.append(rjob) ip = None instance_id = None if 'ali_auth' in self.remote_profile: ip = self.remote_profile['hostname'] instance_id = self.remote_profile['instance_id'] job_record.record_remote_context(cur_hash, context.local_root, context.remote_root, job_uuid, ip, instance_id) else : # finished job, append a None to list job_list.append(None) job_record.dump() assert(len(job_list) == nchunks) job_handler = { 'task_chunks': task_chunks, 'job_list': job_list, 'job_record': job_record, 'command': command, 'resources': resources, 'outlog': outlog, 'errlog': errlog, 'backward_task_files': backward_task_files } return job_handler
def submit(self, job_dirs, cmd, args=None, res=None, restart=False, outlog='log', errlog='err'): if restart: mlog.debug('restart task') status = self.check_status() if status in [ JobStatus.unsubmitted, JobStatus.unknown, JobStatus.terminated ]: mlog.debug('task restart point !!!') self.do_submit(job_dirs, cmd, args, res, outlog=outlog, errlog=errlog) elif status == JobStatus.waiting: mlog.debug('task is waiting') elif status == JobStatus.running: mlog.debug('task is running') elif status == JobStatus.finished: mlog.debug('task is finished') else: raise RuntimeError('unknow job status, must be wrong') else: mlog.debug('new task') self.do_submit(job_dirs, cmd, args, res, outlog=outlog, errlog=errlog) if res is None: sleep = 0 else: sleep = res.get('submit_wait_time', 0) time.sleep( sleep) # For preventing the crash of the tasks while submitting