diff --git a/auto_test/cmpt_02_elastic.py b/auto_test/cmpt_02_elastic.py index 42a6e8eb7..aed23831f 100755 --- a/auto_test/cmpt_02_elastic.py +++ b/auto_test/cmpt_02_elastic.py @@ -68,7 +68,6 @@ def cmpt_deepmd_lammps(jdata, conf_dir, task_name) : lst_strain = [] lst_stress = [] for ii in lst_dfm_path : -# print(ii) strain = np.loadtxt(os.path.join(ii, 'strain.out')) stress = lammps.get_stress(os.path.join(ii, 'log.lammps')) # convert from pressure to stress @@ -83,7 +82,7 @@ def cmpt_deepmd_lammps(jdata, conf_dir, task_name) : def _main() : parser = argparse.ArgumentParser( - description="gen 01.eos") + description="cmpt 02.elastic") parser.add_argument('TASK', type=str, help='the task of generation, vasp or lammps') parser.add_argument('PARAM', type=str, diff --git a/auto_test/cmpt_03_vacancy.py b/auto_test/cmpt_03_vacancy.py index 0fcb49a5f..0b23940c1 100755 --- a/auto_test/cmpt_03_vacancy.py +++ b/auto_test/cmpt_03_vacancy.py @@ -90,7 +90,7 @@ def cmpt_deepmd_lammps(jdata, conf_dir, supercell, task_name) : def _main() : parser = argparse.ArgumentParser( - description="gen 01.eos") + description="cmpt 03.vacancy") parser.add_argument('TASK', type=str, help='the task of generation, vasp or lammps') parser.add_argument('PARAM', type=str, diff --git a/auto_test/cmpt_04_interstitial.py b/auto_test/cmpt_04_interstitial.py index 8a329b48b..f2602b9db 100755 --- a/auto_test/cmpt_04_interstitial.py +++ b/auto_test/cmpt_04_interstitial.py @@ -122,7 +122,7 @@ def _cmpt_deepmd_lammps(jdata, conf_dir, supercell, insert_ele, task_name) : def _main() : parser = argparse.ArgumentParser( - description="gen 01.eos") + description="cmpt 04.interstitial") parser.add_argument('TASK', type=str, help='the task of generation, vasp or lammps') parser.add_argument('PARAM', type=str, diff --git a/auto_test/cmpt_05_surf.py b/auto_test/cmpt_05_surf.py index 796f2b9ed..1e384c4f0 100755 --- a/auto_test/cmpt_05_surf.py +++ b/auto_test/cmpt_05_surf.py @@ -74,7 +74,7 @@ def cmpt_deepmd_lammps(jdata, conf_dir, task_name, static = False) : def _main() : parser = argparse.ArgumentParser( - description="gen 01.eos") + description="cmpt 05.surf") parser.add_argument('TASK', type=str, help='the task of generation, vasp or lammps') parser.add_argument('PARAM', type=str, diff --git a/auto_test/cmpt_06_phonon.py b/auto_test/cmpt_06_phonon.py new file mode 100644 index 000000000..99624b64c --- /dev/null +++ b/auto_test/cmpt_06_phonon.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 + +import os, re, argparse, filecmp, json, glob +import subprocess as sp +import numpy as np +import lib.vasp as vasp +import lib.lammps as lammps +from phonopy import Phonopy +from phonopy.structure.atoms import PhonopyAtoms +import yaml +import phonopy +#from phonolammps import Phonolammps + + + +global_equi_name = '00.equi' +global_task_name = '06.phonon' + +''' +link poscar +link potcar +make incar +''' +def cmpt_vasp(jdata, conf_dir,opt) : + fp_params = jdata['vasp_params'] + ecut = fp_params['ecut'] + ediff = fp_params['ediff'] + npar = fp_params['npar'] + kpar = fp_params['kpar'] + kspacing = fp_params['kspacing'] + kgamma = fp_params['kgamma'] + supercell_matrix=jdata['supercell_matrix'] + + conf_path = os.path.abspath(conf_dir) + task_path = re.sub('confs', global_task_name, conf_path) + task_path = os.path.join(task_path, 'vasp-k%.2f' % kspacing) + cwd = os.getcwd() + os.chdir(task_path) + if os.path.isfile('vasprun.xml'): + os.system('phonopy --fc vasprun.xml') + os.system('phonopy --dim="%d %d %d" -c POSCAR-unitcell band.conf'%(supercell_matrix[0],supercell_matrix[1],supercell_matrix[2])) + else: + print('vasprun.xml No such file') + if opt=='Y': + ph = phonopy.load(supercell_matrix=supercell_matrix,primitive_matrix='auto',unitcell_filename="POSCAR-unitcell",force_constants_filename='FORCE_CONSTANTS') + ph.auto_band_structure(plot=True).show() + + +def cmpt_deepmd_lammps(jdata, conf_dir,opt) : + deepmd_model_dir = jdata['deepmd_model_dir'] + deepmd_type_map = jdata['deepmd_type_map'] + ntypes = len(deepmd_type_map) + deepmd_model_dir = os.path.abspath(deepmd_model_dir) + deepmd_models = glob.glob(os.path.join(deepmd_model_dir, '*pb')) + supercell_matrix=jdata['supercell_matrix'] + + conf_path = os.path.abspath(conf_dir) + task_path = re.sub('confs', global_task_name, conf_path) + task_path = os.path.join(task_path, 'deepmd') + + os.chdir(task_path) + if os.path.isfile('FORCE_CONSTANTS'): + os.system('phonopy --dim="%d %d %d" -c POSCAR-unitcell band.conf'%(supercell_matrix[0],supercell_matrix[1],supercell_matrix[2])) + else: + print('FORCE_CONSTANTS No such file') + if opt=='Y': + ph = phonopy.load(supercell_matrix=supercell_matrix,primitive_matrix='auto',unitcell_filename="POSCAR-unitcell",force_constants_filename='FORCE_CONSTANTS') + ph.auto_band_structure(plot=True).show() + + +def _main() : + parser = argparse.ArgumentParser( + description="cmpt 06.phonon") + parser.add_argument('TASK', type=str, + help='the task of generation, vasp or lammps') + parser.add_argument('PARAM', type=str, + help='json parameter file') + parser.add_argument('CONF', type=str, + help='the path to conf') + parser.add_argument('OPT', type=str, + help='show the band structue or not [Y/N]') + args = parser.parse_args() + + with open (args.PARAM, 'r') as fp : + jdata = json.load (fp) + +# print('generate %s task with conf %s' % (args.TASK, args.CONF)) + if args.TASK == 'vasp': + cmpt_vasp(jdata, args.CONF,args.OPT) + elif args.TASK == 'deepmd' : + cmpt_deepmd_lammps(jdata, args.CONF,args.OPT) + elif args.TASK == 'meam' : + cmpt_meam_lammps(jdata, args.CONF) + else : + raise RuntimeError("unknow task ", args.TASK) + +if __name__ == '__main__' : + _main() + diff --git a/auto_test/gen_01_eos.py b/auto_test/gen_01_eos.py index 98442eab3..99ec54b2f 100755 --- a/auto_test/gen_01_eos.py +++ b/auto_test/gen_01_eos.py @@ -141,7 +141,7 @@ def make_deepmd_lammps (jdata, conf_dir) : print('# generate %s' % (vol_path)) os.makedirs(vol_path, exist_ok = True) os.chdir(vol_path) - print(vol_path) + #print(vol_path) for ii in ['conf.lmp', 'conf.lmp'] + deepmd_models_name : if os.path.exists(ii) : os.remove(ii) @@ -159,7 +159,7 @@ def make_deepmd_lammps (jdata, conf_dir) : os.symlink(os.path.relpath(ii), jj) # make lammps input scale = (vol / vpa) ** (1./3.) - fc = lammps.make_lammps_press_relax('conf.lmp', ntypes, scale, deepmd_models_name) + fc = lammps.make_lammps_press_relax('conf.lmp', ntypes, scale,lammps.inter_deepmd, deepmd_models_name) with open(os.path.join(vol_path, 'lammps.in'), 'w') as fp : fp.write(fc) os.chdir(cwd) @@ -314,12 +314,12 @@ def _main() : if args.TASK == 'vasp': make_vasp(jdata, args.CONF) elif args.TASK == 'deepmd' : - if args.fix_shape is not None : + if args.fix_shape : make_deepmd_lammps_fixv(jdata, args.CONF) else : make_deepmd_lammps(jdata, args.CONF) elif args.TASK == 'meam' : - if args.fix_shape is not None : + if args.fix_shape: make_meam_lammps_fixv(jdata, args.CONF) else : raise RuntimeError("not implemented ", args.TASK) diff --git a/auto_test/gen_02_elastic.py b/auto_test/gen_02_elastic.py index 9d1b972f7..60909d6bc 100755 --- a/auto_test/gen_02_elastic.py +++ b/auto_test/gen_02_elastic.py @@ -250,7 +250,7 @@ def make_meam_lammps(jdata, conf_dir) : def _main() : parser = argparse.ArgumentParser( - description="gen 01.eos") + description="gen 02.elastic") parser.add_argument('TASK', type=str, help='the task of generation, vasp or lammps') parser.add_argument('PARAM', type=str, diff --git a/auto_test/gen_03_vacancy.py b/auto_test/gen_03_vacancy.py index 16cce6960..69db68e8c 100755 --- a/auto_test/gen_03_vacancy.py +++ b/auto_test/gen_03_vacancy.py @@ -234,7 +234,7 @@ def make_meam_lammps(jdata, conf_dir, supercell) : def _main() : parser = argparse.ArgumentParser( - description="gen 01.eos") + description="gen 03.vacancy") parser.add_argument('TASK', type=str, help='the task of generation, vasp or lammps') parser.add_argument('PARAM', type=str, diff --git a/auto_test/gen_04_interstitial.py b/auto_test/gen_04_interstitial.py index a1bddcf6f..291cbc66d 100755 --- a/auto_test/gen_04_interstitial.py +++ b/auto_test/gen_04_interstitial.py @@ -405,7 +405,7 @@ def _make_meam_lammps(jdata, conf_dir, supercell, insert_ele, task_name) : def _main() : parser = argparse.ArgumentParser( - description="gen 01.eos") + description="gen 04.interstitial") parser.add_argument('TASK', type=str, help='the task of generation, vasp or lammps') parser.add_argument('PARAM', type=str, diff --git a/auto_test/gen_05_surf.py b/auto_test/gen_05_surf.py index 8ff3cb46d..1ceca2ae9 100755 --- a/auto_test/gen_05_surf.py +++ b/auto_test/gen_05_surf.py @@ -253,7 +253,7 @@ def make_meam_lammps(jdata, conf_dir, max_miller = 2, static = False, relax_box def _main() : parser = argparse.ArgumentParser( - description="gen 01.eos") + description="gen 05.surf") parser.add_argument('TASK', type=str, help='the task of generation, vasp or lammps') parser.add_argument('PARAM', type=str, diff --git a/auto_test/gen_06_phonon.py b/auto_test/gen_06_phonon.py new file mode 100644 index 000000000..39cc9b3e8 --- /dev/null +++ b/auto_test/gen_06_phonon.py @@ -0,0 +1,233 @@ +#!/usr/bin/env python3 + +import os, re, argparse, filecmp, json, glob +import subprocess as sp +import numpy as np +import lib.vasp as vasp +import lib.lammps as lammps +from phonopy import Phonopy +from phonopy.structure.atoms import PhonopyAtoms +import yaml +import phonopy +#from phonolammps import Phonolammps + + +global_equi_name = '00.equi' +global_task_name = '06.phonon' + +''' +link poscar +link potcar +make incar +''' +def make_vasp(jdata, conf_dir) : + fp_params = jdata['vasp_params'] + ecut = fp_params['ecut'] + ediff = fp_params['ediff'] + npar = fp_params['npar'] + kpar = fp_params['kpar'] + kspacing = fp_params['kspacing'] + kgamma = fp_params['kgamma'] + supercell_matrix=jdata['supercell_matrix'] + band_path=jdata['band'] + + conf_path = os.path.abspath(conf_dir) + conf_poscar = os.path.join(conf_path, 'POSCAR') + equi_path = re.sub('confs', global_equi_name, conf_path) + equi_path = os.path.join(equi_path, 'vasp-k%.2f' % kspacing) + equi_contcar = os.path.join(equi_path, 'CONTCAR') + task_path = re.sub('confs', global_task_name, conf_path) + task_path = os.path.join(task_path, 'vasp-k%.2f' % kspacing) + os.makedirs(task_path, exist_ok=True) + cwd = os.getcwd() + os.chdir(task_path) + print(task_path) + if os.path.isfile('POSCAR-unitcell') : + os.remove('POSCAR-unitcell') + if os.path.isfile('POSCAR') : + os.remove('POSCAR') + os.symlink(os.path.relpath(equi_contcar), 'POSCAR-unitcell') + os.chdir(cwd) + task_poscar = os.path.join(task_path, 'POSCAR-unitcell') + # gen incar + fc = vasp.make_vasp_phonon_incar(ecut, ediff, 1, 1, kspacing = None, kgamma = None) + with open(os.path.join(task_path, 'INCAR'), 'w') as fp : + fp.write(fc) + # gen potcar + with open(task_poscar,'r') as fp : + lines = fp.read().split('\n') + ele_list = lines[5].split() + potcar_map = jdata['potcar_map'] + potcar_list = [] + for ii in ele_list : + assert(os.path.exists(potcar_map[ii])) + potcar_list.append(potcar_map[ii]) + with open(os.path.join(task_path,'POTCAR'), 'w') as outfile: + for fname in potcar_list: + with open(fname) as infile: + outfile.write(infile.read()) + # gen kpoints + fc = vasp.make_kspacing_kpoints(task_poscar, kspacing, kgamma) + with open(os.path.join(task_path,'KPOINTS'), 'w') as fp: + fp.write(fc) + # gen band.conf + os.chdir(task_path) + with open('band.conf','w') as fp: + fp.write('ATOM_NAME = ') + for ii in ele_list: + fp.write(ii) + fp.write(' ') + fp.write('\n') + fp.write('DIM = %d %d %d\n'%(supercell_matrix[0],supercell_matrix[1],supercell_matrix[2])) + fp.write('BAND = %s\n'%band_path) + fp.write('FORCE_CONSTANTS=READ') + # gen POSCAR + ''' + phonon = phonopy.load(supercell_matrix=supercell_matrix, + primitive_matrix='auto', + unitcell_filename='POSCAR-unitcell') + phonon.save(filename='phonopy_disp.yaml') + with open('phonopy_disp.yaml', 'r') as f: + temp = yaml.load(f.read()) + with open('POSCAR', 'w') as fp: + for ii in ele_list: + fp.write(ii) + fp.write(' ') + fp.write('\n') + data=open('POSCAR-unitcell', 'r') + next(data) + fp.write(data.readline()) + for ii in temp['supercell']['lattice']: + fp.write(str(ii).replace(',', '').replace('[', '').replace(']','\n')) + for ii in ele_list: + fp.write(str(str(temp['supercell']['points']).count(ii))) + fp.write(' ') + fp.write('\n') + fp.write('Direct\n') + for ii in temp['supercell']['points']: + fp.write(str(ii['coordinates']).replace(',', '').replace('[', '').replace(']', '\n')) + ''' + os.system('phonopy -d --dim="%d %d %d" -c POSCAR-unitcell'%(supercell_matrix[0],supercell_matrix[1],supercell_matrix[2])) + os.system('cp SPOSCAR POSCAR') + +def make_deepmd_lammps(jdata, conf_dir) : + deepmd_model_dir = jdata['deepmd_model_dir'] + deepmd_type_map = jdata['deepmd_type_map'] + ntypes = len(deepmd_type_map) + deepmd_model_dir = os.path.abspath(deepmd_model_dir) + deepmd_models = glob.glob(os.path.join(deepmd_model_dir, '*pb')) + deepmd_models_name = [os.path.basename(ii) for ii in deepmd_models] + supercell_matrix=jdata['supercell_matrix'] + band_path=jdata['band'] + + conf_path = os.path.abspath(conf_dir) + conf_poscar = os.path.join(conf_path, 'POSCAR') + # get equi poscar + equi_path = re.sub('confs', global_equi_name, conf_path) + equi_path = os.path.join(equi_path, 'deepmd') + task_path = re.sub('confs', global_task_name, conf_path) + task_path = os.path.join(task_path, 'deepmd') + os.makedirs(task_path, exist_ok=True) + + task_poscar = os.path.join(task_path, 'POSCAR') + cwd = os.getcwd() + os.chdir(task_path) + if os.path.isfile('POSCAR') : + os.remove('POSCAR') + os.symlink(os.path.relpath(conf_poscar), 'POSCAR') + os.chdir(cwd) + with open(task_poscar,'r') as fp : + lines = fp.read().split('\n') + ele_list = lines[5].split() + + print(task_path) + # make conf.lmp + conf_file = os.path.join(task_path, 'conf.lmp') + lammps.cvt_lammps_conf(task_poscar, os.path.relpath(conf_file)) + ptypes = vasp.get_poscar_types(task_poscar) + lammps.apply_type_map(conf_file, deepmd_type_map, ptypes) + # make lammps.in + ntypes=len(ele_list) + unitcell=PhonopyAtoms(symbols=ele_list,cell=(np.eye(3)),scaled_positions=np.zeros((ntypes,3))) + fc = lammps.make_lammps_phonon('conf.lmp', + unitcell.masses, + lammps.inter_deepmd, + deepmd_models_name) + f_lammps_in = os.path.join(task_path, 'lammps.in') + with open(f_lammps_in, 'w') as fp : + fp.write(fc) + cwd = os.getcwd() + # link models + os.chdir(task_path) + for ii in deepmd_models_name : + if os.path.exists(ii) : + os.remove(ii) + for (ii,jj) in zip(deepmd_models, deepmd_models_name) : + os.symlink(os.path.relpath(ii), jj) + # gen band.conf + os.chdir(task_path) + with open('band.conf','w') as fp: + fp.write('ATOM_NAME = ') + for ii in ele_list: + fp.write(ii) + fp.write(' ') + fp.write('\n') + fp.write('DIM = %d %d %d\n'%(supercell_matrix[0],supercell_matrix[1],supercell_matrix[2])) + fp.write('BAND = %s\n'%band_path) + fp.write('FORCE_CONSTANTS=READ') + # gen task + ''' + phlammps = Phonolammps('lammps.in',supercell_matrix=supercell_matrix) + unitcell = phlammps.get_unitcell() + phonon = Phonopy(unitcell,supercell_matrix) + phonon.save(filename='phonopy_disp.yaml') + with open('phonopy_disp.yaml', 'r') as f: + temp = yaml.load(f.read()) + with open('POSCAR-unitcell', 'w') as fp: + for ii in ele_list: + fp.write(ii) + fp.write(' ') + fp.write('\n') + data=open('POSCAR', 'r') + next(data) + fp.write(data.readline()) + for ii in temp['unit_cell']['lattice']: + fp.write(str(ii).replace(',', '').replace('[', '').replace(']','\n')) + for ii in ele_list: + fp.write(str(str(temp['unit_cell']['points']).count(ii))) + fp.write(' ') + fp.write('\n') + fp.write('Direct\n') + for ii in temp['unit_cell']['points']: + fp.write(str(ii['coordinates']).replace(',', '').replace('[', '').replace(']', '\n')) + ''' + os.system('phonolammps lammps.in --dim %d %d %d -c POSCAR-unitcell'%(supercell_matrix[0],supercell_matrix[1],supercell_matrix[2])) + + +def _main() : + parser = argparse.ArgumentParser( + description="gen 06.phonon") + parser.add_argument('TASK', type=str, + help='the task of generation, vasp or lammps') + parser.add_argument('PARAM', type=str, + help='json parameter file') + parser.add_argument('CONF', type=str, + help='the path to conf') + args = parser.parse_args() + + with open (args.PARAM, 'r') as fp : + jdata = json.load (fp) + +# print('generate %s task with conf %s' % (args.TASK, args.CONF)) + if args.TASK == 'vasp': + make_vasp(jdata, args.CONF) + elif args.TASK == 'deepmd' : + make_deepmd_lammps(jdata, args.CONF) + elif args.TASK == 'meam' : + make_meam_lammps(jdata, args.CONF) + else : + raise RuntimeError("unknow task ", args.TASK) + +if __name__ == '__main__' : + _main() + diff --git a/auto_test/lib/BatchJob.py b/auto_test/lib/BatchJob.py new file mode 100644 index 000000000..6d68497df --- /dev/null +++ b/auto_test/lib/BatchJob.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 + +import os +import sys +from enum import Enum +from subprocess import Popen, PIPE + +class JobStatus (Enum) : + unsubmitted = 1 + waiting = 2 + running = 3 + terminated = 4 + finished = 5 + unknow = 100 + +class BatchJob (object): + """ + Abstract class of a batch job + It submit a job (leave the id in file tag_jobid) + It check the status of the job (return JobStatus) + NOTICE: I assume that when a job finishes, a tag file named tag_finished should be touched by the user. + TYPICAL USAGE: + job = DERIVED_BatchJob (dir, script) + job.submit () + stat = job.check_status () + """ + def __init__ (self, + job_dir = "", # dir of the job + job_script = "", # name of the job script + job_finish_tag = "tag_finished", # name of the tag for finished job + job_id_file = "tag_jobid") : # job id if making an existing job + self.job_dir = job_dir + self.job_script = job_script + self.job_id_file = job_dir + "/" + job_id_file + self.job_finish_tag = job_dir + "/" + job_finish_tag + self.cwd = os.getcwd() + self.submit_cmd = str(self.submit_command()) + def get_job_id (self) : + if True == os.path.exists (self.job_id_file) : + fp = open (self.job_id_file, 'r') + job_id = fp.read () + return str(job_id) + else : + return "" + def submit_command (self) : + """ + submission is + $ [command] [script] + """ + raise RuntimeError ("submit_command not implemented") + def check_status (self): + raise RuntimeError ("check_status not implemented") + def submit (self) : + if self.get_job_id () != "" : + stat = self.check_status() + if stat != JobStatus.terminated : + if stat == JobStatus.unknow : + raise RuntimeError ("unknown job status, terminate!") + print ("# job %s, dir %s already submitted (waiting, running or finished), would not submit again" % + (self.get_job_id(), self.job_dir)) + return self.get_job_id() + else : + print ("# find terminated job " + self.get_job_id() + ", submit again") + if (False == os.path.isdir (self.job_dir) ) : + raise RuntimeError ("cannot find job dir " + self.job_dir) + abs_job_script = self.job_dir + "/" + self.job_script + if False == os.path.exists (abs_job_script) : + raise RuntimeError ("cannot find job script " + abs_job_script) + cwd = os.getcwd() + os.chdir (self.job_dir) + ret = Popen([self.submit_cmd + " " + self.job_script], stdout=PIPE, stderr=PIPE, shell = True) + stdout, stderr = ret.communicate() + if str(stderr, encoding='ascii') != "": + raise RuntimeError (stderr) + job_id = str(stdout, encoding='ascii').replace('\n','').split()[-1] + print ("# job %s submitted, dir %s " % (job_id, self.job_dir)) + fp = open (self.job_id_file, 'w') + fp.write (job_id) + fp.close() + os.chdir (cwd) + return self.get_job_id() diff --git a/auto_test/lib/MachineLocal.py b/auto_test/lib/MachineLocal.py new file mode 100644 index 000000000..e39dd118d --- /dev/null +++ b/auto_test/lib/MachineLocal.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 + +import os +import logging +import shutil +import time +import subprocess as sp +import multiprocessing as mp + +# global vars +env_source_list = [] +b_vcores = False +encoding_sys = 'utf-8' + +def add_source_file (source_file) : + if os.path.isfile (source_file) : + sf = os.path.abspath (source_file) + global env_source_list + env_source_list += [sf] + else : + raise RuntimeError ("no file " + source_file) + +def has_virtual_cores (yes_or_no) : + global b_vcores + b_vcores = yes_or_no + +def get_node_list () : + hostname = sp.check_output ("hostname", shell = True).rstrip() + hostname = hostname.decode(encoding_sys) + return [hostname] + +def get_core_per_node () : + ncpu = os.cpu_count() + global b_vcores + if b_vcores : + ncpu = ncpu // 2 + return ncpu + +def cmd_source () : + global env_source_list + cmd = "" + for ii in env_source_list : + cmd += "source " + ii + ";" + return cmd + +def exec_cmd (node, + cmd, + cmd_dir_, + cmd_args) : + cmd_dir = os.path.abspath(cmd_dir_) + run_cmd = "" + run_cmd += cmd_source() + run_cmd += "cd " + cmd_dir + ";" + run_cmd += cmd + " " + cmd_args + return sp.Popen(run_cmd, shell = True) + +def exec_batch (cmd, + cmd_dir_, + task_batch, + args_batch, + work_thread) : + cmd_dir = os.path.abspath(cmd_dir_) + cwd = os.getcwd() + os.chdir(cmd_dir) + host_list = get_node_list() + nnode = len(host_list) + ps = [] + for jj in range(len(task_batch)) : + work_path = task_batch[jj] + work_args = args_batch[jj] + host = host_list[jj % nnode] + work_name = os.path.basename (work_path) + ps.append(exec_cmd(host, cmd, work_path, work_args)) + os.chdir(cwd) + return ps + +def _make_mpi_command (cmd, + np, + nthreads) : + ret = "OMP_NUM_THREADS=%d mpirun -n %d %s" \ + % (nthreads, np, cmd) + return ret + +def exec_mpi (cmd, + cmd_dir_, + task_batch, + args_batch, + work_np) : + cwd = os.getcwd() + cmd_dir = os.path.abspath(cmd_dir_) + os.chdir(cmd_dir) + ntasks = len(task_batch) + ret = [] + for ii in range(ntasks): + os.chdir(task_batch[ii]) + myenv = os.environ.copy() + myenv['OMP_NUM_THREADS'] = '1' + mpi_cmd = _make_mpi_command(cmd, work_np, 1) + sph = sp.Popen(mpi_cmd, shell = True, env = myenv) + time.sleep(0.1) + logging.info (mpi_cmd) + ret.append(sph) + os.chdir(cmd_dir) + os.chdir(cwd) + return ret + +# # nlist = get_node_list() +# # print (nlist) +# cpnode = get_core_per_node() +# print (cpnode) +# # add_source_file ('a') +# # add_source_file ('b') +# print (env_source_list) +# cmd = cmd_source () +# print (cmd) +# sp.check_call (cmd, shell = True) + +# p = exec_cmd("localhost", "ls", "~/study", "-lt") +# p.wait() diff --git a/auto_test/lib/MachineLocalGPU.py b/auto_test/lib/MachineLocalGPU.py new file mode 100644 index 000000000..8cb8cf483 --- /dev/null +++ b/auto_test/lib/MachineLocalGPU.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 + +import os +import logging +import shutil +import time +import subprocess as sp +import multiprocessing as mp + +# global vars +env_source_list = [] +b_vcores = False +encoding_sys = 'utf-8' + +def add_source_file (source_file) : + if os.path.isfile (source_file) : + sf = os.path.abspath (source_file) + global env_source_list + env_source_list += [sf] + else : + raise RuntimeError ("no file " + source_file) + +def has_virtual_cores (yes_or_no) : + global b_vcores + b_vcores = yes_or_no + +def get_node_list () : + hostname = sp.check_output ("hostname", shell = True).rstrip() + hostname = hostname.decode(encoding_sys) + return [hostname] + +def get_core_per_node () : + ncpu = os.cpu_count() + global b_vcores + if b_vcores : + ncpu = ncpu // 2 + return ncpu + +def cmd_source () : + global env_source_list + cmd = "" + for ii in env_source_list : + cmd += "source " + ii + ";" + return cmd + +def exec_cmd (node, + cmd, + cmd_dir_, + cmd_args) : + cmd_dir = os.path.abspath(cmd_dir_) + run_cmd = "" + run_cmd += cmd_source() + run_cmd += "cd " + cmd_dir + ";" + run_cmd += cmd + " " + cmd_args + return sp.Popen(run_cmd, shell = True) + +def exec_batch (cmd, + cmd_dir_, + task_batch, + args_batch, + work_thread) : + cmd_dir = os.path.abspath(cmd_dir_) + cwd = os.getcwd() + os.chdir(cmd_dir) + host_list = get_node_list() + nnode = len(host_list) + ps = [] + for jj in range(len(task_batch)) : + work_path = task_batch[jj] + work_args = args_batch[jj] + host = host_list[jj % nnode] + work_name = os.path.basename (work_path) + ps.append(exec_cmd(host, cmd, work_path, work_args)) + os.chdir(cwd) + return ps + +def _make_mpi_command (cmd, + np, + nthreads) : + ret = "OMP_NUM_THREADS=%d mpirun -n %d %s" \ + % (nthreads, np, cmd) + return ret + +def exec_mpi (cmd, + cmd_dir_, + task_batch, + args_batch, + work_np) : + cwd = os.getcwd() + cmd_dir = os.path.abspath(cmd_dir_) + os.chdir(cmd_dir) + ntasks = len(task_batch) + ret = [] + for ii in range(ntasks): + os.chdir(task_batch[ii]) + myenv = os.environ.copy() + myenv['OMP_NUM_THREADS'] = '1' + mpi_cmd = _make_mpi_command(cmd, work_np, 1) + sph = sp.Popen(mpi_cmd, shell = True, env = myenv) + logging.info (mpi_cmd) + ret.append(sph) + os.chdir(cmd_dir) + os.chdir(cwd) + return ret + +def _make_gpu_command (cmd, + idx) : + ret = "CUDA_VISIBLE_DEVICES=%d %s" \ + % (idx, cmd) + return ret + + +def exec_gpu (cmd, + cmd_dir_, + task_batch, + args_batch, + work_np) : + cwd = os.getcwd() + cmd_dir = os.path.abspath(cmd_dir_) + os.chdir(cmd_dir) + ntasks = len(task_batch) + ret = [] + for ii in range(ntasks): + os.chdir(task_batch[ii]) + gpu_cmd = _make_gpu_command(cmd, ii) + myenv = os.environ.copy() + sph = sp.Popen(gpu_cmd, shell = True, env = myenv) + logging.info (gpu_cmd) + ret.append(sph) + os.chdir(cmd_dir) + os.chdir(cwd) + return ret + +# # nlist = get_node_list() +# # print (nlist) +# cpnode = get_core_per_node() +# print (cpnode) +# # add_source_file ('a') +# # add_source_file ('b') +# print (env_source_list) +# cmd = cmd_source () +# print (cmd) +# sp.check_call (cmd, shell = True) + +# p = exec_cmd("localhost", "ls", "~/study", "-lt") +# p.wait() diff --git a/auto_test/lib/MachinePBS.py b/auto_test/lib/MachinePBS.py new file mode 100644 index 000000000..17013021b --- /dev/null +++ b/auto_test/lib/MachinePBS.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 + +import os +import logging +import shutil +import time +import subprocess as sp +import multiprocessing as mp + +# global vars +env_source_list = [] +b_vcores = False +encoding_sys = 'utf-8' + +def add_source_file (source_file) : + if os.path.isfile (source_file) : + sf = os.path.abspath (source_file) + global env_source_list + env_source_list += [sf] + else : + raise RuntimeError ("no file " + source_file) + +def has_virtual_cores (yes_or_no) : + global b_vcores + b_vcores = yes_or_no + +def get_node_list () : + node_file = os.getenv('PBS_NODEFILE') + with open(node_file, 'r') as fp: + nodes = fp.read().rstrip().split('\n') + a = list(set(nodes)) + a.sort() +# a = ['cu03', 'cu04'] + return a + +def get_core_per_node () : + ncpu = os.cpu_count() + global b_vcores + if b_vcores : + ncpu = ncpu // 2 + return ncpu + +def cmd_source () : + global env_source_list + cmd = "" + for ii in env_source_list : + cmd += "source " + ii + ";" + return cmd + +def exec_batch (cmd, + cmd_dir_, + task_batch, + args_batch, + work_threads) : + host_list = get_node_list() + nnode = len(host_list) + ntasks = len(task_batch) + + cwd = os.getcwd() + cmd_dir = os.path.abspath(cmd_dir_) + os.chdir(cmd_dir) + ret = [] + for ii in range(ntasks) : + os.chdir(task_batch[ii]) + exec_host = host_list[ii%nnode] + with open("nodes", "w") as fp: + fp.write(exec_host) + sph = sp.Popen("mpirun -n 1 -hostfile nodes %s" % cmd, shell = True) + ret.append(sph) + os.chdir(cmd_dir) + os.chdir(cwd) + return ret + +def _make_mpi_command (cmd, + np, + node_file, + nthreads) : + ret = "mpirun -n %d -genv OMP_NUM_THREADS %d -hostfile %s %s" \ + % (np, nthreads, node_file, cmd) + return ret + +def _make_mpi_command_nl (cmd, + np, + node_list, + nthreads) : + args = "" + for ii in range(len(node_list)) : + if ii == 0 : + args += node_list[ii] + else: + args += "," + node_list[ii] + ret = "mpirun -n %d -genv OMP_NUM_THREADS %d -hosts %s %s" \ + % (np, nthreads, args, cmd) + return ret + +def exec_mpi (cmd, + cmd_dir_, + task_batch, + args_batch, + work_np) : + cwd = os.getcwd() + cmd_dir = os.path.abspath(cmd_dir_) + os.chdir(cmd_dir) + ntasks = len(task_batch) + node_file = os.getenv('PBS_NODEFILE') + with open(node_file, "r") as fp: + nodes = fp.read().rstrip().split('\n') + numb_nodes = len(nodes) + assert(numb_nodes >= ntasks * work_np) + ret = [] + for ii in range(ntasks): + os.chdir(task_batch[ii]) + mynodefile = "x%06d" % ii + mynodes = [] + with open(mynodefile, "w") as fp: + for jj in range(work_np*ii, work_np*(ii+1)) : + fp.write("%s\n"%nodes[jj]) + mynodes.append(nodes[jj]) + myenv = os.environ.copy() + myenv['OMP_NUM_THREADS'] = '1' + mpi_cmd = _make_mpi_command(cmd, work_np, mynodefile, 1) +# mpi_cmd = _make_mpi_command_nl(cmd, work_np, mynodes, 1) + sph = sp.Popen(mpi_cmd, shell = True, env = myenv) + time.sleep(0.5) + logging.info (mpi_cmd) + ret.append(sph) + os.chdir(cmd_dir) + # nodefiles = glob.glob("x*") + # for ii in nodefiles: + # if os.path.isfile(ii): + # os.remove(ii) + os.chdir(cwd) + return ret + +# print(get_node_list() ) +# print(get_core_per_node() ) +# exec_batch("pwd", "/home/wang_han/study/deepgen.test/", ['iter.000000/00.train/000', 'iter.000000/00.train/001', 'iter.000000/00.train/002', 'iter.000000/00.train/003'], ["", "", "", ""], 7) diff --git a/auto_test/lib/MachineSlurm.py b/auto_test/lib/MachineSlurm.py new file mode 100644 index 000000000..f1c4cedf0 --- /dev/null +++ b/auto_test/lib/MachineSlurm.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import os +import subprocess as sp +import multiprocessing as mp + +# global vars +env_source_list = [] +b_vcores = True +encoding_sys = 'utf-8' + +def add_source_file (source_file) : + if os.path.isfile (source_file) : + sf = os.path.abspath (source_file) + global env_source_list + env_source_list += [sf] + else : + raise RuntimeError ("no file " + source_file) + +def has_virtual_cores (yes_or_no) : + global b_vcores + b_vcores = yes_or_no + +def get_node_list () : + node_dict = os.getenv('SLURM_JOB_NODELIST') + ret = sp.check_output ("scontrol show hostnames " + node_dict, shell = True).rstrip() + ret = ret.decode(encoding_sys) + return ret.split('\n') + +def get_core_per_node () : + ncpu = os.cpu_count() + global b_vcores + if b_vcores : + ncpu = ncpu // 2 + return ncpu + +def cmd_source () : + global env_source_list + cmd = "" + for ii in env_source_list : + cmd += "source " + ii + ";" + return cmd + +def exec_cmd (node, + cmd, + cmd_dir_, + cmd_args) : + cmd_dir = os.path.abspath(cmd_dir_) + run_cmd = "" + run_cmd += cmd_source() + run_cmd += "cd " + cmd_dir + ";" + run_cmd += cmd + " " + cmd_args + ssh_run = 'ssh %s "%s" 2>/dev/null' % (node, run_cmd) + return sp.Popen(ssh_run, shell = True) + +def exec_batch (cmd, + cmd_dir_, + task_batch, + args_batch, + work_thread) : + cmd_dir = os.path.abspath(cmd_dir_) + cwd = os.getcwd() + os.chdir(cmd_dir) + host_list = get_node_list() + nnode = len(host_list) + ntpnode = get_core_per_node() + nsource = ntpnode * nnode + numb_jobs = (nsource // work_thread) + fp = open ("mpmd.conf", "w") + # print ("in exec batch") + # print (len(task_batch)) + # print (work_thread) + # print (nsource) + iend = numb_jobs + if len(task_batch) < numb_jobs : + iend = len(task_batch) + for ii in range(iend) : + thread_s = ii + thread_e = (ii+1) - 1 + fp.write ("%d-%d %s/run.mpmd.sh %s %s\n" % (thread_s, thread_e, cmd_dir, task_batch[ii], args_batch[ii])) + fp.close() + fp = open ("run.mpmd.sh", "w") + fp.write ("#!/bin/bash\n") + fp.write (cmd_source()) + fp.write ("\n") + fp.write ("cd $1\n") + fp.write ("shift 1\n") + fp.write ("%s $*\n" % cmd) + fp.close() + os.chmod("run.mpmd.sh", 0o755) + # print ("srun --tasks-per-node=%d --multi-prog ./mpmd.conf"% (ntpnode//work_thread)) + sph = sp.Popen ("srun --tasks-per-node=%d --multi-prog ./mpmd.conf" % (ntpnode//work_thread), + shell = True) + os.chdir(cwd) + return [sph] + + +# # nlist = get_node_list() +# # print (nlist) +# cpnode = get_core_per_node() +# print (cpnode) +# # add_source_file ('a') +# # add_source_file ('b') +# print (env_source_list) +# cmd = cmd_source () +# print (cmd) +# sp.check_call (cmd, shell = True) + +# p = exec_cmd("localhost", "ls", "~/study", "-lt") +# p.wait() diff --git a/auto_test/lib/RemoteJob.py b/auto_test/lib/RemoteJob.py new file mode 100644 index 000000000..df7b485e9 --- /dev/null +++ b/auto_test/lib/RemoteJob.py @@ -0,0 +1,547 @@ +#!/usr/bin/env python3 + +import os, sys, paramiko, json, uuid, tarfile, time, stat +from enum import Enum + +class JobStatus (Enum) : + unsubmitted = 1 + waiting = 2 + running = 3 + terminated = 4 + finished = 5 + unknow = 100 + +def _default_item(resources, key, value) : + if key not in resources : + resources[key] = value + +def _set_default_resource(res) : + if res == None : + res = {} + _default_item(res, 'numb_node', 1) + _default_item(res, 'task_per_node', 1) + _default_item(res, 'numb_gpu', 0) + _default_item(res, 'time_limit', '1:0:0') + _default_item(res, 'mem_limit', -1) + _default_item(res, 'partition', '') + _default_item(res, 'account', '') + _default_item(res, 'qos', '') + _default_item(res, 'constraint_list', []) + _default_item(res, 'license_list', []) + _default_item(res, 'exclude_list', []) + _default_item(res, 'module_unload_list', []) + _default_item(res, 'module_list', []) + _default_item(res, 'source_list', []) + _default_item(res, 'envs', None) + _default_item(res, 'with_mpi', False) + + +class SSHSession (object) : + def __init__ (self, jdata) : + self.remote_profile = jdata + # with open(remote_profile) as fp : + # self.remote_profile = json.load(fp) + self.remote_host = self.remote_profile['hostname'] + self.remote_port = self.remote_profile['port'] + self.remote_uname = self.remote_profile['username'] + self.remote_password = self.remote_profile['password'] + self.remote_workpath = self.remote_profile['work_path'] + self.ssh = self._setup_ssh(self.remote_host, self.remote_port, username = self.remote_uname,password=self.remote_password) + + def _setup_ssh(self, + hostname, + port, + username = None, + password = None): + ssh_client = paramiko.SSHClient() + ssh_client.load_system_host_keys() + ssh_client.set_missing_host_key_policy(paramiko.WarningPolicy) + ssh_client.connect(hostname, port=port, username=username, password=password) + assert(ssh_client.get_transport().is_active()) + return ssh_client + + def get_ssh_client(self) : + return self.ssh + + def get_session_root(self) : + return self.remote_workpath + + def close(self) : + self.ssh.close() + + +class RemoteJob (object): + def __init__ (self, + ssh_session, + local_root + ) : + + self.local_root = os.path.abspath(local_root) + self.job_uuid = str(uuid.uuid4()) + # self.job_uuid = 'a21d0017-c9f1-4d29-9a03-97df06965cef' + self.remote_root = os.path.join(ssh_session.get_session_root(), self.job_uuid) + print("local_root is ", local_root) + print("remote_root is", self.remote_root) + self.ssh = ssh_session.get_ssh_client() + sftp = self.ssh.open_sftp() + sftp.mkdir(self.remote_root) + sftp.close() + # open('job_uuid', 'w').write(self.job_uuid) + + def get_job_root(self) : + return self.remote_root + + def upload(self, + job_dirs, + local_up_files, + dereference = True) : + cwd = os.getcwd() + os.chdir(self.local_root) + file_list = [] + for ii in job_dirs : + for jj in local_up_files : + file_list.append(os.path.join(ii,jj)) + self._put_files(file_list, dereference = dereference) + os.chdir(cwd) + + def download(self, + job_dirs, + remote_down_files) : + cwd = os.getcwd() + os.chdir(self.local_root) + file_list = [] + for ii in job_dirs : + for jj in remote_down_files : + file_list.append(os.path.join(ii,jj)) + self._get_files(file_list) + os.chdir(cwd) + + def block_checkcall(self, + cmd) : + stdin, stdout, stderr = self.ssh.exec_command(('cd %s ;' % self.remote_root) + cmd) + exit_status = stdout.channel.recv_exit_status() + if exit_status != 0: + raise RuntimeError("Get error code %d in calling through ssh with job: %s ", (exit_status, self.job_uuid)) + return stdin, stdout, stderr + + def block_call(self, + cmd) : + stdin, stdout, stderr = self.ssh.exec_command(('cd %s ;' % self.remote_root) + cmd) + exit_status = stdout.channel.recv_exit_status() + return exit_status, stdin, stdout, stderr + + def clean(self) : + sftp = self.ssh.open_sftp() + self._rmtree(sftp, self.remote_root) + sftp.close() + + def _rmtree(self, sftp, remotepath, level=0, verbose = False): + for f in sftp.listdir_attr(remotepath): + rpath = os.path.join(remotepath, f.filename) + if stat.S_ISDIR(f.st_mode): + self._rmtree(sftp, rpath, level=(level + 1)) + else: + rpath = os.path.join(remotepath, f.filename) + if verbose: print('removing %s%s' % (' ' * level, rpath)) + sftp.remove(rpath) + if verbose: print('removing %s%s' % (' ' * level, remotepath)) + sftp.rmdir(remotepath) + + def _put_files(self, + files, + dereference = True) : + of = self.job_uuid + '.tgz' + # local tar + cwd = os.getcwd() + os.chdir(self.local_root) + if os.path.isfile(of) : + os.remove(of) + with tarfile.open(of, "w:gz", dereference = dereference) as tar: + for ii in files : + tar.add(ii) + os.chdir(cwd) + # trans + from_f = os.path.join(self.local_root, of) + to_f = os.path.join(self.remote_root, of) + sftp = self.ssh.open_sftp() + sftp.put(from_f, to_f) + # remote extract + self.block_checkcall('tar xf %s' % of) + # clean up + os.remove(from_f) + sftp.remove(to_f) + sftp.close() + + def _get_files(self, + files) : + of = self.job_uuid + '.tgz' + flist = "" + for ii in files : + flist += " " + ii + # remote tar + os.chdir(self.remote_root) + self.block_checkcall('tar czf %s %s' % (of, flist)) + # trans + from_f = os.path.join(self.remote_root, of) + to_f = os.path.join(self.local_root, of) + if os.path.isfile(to_f) : + os.remove(to_f) + sftp = self.ssh.open_sftp() + sftp.get(from_f, to_f) + # extract + cwd = os.getcwd() + os.chdir(self.local_root) + with tarfile.open(of, "r:gz") as tar: + tar.extractall() + os.chdir(cwd) + # cleanup + os.remove(to_f) + sftp.remove(from_f) + +class CloudMachineJob (RemoteJob) : + def submit(self, + job_dirs, + cmd, + args = None, + resources = None) : + + #print("Current path is",os.getcwd()) + + #for ii in job_dirs : + # if not os.path.isdir(ii) : + # raise RuntimeError("cannot find dir %s" % ii) + # print(self.remote_root) + script_name = self._make_script(job_dirs, cmd, args, resources) + self.stdin, self.stdout, self.stderr = self.ssh.exec_command(('cd %s; bash %s' % (self.remote_root, script_name))) + # print(self.stderr.read().decode('utf-8')) + # print(self.stdout.read().decode('utf-8')) + + def check_status(self) : + if not self._check_finish(self.stdout) : + return JobStatus.running + elif self._get_exit_status(self.stdout) == 0 : + return JobStatus.finished + else : + return JobStatus.terminated + + def _check_finish(self, stdout) : + return stdout.channel.exit_status_ready() + + def _get_exit_status(self, stdout) : + return stdout.channel.recv_exit_status() + + def _make_script(self, + job_dirs, + cmd, + args = None, + resources = None) : + _set_default_resource(resources) + envs = resources['envs'] + module_list = resources['module_list'] + module_unload_list = resources['module_unload_list'] + task_per_node = resources['task_per_node'] + + script_name = 'run.sh' + if args == None : + args = [] + for ii in job_dirs: + args.append('') + script = os.path.join(self.remote_root, script_name) + sftp = self.ssh.open_sftp() + with sftp.open(script, 'w') as fp : + fp.write('#!/bin/bash\n\n') + # fp.write('set -euo pipefail\n') + if envs != None : + for key in envs.keys() : + fp.write('export %s=%s\n' % (key, envs[key])) + fp.write('\n') + if module_unload_list is not None : + for ii in module_unload_list : + fp.write('module unload %s\n' % ii) + fp.write('\n') + if module_list is not None : + for ii in module_list : + fp.write('module load %s\n' % ii) + fp.write('\n') + for ii,jj in zip(job_dirs, args) : + fp.write('cd %s\n' % ii) + fp.write('test $? -ne 0 && exit\n') + if resources['with_mpi'] == True : + fp.write('mpirun -n %d %s %s\n' + % (task_per_node, cmd, jj)) + else : + fp.write('%s %s\n' % (cmd, jj)) + fp.write('test $? -ne 0 && exit\n') + fp.write('cd %s\n' % self.remote_root) + fp.write('test $? -ne 0 && exit\n') + fp.write('\ntouch tag_finished\n') + sftp.close() + return script_name + + +class SlurmJob (RemoteJob) : + def submit(self, + job_dirs, + cmd, + args = None, + resources = None) : + script_name = self._make_script(job_dirs, cmd, args, res = resources) + stdin, stdout, stderr = self.block_checkcall(('cd %s; sbatch %s' % (self.remote_root, script_name))) + subret = (stdout.readlines()) + job_id = subret[0].split()[-1] + sftp = self.ssh.open_sftp() + with sftp.open(os.path.join(self.remote_root, 'job_id'), 'w') as fp: + fp.write(job_id) + sftp.close() + + def check_status(self) : + job_id = self._get_job_id() + if job_id == "" : + raise RuntimeError("job %s is has not been submitted" % self.remote_root) + ret, stdin, stdout, stderr\ + = self.block_call ("squeue --job " + job_id) + err_str = stderr.read().decode('utf-8') + if (ret != 0) : + if str("Invalid job id specified") in err_str : + if self._check_finish_tag() : + return JobStatus.finished + else : + return JobStatus.terminated + else : + raise RuntimeError\ + ("status command squeue fails to execute\nerror message:%s\nreturn code %d\n" % (err_str, ret)) + status_line = stdout.read().decode('utf-8').split ('\n')[-2] + status_word = status_line.split ()[-4] + if status_word in ["PD","CF","S"] : + return JobStatus.waiting + elif status_word in ["R","CG"] : + return JobStatus.running + elif status_word in ["C","E","K","BF","CA","CD","F","NF","PR","SE","ST","TO"] : + if self._check_finish_tag() : + return JobStatus.finished + else : + return JobStatus.terminated + else : + return JobStatus.unknown + + def _get_job_id(self) : + sftp = self.ssh.open_sftp() + with sftp.open(os.path.join(self.remote_root, 'job_id'), 'r') as fp: + ret = fp.read().decode('utf-8') + sftp.close() + return ret + + def _check_finish_tag(self) : + sftp = self.ssh.open_sftp() + try: + sftp.stat(os.path.join(self.remote_root, 'tag_finished')) + ret = True + except IOError: + ret = False + sftp.close() + return ret + + def _make_script(self, + job_dirs, + cmd, + args = None, + res = None) : + _set_default_resource(res) + ret = '' + ret += "#!/bin/bash -l\n" + ret += "#SBATCH -N %d\n" % res['numb_node'] + ret += "#SBATCH --ntasks-per-node %d\n" % res['task_per_node'] + ret += "#SBATCH -t %s\n" % res['time_limit'] + if res['mem_limit'] > 0 : + ret += "#SBATCH --mem %dG \n" % res['mem_limit'] + if len(res['account']) > 0 : + ret += "#SBATCH --account %s \n" % res['account'] + if len(res['partition']) > 0 : + ret += "#SBATCH --partition %s \n" % res['partition'] + if len(res['qos']) > 0 : + ret += "#SBATCH --qos %s \n" % res['qos'] + if res['numb_gpu'] > 0 : + ret += "#SBATCH --gres=gpu:%d\n" % res['numb_gpu'] + for ii in res['constraint_list'] : + ret += '#SBATCH -C %s \n' % ii + for ii in res['license_list'] : + ret += '#SBATCH -L %s \n' % ii + for ii in res['exclude_list'] : + ret += '#SBATCH --exclude %s \n' % ii + ret += "\n" + # ret += 'set -euo pipefail\n\n' + for ii in res['module_unload_list'] : + ret += "module unload %s\n" % ii + for ii in res['module_list'] : + ret += "module load %s\n" % ii + ret += "\n" + for ii in res['source_list'] : + ret += "source %s\n" %ii + ret += "\n" + envs = res['envs'] + if envs != None : + for key in envs.keys() : + ret += 'export %s=%s\n' % (key, envs[key]) + ret += '\n' + + if args == None : + args = [] + for ii in job_dirs: + args.append('') + for ii,jj in zip(job_dirs, args) : + ret += 'cd %s\n' % ii + ret += 'test $? -ne 0 && exit\n' + if res['with_mpi'] : + ret += 'mpirun -n %d %s %s\n' % (res['task_per_node'],cmd, jj) + else : + ret += '%s %s\n' % (cmd, jj) + ret += 'test $? -ne 0 && exit\n' + ret += 'cd %s\n' % self.remote_root + ret += 'test $? -ne 0 && exit\n' + ret += '\ntouch tag_finished\n' + + script_name = 'run.sub' + script = os.path.join(self.remote_root, script_name) + sftp = self.ssh.open_sftp() + with sftp.open(script, 'w') as fp : + fp.write(ret) + sftp.close() + + return script_name + + +class PBSJob (RemoteJob) : + def submit(self, + job_dirs, + cmd, + args = None, + resources = None) : + script_name = self._make_script(job_dirs, cmd, args, res = resources) + stdin, stdout, stderr = self.block_checkcall(('cd %s; qsub %s' % (self.remote_root, script_name))) + subret = (stdout.readlines()) + job_id = subret[0].split()[0] + sftp = self.ssh.open_sftp() + with sftp.open(os.path.join(self.remote_root, 'job_id'), 'w') as fp: + fp.write(job_id) + sftp.close() + + def check_status(self) : + job_id = self._get_job_id() + if job_id == "" : + raise RuntimeError("job %s is has not been submitted" % self.remote_root) + ret, stdin, stdout, stderr\ + = self.block_call ("qstat " + job_id) + err_str = stderr.read().decode('utf-8') + if (ret != 0) : + if str("qstat: Unknown Job Id") in err_str : + if self._check_finish_tag() : + return JobStatus.finished + else : + return JobStatus.terminated + else : + raise RuntimeError ("status command qstat fails to execute. erro info: %s return code %d" + % (err_str, ret)) + status_line = stdout.read().decode('utf-8').split ('\n')[-2] + status_word = status_line.split ()[-2] +# print (status_word) + if status_word in ["Q","H"] : + return JobStatus.waiting + elif status_word in ["R"] : + return JobStatus.running + elif status_word in ["C","E","K"] : + if self._check_finish_tag() : + return JobStatus.finished + else : + return JobStatus.terminated + else : + return JobStatus.unknown + + def _get_job_id(self) : + sftp = self.ssh.open_sftp() + with sftp.open(os.path.join(self.remote_root, 'job_id'), 'r') as fp: + ret = fp.read().decode('utf-8') + sftp.close() + return ret + + def _check_finish_tag(self) : + sftp = self.ssh.open_sftp() + try: + sftp.stat(os.path.join(self.remote_root, 'tag_finished')) + ret = True + except IOError: + ret = False + sftp.close() + return ret + + def _make_script(self, + job_dirs, + cmd, + args = None, + res = None) : + _set_default_resource(res) + ret = '' + ret += "#!/bin/bash -l\n" + if res['numb_gpu'] == 0: + ret += '#PBS -l nodes=%d:ppn=%d\n' % (res['numb_node'], res['task_per_node']) + else : + ret += '#PBS -l nodes=%d:ppn=%d:gpus=%d\n' % (res['numb_node'], res['task_per_node'], res['numb_gpu']) + ret += '#PBS -l walltime=%s\n' % (res['time_limit']) + if res['mem_limit'] > 0 : + ret += "#PBS -l mem=%dG \n" % res['mem_limit'] + ret += '#PBS -j oe\n' + if len(res['partition']) > 0 : + ret += '#PBS -q %s\n' % res['partition'] + ret += "\n" + for ii in res['module_unload_list'] : + ret += "module unload %s\n" % ii + for ii in res['module_list'] : + ret += "module load %s\n" % ii + ret += "\n" + for ii in res['source_list'] : + ret += "source %s\n" %ii + ret += "\n" + envs = res['envs'] + if envs != None : + for key in envs.keys() : + ret += 'export %s=%s\n' % (key, envs[key]) + ret += '\n' + ret += 'cd $PBS_O_WORKDIR\n\n' + + if args == None : + args = [] + for ii in job_dirs: + args.append('') + for ii,jj in zip(job_dirs, args) : + ret += 'cd %s\n' % ii + ret += 'test $? -ne 0 && exit\n' + if res['with_mpi'] : + ret += 'mpirun -machinefile $PBS_NODEFILE -n %d %s %s\n' % (res['numb_node'] * res['task_per_node'], cmd, jj) + else : + ret += '%s %s\n' % (cmd, jj) + ret += 'test $? -ne 0 && exit\n' + ret += 'cd %s\n' % self.remote_root + ret += 'test $? -ne 0 && exit\n' + ret += '\ntouch tag_finished\n' + + script_name = 'run.sub' + script = os.path.join(self.remote_root, script_name) + sftp = self.ssh.open_sftp() + with sftp.open(script, 'w') as fp : + fp.write(ret) + sftp.close() + + return script_name + + +# ssh_session = SSHSession('localhost.json') +# rjob = CloudMachineJob(ssh_session, '.') +# # can upload dirs and normal files +# rjob.upload(['job0', 'job1'], ['batch_exec.py', 'test']) +# rjob.submit(['job0', 'job1'], 'touch a; sleep 2') +# while rjob.check_status() == JobStatus.running : +# print('checked') +# time.sleep(2) +# print(rjob.check_status()) +# # can download dirs and normal files +# rjob.download(['job0', 'job1'], ['a']) +# # rjob.clean() diff --git a/auto_test/lib/SlurmJob.py b/auto_test/lib/SlurmJob.py new file mode 100644 index 000000000..e997917de --- /dev/null +++ b/auto_test/lib/SlurmJob.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +import os +import sys +from enum import Enum +from subprocess import Popen, PIPE +from lib.BatchJob import BatchJob +from lib.BatchJob import JobStatus + +class SlurmJob (BatchJob) : + def submit_command (self): + return "sbatch" + def check_status (self): + job_id = self.get_job_id () + if len(job_id) == 0 : + return JobStatus.unsubmitted + ret = Popen (["squeue --job " + job_id], shell=True, stdout=PIPE, stderr=PIPE) + stdout, stderr = ret.communicate() + if (ret.returncode != 0) : + if str("Invalid job id specified") in str(stderr, encoding='ascii') : + if os.path.exists (self.job_finish_tag) : + return JobStatus.finished + else : + return JobStatus.terminated + else : + Logger.error ("status command " + "squeue" + " fails to execute") + Logger.error ("erro info: " + str(stderr, encoding='ascii')) + Logger.error ("return code: " + str(ret.returncode)) + sys.exit () + status_line = str(stdout, encoding='ascii').split ('\n')[-2] + status_word = status_line.split ()[4] +# status_word = status_line.split ()[-4] +# print ("status line: " + status_line) +# print ("status word: " + status_word) +# print (status_word) + if status_word in ["PD","CF","S"] : + return JobStatus.waiting + elif status_word in ["R","CG"] : + return JobStatus.running + elif status_word in ["C","E","K","BF","CA","CD","F","NF","PR","SE","ST","TO"] : + if os.path.exists (self.job_finish_tag) : + return JobStatus.finished + else : + return JobStatus.terminated + else : + return JobStatus.unknown + +if __name__ == "__main__" : + job = SlurmJob ("/home/han.wang/data/test/string/test", "cu01.sleep") + job.submit () + print ("submit done") + stat = job.check_status () + print ("check done") + print (stat) + diff --git a/auto_test/lib/batch_exec.py b/auto_test/lib/batch_exec.py new file mode 100644 index 000000000..ca2b3ee23 --- /dev/null +++ b/auto_test/lib/batch_exec.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python3 + +import os, time +from subprocess import Popen, PIPE +import subprocess as sp + +from lib.BatchJob import JobStatus +from lib.BatchJob import BatchJob +from lib.SlurmJob import SlurmJob + +def make_slurm_script (cmd, + numb_node = 1, + work_thread = 1, + numb_gpu = 0, + task_args = None, + time_limit = "0:30:0", + mem_limit = 32, + modules = None, + sources = None, + fin_tag = 'tag_finished') : + ret = "" + ret += "#!/bin/bash -l\n" + ret += "#SBATCH -N %d\n" % numb_node + ret += "#SBATCH --exclude tiger-i23g1\n" + ret += "#SBATCH -t %s\n" % time_limit + ret += "#SBATCH --mem %dG \n" % mem_limit + ret += "#SBATCH --ntasks-per-node %d\n" % work_thread + if numb_gpu > 0 : + ret += "#SBATCH --gres=gpu:%d\n" % numb_gpu + ret += "\n" + for ii in modules : + ret += "module load %s\n" % ii + ret += "\n" + for ii in sources : + ret += "source %s\n" %ii + ret += "\n" + if task_args is not None : + ret += cmd + task_args + "\n" + else : + ret += cmd + "\n" + ret += "if test $? -eq 0; then\n" + ret += " touch %s\n" % fin_tag + ret += "fi\n" + ret += "sleep 1\n" + return ret + +def make_slurm_script_group (cmd, + task_dir, + numb_node = 1, + work_thread = 1, + numb_gpu = 0, + task_args = None, + time_limit = "0:30:0", + mem_limit = 32, + modules = None, + sources = None, + fin_tag = 'tag_finished') : + if task_args is not None : + assert(len(task_dir) == len(task_args)) + + ret = "" + ret += "#!/bin/bash -l\n" + ret += "#SBATCH -N %d\n" % numb_node + ret += "#SBATCH -t %s\n" % time_limit + ret += "#SBATCH --mem %dG \n" % mem_limit + ret += "#SBATCH --ntasks-per-node %d\n" % work_thread + if numb_gpu > 0 : + ret += "#SBATCH --gres=gpu:%d\n" % numb_gpu + ret += "\n" +# ret += "set -euo pipefail\n" + for ii in modules : + ret += "module load %s\n" % ii + ret += "\n" + for ii in sources : + ret += "source %s\n" %ii + ret += "\n" + ret += "cwd=`pwd`" + ret += "\n" + for ii in range(len(task_dir)) : + ret += "cd " + str(task_dir[ii]) + "\n" + if task_args is not None : + ret += cmd + task_args[ii] + "\n" + else : + ret += cmd + "\n" + ret += "if test $? -ne 0; then exit ; fi\n" + ret += "cd $cwd\n" + ret += "\n" + ret += "if test $? -eq 0; then\n" + ret += " touch %s\n" % fin_tag + ret += "fi\n" + ret += "sleep 1\n" + return ret + +def exec_batch (cmd, + numb_node, + work_thread, + numb_gpu, + task_dirs, + task_args = None, + time_limit = "24:0:0", + mem_limit = 32, + modules = None, + sources = None) : + cwd = os.getcwd() + job_list = [] + fin_tag = 'tag_finished' + for ii,mydir in enumerate(task_dirs) : + os.chdir(mydir) + myarg = None + if task_args is not None : + myarg = task_args[ii] + with open('_sub', 'w') as fp : + fp.write(make_slurm_script(cmd, + numb_node, work_thread, numb_gpu, + myarg, + time_limit, + mem_limit, + modules, + sources, + fin_tag)) + job = SlurmJob(os.getcwd(), '_sub', job_finish_tag = fin_tag) + job_list.append (job) + os.chdir(cwd) + + for ii in job_list: + ii.submit() +# time.sleep(1) + + while True : + find_unfinish = False + for job in job_list : + stat = job.check_status () + if stat == JobStatus.terminated : + raise RuntimeError("find terminated job") + old_job_id = job.get_job_id() + new_job_id = job.submit () + find_unfinish = True + if stat != JobStatus.finished : + find_unfinish = True + if find_unfinish == False : + return + else : + time.sleep (10) + +def exec_batch_group (cmd, + numb_node, + work_thread, + numb_gpu, + task_dirs_, + group_size = 10, + task_args = None, + time_limit = "24:0:0", + mem_limit = 32, + modules = None, + sources = None) : + cwd = os.getcwd() + job_list = [] + fin_tag = 'tag_finished' + + os.chdir(task_dirs_[0]) + os.chdir('..') + working_dir = os.getcwd() + os.chdir(cwd) + + task_dirs = [] + for ii in task_dirs_ : + task_dirs.append(os.path.abspath(ii)) + if task_args is not None : + assert(len(task_dirs) == len(task_args)) + if task_args is None : + task_args = [] + for ii in task_dirs : + task_args.append("") + + ntasks = len(task_dirs) + task_chunks = [task_dirs[i:i + group_size] for i in range(0, ntasks, group_size)] + args_chunks = [task_args[i:i + group_size] for i in range(0, ntasks, group_size)] + + os.chdir(working_dir) + for ii in range(len(task_chunks)): + group_dir = "group.%06d" % ii + if not os.path.isdir(group_dir) : + os.mkdir(group_dir) + os.chdir(group_dir) + with open('_sub', 'w') as fp: + fp.write(make_slurm_script_group(cmd, + task_chunks[ii], + numb_node, work_thread, numb_gpu, + args_chunks[ii], + time_limit, + mem_limit, + modules, + sources, + fin_tag)) + job = SlurmJob(os.getcwd(), '_sub', job_finish_tag = fin_tag) + job_list.append (job) + os.chdir(working_dir) + os.chdir(cwd) + + # for ii,mydir in enumerate(task_dirs) : + # os.chdir(mydir) + # myarg = None + # if task_args is not None : + # myarg = task_args[ii] + # with open('_sub', 'w') as fp : + # fp.write(make_slurm_script(cmd, work_thread, numb_gpu, myarg, time_limit, mem_limit, modules, sources, fin_tag)) + # job = SlurmJob(os.getcwd(), '_sub', job_finish_tag = fin_tag) + # job_list.append (job) + # os.chdir(cwd) + + for ii in job_list: + ii.submit() +# time.sleep(1) + + while True : + find_unfinish = False + for job in job_list : + stat = job.check_status () + if stat == JobStatus.terminated : + raise RuntimeError("find terminated job") + old_job_id = job.get_job_id() + new_job_id = job.submit () + find_unfinish = True + if stat != JobStatus.finished : + find_unfinish = True + if find_unfinish == False : + return + else : + time.sleep (10) + diff --git a/auto_test/lib/lammps.py b/auto_test/lib/lammps.py index 691bb8c0a..2ef9e5e47 100644 --- a/auto_test/lib/lammps.py +++ b/auto_test/lib/lammps.py @@ -294,6 +294,27 @@ def make_lammps_press_relax(conf, ntypes, scale2equi, interaction, param, ret += "print \"Final Stress (xx yy zz xy xz yz) = ${Pxx} ${Pyy} ${Pzz} ${Pxy} ${Pxz} ${Pyz}\"\n" return ret +def make_lammps_phonon(conf, masses, interaction, param, + etol=1e-12, ftol=1e-6, + maxiter=5000, maxeval=500000): + """ + make lammps input for elastic calculation + """ + ret = "" + ret += "clear\n" + ret += "units metal\n" + ret += "dimension 3\n" + ret += "boundary p p p\n" + ret += "atom_style atomic\n" + ret += "box tilt large\n" + ret += "read_data %s\n" % conf + ntypes=len(masses) + for ii in range(ntypes) : + ret += "mass %d %f\n" % (ii+1,masses[ii]) + ret += "neigh_modify every 1 delay 0 check no\n" + ret += interaction(param) + return ret + def _get_epa (lines) : for ii in lines: if ("Final energy per atoms" in ii) and (not 'print' in ii): diff --git a/auto_test/lib/lmp.py b/auto_test/lib/lmp.py new file mode 100644 index 000000000..22fd74cfb --- /dev/null +++ b/auto_test/lib/lmp.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 + +import numpy as np + +def _get_block (lines, keys) : + for idx in range(len(lines)) : + if keys in lines[idx] : + break + if idx == len(lines) - 1: + return None + idx_s = idx+2 + idx = idx_s + ret = [] + while True : + if len(lines[idx].split()) == 0 : + break + else : + ret.append(lines[idx]) + idx += 1 + return ret + +def lmpbox2box(lohi, tilt) : + xy = tilt[0] + xz = tilt[1] + yz = tilt[2] + orig = np.array([lohi[0][0], lohi[1][0], lohi[2][0]]) + lens = [] + for dd in range(3) : + lens.append(lohi[dd][1] - lohi[dd][0]) + xx = [lens[0], 0, 0] + yy = [xy, lens[1], 0] + zz= [xz, yz, lens[2]] + return orig, np.array([xx, yy, zz]) + +def box2lmpbox(orig, box) : + lohi = np.zeros([3,2]) + for dd in range(3) : + lohi[dd][0] = orig[dd] + tilt = np.zeros(3) + tilt[0] = box[1][0] + tilt[1] = box[2][0] + tilt[2] = box[2][1] + lens = np.zeros(3) + lens[0] = box[0][0] + lens[1] = box[1][1] + lens[2] = box[2][2] + for dd in range(3) : + lohi[dd][1] = lohi[dd][0] + lens[dd] + return lohi, tilt + +def get_atoms(lines) : + return _get_block(lines, 'Atoms') + +def get_natoms(lines) : + for ii in lines : + if 'atoms' in ii : + return int(ii.split()[0]) + return None + +def get_natomtypes(lines) : + for ii in lines : + if 'atom types' in ii : + return int(ii.split()[0]) + return None + +def _atom_info_mol(line) : + vec = line.split() + # idx, mole_type, atom_type, charge, x, y, z + return int(vec[0]), int(vec[1]), int(vec[2]), float(vec[3]), float(vec[4]), float(vec[5]), float(vec[6]) + +def _atom_info_atom(line) : + vec = line.split() + # idx, atom_type, x, y, z + return int(vec[0]), int(vec[1]), float(vec[2]), float(vec[3]), float(vec[4]) + +def get_natoms_vec(lines) : + atype = get_atype(lines) + natoms_vec = [] + natomtypes = get_natomtypes(lines) + for ii in range(natomtypes) : + natoms_vec.append(sum(atype == ii+1)) + assert (sum(natoms_vec) == get_natoms(lines)) + return natoms_vec + +def get_atype(lines) : + alines = get_atoms(lines) + atype = [] + for ii in alines : + # idx, mt, at, q, x, y, z = _atom_info_mol(ii) + idx, at, x, y, z = _atom_info_atom(ii) + atype.append(at) + return np.array(atype, dtype = int) + +def get_posi(lines) : + atom_lines = get_atoms(lines) + posis = [] + for ii in atom_lines : + # posis.append([float(jj) for jj in ii.split()[4:7]]) + posis.append([float(jj) for jj in ii.split()[2:5]]) + return np.array(posis) + +def get_lmpbox(lines) : + box_info = [] + tilt = np.zeros(3) + for ii in lines : + if 'xlo' in ii and 'xhi' in ii : + box_info.append([float(ii.split()[0]), float(ii.split()[1])]) + break + for ii in lines : + if 'ylo' in ii and 'yhi' in ii : + box_info.append([float(ii.split()[0]), float(ii.split()[1])]) + break + for ii in lines : + if 'zlo' in ii and 'zhi' in ii : + box_info.append([float(ii.split()[0]), float(ii.split()[1])]) + break + for ii in lines : + if 'xy' in ii and 'xz' in ii and 'yz' in ii : + tilt = np.array([float(jj) for jj in ii.split()[0:3]]) + return box_info, tilt + + +def system_data(lines) : + system = {} + system['atom_numbs'] = get_natoms_vec(lines) + system['atom_names'] = [] + for ii in range(len(system['atom_numbs'])) : + system['atom_names'].append('Type_%d' % ii) + lohi, tilt = get_lmpbox(lines) + orig, cell = lmpbox2box(lohi, tilt) + system['orig'] = np.array(orig) + system['cell'] = np.array(cell) + natoms = sum(system['atom_numbs']) + system['atom_types'] = get_atype(lines) + system['coordinates'] = get_posi(lines) + return system + +def to_system_data(lines) : + return system_data(lines) + +def from_system_data(system) : + ret = '' + ret += '\n' + natoms = sum(system['atom_numbs']) + ntypes = len(system['atom_numbs']) + ret += '%d atoms\n' % natoms + ret += '%d atom types\n' % ntypes + ret += '0 %f xlo xhi\n' % system['cell'][0][0] + ret += '0 %f ylo yhi\n' % system['cell'][1][1] + ret += '0 %f zlo zhi\n' % system['cell'][2][2] + ret += '%f %f %f xy xz yz\n' % \ + (system['cell'][1][0], system['cell'][2][0], system['cell'][2][1]) + ret += '\n' + ret += 'Atoms # atomic\n' + ret += '\n' + for ii in range(natoms) : + ret += '%d %d %f %f %f\n' % \ + (ii+1, + system['atom_types'][ii], + system['coordinates'][ii][0] - system['orig'][0], + system['coordinates'][ii][1] - system['orig'][1], + system['coordinates'][ii][2] - system['orig'][2] + ) + return ret + + +if __name__ == '__main__' : + fname = 'water-SPCE.data' + lines = open(fname).read().split('\n') + bonds, tilt = get_lmpbox(lines) + # print(bonds, tilt) + orig, box = lmpbox2box(bonds, tilt) + # print(orig, box) + bonds1, tilt1 = box2lmpbox(orig, box) + # print(bonds1, tilt1) + print(bonds1 - bonds) + print(tilt1 - tilt) + print(box) + print(get_atype(lines)) + print(get_posi(lines)) diff --git a/auto_test/lib/localhost.json b/auto_test/lib/localhost.json new file mode 100644 index 000000000..f2feaed5d --- /dev/null +++ b/auto_test/lib/localhost.json @@ -0,0 +1,7 @@ +{ + "hostname" : "localhost", + "port" : 22, + "username": "wanghan", + "work_path" : "/home/wanghan/tmp", + "_comment" : "that's all" +} diff --git a/auto_test/lib/machine_exec.py b/auto_test/lib/machine_exec.py new file mode 100644 index 000000000..deb8477ef --- /dev/null +++ b/auto_test/lib/machine_exec.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 + +import os +import numpy as np +import subprocess as sp +import logging +import time + +def run_node_tasks (max_thread, + work_thread, + all_task, + run_cmd) : + numb_jobs = max_thread // work_thread + task_chunks = [all_task[i:i + numb_jobs] for i in range(0, len(all_task), numb_jobs)] + base_path = os.getcwd() + "/" + count_batch = 0 + for task_batch in task_chunks : + ps = [] + for work_path in task_batch : + work_name = os.path.basename (work_path) + log_task ("%03d %s: %s" % (count_batch, work_name, run_cmd)) + os.chdir(work_path) + ps.append(sp.Popen(run_cmd, shell = True)) + os.chdir(base_path) + while True : + if not(any(p.wait() for p in ps)) : + break + time.sleep(1) + count_batch += 1 + + +def exec_hosts (machine_env, + cmd, + work_thread, + task_dirs, + task_args = None, + verbose = False) : + ntasks = len(task_dirs) + if task_args != None : + assert ntasks == len(task_args) or len(task_args) == 1 + if len(task_args) == 1 : + tmp_arg = task_args[0] + task_args = [tmp_arg for ii in range(ntasks)] + else : + task_args = ["" for ii in range(ntasks)] + assert ntasks == len(task_args) + + host_list = machine_env.get_node_list() + nnode = len(host_list) + ntpnode = machine_env.get_core_per_node() + nsource = ntpnode * nnode + numb_jobs = (nsource // work_thread) + task_chunks = [task_dirs[i:i + numb_jobs] for i in range(0, ntasks, numb_jobs)] + args_chunks = [task_args[i:i + numb_jobs] for i in range(0, ntasks, numb_jobs)] + nbatch = len(task_chunks) + assert nbatch == len(args_chunks) + + base_path = os.getcwd() + "/" + for ii in range(nbatch) : + task_batch = task_chunks[ii] + args_batch = args_chunks[ii] + ps = [] + for jj in range(len(task_batch)) : + work_path = task_batch[jj] + work_args = args_batch[jj] + host = host_list[jj % nnode] + work_name = os.path.basename (work_path) + if verbose: + logging.info(("%s %03d %s: %s %s" % (host, ii, work_name, cmd, work_args))) + ps.append(machine_env.exec_cmd(host, cmd, work_path, work_args)) + while True : + if not(any(p.wait() for p in ps)) : + break + time.sleep(1) + +def exec_hosts_batch (machine_env, + cmd, + work_thread, + task_dirs, + task_args = None, + verbose = False, + mpi = False, + gpu = False) : + ntasks = len(task_dirs) + if task_args != None : + assert ntasks == len(task_args) or len(task_args) == 1 + if len(task_args) == 1 : + tmp_arg = task_args[0] + task_args = [tmp_arg for ii in range(ntasks)] + else : + task_args = ["" for ii in range(ntasks)] + assert ntasks == len(task_args) + + host_list = machine_env.get_node_list() + nnode = len(host_list) + ntpnode = machine_env.get_core_per_node() + nsource = ntpnode * nnode + numb_jobs = (nsource // work_thread) + task_chunks = [task_dirs[i:i + numb_jobs] for i in range(0, ntasks, numb_jobs)] + args_chunks = [task_args[i:i + numb_jobs] for i in range(0, ntasks, numb_jobs)] + nbatch = len(task_chunks) + assert nbatch == len(args_chunks) + + base_path = os.getcwd() + "/" + for ii in range(nbatch) : + task_batch = task_chunks[ii] + args_batch = args_chunks[ii] + if verbose: + logging.info(("%s %03d : %s with %d jobs %s" % (host_list, ii, cmd, len(task_batch), task_batch))) + if mpi : + ps = machine_env.exec_mpi(cmd, ".", task_batch, task_args, work_thread) + elif gpu : + ps = machine_env.exec_gpu(cmd, ".", task_batch, task_args, work_thread) + else: + ps = machine_env.exec_batch(cmd, ".", task_batch, task_args, work_thread) + while True : + if not(any(p.wait() for p in ps)) : + break diff --git a/auto_test/lib/ovito_file_convert.py b/auto_test/lib/ovito_file_convert.py index ea530f3ec..aa88fa457 120000 --- a/auto_test/lib/ovito_file_convert.py +++ b/auto_test/lib/ovito_file_convert.py @@ -1 +1,49 @@ -../../generator/lib/ovito_file_convert.py \ No newline at end of file +#!/usr/bin/env ovitos +''' +This Script is adapted from Alexander Stukowski, the author of OVITO. +See: http://forum.ovito.org/index.php?topic=131.0 for details. +''' +import os +import sys +import argparse +import numpy as np + +from ovito.io import * + +supp_ofmt = ['lammps_dump', 'lammps_data', 'vasp'] +supp_exts = ['dump', 'lmp', 'poscar/POSCAR'] + +parser = argparse.ArgumentParser() +parser.add_argument("-m", "--ofmt", type=str, + help="the output format, supported: " + str(supp_ofmt)) +parser.add_argument("INPUT", type=str, + help="the input file") +parser.add_argument("OUTPUT", type=str, + help="the output file, supported ext: " + str(supp_exts)) +args = parser.parse_args() + +fin = args.INPUT +fout = args.OUTPUT +if args.ofmt is not None : + ofmt = args.ofmt +else : + ext = fout.split('.')[-1] + if ext == 'dump' : + ofmt = 'lammps_dump' + elif ext == 'lmp' : + ofmt = 'lammps_data' + elif ext == 'poscar' or ext == 'POSCAR' : + ofmt = 'vasp' +if not ofmt in supp_ofmt : + raise RuntimeError ("output format " + ofmt + " is not supported. use one of " + str(supp_ofmt)) + +columns = None +if ofmt == "lammps_dump" : + columns=["Particle Identifier", "Particle Type", "Position.X", "Position.Y", "Position.Z"] + +node = import_file(fin) +if columns is not None : + export_file(node, fout, ofmt, columns = columns) +else : + export_file(node, fout, ofmt) + diff --git a/auto_test/lib/pwscf.py b/auto_test/lib/pwscf.py new file mode 100644 index 000000000..ca54def1c --- /dev/null +++ b/auto_test/lib/pwscf.py @@ -0,0 +1,141 @@ +#!/usr/bin/python3 + +import numpy as np +# from lib.vasp import system_from_poscar + +def _make_pwscf_01_runctrl(sys_data, ecut, ediff, smearing, degauss) : + tot_natoms = sum(sys_data['atom_numbs']) + ntypes = len(sys_data['atom_names']) + ret = "" + ret += '&control\n' + ret += "calculation='scf',\n" + ret += "restart_mode='from_scratch',\n" + ret += "pseudo_dir='./',\n" + ret += "outdir='./OUT',\n" + ret += "tprnfor = .TRUE.,\n" + ret += "tstress = .TRUE.,\n" + ret += "disk_io = 'none',\n" + ret += "/\n" + ret += "&system\n" + ret += "ibrav= 0,\n" + ret += "nat = %d,\n" % tot_natoms + ret += "ntyp = %d,\n" % ntypes + ret += "vdw_corr = 'TS',\n" + ret += "ecutwfc = %f,\n" % ecut + ret += "ts_vdw_econv_thr=%e,\n" % ediff + ret += "nosym = .TRUE.,\n" + if degauss is not None : + ret += 'degauss = %f,\n' % degauss + if smearing is not None : + ret += 'smearing = \'%s\',\n' % (smearing.lower()) + ret += "/\n" + ret += "&electrons\n" + ret += "conv_thr = %e,\n" % ediff + ret += "/\n" + return ret + +def _make_pwscf_02_species(sys_data, pps) : + atom_names = (sys_data['atom_names']) + if 'atom_masses' in sys_data: + atom_masses = (sys_data['atom_masses']) + else : + atom_masses = [1 for ii in atom_names] + ret = "" + ret += "ATOMIC_SPECIES\n" + ntypes = len(atom_names) + assert(ntypes == len(atom_names)) + assert(ntypes == len(atom_masses)) + assert(ntypes == len(pps)) + for ii in range(ntypes) : + ret += "%s %d %s\n" % (atom_names[ii], atom_masses[ii], pps[ii]) + return ret + +def _make_pwscf_03_config(sys_data) : + cell = sys_data['cell'] + cell = np.reshape(cell, [3,3]) + coordinates = sys_data['coordinates'] + atom_names = (sys_data['atom_names']) + atom_numbs = (sys_data['atom_numbs']) + ntypes = len(atom_names) + ret = "" + ret += "CELL_PARAMETERS { angstrom }\n" + for ii in range(3): + for jj in range(3): + ret += "%f " % cell[ii][jj] + ret += "\n" + ret += "\n" + ret += "ATOMIC_POSITIONS { angstrom }\n" + cc = 0 + for ii in range(ntypes): + for jj in range(atom_numbs[ii]): + ret += "%s %f %f %f\n" % (atom_names[ii], + coordinates[cc][0], + coordinates[cc][1], + coordinates[cc][2]) + cc += 1 + return ret + +def _kshift(nkpt) : + if (nkpt//2) * 2 == nkpt : + return 1 + else : + return 0 + +def _make_pwscf_04_kpoints(sys_data, kspacing): + cell = sys_data['cell'] + cell = np.reshape(cell, [3,3]) + rcell = np.linalg.inv(cell) + rcell = rcell.T + kpoints = [(np.ceil(2 * np.pi * np.linalg.norm(ii) / kspacing).astype(int)) + for ii in rcell] + ret = "" + ret += "K_POINTS { automatic }\n" + for ii in range(3) : + ret += "%d " % kpoints[ii] + for ii in range(3) : + ret += "%d " % _kshift(kpoints[ii]) + ret += "\n" + return ret + +def _make_smearing(fp_params) : + smearing = None + degauss = None + if 'smearing' in fp_params : + smearing = (fp_params['smearing']).lower() + if 'sigma' in fp_params : + degauss = fp_params['sigma'] + if (smearing is not None) and (smearing.split(':')[0] == 'mp') : + smearing = 'mp' + if not (smearing in [None, 'gauss', 'mp', 'fd']) : + raise RuntimeError("unknow smearing method " + smearing) + return smearing, degauss + +def make_pwscf_input(sys_data, fp_pp_files, fp_params) : + ecut = fp_params['ecut'] + ediff = fp_params['ediff'] + kspacing = fp_params['kspacing'] + smearing, degauss = _make_smearing(fp_params) + ret = "" + ret += _make_pwscf_01_runctrl(sys_data, ecut, ediff, smearing, degauss) + ret += "\n" + ret += _make_pwscf_02_species(sys_data, fp_pp_files) + ret += "\n" + ret += _make_pwscf_03_config(sys_data) + ret += "\n" + ret += _make_pwscf_04_kpoints(sys_data, kspacing) + ret += "\n" + return ret + + +# sys_data = system_from_poscar('POSCAR') +# ret = "" +# ret += _make_pwscf_01_runctrl(sys_data, 20, 1e-8) +# ret += "\n" +# ret += _make_pwscf_02_species(sys_data, ['../pp/C_HSCV_PBE-1.0.UPF', '../H_HSCV_PBE-1.0.UPF', '../N_HSCV_PBE-1.0.UPF']) +# ret += "\n" +# ret += _make_pwscf_03_config(sys_data) +# ret += "\n" +# ret += _make_pwscf_04_kpoints(sys_data, 0.6) +# ret += "\n" + +# open('input', 'w').write(ret) diff --git a/auto_test/lib/utils.py b/auto_test/lib/utils.py new file mode 100644 index 000000000..02bce1da5 --- /dev/null +++ b/auto_test/lib/utils.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 + +import os, re, shutil, logging + +iter_format = "%s" +task_format = "%s" +log_iter_head = "task type: " + iter_format + " task: " + task_format + " process: " + +def make_iter_name (iter_index) : + return "task type:" + (iter_format) + +def create_path (path) : + path += '/' + if os.path.isdir(path) : + dirname = os.path.dirname(path) + counter = 0 + while True : + bk_dirname = dirname + ".bk%03d" % counter + if not os.path.isdir(bk_dirname) : + shutil.move (dirname, bk_dirname) + break + counter += 1 + os.makedirs (path) + +def replace (file_name, pattern, subst) : + file_handel = open (file_name, 'r') + file_string = file_handel.read () + file_handel.close () + file_string = ( re.sub (pattern, subst, file_string) ) + file_handel = open (file_name, 'w') + file_handel.write (file_string) + file_handel.close () + +def copy_file_list (file_list, from_path, to_path) : + for jj in file_list : + if os.path.isfile(os.path.join(from_path, jj)) : + shutil.copy (os.path.join(from_path, jj), to_path) + elif os.path.isdir(os.path.join(from_path, jj)) : + shutil.copytree (os.path.join(from_path, jj), os.path.join(to_path, jj)) + +def cmd_append_log (cmd, + log_file) : + ret = cmd + ret = ret + " 1> " + log_file + ret = ret + " 2> " + log_file + return ret + +def log_iter (task, ii, jj) : + logging.info ((log_iter_head + "%s") % (ii, jj, task)) + +def repeat_to_length(string_to_expand, length): + ret = "" + for ii in range (length) : + ret += string_to_expand + return ret + +def log_task (message) : + header = repeat_to_length (" ", len(log_iter_head % (0, 0))) + logging.info (header + message) + +def record_iter (record, ii, jj) : + with open (record, "a") as frec : + frec.write ("%s %s\n" % (ii, jj)) diff --git a/auto_test/lib/vasp.py b/auto_test/lib/vasp.py index 515f31582..2156b2152 100644 --- a/auto_test/lib/vasp.py +++ b/auto_test/lib/vasp.py @@ -317,6 +317,44 @@ def make_vasp_relax_incar (ecut, ediff, ret += 'KGAMMA=F\n' return ret +def make_vasp_phonon_incar (ecut, ediff, + npar, kpar, + kspacing = 0.5, kgamma = True, + ismear = 1, sigma = 0.2) : + isif = 2 + ret = '' + ret += 'PREC=A\n' + ret += 'ENCUT=%d\n' % ecut + ret += '# ISYM=0\n' + ret += 'ALGO=fast\n' + ret += 'EDIFF=%e\n' % ediff + ret += 'LREAL=F\n' + ret += 'NPAR=%d\n' % npar + ret += 'KPAR=%d\n' % kpar + ret += "\n" + ret += 'ISMEAR=%d\n' % ismear + ret += 'SIGMA=%f\n' % sigma + ret += "\n" + ret += 'ISTART=0\n' + ret += 'ICHARG=2\n' + ret += 'NELMIN=4\n' + ret += 'ISIF=%d\n' % isif + ret += 'IBRION=8\n' + ret += "\n" + ret += 'NSW=1\n' + ret += "\n" + ret += 'LWAVE=F\n' + ret += 'LCHARG=F\n' + ret += 'PSTRESS=0\n' + ret += "\n" + if kspacing is not None : + ret += 'KSPACING=%f\n' % kspacing + if kgamma is not None : + if kgamma: + ret += 'KGAMMA=T\n' + else : + ret += 'KGAMMA=F\n' + return ret def get_poscar_types (fname) : with open(fname, 'r') as fp : diff --git a/auto_test/machine.json b/auto_test/machine.json new file mode 100644 index 000000000..d23e425b9 --- /dev/null +++ b/auto_test/machine.json @@ -0,0 +1,75 @@ +{ + "deepmd_path": "the folder of deepmd", + "train_machine": { + "machine_type": "slurm", + "hostname" : "localhost", + "port" : 22, + "username": "username", + "password": "password", + "work_path" : "the path of workplace", + "_comment" : "that's all" + }, + "train_resources": { + "numb_node": 1, + "numb_gpu": 1, + "task_per_node":7, + "source_list": [ "the path of deepmd source" ], + "module_list": [ ], + "time_limit": "23:0:0", + "mem_limit": 32, + "_comment": "that's all" + }, + + "lmp_command": "the command of lammps", + "model_devi_group_size": 10, + "_comment": "model_devi on localhost", + "model_devi_machine": { + "machine_type": "slurm", + "hostname" : "localhost", + "port" : 22, + "username": "username", + "password": "password", + "work_path" : "the path of workplace", + "_comment" : "that's all" + }, + "_comment": " if use GPU, numb_nodes(nn) should always be 1 ", + "_comment": " if numb_nodes(nn) = 1 multi-threading rather than mpi is assumed", + "model_devi_resources": { + "numb_node": 1, + "numb_gpu": 0, + "task_per_node":8, + "partition" : "partition", + "source_list": ["the path of lammps source" ], + "module_list": [ ], + "time_limit": "19:0:0", + "mem_limit": 32, + "_comment": "that's all" + }, + + "_comment": "fp on localhost ", + "fp_command": "the command of vasp", + "fp_group_size": 1, + "fp_machine": { + "machine_type": "slurm", + "hostname" : "localhost", + "port" : 22, + "username": "username", + "password": "password", + "work_path" : "the path of workplace", + "_comment" : "that's all" + }, + "fp_resources": { + "task_per_node":16, + "numb_gpu": 0, + "source_list": ["the path of source" ], + "module_list": [], + "with_mpi" : 1, + "partition" : "CPU-Node", + "time_limit": "20:0:0", + "mem_limit": 64, + "_comment": "that's all" + }, + + + "_comment": " that's all " +} diff --git a/auto_test/param.json b/auto_test/param.json index 0ea9e92c0..acba2ca1c 100644 --- a/auto_test/param.json +++ b/auto_test/param.json @@ -1,21 +1,24 @@ { "_comment": "models", "potcar_map" : { - "Al" : "/home/wanghan/Soft/vasp/potcar.unknown/potpaw_PBE/Al/POTCAR", - "Mg" : "/home/wanghan/Soft/vasp/potcar.unknown/potpaw_PBE/Mg/POTCAR" + "Cu" : "/somewhere/POTCAR" }, + "conf_dir":"the folder of configuration", + "task_type":1, + "task":2, + "vasp_params": { - "ecut": 600, + "ecut": 520, "ediff": 1e-6, - "kspacing": 0.08, + "kspacing": 0.32, "kgamma": false, "npar": 1, "kpar": 1, "_comment": " that's all " }, - "deepmd_model_dir": "models", + "deepmd_model_dir": "the folder of deepmd model", "deepmd_type_map": [ - "Al", "Mg" + "Cu" ], "meam_potfile_dir": "meam", "meam_type_map": [ @@ -29,20 +32,38 @@ "AlS", "SiS", "MgS", "CuS", "FeS" ], + "_comment":"00.equi", + "store_stable":true, + "_comment": "01.eos", - "vol_start": 10, - "vol_end": 50, + "vol_start": 6, + "vol_end": 16, "vol_step": 0.5, + "store_fix":false, "_comment": "02.elastic", "norm_deform": 2e-2, "shear_deform": 5e-2, + + "_comment":"03.vacancy", + "supercell":[2,2,2], + + "_comment":"04.interstitial", + "insert_ele":"Zr", + "reprod-opt":false, "_comment": "05.surface", "min_slab_size": 10, "min_vacuum_size": 11, "_comment": "pert xz to work around vasp bug...", "pert_xz": 0.01, + "max_miller": 2, + "static-opt":false, + "store_relax":false, + + "_comment":"06.phonon", + "supercell_matrix":[2,2,2], + "band":"0 1 0 0.5 1 0.5 0.375 0.75 0.375 0 0 0 0.5 0.5 0.5", "_comment": "that's all" } diff --git a/auto_test/run.py b/auto_test/run.py new file mode 100644 index 000000000..5233bd415 --- /dev/null +++ b/auto_test/run.py @@ -0,0 +1,1191 @@ +#!/usr/bin/env python3 + +""" +init: crystal configuration +task: + 00.equi + 01.eos + 02.elastic + 03.vacancy + 04.interstitial + 05.surf + 06.phonon +""" + + +import sys +import os, re, argparse, filecmp, json, glob +import lib.vasp as vasp +import lib.lammps as lammps +import random +import logging +import warnings +import shutil +import time +import numpy as np +import subprocess as sp +from lib.utils import make_iter_name +from lib.utils import create_path +from lib.utils import copy_file_list +from lib.utils import replace +from lib.utils import cmd_append_log +from lib.utils import log_iter +from lib.utils import record_iter +from lib.utils import log_iter +from lib.pwscf import make_pwscf_input +import lib.MachineLocal as MachineLocal +import lib.MachineLocalGPU as MachineLocalGPU +import lib.MachineSlurm as MachineSlurm +import lib.MachinePBS as MachinePBS +from lib.machine_exec import exec_hosts +from lib.machine_exec import exec_hosts_batch +from lib.batch_exec import exec_batch +from lib.batch_exec import exec_batch_group +from lib.RemoteJob import SSHSession, JobStatus, SlurmJob, PBSJob, CloudMachineJob +import gen_00_equi,cmpt_00_equi +import gen_01_eos,cmpt_01_eos +import gen_02_elastic,cmpt_02_elastic +import gen_03_vacancy,cmpt_03_vacancy +import gen_04_interstitial,cmpt_04_interstitial +import gen_05_surf,cmpt_05_surf +import requests +from hashlib import sha1 + +def _verfy_ac(private_key, params): + items= sorted(params.items()) + + params_data = "" + for key, value in items: + params_data = params_data + str(key) + str(value) + params_data = params_data + private_key + sign = sha1() + sign.update(params_data.encode()) + signature = sign.hexdigest() + return signature + +def _ucloud_remove_machine(machine, UHostId): + ucloud_url = machine['url'] + ucloud_stop_param = {} + ucloud_stop_param['Action'] = "StopUHostInstance" + ucloud_stop_param['Region'] = machine['ucloud_param']['Region'] + ucloud_stop_param['UHostId'] = UHostId + ucloud_stop_param['PublicKey'] = machine['ucloud_param']['PublicKey'] + ucloud_stop_param['Signature'] = _verfy_ac(machine['Private'], ucloud_stop_param) + + + req = requests.get(ucloud_url, ucloud_stop_param) + if req.json()['RetCode'] != 0 : + raise RuntimeError ("failed to stop ucloud machine") + + terminate_fin = False + try_time = 0 + while not terminate_fin: + ucloud_delete_param = {} + ucloud_delete_param['Action'] = "TerminateUHostInstance" + ucloud_delete_param['Region'] = machine['ucloud_param']['Region'] + ucloud_delete_param['UHostId'] = UHostId + ucloud_delete_param['PublicKey'] = machine['ucloud_param']['PublicKey'] + ucloud_delete_param['Signature'] = _verfy_ac(machine['Private'], ucloud_delete_param) + req = requests.get(ucloud_url, ucloud_delete_param) + if req.json()['RetCode'] == 0 : + terminate_fin = True + try_time = try_time + 1 + if try_time >= 200: + raise RuntimeError ("failed to terminate ucloud machine") + time.sleep(10) + print("Machine ",UHostId,"has been successfully terminated!") + +def _ucloud_submit_jobs(machine, + resources, + command, + work_path, + tasks, + group_size, + forward_common_files, + forward_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) + ] + njob = len(task_chunks) + continue_status = False + if os.path.isfile("record.machine"): + with open ("record.machine", "r") as fr: + record_machine = json.load(fr) + if record_machine["purpose"] == machine["purpose"] and record_machine["njob"] == njob: + continue_status = True + ucloud_machines = record_machine["ucloud_machines"] + ucloud_hostids = record_machine["ucloud_hostids"] + fr.close() + ucloud_url = machine['url'] + if continue_status == False: + assert machine['machine_type'] == 'ucloud' + ucloud_start_param = machine['ucloud_param'] + ucloud_start_param['Action'] = "CreateUHostInstance" + ucloud_start_param['Name'] = "train" + ucloud_start_param['Signature'] = _verfy_ac(machine['Private'], ucloud_start_param) + + + ucloud_machines = [] + ucloud_hostids = [] + for ii in range(njob) : + req = requests.get(ucloud_url, ucloud_start_param) + if req.json()['RetCode'] != 0 : + print(json.dumps(req.json(),indent=2, sort_keys=True)) + raise RuntimeError ("failed to start ucloud machine") + ucloud_machines.append(str(req.json()["IPs"][0])) + ucloud_hostids.append(str(req.json()["UHostIds"][0])) + + new_record_machine = {} + new_record_machine["purpose"] = machine["purpose"] + new_record_machine["njob"] = njob + new_record_machine["ucloud_machines"] = ucloud_machines + new_record_machine["ucloud_hostids"] = ucloud_hostids + with open ("record.machine", "w") as fw: + json.dump(new_record_machine, fw) + fw.close() + + machine_fin = [False for ii in ucloud_machines] + total_machine_num = len(ucloud_machines) + fin_machine_num = 0 + while not all(machine_fin): + for idx,mac in enumerate(ucloud_machines): + if not machine_fin[idx]: + ucloud_check_param = {} + ucloud_check_param['Action'] = "GetUHostInstanceVncInfo" + ucloud_check_param['Region'] = machine['ucloud_param']['Region'] + ucloud_check_param['UHostId'] = ucloud_hostids[idx] + ucloud_check_param['PublicKey'] = machine['ucloud_param']['PublicKey'] + ucloud_check_param['Signature'] = _verfy_ac(machine['Private'], ucloud_check_param) + req = requests.get(ucloud_url, ucloud_check_param) + print("the UHostId is", ucloud_hostids[idx]) + print(json.dumps(req.json(),indent=2, sort_keys=True)) + if req.json()['RetCode'] == 0 : + machine_fin[idx] = True + fin_machine_num = fin_machine_num + 1 + print("Current finish",fin_machine_num,"/", total_machine_num) + + + ucloud_check_param1 = {} + ucloud_check_param1['Action'] = "DescribeUHostInstance" + ucloud_check_param1['Region'] = machine['ucloud_param']['Region'] + ucloud_check_param1["Limit"] = 100 + ucloud_check_param1['PublicKey'] = machine['ucloud_param']['PublicKey'] + ucloud_check_param1['Signature'] = _verfy_ac(machine['Private'], ucloud_check_param1) + req1 = requests.get(ucloud_url, ucloud_check_param1).json() + + machine_all_fin = True + for idx1 in range(int(req1["TotalCount"])): + if req1["UHostSet"][idx1]["State"] != "Running": + machine_all_fin = False + break + if machine_all_fin == True: + machine_fin = [True for i in machine_fin] + time.sleep(10) + ssh_sess = [] + ssh_param = {} + ssh_param['port'] = 22 + ssh_param['username'] = 'root' + ssh_param['work_path'] = machine['work_path'] + for ii in ucloud_machines : + ssh_param['hostname'] = ii + ssh_sess.append(SSHSession(ssh_param)) + + job_list = [] + for ii in range(njob) : + chunk = task_chunks[ii] + print("Current machine is", ucloud_machines[ii]) + rjob = CloudMachineJob(ssh_sess[ii], work_path) + rjob.upload('.', forward_common_files) + rjob.upload(chunk, forward_task_files) + rjob.submit(chunk, command, resources = resources) + job_list.append(rjob) + + job_fin = [False for ii in job_list] + while not all(job_fin) : + for idx,rjob in enumerate(job_list) : + if not job_fin[idx] : + status = rjob.check_status() + if status == JobStatus.terminated : + raise RuntimeError("find unsuccessfully terminated job on machine" % ucloud_machines[idx]) + elif status == JobStatus.finished : + rjob.download(task_chunks[idx], backward_task_files) + rjob.clean() + _ucloud_remove_machine(machine, ucloud_hostids[idx]) + job_fin[idx] = True + time.sleep(10) + os.remove("record.machine") + +def _group_slurm_jobs(ssh_sess, + resources, + command, + work_path, + tasks, + group_size, + forward_common_files, + forward_task_files, + backward_task_files, + remote_job = SlurmJob) : + task_chunks = [ + [os.path.basename(j) for j in tasks[i:i + group_size]] \ + for i in range(0, len(tasks), group_size) + ] + job_list = [] + for chunk in task_chunks : + rjob = remote_job(ssh_sess, work_path) + cwd=[os.path.basename(ii) for ii in chunk] + rjob.upload(cwd,forward_common_files) + rjob.upload(chunk, forward_task_files) + rjob.submit(chunk, command, resources = resources) + job_list.append(rjob) + + job_fin = [False for ii in job_list] + while not all(job_fin) : + for idx,rjob in enumerate(job_list) : + if not job_fin[idx] : + status = rjob.check_status() + if status == JobStatus.terminated : + raise RuntimeError("find unsuccessfully terminated job in %s" % rjob.get_job_root()) + elif status == JobStatus.finished : + rjob.download(task_chunks[idx], backward_task_files) + rjob.clean() + job_fin[idx] = True + time.sleep(10) + +def _group_local_jobs(ssh_sess, + resources, + command, + work_path, + tasks, + group_size, + forward_common_files, + forward_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) + ] + job_list = [] + for chunk in task_chunks : + rjob = CloudMachineJob(ssh_sess, work_path) + cwd=[os.path.basename(ii) for ii in chunk] + rjob.upload(cwd,forward_common_files) + rjob.upload(chunk, forward_task_files) + rjob.submit(chunk, command, resources = resources) + job_list.append(rjob) + job_fin = False + while not job_fin : + status = rjob.check_status() + if status == JobStatus.terminated : + raise RuntimeError("find unsuccessfully terminated job in %s" % rjob.get_job_root()) + elif status == JobStatus.finished : + rjob.download(chunk, backward_task_files) + rjob.clean() + job_fin = True + time.sleep(10) + +def _run(machine, + machine_type, + ssh_sess, + resources, + command, + work_path, + run_tasks, + group_size, + model_names, + forward_files, + backward_files): + + print("group_size",group_size) + if ssh_sess == None and machine_type == 'ucloud': + print("The first situation!") + _ucloud_submit_jobs(machine, + resources, + command, + work_path, + run_tasks, + group_size, + model_names, + forward_files, + backward_files) + elif machine_type == 'slurm' : + print("The second situation!") + _group_slurm_jobs(ssh_sess, + resources, + command, + work_path, + run_tasks, + group_size, + model_names, + forward_files, + backward_files) + elif machine_type == 'pbs' : + _group_slurm_jobs(ssh_sess, + resources, + command, + work_path, + run_tasks, + group_size, + model_names, + forward_files, + backward_files, + remote_job = PBSJob) + elif machine_type == 'local' : + _group_local_jobs(ssh_sess, + resources, + command, + work_path, + run_tasks, + group_size, + model_names, + forward_files, + backward_files) + else : + raise RuntimeError("unknow machine type") + +def gen_equi(task_type,jdata,mdata): + conf_dir=jdata['conf_dir'] + cwd=os.getcwd() + #vasp + if task_type=="vasp": + gen_00_equi.make_vasp(jdata, conf_dir) + #deepmd + elif task_type=="deepmd": + gen_00_equi.make_deepmd_lammps (jdata, conf_dir) + #meam + elif task_type=="meam": + gen_00_equi.make_meam_lammps (jdata, conf_dir) + else : + raise RuntimeError ("unknow task %s, something wrong" % task_type) + os.chdir(cwd) + +def run_equi(task_type,jdata,mdata,ssh_sess): + #rmprint("This module has been run !") + + conf_dir=jdata['conf_dir'] + fp_params = jdata['vasp_params'] + kspacing = fp_params['kspacing'] + deepmd_model_dir = jdata['deepmd_model_dir'] + deepmd_model_dir = os.path.abspath(deepmd_model_dir) + + conf_path = os.path.abspath(conf_dir) + equi_path = re.sub('confs', '00.equi', conf_path) + if task_type=="vasp": + work_path=os.path.join(equi_path, 'vasp-k%.2f' % kspacing) + elif task_type=="deepmd": + work_path=os.path.join(equi_path, 'deepmd') + elif task_type=="meam": + work_path=os.path.join(equi_path, 'meam') + assert(os.path.isdir(work_path)) + + all_task = glob.glob(os.path.join(work_path,'.')) + + #vasp + if task_type=="vasp": + vasp_exec=mdata['fp_command'] + group_size = mdata['fp_group_size'] + resources = mdata['fp_resources'] + machine=mdata['fp_machine'] + machine_type = mdata['fp_machine']['machine_type'] + command = vasp_exec + command = cmd_append_log(command, "log") + + run_tasks_ = [] + for ii in all_task: + fres = os.path.join(ii, 'OUTCAR') + if os.path.isfile(fres) : + if not vasp.check_finished(fres): + run_tasks_.append(ii) + else : + run_tasks_.append(ii) + + run_tasks = [os.path.basename(ii) for ii in run_tasks_] + forward_files = ['INCAR', 'POSCAR','POTCAR'] + backward_files = ['OUTCAR','CONTCAR'] + model_names=[] + + #lammps + elif task_type=="deepmd" or task_type=="meam": + lmp_exec = mdata['lmp_command'] + group_size = mdata['model_devi_group_size'] + resources = mdata['model_devi_resources'] + machine=mdata['model_devi_machine'] + machine_type = mdata['model_devi_machine']['machine_type'] + command = lmp_exec + " -i lammps.in" + command = cmd_append_log(command, "model_devi.log") + + run_tasks_ = [] + for ii in all_task: + fres = os.path.join(ii, 'log.lammps') + if os.path.isfile(fres) : + with open(fres, 'r') as fp : + lines = fp.read().split('\n') + flag=False + for jj in lines: + if ("Final energy per atoms" in jj) and (not 'print' in jj): + flag=True + if not flag: + run_tasks_.append(ii) + else : + run_tasks_.append(ii) + run_tasks = [os.path.basename(ii) for ii in run_tasks_] + forward_files = ['conf.lmp', 'lammps.in'] + backward_files = ['dump.relax','log.lammps','model_devi.out', 'model_devi.log'] + all_models = glob.glob(os.path.join(deepmd_model_dir, '*.pb')) + model_names = [os.path.basename(ii) for ii in all_models] + else: + raise RuntimeError ("unknow task %s, something wrong" % task_type) + + _run(machine, + machine_type, + ssh_sess, + resources, + command, + work_path, + run_tasks, + group_size, + model_names, + forward_files, + backward_files) + +def cmpt_equi(task_type,jdata,mdata): + conf_dir=jdata['conf_dir'] + stable=jdata['store_stable'] + #vasp + if task_type=="vasp": + vn, ve, vv = cmpt_00_equi.comput_vasp_nev(jdata, conf_dir, stable) + print("%s\t %8.4f %7.3f " % (conf_dir, ve, vv)) + #deepmd + elif task_type=="deepmd": + ln, le, lv = cmpt_00_equi.comput_lmp_nev(conf_dir, 'deepmd', stable) + print("%s\t %8.4f %7.3f " % (conf_dir, le, lv)) + #meam + elif task_type=="meam": + ln, le, lv = cmpt_00_equi.comput_lmp_nev(conf_dir, 'meam', stable) + print("%s\t %8.4f %7.3f " % (conf_dir, le, lv)) + else : + raise RuntimeError ("unknow task %s, something wrong" % task_type) + +def gen_eos(task_type,jdata,mdata): + conf_dir=jdata['conf_dir'] + fix_shape=jdata['store_fix'] + cwd=os.getcwd() + #vasp + if task_type == "vasp": + gen_01_eos.make_vasp(jdata, conf_dir) + #deepmd + elif task_type == "deepmd" : + if fix_shape : + gen_01_eos.make_deepmd_lammps_fixv(jdata, conf_dir) + else : + gen_01_eos.make_deepmd_lammps(jdata, conf_dir) + #meam + elif task_type == "meam" : + if fix_shape : + gen_01_eos.make_meam_lammps_fixv(jdata, conf_dir) + else : + raise RuntimeError("not implemented ", 'meam') + else : + raise RuntimeError("unknow task ", task_type) + os.chdir(cwd) + +def run_eos(task_type,jdata,mdata,ssh_sess): + conf_dir=jdata['conf_dir'] + fp_params = jdata['vasp_params'] + kspacing = fp_params['kspacing'] + deepmd_model_dir = jdata['deepmd_model_dir'] + deepmd_model_dir = os.path.abspath(deepmd_model_dir) + + conf_path = os.path.abspath(conf_dir) + task_path = re.sub('confs', '01.eos', conf_path) + if task_type=="vasp": + work_path=os.path.join(task_path, 'vasp-k%.2f' % kspacing) + elif task_type=="deepmd": + work_path=os.path.join(task_path, 'deepmd') + elif task_type=="meam": + work_path=os.path.join(task_path, 'meam') + assert(os.path.isdir(work_path)) + print(work_path) + + all_task = glob.glob(os.path.join(work_path, "vol-*")) + all_task.sort() + + #vasp + if task_type=="vasp": + vasp_exec=mdata['fp_command'] + group_size = mdata['fp_group_size'] + resources = mdata['fp_resources'] + machine=mdata['fp_machine'] + machine_type = mdata['fp_machine']['machine_type'] + command = vasp_exec + command = cmd_append_log(command, "log") + + run_tasks_ = [] + for ii in all_task: + fres = os.path.join(ii, 'OUTCAR') + if os.path.isfile(fres) : + if not vasp.check_finished(fres): + run_tasks_.append(ii) + else : + run_tasks_.append(ii) + + run_tasks = [os.path.basename(ii) for ii in run_tasks_] + forward_files = ['INCAR', 'POSCAR','POTCAR'] + backward_files = ['OUTCAR'] + model_names=[] + + #lammps + elif task_type=="deepmd" or task_type=="meam": + lmp_exec = mdata['lmp_command'] + group_size = mdata['model_devi_group_size'] + resources = mdata['model_devi_resources'] + machine=mdata['model_devi_machine'] + machine_type = mdata['model_devi_machine']['machine_type'] + command = lmp_exec + " -i lammps.in" + command = cmd_append_log(command, "model_devi.log") + + run_tasks_ = [] + for ii in all_task: + fres = os.path.join(ii, 'log.lammps') + if os.path.isfile(fres) : + with open(fres, 'r') as fp : + lines = fp.read().split('\n') + flag=False + for jj in lines: + if ("Final energy per atoms" in jj) and (not 'print' in jj): + flag=True + if not flag: + run_tasks_.append(ii) + else : + run_tasks_.append(ii) + + run_tasks = [os.path.basename(ii) for ii in run_tasks_] + forward_files = ['conf.lmp', 'lammps.in'] + backward_files = ['log.lammps','model_devi.out', 'model_devi.log'] + all_models = glob.glob(os.path.join(deepmd_model_dir, '*.pb')) + model_names = [os.path.basename(ii) for ii in all_models] + else: + raise RuntimeError ("unknow task %s, something wrong" % task_type) + + _run(machine, + machine_type, + ssh_sess, + resources, + command, + work_path, + run_tasks, + group_size, + model_names, + forward_files, + backward_files) + +def cmpt_eos(task_type,jdata,mdata): + conf_dir=jdata['conf_dir'] + #vasp + if task_type == "vasp": + cmpt_01_eos.comput_vasp_eos(jdata, conf_dir) + #deepmd + elif task_type == "deepmd" : + cmpt_01_eos.comput_lmp_eos(conf_dir, 'deepmd') + #meam + elif task_type == "meam" : + cmpt_01_eos.comput_lmp_eos(conf_dir, 'meam') + else : + raise RuntimeError("unknow task ", task_type) + +def gen_elastic(task_type,jdata,mdata): + conf_dir=jdata['conf_dir'] + cwd=os.getcwd() + #vasp + if task_type == "vasp": + gen_02_elastic.make_vasp(jdata, conf_dir) + #deepmd + elif task_type == "deepmd": + gen_02_elastic.make_deepmd_lammps (jdata, conf_dir) + #meam + elif task_type == "meam": + gen_02_elastic.make_meam_lammps (jdata, conf_dir) + else: + raise RuntimeError ("unknow task %s, something wrong" % task_type) + os.chdir(cwd) + +def run_elastic(task_type,jdata,mdata,ssh_sess): + conf_dir=jdata['conf_dir'] + fp_params = jdata['vasp_params'] + kspacing = fp_params['kspacing'] + deepmd_model_dir = jdata['deepmd_model_dir'] + deepmd_model_dir = os.path.abspath(deepmd_model_dir) + + conf_path = os.path.abspath(conf_dir) + task_path = re.sub('confs', '02.elastic', conf_path) + if task_type == "vasp": + work_path=os.path.join(task_path, 'vasp-k%.2f' % kspacing) + elif task_type == "deepmd": + work_path=os.path.join(task_path, 'deepmd') + elif task_type == "meam": + work_path=os.path.join(task_path, 'meam') + assert(os.path.isdir(work_path)) + print(work_path) + + all_task = glob.glob(os.path.join(work_path, "dfm-*")) + all_task.sort() + + #vasp + if task_type == "vasp": + vasp_exec=mdata['fp_command'] + group_size = mdata['fp_group_size'] + resources = mdata['fp_resources'] + machine=mdata['fp_machine'] + machine_type = mdata['fp_machine']['machine_type'] + command = vasp_exec + command = cmd_append_log(command, "log") + + run_tasks_ = [] + for ii in all_task: + fres = os.path.join(ii, 'OUTCAR') + if os.path.isfile(fres) : + if not vasp.check_finished(fres): + run_tasks_.append(ii) + else : + run_tasks_.append(ii) + + run_tasks = [os.path.basename(ii) for ii in run_tasks_] + forward_files = ['INCAR', 'POSCAR','POTCAR','KPOINTS'] + backward_files = ['OUTCAR','CONTCAR'] + model_names=[] + + #lammps + elif task_type == "deepmd" or task_type == "meam": + lmp_exec = mdata['lmp_command'] + group_size = mdata['model_devi_group_size'] + resources = mdata['model_devi_resources'] + machine=mdata['model_devi_machine'] + machine_type = mdata['model_devi_machine']['machine_type'] + command = lmp_exec + " -i lammps.in" + command = cmd_append_log(command, "model_devi.log") + + run_tasks_ = [] + for ii in all_task: + fres = os.path.join(ii, 'log.lammps') + if os.path.isfile(fres) : + with open(fres, 'r') as fp : + lines = fp.read().split('\n') + flag=False + for jj in lines: + if ('Final Stress' in jj) and (not 'print' in jj): + flag=True + if not flag: + run_tasks_.append(ii) + else : + run_tasks_.append(ii) + + run_tasks = [os.path.basename(ii) for ii in run_tasks_] + forward_files = ['conf.lmp', 'lammps.in','strain.out'] + backward_files = ['log.lammps','model_devi.out', 'model_devi.log'] + all_models = glob.glob(os.path.join(deepmd_model_dir, '*.pb')) + model_names = [os.path.basename(ii) for ii in all_models] + else: + raise RuntimeError ("unknow task %s, something wrong" % task_type) + + _run(machine, + machine_type, + ssh_sess, + resources, + command, + work_path, + run_tasks, + group_size, + model_names, + forward_files, + backward_files) + +def cmpt_elastic(task_type,jdata,mdata): + conf_dir=jdata['conf_dir'] + if task_type == "vasp": + cmpt_02_elastic.cmpt_vasp(jdata, conf_dir) + elif task_type == "deepmd": + cmpt_02_elastic.cmpt_deepmd_lammps(jdata, conf_dir, 'deepmd') + elif task_type == "meam": + cmpt_02_elastic.cmpt_deepmd_lammps(jdata, conf_dir, 'meam') + else : + raise RuntimeError ("unknow task %s, something wrong" % task_type) + +def gen_vacancy(task_type,jdata,mdata): + conf_dir=jdata['conf_dir'] + supercell=jdata['supercell'] + cwd=os.getcwd() + #vasp + if task_type == "vasp": + gen_03_vacancy.make_vasp(jdata, conf_dir, supercell) + #deepmd + elif task_type == "deepmd": + gen_03_vacancy.make_deepmd_lammps(jdata, conf_dir, supercell) + #meam + elif task_type == "meam": + gen_03_vacancy.make_meam_lammps(jdata, conf_dir, supercell) + else : + raise RuntimeError("unknow task ", task_type) + os.chdir(cwd) + +def run_vacancy(task_type,jdata,mdata,ssh_sess): + conf_dir=jdata['conf_dir'] + fp_params = jdata['vasp_params'] + kspacing = fp_params['kspacing'] + deepmd_model_dir = jdata['deepmd_model_dir'] + deepmd_model_dir = os.path.abspath(deepmd_model_dir) + + conf_path = os.path.abspath(conf_dir) + task_path = re.sub('confs', '03.vacancy', conf_path) + if task_type == "vasp": + work_path=os.path.join(task_path, 'vasp-k%.2f' % kspacing) + elif task_type == "deepmd": + work_path=os.path.join(task_path, 'deepmd') + elif task_type == "meam": + work_path=os.path.join(task_path, 'meam') + assert(os.path.isdir(work_path)) + + all_task = glob.glob(os.path.join(work_path,'struct-*')) + + #vasp + if task_type == "vasp": + vasp_exec=mdata['fp_command'] + group_size = mdata['fp_group_size'] + resources = mdata['fp_resources'] + machine=mdata['fp_machine'] + machine_type = mdata['fp_machine']['machine_type'] + command = vasp_exec + command = cmd_append_log(command, "log") + + run_tasks_ = [] + for ii in all_task: + fres = os.path.join(ii, 'OUTCAR') + if os.path.isfile(fres) : + if not vasp.check_finished(fres): + run_tasks_.append(ii) + else : + run_tasks_.append(ii) + + run_tasks = [os.path.basename(ii) for ii in run_tasks_] + forward_files = ['INCAR', 'POSCAR','POTCAR'] + backward_files = ['OUTCAR'] + model_names=[] + + #lammps + elif task_type == "deepmd" or task_type == "meam": + lmp_exec = mdata['lmp_command'] + group_size = mdata['model_devi_group_size'] + resources = mdata['model_devi_resources'] + machine=mdata['model_devi_machine'] + machine_type = mdata['model_devi_machine']['machine_type'] + command = lmp_exec + " -i lammps.in" + command = cmd_append_log(command, "model_devi.log") + + run_tasks_ = [] + for ii in all_task: + fres = os.path.join(ii, 'log.lammps') + if os.path.isfile(fres) : + with open(fres, 'r') as fp : + lines = fp.read().split('\n') + flag=False + for jj in lines: + if ("Final energy per atoms" in jj) and (not 'print' in jj): + flag=True + if not flag: + run_tasks_.append(ii) + else : + run_tasks_.append(ii) + + run_tasks = [os.path.basename(ii) for ii in run_tasks_] + forward_files = ['conf.lmp', 'lammps.in'] + backward_files = ['log.lammps','model_devi.out', 'model_devi.log'] + all_models = glob.glob(os.path.join(deepmd_model_dir, '*.pb')) + model_names = [os.path.basename(ii) for ii in all_models] + else: + raise RuntimeError ("unknow task %s, something wrong" % task_type) + + _run(machine, + machine_type, + ssh_sess, + resources, + command, + work_path, + run_tasks, + group_size, + model_names, + forward_files, + backward_files) + +def cmpt_vacancy(task_type,jdata,mdata): + conf_dir=jdata['conf_dir'] + supercell=jdata['supercell'] + #vasp + if task_type == "vasp": + cmpt_03_vacancy.cmpt_vasp(jdata, conf_dir, supercell) + #deepmd + elif task_type == "deepmd": + cmpt_03_vacancy.cmpt_deepmd_lammps(jdata, conf_dir, supercell, 'deepmd') + #meam + elif task_type == "meam": + cmpt_03_vacancy.cmpt_deepmd_lammps(jdata, conf_dir, supercell,'meam') + else : + raise RuntimeError("unknow task ", task_type) + +def gen_interstitial(task_type,jdata,mdata): + conf_dir=jdata['conf_dir'] + supercell=jdata['supercell'] + insert_ele=jdata['insert_ele'] + reprod_opt=jdata['reprod-opt'] + cwd=os.getcwd() + #vasp + if task_type == "vasp": + gen_04_interstitial.make_vasp(jdata, conf_dir, supercell, insert_ele) + #deepmd + elif task_type == "deepmd": + if not reprod_opt: + gen_04_interstitial.make_deepmd_lammps(jdata, conf_dir, supercell, insert_ele, task_type) + else : + gen_04_interstitial.make_deepmd_reprod_traj(jdata, conf_dir, supercell, insert_ele, task_type) + #meam + elif task_type == "meam" : + if not reprod_opt: + gen_04_interstitial.make_meam_lammps(jdata, conf_dir, supercell, insert_ele, task_type) + else : + gen_04_interstitial.make_meam_reprod_traj(jdata, conf_dir, supercell, insert_ele, task_type) + else : + raise RuntimeError("unknow task ", task_type) + os.chdir(cwd) + +def run_interstitial(task_type,jdata,mdata,ssh_sess): + conf_dir=jdata['conf_dir'] + fp_params = jdata['vasp_params'] + kspacing = fp_params['kspacing'] + deepmd_model_dir = jdata['deepmd_model_dir'] + deepmd_model_dir = os.path.abspath(deepmd_model_dir) + + conf_path = os.path.abspath(conf_dir) + task_path = re.sub('confs', '04.intersitial', conf_path) + if task_type == "vasp": + work_path=os.path.join(task_path, 'vasp-k%.2f' % kspacing) + elif task_type == "deepmd": + work_path=os.path.join(task_path, 'deepmd') + elif task_type == "meam": + work_path=os.path.join(task_path, 'meam') + assert(os.path.isdir(work_path)) + + all_task = glob.glob(os.path.join(work_path,'struct-*')) + + #vasp + if task_type == "vasp": + vasp_exec=mdata['fp_command'] + group_size = mdata['fp_group_size'] + resources = mdata['fp_resources'] + machine=mdata['fp_machine'] + machine_type = mdata['fp_machine']['machine_type'] + command = vasp_exec + command = cmd_append_log(command, "log") + + run_tasks_ = [] + for ii in all_task: + fres = os.path.join(ii, 'OUTCAR') + if os.path.isfile(fres) : + if not vasp.check_finished(fres): + run_tasks_.append(ii) + else : + run_tasks_.append(ii) + + run_tasks = [os.path.basename(ii) for ii in run_tasks_] + forward_files = ['INCAR', 'POSCAR','POTCAR'] + backward_files = ['OUTCAR','XDATCAR'] + model_names=[] + + #lammps + elif task_type == "deepmd" or task_type == "meam": + lmp_exec = mdata['lmp_command'] + group_size = mdata['model_devi_group_size'] + resources = mdata['model_devi_resources'] + machine=mdata['model_devi_machine'] + machine_type = mdata['model_devi_machine']['machine_type'] + command = lmp_exec + " -i lammps.in" + command = cmd_append_log(command, "model_devi.log") + + run_tasks_ = [] + for ii in all_task: + fres = os.path.join(ii, 'log.lammps') + if os.path.isfile(fres) : + with open(fres, 'r') as fp : + lines = fp.read().split('\n') + flag=False + for jj in lines: + if ("Final energy per atoms" in jj) and (not 'print' in jj): + flag=True + if not flag: + run_tasks_.append(ii) + else : + run_tasks_.append(ii) + + run_tasks = [os.path.basename(ii) for ii in run_tasks_] + forward_files = ['conf.lmp', 'lammps.in'] + backward_files = ['log.lammps','model_devi.out', 'model_devi.log'] + all_models = glob.glob(os.path.join(deepmd_model_dir, '*.pb')) + model_names = [os.path.basename(ii) for ii in all_models] + else: + raise RuntimeError ("unknow task %s, something wrong" % task_type) + + _run(machine, + machine_type, + ssh_sess, + resources, + command, + work_path, + run_tasks, + group_size, + model_names, + forward_files, + backward_files) + +def cmpt_interstitial(task_type,jdata,mdata): + conf_dir=jdata['conf_dir'] + supercell=jdata['supercell'] + insert_ele=jdata['insert_ele'] + reprod_opt=jdata['reprod-opt'] + cwd=os.getcwd() + #vasp + if task_type == "vasp": + cmpt_04_interstitial.cmpt_vasp(jdata, conf_dir, supercell, insert_ele) + #deepmd + elif task_type == "deepmd": + if not reprod_opt: + cmpt_04_interstitial.cmpt_deepmd_lammps(jdata, conf_dir, supercell, insert_ele, task_type) + else : + cmpt_04_interstitial.cmpt_deepmd_reprod_traj(jdata, conf_dir, supercell, insert_ele, task_type) + #meam + elif task_type == "meam" : + if not reprod_opt: + cmpt_04_interstitial.cmpt_meam_lammps(jdata, conf_dir, supercell, insert_ele, task_type) + else : + cmpt_04_interstitial.cmpt_meam_reprod_traj(jdata, conf_dir, supercell, insert_ele, task_type) + else : + raise RuntimeError("unknow task ", task_type) + os.chdir(cwd) + +def gen_surf(task_type,jdata,mdata): + conf_dir=jdata['conf_dir'] + max_miller=jdata['max_miller'] + relax=jdata['store_relax'] + static_opt=jdata['static-opt'] + cwd=os.getcwd() + #vasp + if task_type == "vasp": + gen_05_surf.make_vasp(jdata, conf_dir, max_miller, static = static_opt, relax_box = relax) + #deepmd + elif task_type == "deepmd" : + gen_05_surf.make_deepmd_lammps(jdata, conf_dir, max_miller, static = static_opt, relax_box = relax, task_name = 'deepmd') + #meam + elif task_type == "meam" : + gen_05_surf.make_meam_lammps(jdata, conf_dir, max_miller, static = static_opt, relax_box = relax, task_name = 'meam') + else : + raise RuntimeError("unknow task ", task_type) + os.chdir(cwd) + +def run_surf(task_type,jdata,mdata,ssh_sess): + conf_dir=jdata['conf_dir'] + fp_params = jdata['vasp_params'] + kspacing = fp_params['kspacing'] + deepmd_model_dir = jdata['deepmd_model_dir'] + deepmd_model_dir = os.path.abspath(deepmd_model_dir) + + conf_path = os.path.abspath(conf_dir) + task_path = re.sub('confs', '05.surf', conf_path) + if task_type == "vasp": + work_path=os.path.join(task_path, 'vasp-k%.2f' % kspacing) + elif task_type == "deepmd": + work_path=os.path.join(task_path, 'deepmd') + elif task_type == "meam": + work_path=os.path.join(task_path, 'meam') + assert(os.path.isdir(work_path)) + + all_task = glob.glob(os.path.join(work_path,'struct-*')) + + #vasp + if task_type == "vasp": + vasp_exec=mdata['fp_command'] + group_size = mdata['fp_group_size'] + resources = mdata['fp_resources'] + machine=mdata['fp_machine'] + machine_type = mdata['fp_machine']['machine_type'] + command = vasp_exec + command = cmd_append_log(command, "log") + + run_tasks_ = [] + for ii in all_task: + fres = os.path.join(ii, 'OUTCAR') + if os.path.isfile(fres) : + if not vasp.check_finished(fres): + run_tasks_.append(ii) + else : + run_tasks_.append(ii) + + run_tasks = [os.path.basename(ii) for ii in run_tasks_] + forward_files = ['INCAR', 'POSCAR','POTCAR'] + backward_files = ['OUTCAR'] + model_names=[] + + #lammps + elif task_type == "deepmd" or task_type == "meam": + lmp_exec = mdata['lmp_command'] + group_size = mdata['model_devi_group_size'] + resources = mdata['model_devi_resources'] + machine=mdata['model_devi_machine'] + machine_type = mdata['model_devi_machine']['machine_type'] + command = lmp_exec + " -i lammps.in" + command = cmd_append_log(command, "model_devi.log") + + run_tasks_ = [] + for ii in all_task: + fres = os.path.join(ii, 'log.lammps') + if os.path.isfile(fres) : + with open(fres, 'r') as fp : + lines = fp.read().split('\n') + flag=False + for jj in lines: + if ("Final energy per atoms" in jj) and (not 'print' in jj): + flag=True + if not flag: + run_tasks_.append(ii) + else : + run_tasks_.append(ii) + + run_tasks = [os.path.basename(ii) for ii in run_tasks_] + forward_files = ['conf.lmp', 'lammps.in'] + backward_files = ['log.lammps','model_devi.out', 'model_devi.log'] + all_models = glob.glob(os.path.join(deepmd_model_dir, '*.pb')) + model_names = [os.path.basename(ii) for ii in all_models] + else: + raise RuntimeError ("unknow task %s, something wrong" % task_type) + + _run(machine, + machine_type, + ssh_sess, + resources, + command, + work_path, + run_tasks, + group_size, + model_names, + forward_files, + backward_files) + +def cmpt_surf(task_type,jdata,mdata): + conf_dir=jdata['conf_dir'] + static_opt=jdata['static-opt'] + cwd=os.getcwd() + #vasp + if task_type == "vasp": + cmpt_05_surf.cmpt_vasp(jdata, conf_dir, static = static_opt) + #deepmd + elif task_type == "deepmd" : + cmpt_05_surf.cmpt_deepmd_lammps(jdata, conf_dir, 'deepmd', static = static_opt) + #meam + elif task_type == "meam" : + cmpt_05_surf.cmpt_deepmd_lammps(jdata, conf_dir, 'meam', static = static_opt) + else : + raise RuntimeError("unknow task ", task_type) + os.chdir(cwd) + +def run_task (json_file, machine_file) : + with open (json_file, 'r') as fp : + jdata = json.load (fp) + with open (machine_file, 'r') as fp: + mdata = json.load (fp) + + record = "record.auto_test" + + train_machine = mdata['train_machine'] + if ('machine_type' in train_machine) and \ + (train_machine['machine_type'] == 'ucloud'): + train_ssh_sess = None + else : + train_ssh_sess = SSHSession(train_machine) + + model_devi_machine = mdata['model_devi_machine'] + if ('machine_type' in model_devi_machine) and \ + (model_devi_machine['machine_type'] == 'ucloud'): + model_devi_ssh_sess = None + else : + model_devi_ssh_sess = SSHSession(model_devi_machine) + + fp_machine = mdata['fp_machine'] + if ('machine_type' in fp_machine) and \ + (fp_machine['machine_type'] == 'ucloud'): + fp_ssh_sess = None + else : + fp_ssh_sess = SSHSession(fp_machine) + + ii = jdata['task_type'] + jj=jdata['task'] + #default task + log_iter ("gen_equi", ii, "equi") + gen_equi (ii, jdata, mdata) + log_iter ("run_equi", ii, "equi") + run_equi (ii, jdata, mdata,model_devi_ssh_sess) + log_iter ("cmpt_equi", ii,"equi") + cmpt_equi (ii, jdata, mdata) + if jj == "eos" or jj=="all": + log_iter ("gen_eos", ii, "eos") + gen_eos (ii, jdata, mdata) + log_iter ("run_eos", ii, "eos") + run_eos (ii, jdata, mdata,model_devi_ssh_sess) + log_iter ("cmpt_eos", ii, "eos") + cmpt_eos (ii, jdata, mdata) + elif jj=="elastic" or jj=="all": + log_iter ("gen_elastic", ii, "elastic") + gen_elastic (ii, jdata, mdata) + log_iter ("run_elastic", ii, "elastic") + run_elastic (ii, jdata, mdata,model_devi_ssh_sess) + log_iter ("cmpt_elastic", ii, "elastic") + cmpt_elastic (ii, jdata, mdata) + elif jj=="vacancy" or jj=="all": + log_iter ("gen_vacancy", ii, "vacancy") + gen_vacancy (ii, jdata, mdata) + log_iter ("run_vacancy", ii, "vacancy") + run_vacancy (ii, jdata, mdata,model_devi_ssh_sess) + log_iter ("cmpt_vacancy", ii, "vacancy") + cmpt_vacancy (ii, jdata, mdata) + elif jj=="interstitial" or jj=="all": + log_iter ("gen_interstitial", ii, "interstitial") + gen_interstitial (ii, jdata, mdata) + log_iter ("run_interstitial", ii, "interstitial") + run_interstitial (ii, jdata, mdata,model_devi_ssh_sess) + log_iter ("cmpt_interstitial", ii, "interstitial") + cmpt_interstitial (ii, jdata, mdata) + elif jj=="surf" or jj=="all": + log_iter ("gen_surf", ii, "surf") + gen_surf (ii, jdata, mdata) + log_iter ("run_surf", ii, "surf") + run_surf (ii, jdata, mdata,model_devi_ssh_sess) + log_iter ("cmpt_surf", ii, "surf") + cmpt_surf (ii, jdata, mdata) + elif jj!="equi" : + raise RuntimeError ("unknow task %s, something wrong" % jj) + record_iter (record, ii, jj) + +def _main () : + parser = argparse.ArgumentParser() + parser.add_argument("PARAM", type=str, + help="The parameters of the generator") + parser.add_argument("MACHINE", type=str, + help="The settings of the machine running the generator") + args = parser.parse_args() + + logging.basicConfig (level=logging.INFO, format='%(asctime)s %(message)s') + # logging.basicConfig (filename="compute_string.log", filemode="a", level=logging.INFO, format='%(asctime)s %(message)s') + logging.getLogger("paramiko").setLevel(logging.WARNING) + + logging.info ("start auto-testing") + run_task (args.PARAM, args.MACHINE) + logging.info ("finished!") + +if __name__ == '__main__': + _main() +