diff --git a/.gitignore b/.gitignore index 936bfd426..ecfb6d73e 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ dbconfig.json _build tests/generator/calypso_test_path doc/api/ + diff --git a/README.md b/README.md index ac33210f8..a0e270e9b 100644 --- a/README.md +++ b/README.md @@ -590,15 +590,15 @@ The bold notation of key (such as **calypso_path**) means that it's a necessary | **model_devi_jobs["NameOfAtoms"]** | List of string |["Al","Cu"] | Parameter of CALYPSO input file, means the element species of structures to be generated. | | **model_devi_jobs["NumberOfAtoms"]** | List of int |[1,10] | Parameter of CALYPSO input file, means the number of atoms for each chemical species in one formula unit. | | **model_devi_jobs["NumberOfFormula"]** | List of int |[1,2] | Parameter of CALYPSO input file, means the range of formula unit per cell. | -| **model_devi_jobs["Volume"]** | List of int |[300] | Parameter of CALYPSO input file, means the colume per formula unit(angstrom^3). | +| **model_devi_jobs["Volume"]** | int | 300 | Parameter of CALYPSO input file, means the colume per formula unit(angstrom^3). | | **model_devi_jobs["DistanceOfIon"]** | List of float |[[ 1.48,1.44],[ 1.44,1.41]] | Parameter of CALYPSO input file, means minimal distance between atoms of each chemical species. Unit is in angstrom. | -| **model_devi_jobs["PsoRatio"]** | List of float |[0.6] | Parameter of CALYPSO input file, means the proportion of the structures generated by PSO. | -| **model_devi_jobs["PopSize"]** | List of int |[5] | Parameter of CALYPSO input file, means the number of structures to be generated in one step in CALYPSO. | -| **model_devi_jobs["MaxStep"]** | List of int |[3] | Parameter of CALYPSO input file, means the number of max step in CALYPSO.| -| **model_devi_jobs["ICode"]** | List of int |[13] | Parameter of CALYPSO input file, means the chosen of local optimization, 1 is vasp and 13 is ASE with dp. | +| **model_devi_jobs["PsoRatio"]** | float or int | 0.6 | Parameter of CALYPSO input file, means the proportion of the structures generated by PSO. | +| **model_devi_jobs["PopSize"]** | int | 5 | Parameter of CALYPSO input file, means the number of structures to be generated in one step in CALYPSO. | +| **model_devi_jobs["MaxStep"]** | int | 3 | Parameter of CALYPSO input file, means the number of max step in CALYPSO.| +| **model_devi_jobs["ICode"]** | int | 13 | Parameter of CALYPSO input file, means the chosen of local optimization, 1 is vasp and 13 is ASE with dp. | | **model_devi_jobs["Split"]** | String |"T" | Parameter of CALYPSO input file, means that generating structures and optimizing structures are split into two parts, in dpgen workflow, Split must be T. | -| **model_devi_jobs["PSTRESS"]** | List of float |[0.001] | Same as PSTRESS in INCAR. | -| **model_devi_jobs["fmax"]** | List of float |[0.01] | The convergence criterion is that the force on all individual atoms should be less than *fmax*. | +| **model_devi_jobs["PSTRESS"]** | List of float or int |[0.001] | Same as PSTRESS in INCAR. | +| **model_devi_jobs["fmax"]** | float | 0.01 | The convergence criterion is that the force on all individual atoms should be less than *fmax*. | | *in machine file* | **model_devi["deepmdkit_python"]** | String | "/home/zhenyu/soft/deepmd-kit/bin/python" | A python path with deepmd package. | | **model_devi["calypso_path"]** | string | "/home/zhenyu/workplace/debug" | The absolute path of calypso.x.| diff --git a/dpgen/generator/lib/calypso_check_outcar.py b/dpgen/generator/lib/calypso_check_outcar.py index c07a00590..5e9b8490b 100644 --- a/dpgen/generator/lib/calypso_check_outcar.py +++ b/dpgen/generator/lib/calypso_check_outcar.py @@ -1,107 +1,104 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import numpy as np -import os,sys,glob,time -from deepmd.calculator import DP -from ase.io import read +import numpy as np +import os,sys,glob,time +from deepmd.calculator import DP +from ase.io import read ''' check if structure optimization worked well if not, this script will generate a fake outcar ''' - -def Get_Element_Num(elements): + +def Get_Element_Num(elements): '''Using the Atoms.symples to Know Element&Num''' - element = [] - ele = {} - element.append(elements[0]) - for x in elements: - if x not in element : - element.append(x) - for x in element: - ele[x] = elements.count(x) - return element, ele - -def Write_Contcar(element, ele, lat, pos): - '''Write CONTCAR''' - f = open('CONTCAR','w') - f.write('ASE-DPKit-FAILED-nan\n') - f.write('1.0\n') - for i in range(3): - f.write('%15.10f %15.10f %15.10f\n' % tuple(lat[i])) - for x in element: - f.write(x + ' ') - f.write('\n') - for x in element: - f.write(str(ele[x]) + ' ') - f.write('\n') - f.write('Direct\n') - na = sum(ele.values()) - dpos = np.dot(pos,np.linalg.inv(lat)) - for i in range(na): - f.write('%15.10f %15.10f %15.10f\n' % tuple(dpos[i])) - -def Write_Outcar(element, ele, volume, lat, pos, ene, force, stress,pstress): - '''Write OUTCAR''' - f = open('OUTCAR','w') - for x in element: - f.write('VRHFIN =' + str(x) + '\n') - f.write('ions per type =') - for x in element: - f.write('%5d' % ele[x]) - #f.write('\nvolume of cell :\n') + element = [] + ele = {} + element.append(elements[0]) + for x in elements: + if x not in element : + element.append(x) + for x in element: + ele[x] = elements.count(x) + return element, ele + +def Write_Contcar(element, ele, lat, pos): + '''Write CONTCAR''' + f = open('CONTCAR','w') + f.write('ASE-DPKit-FAILED-nan\n') + f.write('1.0\n') + for i in range(3): + f.write('%15.10f %15.10f %15.10f\n' % tuple(lat[i])) + for x in element: + f.write(x + ' ') + f.write('\n') + for x in element: + f.write(str(ele[x]) + ' ') + f.write('\n') + f.write('Direct\n') + na = sum(ele.values()) + dpos = np.dot(pos,np.linalg.inv(lat)) + for i in range(na): + f.write('%15.10f %15.10f %15.10f\n' % tuple(dpos[i])) + +def Write_Outcar(element, ele, volume, lat, pos, ene, force, stress,pstress): + '''Write OUTCAR''' + f = open('OUTCAR','w') + for x in element: + f.write('VRHFIN =' + str(x) + '\n') + f.write('ions per type =') + for x in element: + f.write('%5d' % ele[x]) f.write('\nDirection XX YY ZZ XY YZ ZX\n') - f.write('in kB') - f.write('%15.6f' % stress[0]) - f.write('%15.6f' % stress[1]) - f.write('%15.6f' % stress[2]) - f.write('%15.6f' % stress[3]) - f.write('%15.6f' % stress[4]) - f.write('%15.6f' % stress[5]) - f.write('\n') - ext_pressure = np.sum(stress[0] + stress[1] + stress[2])/3.0 - pstress + f.write('in kB') + f.write('%15.6f' % stress[0]) + f.write('%15.6f' % stress[1]) + f.write('%15.6f' % stress[2]) + f.write('%15.6f' % stress[3]) + f.write('%15.6f' % stress[4]) + f.write('%15.6f' % stress[5]) + f.write('\n') + ext_pressure = np.sum(stress[0] + stress[1] + stress[2])/3.0 - pstress f.write('external pressure = %20.6f kB Pullay stress = %20.6f kB\n'% (ext_pressure, pstress)) - f.write('volume of cell : %20.6f\n' % volume) - f.write('direct lattice vectors\n') - for i in range(3): - f.write('%10.6f %10.6f %10.6f\n' % tuple(lat[i])) - f.write('POSITION TOTAL-FORCE(eV/Angst)\n') - f.write('-------------------------------------------------------------------\n') - na = sum(ele.values()) - for i in range(na): - f.write('%15.6f %15.6f %15.6f' % tuple(pos[i])) - f.write('%15.6f %15.6f %15.6f\n' % tuple(force[i])) - f.write('-------------------------------------------------------------------\n') - f.write('energy without entropy= %20.6f %20.6f\n' % (ene, ene)) - enthalpy = ene + pstress * volume / 1602.17733 - f.write('enthalpy is TOTEN = %20.6f %20.6f\n' % (enthalpy, enthalpy)) - -def check(): - - from deepmd.calculator import DP - from ase.io import read - model_path = sys.argv[1] - Model_List = glob.glob('%s/graph*pb'%model_path) - calc = DP(model='%s'%(Model_List[0])) # init the model before iteration - - to_be_opti = read('POSCAR') - to_be_opti.calc = calc - # --------------------------------- - # for failed outcar - atoms_symbols_f = to_be_opti.get_chemical_symbols() - element_f, ele_f = Get_Element_Num(atoms_symbols_f) - atoms_vol_f = to_be_opti.get_volume() - atoms_stress_f = to_be_opti.get_stress() - atoms_stress_f = atoms_stress_f/(0.01*0.6242) - atoms_lat_f = to_be_opti.cell - atoms_pos_f = to_be_opti.positions - atoms_force_f = to_be_opti.get_forces() - atoms_ene_f = 610612509 - # --------------------------------- - Write_Contcar(element_f, ele_f, atoms_lat_f, atoms_pos_f) + f.write('volume of cell : %20.6f\n' % volume) + f.write('direct lattice vectors\n') + for i in range(3): + f.write('%10.6f %10.6f %10.6f\n' % tuple(lat[i])) + f.write('POSITION TOTAL-FORCE(eV/Angst)\n') + f.write('-------------------------------------------------------------------\n') + na = sum(ele.values()) + for i in range(na): + f.write('%15.6f %15.6f %15.6f' % tuple(pos[i])) + f.write('%15.6f %15.6f %15.6f\n' % tuple(force[i])) + f.write('-------------------------------------------------------------------\n') + f.write('energy without entropy= %20.6f %20.6f\n' % (ene, ene)) + enthalpy = ene + pstress * volume / 1602.17733 + f.write('enthalpy is TOTEN = %20.6f %20.6f\n' % (enthalpy, enthalpy)) + +def check(): + + from deepmd.calculator import DP + from ase.io import read + calc = DP(model='../graph.000.pb') # init the model before iteration + + to_be_opti = read('POSCAR') + to_be_opti.calc = calc + # --------------------------------- + # for failed outcar + atoms_symbols_f = to_be_opti.get_chemical_symbols() + element_f, ele_f = Get_Element_Num(atoms_symbols_f) + atoms_vol_f = to_be_opti.get_volume() + atoms_stress_f = to_be_opti.get_stress() + atoms_stress_f = atoms_stress_f/(0.01*0.6242) + atoms_lat_f = to_be_opti.cell + atoms_pos_f = to_be_opti.positions + atoms_force_f = to_be_opti.get_forces() + atoms_ene_f = 610612509 + # --------------------------------- + Write_Contcar(element_f, ele_f, atoms_lat_f, atoms_pos_f) Write_Outcar(element_f, ele_f, atoms_vol_f, atoms_lat_f, atoms_pos_f,atoms_ene_f, atoms_force_f, atoms_stress_f * -10.0, 0) -cwd = os.getcwd() -if not os.path.exists(os.path.join(cwd,'OUTCAR')): - check() +cwd = os.getcwd() +if not os.path.exists(os.path.join(cwd,'OUTCAR')): + check() diff --git a/dpgen/generator/lib/calypso_run_model_devi.py b/dpgen/generator/lib/calypso_run_model_devi.py index c4d5b5f27..95f7e7d37 100644 --- a/dpgen/generator/lib/calypso_run_model_devi.py +++ b/dpgen/generator/lib/calypso_run_model_devi.py @@ -70,9 +70,12 @@ def Modd(all_models,type_map): pdata.to_vasp_poscar(os.path.join(put_poscar,'%s.poscar'%str(index))) nopbc = pdata.nopbc coord = pdata.data['coords'] - cell = pdata.data['cells'] + cell = pdata.data['cells'] if not nopbc else None atom_types = pdata.data['atom_types'] - devi = calc_model_devi(coord,cell,atom_types,graphs,nopbc=nopbc) + try: + devi = calc_model_devi(coord,cell,atom_types,graphs,nopbc=nopbc) + except TypeError: + devi = calc_model_devi(coord,cell,atom_types,graphs) # ------------------------------------------------------------------------------------ # append min-distance in devi list dis = pdata.to_ase_structure()[0].get_all_distances(mic=True) diff --git a/dpgen/generator/lib/calypso_run_opt.py b/dpgen/generator/lib/calypso_run_opt.py index 3344d0f37..dc84864fd 100644 --- a/dpgen/generator/lib/calypso_run_opt.py +++ b/dpgen/generator/lib/calypso_run_opt.py @@ -1,88 +1,82 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import os,sys,glob,time -import numpy as np -from ase.io import read -from ase.optimize import BFGS,QuasiNewton,LBFGS +import os,sys,glob,time +import numpy as np +from ase.io import read +from ase.optimize import BFGS,QuasiNewton,LBFGS from ase.constraints import UnitCellFilter, ExpCellFilter -from deepmd.calculator import DP +from deepmd.calculator import DP ''' structure optimization with DP model and ASE PSTRESS and fmax should exist in input.dat ''' - -def Get_Element_Num(elements): - '''Using the Atoms.symples to Know Element&Num''' - element = [] - ele = {} - element.append(elements[0]) - for x in elements: - if x not in element : - element.append(x) - for x in element: - ele[x] = elements.count(x) - return element, ele - -def Write_Contcar(element, ele, lat, pos): - '''Write CONTCAR''' - f = open('CONTCAR','w') - f.write('ASE-DPKit-Optimization\n') - f.write('1.0\n') - for i in range(3): - f.write('%15.10f %15.10f %15.10f\n' % tuple(lat[i])) - for x in element: - f.write(x + ' ') - f.write('\n') - for x in element: - f.write(str(ele[x]) + ' ') - f.write('\n') - f.write('Direct\n') - na = sum(ele.values()) - dpos = np.dot(pos,np.linalg.inv(lat)) - for i in range(na): - f.write('%15.10f %15.10f %15.10f\n' % tuple(dpos[i])) - -def Write_Outcar(element, ele, volume, lat, pos, ene, force, stress,pstress): - '''Write OUTCAR''' - f = open('OUTCAR','w') - for x in element: - f.write('VRHFIN =' + str(x) + '\n') - f.write('ions per type =') - for x in element: - f.write('%5d' % ele[x]) - #f.write('\nvolume of cell :\n') + +def Get_Element_Num(elements): + '''Using the Atoms.symples to Know Element&Num''' + element = [] + ele = {} + element.append(elements[0]) + for x in elements: + if x not in element : + element.append(x) + for x in element: + ele[x] = elements.count(x) + return element, ele + +def Write_Contcar(element, ele, lat, pos): + '''Write CONTCAR''' + f = open('CONTCAR','w') + f.write('ASE-DPKit-Optimization\n') + f.write('1.0\n') + for i in range(3): + f.write('%15.10f %15.10f %15.10f\n' % tuple(lat[i])) + for x in element: + f.write(x + ' ') + f.write('\n') + for x in element: + f.write(str(ele[x]) + ' ') + f.write('\n') + f.write('Direct\n') + na = sum(ele.values()) + dpos = np.dot(pos,np.linalg.inv(lat)) + for i in range(na): + f.write('%15.10f %15.10f %15.10f\n' % tuple(dpos[i])) + +def Write_Outcar(element, ele, volume, lat, pos, ene, force, stress,pstress): + '''Write OUTCAR''' + f = open('OUTCAR','w') + for x in element: + f.write('VRHFIN =' + str(x) + '\n') + f.write('ions per type =') + for x in element: + f.write('%5d' % ele[x]) f.write('\nDirection XX YY ZZ XY YZ ZX\n') - f.write('in kB') - f.write('%15.6f' % stress[0]) - f.write('%15.6f' % stress[1]) - f.write('%15.6f' % stress[2]) - f.write('%15.6f' % stress[3]) - f.write('%15.6f' % stress[4]) - f.write('%15.6f' % stress[5]) - f.write('\n') - ext_pressure = np.sum(stress[0] + stress[1] + stress[2])/3.0 - pstress + f.write('in kB') + f.write('%15.6f' % stress[0]) + f.write('%15.6f' % stress[1]) + f.write('%15.6f' % stress[2]) + f.write('%15.6f' % stress[3]) + f.write('%15.6f' % stress[4]) + f.write('%15.6f' % stress[5]) + f.write('\n') + ext_pressure = np.sum(stress[0] + stress[1] + stress[2])/3.0 - pstress f.write('external pressure = %20.6f kB Pullay stress = %20.6f kB\n'% (ext_pressure, pstress)) - f.write('volume of cell : %20.6f\n' % volume) - f.write('direct lattice vectors\n') - for i in range(3): - f.write('%10.6f %10.6f %10.6f\n' % tuple(lat[i])) + f.write('volume of cell : %20.6f\n' % volume) + f.write('direct lattice vectors\n') + for i in range(3): + f.write('%10.6f %10.6f %10.6f\n' % tuple(lat[i])) f.write('POSITION TOTAL-FORCE(eV/Angst)\n') - f.write('-------------------------------------------------------------------\n') - na = sum(ele.values()) - for i in range(na): - f.write('%15.6f %15.6f %15.6f' % tuple(pos[i])) - f.write('%15.6f %15.6f %15.6f\n' % tuple(force[i])) - f.write('-------------------------------------------------------------------\n') - f.write('energy without entropy= %20.6f %20.6f\n' % (ene, ene/na)) - enthalpy = ene + pstress * volume / 1602.17733 - f.write('enthalpy is TOTEN = %20.6f %20.6f\n' % (enthalpy, enthalpy/na)) - -def Write_calylog(templog): - '''For Write Evolve Structures Log into caly.log''' - f = open('opt.log','a+') - f.write(templog+'\n') - f.close() + f.write('-------------------------------------------------------------------\n') + na = sum(ele.values()) + for i in range(na): + f.write('%15.6f %15.6f %15.6f' % tuple(pos[i])) + f.write('%15.6f %15.6f %15.6f\n' % tuple(force[i])) + f.write('-------------------------------------------------------------------\n') + f.write('energy without entropy= %20.6f %20.6f\n' % (ene, ene/na)) + enthalpy = ene + pstress * volume / 1602.17733 + f.write('enthalpy is TOTEN = %20.6f %20.6f\n' % (enthalpy, enthalpy/na)) + def read_stress_fmax(): pstress = 0 fmax = 0.01 @@ -102,75 +96,53 @@ def read_stress_fmax(): if 'fmax' in line: fmax = float(line.split('=')[1]) return fmax,pstress - - -def run_opt(fmax,stress): - '''Using the ASE&DP to Optimize Configures''' - ''' > 600 Steps Called Failure Optimization''' + +def run_opt(fmax,stress): + '''Using the ASE&DP to Optimize Configures''' + calc = DP(model='../graph.000.pb') # init the model before iteration os.system('mv OUTCAR OUTCAR-last') - is_dpgen = True - nn = 1 - try: - model_path = sys.argv[1] - Model_List = glob.glob('%s/graph*pb'%model_path) - calc = DP(model=Model_List[0]) # init the model before iteration - except: - assert os.path.exists('graph.pb'), 'did not found graph.pb in this directory %s, or did you forget to add args?'%(os.getcwd()) - calc = DP(model='graph.pb') # init the model before iteration - is_dpgen = False - nn = 3 - - print('Start to Optimize Structures by DP----------') - - Opt_Step = 600 - start = time.time() + + print('Start to Optimize Structures by DP----------') + + Opt_Step = 1000 + start = time.time() # pstress kbar pstress = stress # kBar to eV/A^3 # 1 eV/A^3 = 160.21766028 GPa # 1 / 160.21766028 ~ 0.006242 - aim_stress = 1.0 * pstress* 0.01 * 0.6242 / 10.0 - to_be_opti = read('POSCAR') - to_be_opti.calc = calc + aim_stress = 1.0 * pstress* 0.01 * 0.6242 / 10.0 + to_be_opti = read('POSCAR') + to_be_opti.calc = calc ucf = UnitCellFilter(to_be_opti, scalar_pressure=aim_stress) - atoms_vol_2 = to_be_opti.get_volume() - for i in range(nn): - if is_dpgen: - opt = LBFGS(ucf,trajectory='traj.traj') - else: - opt = LBFGS(ucf) - #opt = QuasiNewton(to_be_opti) - #opt = BFGS(to_be_opti) - #opt = BFGS(to_be_opti,trajectory='traj.traj',logfile='opt.log') - opt.run(fmax=fmax,steps=Opt_Step) - - atoms_lat = to_be_opti.cell - atoms_pos = to_be_opti.positions - atoms_force = to_be_opti.get_forces() - atoms_stress = to_be_opti.get_stress() - # eV/A^3 to GPa - atoms_stress = atoms_stress/(0.01*0.6242) - #atoms_num = to_be_opti.get_atomic_numbers() - atoms_symbols = to_be_opti.get_chemical_symbols() - #atoms_formula = to_be_opti.get_chemical_formula() - atoms_ene = to_be_opti.get_potential_energy() - atoms_vol = to_be_opti.get_volume() - - element, ele = Get_Element_Num(atoms_symbols) - - Write_Contcar(element, ele, atoms_lat, atoms_pos) - Write_Outcar(element, ele, atoms_vol, atoms_lat, atoms_pos,atoms_ene, atoms_force, atoms_stress * -10.0, pstress) - - - stop = time.time() - _cwd = os.getcwd() - _cwd = os.path.basename(_cwd) - print('%s is done, time: %s' % (_cwd,stop-start)) + atoms_vol_2 = to_be_opti.get_volume() + # opt + opt = LBFGS(ucf,trajectory='traj.traj') + opt.run(fmax=fmax,steps=Opt_Step) + + atoms_lat = to_be_opti.cell + atoms_pos = to_be_opti.positions + atoms_force = to_be_opti.get_forces() + atoms_stress = to_be_opti.get_stress() + # eV/A^3 to GPa + atoms_stress = atoms_stress/(0.01*0.6242) + atoms_symbols = to_be_opti.get_chemical_symbols() + atoms_ene = to_be_opti.get_potential_energy() + atoms_vol = to_be_opti.get_volume() + element, ele = Get_Element_Num(atoms_symbols) + + Write_Contcar(element, ele, atoms_lat, atoms_pos) + Write_Outcar(element, ele, atoms_vol, atoms_lat, atoms_pos,atoms_ene, atoms_force, atoms_stress * -10.0, pstress) + + stop = time.time() + _cwd = os.getcwd() + _cwd = os.path.basename(_cwd) + print('%s is done, time: %s' % (_cwd,stop-start)) def run(): fmax, stress = read_stress_fmax() - run_opt(fmax, stress) + run_opt(fmax, stress) if __name__=='__main__': - run() + run() diff --git a/dpgen/generator/lib/make_calypso.py b/dpgen/generator/lib/make_calypso.py index 4c5ce7d66..bb2db0af8 100644 --- a/dpgen/generator/lib/make_calypso.py +++ b/dpgen/generator/lib/make_calypso.py @@ -2,7 +2,9 @@ import os import shutil import json +import glob import numpy as np +from dpgen.generator.lib.utils import create_path def make_calypso_input(nameofatoms,numberofatoms, numberofformula,volume, @@ -11,20 +13,23 @@ def make_calypso_input(nameofatoms,numberofatoms, maxnumatom,ctrlrange,pstress,fmax): ret = "################################ The Basic Parameters of CALYPSO ################################\n" ret+= "# A string of one or several words contain a descriptive name of the system (max. 40 characters).\n" - assert (nameofatoms != None ) + assert nameofatoms is not None ret+= "SystemName = %s\n"%(''.join(nameofatoms)) ret+= "# Number of different atomic species in the simulation.\n" ret+= "NumberOfSpecies = %d\n"%(len(nameofatoms)) ret+= "# Element symbols of the different chemical species.\n" ret+= "NameOfAtoms = %s\n"%(' '.join(nameofatoms)) ret+= "# Number of atoms for each chemical species in one formula unit. \n" - assert numberofatoms != None or len(numberofatoms) == len(nameofatoms) + assert numberofatoms is not None and len(numberofatoms) == len(nameofatoms) ret+= "NumberOfAtoms = %s\n"%(' '.join(list(map(str,numberofatoms)))) ret+= "# The range of formula unit per cell in your simulation. \n" - assert numberofformula != None or len(numberofformula) == 2 or type(numberofformula) == type([1,2]) + assert numberofformula is not None and len(numberofformula) == 2 and type(numberofformula) is list ret+= "NumberOfFormula = %s\n"%(' '.join(list(map(str,numberofformula)))) ret+= "# The volume per formula unit. Unit is in angstrom^3.\n" - ret+= "Volume = %s\n"%(volume[0]) + if volume is None: + ret+= "# volume not found, CALYPSO will set one!\n" + else: + ret+= "Volume = %s\n"%(volume) ret+= "# Minimal distance between atoms of each chemical species. Unit is in angstrom.\n" assert len(distanceofion) == len(nameofatoms) #"check distance of ions and the number of atoms" assert len(distanceofion[0]) == len(nameofatoms) @@ -37,14 +42,14 @@ def make_calypso_input(nameofatoms,numberofatoms, ret+= "# Ialgo = 1 for Global PSO\n" ret+= "# Ialgo = 2 for Local PSO (default value)\n" ret+= "# The proportion of the structures generated by PSO.\n" - assert (0 <= psoratio[0] <= 1 ) - ret+= "PsoRatio = %s\n"%(psoratio[0]) + assert (0 <= psoratio <= 1 ) + ret+= "PsoRatio = %s\n"%(psoratio) ret+= "# The population size. Normally, it has a larger number for larger systems.\n" - assert popsize[0] != None or popsize!=None or type(popsize) == type([0,1]) or type(popsize[0]) == type(0) - ret+= "PopSize = %d\n"%(popsize[0]) - assert maxstep[0] != None or maxstep!=None or type(maxstep) == type([0,1]) or type(maxstep[0]) == type(0) + assert popsize is not None and type(popsize) is int + ret+= "PopSize = %d\n"%(popsize) + assert maxstep is not None and type(maxstep) is int ret+= "# The Max step for iteration\n" - ret+= "MaxStep = %d\n"%(maxstep[0]) + ret+= "MaxStep = %d\n"%(maxstep) ret+= "#It determines which method should be adopted in generation the random structure. \n" ret+= "GenType= 1 \n" ret+= "# 1 under symmetric constraints\n" @@ -53,8 +58,8 @@ def make_calypso_input(nameofatoms,numberofatoms, ret+= "# 0 combination of all method\n" ret+= "# If GenType=3 or 4, it determined the small unit to grow the whole structure\n" ret+= "# It determines which local optimization method should be interfaced in the simulation.\n" - assert icode != None or type(icode) == type([0,1]) or type(icode[0]) == type(0) - ret+= "ICode= %d\n"%(icode[0]) + assert icode is not None and type(icode) is int + ret+= "ICode= %d\n"%(icode) ret+= "# ICode= 1 interfaced with VASP\n" ret+= "# ICode= 2 interfaced with SIESTA\n" ret+= "# ICode= 3 interfaced with GULP\n" @@ -73,12 +78,12 @@ def make_calypso_input(nameofatoms,numberofatoms, ret+= "Parallel = F\n" ret+= "# The number node for parallel \n" ret+= "NumberOfParallel = 4\n" - assert split != None + assert split is not None ret+= "Split = %s\n"%(split) - assert pstress != None or type(pstress) == type([200]) - ret+= "PSTRESS = %f\n"%(pstress[0]) - assert fmax != None or type(fmax) == type([200]) - ret+= "fmax = %f\n"%(fmax[0]) + assert pstress is not None and (type(pstress) is int or type(pstress) is float) + ret+= "PSTRESS = %f\n"%(pstress) + assert fmax is not None or type(fmax) is float + ret+= "fmax = %f\n"%(fmax) ret+= "################################ End of The Basic Parameters of CALYPSO #######################\n" if vsc == 'T': assert len(ctrlrange) == len(nameofatoms) #'check distance of ions and the number of atoms' @@ -86,7 +91,7 @@ def make_calypso_input(nameofatoms,numberofatoms, ret+= "## If True, Variational Stoichiometry structure prediction is performed\n" ret+= "VSC = %s\n"%(vsc) ret+= "# The Max Number of Atoms in unit cell\n" - ret+= "MaxNumAtom = %s\n"%(maxnumatom[0]) + ret+= "MaxNumAtom = %s\n"%(maxnumatom) ret+= "# The Variation Range for each type atom \n" ret+= "@CtrlRange\n" for ttemp in ctrlrange: @@ -98,7 +103,29 @@ def make_calypso_input(nameofatoms,numberofatoms, def _make_model_devi_buffet(jdata,calypso_run_opt_path): calypso_input_path = jdata.get('calypso_input_path') - shutil.copyfile(os.path.join(calypso_input_path,'input.dat'),os.path.join(calypso_run_opt_path, 'input.dat')) + if jdata.get('vsc', False): + # [input.dat.Li.250, input.dat.Li.300] + one_ele_inputdat_list = list( + set(glob.glob( + f"{jdata.get('calypso_input_path')}/input.dat.{jdata.get('type_map')[0]}.*" + )) + ) + # [input.dat.La, input.dat.H, input.dat.LaH,] only one pressure + if len(one_ele_inputdat_list) == 0: + os.system(f"cp {calypso_input_path}/input.dat.* {calypso_run_opt_path[0]}") + # different pressure, 250GPa and 300GPa + # [input.dat.La.250, input.dat.H.250, input.dat.LaH.250, input.dat.La.300, input.dat.H.300, input.dat.LaH.300,] + else: + pressures_list = [temp.split('.')[-1] for temp in one_ele_inputdat_list] + pressures_list = list(map(int, pressures_list)) + # calypso_run_opt_path = ['gen_struc_analy.000','gen_struc_analy.001'] + for press_idx, temp_calypso_run_opt_path in enumerate(calypso_run_opt_path): + cur_press = pressures_list[press_idx] + os.system(f"cp {calypso_input_path}/input.dat.*.{cur_press} {temp_calypso_run_opt_path}") + elif not jdata.get('vsc', False): + shutil.copyfile(os.path.join(calypso_input_path,'input.dat'),os.path.join(calypso_run_opt_path[0], 'input.dat')) + if not os.path.exists(os.path.join(calypso_run_opt_path[0], 'input.dat')): + raise FileNotFoundError('input.dat') def _make_model_devi_native_calypso(iter_index,model_devi_jobs, calypso_run_opt_path): @@ -106,7 +133,8 @@ def _make_model_devi_native_calypso(iter_index,model_devi_jobs, calypso_run_opt_ if iter_index in jobbs.get('times'): cur_job = model_devi_jobs[iiidx] - work_path = os.path.dirname(calypso_run_opt_path) + work_path = os.path.dirname(calypso_run_opt_path[0]) + # cur_job.json with open(os.path.join(work_path, 'cur_job.json'), 'w') as outfile: json.dump(cur_job, outfile, indent = 4) @@ -116,11 +144,15 @@ def _make_model_devi_native_calypso(iter_index,model_devi_jobs, calypso_run_opt_ numberofformula = cur_job.get('NumberOfFormula',[1,1]) volume = cur_job.get('Volume') distanceofion = cur_job.get('DistanceOfIon') - psoratio = cur_job.get('PsoRatio') - popsize = cur_job.get('PopSize') - maxstep = cur_job.get('MaxStep') - icode = cur_job.get('ICode',[1]) + psoratio = cur_job.get('PsoRatio', 0.6) + popsize = cur_job.get('PopSize', 30) + maxstep = cur_job.get('MaxStep', 5) + icode = cur_job.get('ICode',1) split = cur_job.get('Split','T') + # Cluster + + # 2D + # VSC Control maxnumatom = None ctrlrange = None @@ -128,22 +160,21 @@ def _make_model_devi_native_calypso(iter_index,model_devi_jobs, calypso_run_opt_ if vsc == 'T': maxnumatom = cur_job.get('MaxNumAtom') ctrlrange = cur_job.get('CtrlRange') - # Optimization + fmax = cur_job.get('fmax',0.01) + # pstress is a List which contains the target stress pstress = cur_job.get('PSTRESS',[0.001]) - fmax = cur_job.get('fmax',[0.01]) - - # Cluster - - # 2D - - file_c = make_calypso_input(nameofatoms,numberofatoms, + # pressures + for press_idx, temp_calypso_run_opt_path in enumerate(calypso_run_opt_path): + # cur_press + cur_press = pstress[press_idx] + file_c = make_calypso_input(nameofatoms,numberofatoms, numberofformula,volume, distanceofion,psoratio,popsize, maxstep,icode,split,vsc, - maxnumatom,ctrlrange,pstress,fmax) - with open(os.path.join(calypso_run_opt_path, 'input.dat'), 'w') as cin : - cin.write(file_c) + maxnumatom,ctrlrange,cur_press,fmax) + with open(os.path.join(temp_calypso_run_opt_path, 'input.dat'), 'w') as cin : + cin.write(file_c) def write_model_devi_out(devi, fname): assert devi.shape[1] == 8 diff --git a/dpgen/generator/lib/parse_calypso.py b/dpgen/generator/lib/parse_calypso.py index 123a77e94..df842c789 100644 --- a/dpgen/generator/lib/parse_calypso.py +++ b/dpgen/generator/lib/parse_calypso.py @@ -2,10 +2,13 @@ import os def _parse_calypso_input(var,input_path): - try: - f = open(input_path,'r') - except: - f = open(os.path.join(input_path,'input.dat'),'r') + + if os.path.basename(input_path) != 'input.dat': + input_path = os.path.join(input_path,'input.dat') + if not os.path.exists(input_path): + raise FileNotFoundError(input_path) + + f = open(input_path,'r') lines = f.readlines() f.close() diff --git a/dpgen/generator/lib/run_calypso.py b/dpgen/generator/lib/run_calypso.py index c15989486..5fc0ad934 100644 --- a/dpgen/generator/lib/run_calypso.py +++ b/dpgen/generator/lib/run_calypso.py @@ -14,11 +14,14 @@ import re import glob import shutil +import sys from ase.io.vasp import write_vasp from ase.io.trajectory import Trajectory from pathlib import Path +from itertools import combinations from distutils.version import LooseVersion from dpgen import dlog +from dpgen.generator.lib.utils import create_path from dpgen.generator.lib.utils import make_iter_name from dpgen.generator.lib.parse_calypso import _parse_calypso_input from dpgen.dispatcher.Dispatcher import make_dispatcher, make_submission @@ -29,7 +32,7 @@ calypso_run_opt_name = 'gen_stru_analy' calypso_model_devi_name = 'model_devi_results' -def gen_structures(iter_index,jdata,mdata): +def gen_structures(iter_index, jdata, mdata, caly_run_path, current_idx, length_of_caly_runopt_list): # run calypso # vsc means generate elemental, binary and ternary at the same time @@ -43,22 +46,21 @@ def gen_structures(iter_index,jdata,mdata): iter_name = make_iter_name(iter_index) work_path = os.path.join(iter_name, model_devi_name) assert(os.path.isdir(work_path)) - # - calypso_run_opt_path = os.path.join(work_path,calypso_run_opt_name) + + calypso_run_opt_path = caly_run_path calypso_model_devi_path = os.path.join(work_path,calypso_model_devi_name) - # calypso_path = mdata.get('model_devi_calypso_path') #calypso_input_path = jdata.get('calypso_input_path') - popsize = int(_parse_calypso_input('PopSize',calypso_run_opt_path)) - maxstep = int(_parse_calypso_input('MaxStep',calypso_run_opt_path)) all_models = glob.glob(os.path.join(calypso_run_opt_path, 'graph*pb')) model_names = [os.path.basename(ii) for ii in all_models] deepmdkit_python = mdata.get('model_devi_deepmdkit_python') - command = "%s calypso_run_opt.py %s 1>> model_devi.log 2>> model_devi.log" % (deepmdkit_python,os.path.abspath(calypso_run_opt_path)) - command += " || %s check_outcar.py %s " % (deepmdkit_python,os.path.abspath(calypso_run_opt_path)) + command = "%s calypso_run_opt.py 1>> model_devi.log 2>> model_devi.log" % (deepmdkit_python) + # command = "%s calypso_run_opt.py %s 1>> model_devi.log 2>> model_devi.log" % (deepmdkit_python,os.path.abspath(calypso_run_opt_path)) + # command += " || %s check_outcar.py %s " % (deepmdkit_python,os.path.abspath(calypso_run_opt_path)) + command += " || %s check_outcar.py " % (deepmdkit_python) commands = [command] cwd = os.getcwd() @@ -87,16 +89,13 @@ def gen_structures(iter_index,jdata,mdata): os.mkdir('opt') except: pass - #shutil.rmtree('opt') - #os.mkdir('opt') + popsize = int(_parse_calypso_input('PopSize', '.')) + maxstep = int(_parse_calypso_input('MaxStep', '.')) for ii in range(int(PickUpStep)-1,maxstep+1): dlog.info('CALYPSO step %s'%ii) if ii == maxstep : - while True: - if len(glob.glob('OUTCAR_*')) == popsize: - break os.system('%s'%run_calypso) break # run calypso @@ -179,17 +178,38 @@ def gen_structures(iter_index,jdata,mdata): else: # -------------------------------------------------------------- - # TODO(zhenyu) make this code work for other situation - component = ['Mg','Al','Cu','MgAl','MgCu','AlCu','MgAlCu'] + type_map = jdata['type_map'] + how_many_spec = len(type_map) + if how_many_spec == 1: + dlog.info('vsc mode can not work in one-element situation' ) + sys.exit() + + comp_temp = list(map(list,list(combinations(type_map,1)))) + for hms in range(2,how_many_spec+1): + # comp_temp = [['Mg'],['Al'],['Cu'],['Mg','Al'],['Mg','Cu'],['Al','Cu'],['Mg','Al','Cu']] + comp_temp.extend(list(map(list,list(combinations(type_map,hms))))) + + component = [] + for comp_temp_ in comp_temp: + component.append(''.join(comp_temp_)) # component = ['Mg','Al','Cu','MgAl','MgCu','AlCu','MgAlCu'] + + dlog.info(component) + # calypso_input_path = jdata.get('calypso_input_path') - for idx,com in enumerate(component): - pwd = os.getcwd() - os.mkdir(str(idx)) - shutil.copyfile(os.path.join(cwd,'calypso_input','input.dat.%s'%com),os.path.join(str(idx),'input.dat')) - os.chdir(str(idx)) + pwd = os.getcwd() + if len(glob.glob(f'input.dat.{component[0]}.*')) != 0: + os.system('for i in input.dat.*;do mv $i ${i%.*};done') + for idx, com in enumerate(component): + if not os.path.exists(com): + os.mkdir(com) + #shutil.copyfile(os.path.join(calypso_input_path,'input.dat.%s'%com),os.path.join(com,'input.dat')) + shutil.copyfile('input.dat.%s'%com ,os.path.join(com,'input.dat')) + os.chdir(com) os.system(run_calypso) os.chdir(pwd) - + + shutil.copyfile('input.dat.%s'%component[-1], 'input.dat') + name_list = Path('.').glob('*/POSCAR_*') for idx,name in enumerate(name_list): shutil.copyfile(name,'POSCAR_%s'%(idx+1)) @@ -203,7 +223,9 @@ def gen_structures(iter_index,jdata,mdata): shutil.copyfile('POSCAR_%s'%str(idx+1),os.path.join('task.%04d'%(idx+1),'POSCAR')) shutil.copyfile('input.dat',os.path.join('task.%04d'%(idx+1),'input.dat')) - all_task = glob.glob( "task.*") + # sys.exit() + + all_task = glob.glob("task.*") all_task.sort() run_tasks_ = all_task @@ -260,37 +282,59 @@ def gen_structures(iter_index,jdata,mdata): shutil.rmtree(t) # -------------------------------------------------------------- + if current_idx < length_of_caly_runopt_list - 1: + tobewrite = '1 %s\n'%(str(current_idx + 1)) + elif current_idx == length_of_caly_runopt_list - 1 : + tobewrite = '2\n' + os.chdir(cwd) os.chdir(work_path) f = open('record.calypso','a+') - f.write('2\n') + f.write(tobewrite) f.close() os.chdir(cwd) -def analysis(iter_index,jdata,calypso_run_opt_path,calypso_model_devi_path): +def gen_main(iter_index, jdata, mdata, caly_run_opt_list, gen_idx): - # Analysis + iter_name = make_iter_name(iter_index) + work_path = os.path.join(iter_name, model_devi_name) + current_gen_path = os.path.join(work_path, '%s.%03d'%(calypso_run_opt_name, int(gen_idx))) + if current_gen_path not in caly_run_opt_list: + dlog.info(f"current gen path {current_gen_path} not in caly run opt list {caly_run_opt_list}") + sys.exit() - #dlog.info('$$$$$$$$$$$$$$$ Analysis Started $$$$$$$$$$$$$$$$$$') + indice = caly_run_opt_list.index(current_gen_path) + for iidx, temp_path in enumerate(caly_run_opt_list): + if iidx >= indice: + gen_structures(iter_index, jdata, mdata, temp_path, iidx, len(caly_run_opt_list)) + + +def analysis(iter_index, jdata, calypso_model_devi_path): + # Analysis ms = dpdata.MultiSystems() cwd = os.getcwd() iter_name = make_iter_name(iter_index) work_path = os.path.join(iter_name, model_devi_name) - result_path = os.path.join(calypso_run_opt_path,'results') - # trajs to be model devi - traj_path = os.path.join(calypso_run_opt_path,'traj') - traj_list = glob.glob(traj_path+'/*.traj') + deepmd_data_path = os.path.join(work_path,'confs', 'deepmd') + traj_pos_path = os.path.join(work_path,'confs', 'traj_confs') + create_path(deepmd_data_path) + create_path(traj_pos_path) - #dlog.info('len(traj_list) %s'%str(len(traj_list))) + # trajs to be model devi + # traj_path = os.path.join(calypso_run_opt_path,'traj') + # traj_list = glob.glob(traj_path+'/*.traj') + # 'gen_struc_analy.000/traj/*.traj' 'gen_struc_analy.001/traj/*.traj' 'gen_struc_analy.002/traj/*.traj' + traj_list = glob.glob(f'{work_path}/*/traj/*.traj') - # read confs from traj + # read poscar from traj file in confs/traj/*.traj record_traj_num = 0 for traj_name in traj_list: traj_num = os.path.basename(traj_name).split('.')[0] + press_num = traj_name.split('/')[-3].split('.')[-1] trajs_origin = Trajectory(traj_name) record_traj_num += len(trajs_origin) @@ -311,16 +355,13 @@ def analysis(iter_index,jdata,calypso_run_opt_path,calypso_model_devi_path): for idx, traj in enumerate(trajs): write_vasp(os.path.join( - traj_path,'%03d.%03d.poscar' % ( - int(traj_num), int(idx) + traj_pos_path,'%d.%03d.%03d.poscar' % ( + int(press_num), int(traj_num), int(idx) ) ), traj) - traj_pos_list = glob.glob(traj_path+'/*.poscar') - - #dlog.info('traj_num %s'%str(len(traj_pos_list))) - #dlog.info('total_traj_num %s'%str(record_traj_num)) + traj_pos_list = glob.glob(traj_pos_path+'/*.poscar') for npos in traj_pos_list: try: @@ -329,20 +370,16 @@ def analysis(iter_index,jdata,calypso_run_opt_path,calypso_model_devi_path): dlog.info(npos,'failed : ',e) if len(ms) == 0: - print('too little confs, ') - return + dlog.info('too little confs, ') + raise RuntimeError('no confs found in Analysis part and this should not happen!') - if os.path.exists(os.path.join(result_path,'deepmd')): - shutil.rmtree(os.path.join(result_path,'deepmd')) - ms.to_deepmd_raw(os.path.join(result_path,'deepmd')) - ms.to_deepmd_npy(os.path.join(result_path,'deepmd')) - + if os.path.exists(deepmd_data_path): + shutil.rmtree(deepmd_data_path) + ms.to_deepmd_raw(deepmd_data_path) + ms.to_deepmd_npy(deepmd_data_path) - split_lists = glob.glob(os.path.join(result_path,'deepmd','*')) + split_lists = glob.glob(os.path.join(deepmd_data_path,'*')) for i,split_list in enumerate(split_lists): - #ss = dpdata.System(split_list,fmt='deepmd') - #for j in range(ss.get_nframes()): - # ss.to('vasp/poscar',os.path.join(split_list,'%03d.%03d.poscar'%(i,j)),frame_idx=j) strus_path = os.path.join(calypso_model_devi_path,'%03d.structures'%i) if not os.path.exists(strus_path): shutil.copytree(split_list,strus_path) @@ -364,39 +401,45 @@ def run_calypso_model_devi (iter_index, dlog.info('start running CALYPSO') - iter_name = make_iter_name(iter_index) work_path = os.path.join(iter_name, model_devi_name) assert(os.path.isdir(work_path)) - calypso_run_opt_path = os.path.join(work_path,calypso_run_opt_name) calypso_model_devi_path = os.path.join(work_path,calypso_model_devi_name) - cwd = os.getcwd() + _caly_run_opt_list = glob.glob(os.path.join(work_path,'%s.*'%(str(calypso_run_opt_name)))) + caly_run_opt_list = _caly_run_opt_list.copy() + # check if gen_struc_analy.000.bk000 in caly_run_opt_list + for temp_value in _caly_run_opt_list: + if 'bk' in temp_value: + caly_run_opt_list.remove(temp_value) + caly_run_opt_list.sort() + cwd = os.getcwd() record_calypso_path = os.path.join(work_path,'record.calypso') while True: if not os.path.exists(record_calypso_path): f = open(record_calypso_path,'w') - f.write('1\n') - lines = '1' + f.write('1 0\n') + lines = ['1 0\n'] f.close() else: f = open(record_calypso_path,'r') lines = f.readlines() f.close() - if lines[-1].strip().strip('\n') == '1': + if lines[-1].strip().strip('\n').split()[0] == '1': # Gen Structures - gen_structures(iter_index,jdata,mdata) + gen_index = lines[-1].strip().strip('\n').split()[1] + gen_main(iter_index, jdata, mdata, caly_run_opt_list, gen_index) elif lines[-1].strip().strip('\n') == '2': # Analysis & to deepmd/raw - analysis(iter_index,jdata,calypso_run_opt_path,calypso_model_devi_path) + analysis(iter_index, jdata, calypso_model_devi_path) elif lines[-1].strip().strip('\n') == '3': # Model Devi - _calypso_run_opt_path = os.path.abspath(calypso_run_opt_path) + _calypso_run_opt_path = os.path.abspath(caly_run_opt_list[0]) all_models = glob.glob(os.path.join(_calypso_run_opt_path, 'graph*pb')) cwd = os.getcwd() os.chdir(calypso_model_devi_path) @@ -407,5 +450,6 @@ def run_calypso_model_devi (iter_index, os.chdir(cwd) elif lines[-1].strip().strip('\n') == '4': - #dlog.info('Model Devi is done.') + dlog.info('Model Devi is done.') + # return break diff --git a/dpgen/generator/run.py b/dpgen/generator/run.py index 7de7854c0..24baf1ed4 100644 --- a/dpgen/generator/run.py +++ b/dpgen/generator/run.py @@ -779,6 +779,7 @@ def make_model_devi (iter_index, return False else: # mode 1: generate structures according to the user-provided input.dat file, so calypso_input_path and model_devi_max_iter are needed + run_mode = 1 if "calypso_input_path" in jdata: try: maxiter = jdata.get('model_devi_max_iter') @@ -788,10 +789,11 @@ def make_model_devi (iter_index, else: try: maxiter = max(model_devi_jobs[-1].get('times')) + run_mode = 2 except KeyError: raise KeyError('did not find model_devi_jobs["times"] key') if (iter_index > maxiter) : - print(f'iter_index is {iter_index} and maxiter is {maxiter}') + dlog.info(f'iter_index is {iter_index} and maxiter is {maxiter}') return False if "sys_configs_prefix" in jdata: @@ -808,7 +810,7 @@ def make_model_devi (iter_index, cur_job = model_devi_jobs[iter_index] sys_idx = expand_idx(cur_job['sys_idx']) else: - cur_job = [] + cur_job = {'model_devi_engine':'calypso','input.dat':'user_provided'} sys_idx = [] if (len(sys_idx) != len(list(set(sys_idx)))) : @@ -831,25 +833,65 @@ def make_model_devi (iter_index, work_path = os.path.join(iter_name, model_devi_name) create_path(work_path) if model_devi_engine == 'calypso': - calypso_run_opt_path = os.path.join(work_path,calypso_run_opt_name) + _calypso_run_opt_path = os.path.join(work_path,calypso_run_opt_name) calypso_model_devi_path = os.path.join(work_path,calypso_model_devi_name) - create_path(calypso_run_opt_path) create_path(calypso_model_devi_path) # run model devi script calypso_run_model_devi_script = os.path.join(calypso_model_devi_path,'calypso_run_model_devi.py') shutil.copyfile(calypso_run_model_devi_file,calypso_run_model_devi_script) - # run confs opt script - run_opt_script = os.path.join(calypso_run_opt_path,'calypso_run_opt.py') - shutil.copyfile(run_opt_file,run_opt_script) - # check outcar script - check_outcar_script = os.path.join(calypso_run_opt_path,'check_outcar.py') - shutil.copyfile(check_outcar_file,check_outcar_script) + # Create work path list + calypso_run_opt_path = [] + + # mode 1: generate structures according to the user-provided input.dat file, + # so calypso_input_path and model_devi_max_iter are needed + if run_mode == 1: + if jdata.get('vsc', False) and len(jdata.get('type_map')) > 1: + # [input.dat.Li.250, input.dat.Li.300] + one_ele_inputdat_list = glob.glob( + f"{jdata.get('calypso_input_path')}/input.dat.{jdata.get('type_map')[0]}.*" + ) + if len(one_ele_inputdat_list) == 0: + number_of_pressure = 1 + else: + number_of_pressure = len(list(set(one_ele_inputdat_list))) + + # calypso_run_opt_path = ['gen_struc_analy.000','gen_struc_analy.001'] + for temp_idx in range(number_of_pressure): + calypso_run_opt_path.append('%s.%03d'%(_calypso_run_opt_path, temp_idx)) + elif not jdata.get('vsc', False): + calypso_run_opt_path.append('%s.%03d'%(_calypso_run_opt_path, 0)) + + # mode 2: control each iteration to generate structures in specific way + # by providing model_devi_jobs key + elif run_mode == 2: + for iiidx, jobbs in enumerate(model_devi_jobs): + if iter_index in jobbs.get('times'): + cur_job = model_devi_jobs[iiidx] + + pressures_list = cur_job.get('PSTRESS', [0.0001]) + for temp_idx in range(len(pressures_list)): + calypso_run_opt_path.append('%s.%03d'%(_calypso_run_opt_path, temp_idx)) + # to different directory + # calypso_run_opt_path = ['gen_struc_analy.000','gen_struc_analy.001','gen_struc_analy.002',] + for temp_calypso_run_opt_path in calypso_run_opt_path: + create_path(temp_calypso_run_opt_path) + # run confs opt script + run_opt_script = os.path.join(temp_calypso_run_opt_path,'calypso_run_opt.py') + shutil.copyfile(run_opt_file,run_opt_script) + # check outcar script + check_outcar_script = os.path.join(temp_calypso_run_opt_path,'check_outcar.py') + shutil.copyfile(check_outcar_file,check_outcar_script) + for mm in models : model_name = os.path.basename(mm) if model_devi_engine != 'calypso': os.symlink(mm, os.path.join(work_path, model_name)) else: - os.symlink(mm, os.path.join(calypso_run_opt_path, model_name)) + for temp_calypso_run_opt_path in calypso_run_opt_path: + models_path = os.path.join(temp_calypso_run_opt_path, model_name) + if not os.path.exists(models_path): + os.symlink(mm, models_path) + with open(os.path.join(work_path, 'cur_job.json'), 'w') as outfile: json.dump(cur_job, outfile, indent = 4) @@ -1660,7 +1702,8 @@ def _select_by_model_devi_standard( if model_devi_engine == 'calypso': iter_name = modd_system_task[0].split('/')[0] _work_path = os.path.join(iter_name, model_devi_name) - calypso_run_opt_path = os.path.join(_work_path,calypso_run_opt_name) + # calypso_run_opt_path = os.path.join(_work_path,calypso_run_opt_name) + calypso_run_opt_path = glob.glob('%s/%s.*'%(_work_path, calypso_run_opt_name))[0] numofspecies = _parse_calypso_input('NumberOfSpecies',calypso_run_opt_path) min_dis = _parse_calypso_dis_mtx(numofspecies,calypso_run_opt_path) fp_candidate = [] @@ -1851,7 +1894,8 @@ def _make_fp_vasp_inner (modd_path, if model_devi_engine == 'calypso': iter_name = work_path.split('/')[0] _work_path = os.path.join(iter_name, model_devi_name) - calypso_run_opt_path = os.path.join(_work_path,calypso_run_opt_name) + # calypso_run_opt_path = os.path.join(_work_path,calypso_run_opt_name) + calypso_run_opt_path = glob.glob('%s/%s.*'%(_work_path, calypso_run_opt_name))[0] numofspecies = _parse_calypso_input('NumberOfSpecies',calypso_run_opt_path) min_dis = _parse_calypso_dis_mtx(numofspecies,calypso_run_opt_path) @@ -1982,6 +2026,7 @@ def _trust_limitation_check(sys_idx, lim): fp_candidate.append([tt, cc]) counter['candidate'] += 1 cc += 1 + else: raise RuntimeError('unknown model_devi_engine', model_devi_engine) diff --git a/examples/run/dp-calypso-vasp/machine.json b/examples/run/dp-calypso-vasp/machine.json new file mode 100644 index 000000000..f07f2dd87 --- /dev/null +++ b/examples/run/dp-calypso-vasp/machine.json @@ -0,0 +1,70 @@ +{ + "api_version": "1.0", + "deepmd_version": "2.0.1", + "train" :[ + { + "command": "dp", + "machine": { + "batch_type": "pbs", + "context_type": "lazylocal", + "local_root" : "./" + }, + "resources": { + "envs": {"LD_LIBRARY_PATH": "/opt/software/cuda/10.1/lib64:$LD_LIBRARY_PATH"}, + "custom_flags":["#PBS -l walltime=48:0:0"], + "number_node": 1, + "local_root":"./", + "cpu_per_node": 16, + "gpu_per_node": 1, + "queue_name": "T4_16_62", + "group_size": 1 + } + }], + "model_devi": + [{ + "calypso_path":"/home/zhenyu/workplace/dpgen/AA-2400/debug/calypso_input", + "deepmdkit_python":"/home/zhenyu/soft/deepmd-kit/envs/debug/bin/python", + "_deepmdkit_python":"this python will be used to optimize structures generated by CALYPSO with ase", + "_deepmdkit_python":"and also will be used to calculate model deviation in iter.000001/01.model_devi/model_devi_results", + "_deepmdkit_python":"with calypso_run_model_devi.py script", + "command": "", + "machine": { + "_batch_type": "pbs", + "batch_type": "shell", + "context_type": "lazylocal", + "remote_root": "/home/zhenyu/workplace/dpgen/AA-2400/debug/temp", + "local_root" : "./" + }, + "resources": { + "envs": {"LD_LIBRARY_PATH": "/opt/software/cuda/10.1/lib64:$LD_LIBRARY_PATH"}, + "custom_flags":["#PBS -l walltime=48:0:0"], + "number_node": 1, + "local_root":"./", + "cpu_per_node": 16, + "gpu_per_node": 1, + "queue_name": "T4_16_62", + "group_size": 50 + } + }], + "fp": + [{ + "command": "mpirun -n 32 /opt/vasp/vasp_std", + "machine": { + "batch_type": "shell", + "context_type": "lazylocal", + "local_root" : "./", + "remote_root": "/home/zhenyu/workplace/dpgen/AA-2400/debug/temp" + }, + "resources": { + "number_node": 1, + "cpu_per_node": 12, + "gpu_per_node": 0, + "queue_name": "C_32_64", + "group_size": 10, + "local_root":"./", + "custom_flags":["#PBS -l walltime=200:0:0"], + "source_list": ["/opt/intel/oneapi/setvars.sh"] + } + } + ] +} diff --git a/examples/run/dp-calypso-vasp/param.json b/examples/run/dp-calypso-vasp/param.json new file mode 100644 index 000000000..1818a12fb --- /dev/null +++ b/examples/run/dp-calypso-vasp/param.json @@ -0,0 +1,127 @@ +{ + "model_devi_engine":"calypso", + "_calypso_path":"/home/zhenyu/workplace/dpgen/AA-2400/debug", + "_calypso_input_path":"/home/zhenyu/workplace/dpgen/AA-2400/debug/calypso_input", + "_model_devi_max_iter": 50, + "vsc":false, + + "type_map": [ + "Mg", + "Al", + "Cu" + ], + "mass_map": [ + 24, + 27, + 64 + ], + "init_data_prefix":"/home/zhenyu/workplace/dpgen/AA-2400/data/", + "init_data_sys": [ + "data.init/data.init/AlCuMg/init.000" + ], + "_comment": " that's all ", + + "training_init_model": false, + "training_iter0_model_path": "/home/zhenyu/workplace/dpgen/AA-2400/pb/00[0-3]", + "training_reuse_iter": 0, + "training_reuse_old_ratio": 0.9, + "training_reuse_start_lr": 1e-4, + "training_reuse_stop_batch": 1000000, + "training_reuse_start_pref_e": 0.2, + "training_reuse_start_pref_f": 100, + + "numb_models": 4, + "default_training_param": { + "model": { + "descriptor": { + "type": "se_e2_a", + "sel": [ + 500, + 700, + 1100 + ], + "rcut_smth": 2.0, + "rcut": 12.0, + "neuron": [ + 25, + 50, + 100 + ], + "resnet_dt": false, + "axis_neuron": 12, + "type_one_side": true, + "seed": 1801819940, + "_activation_function": "tanh" + }, + "fitting_net": { + "neuron": [ + 240, + 240, + 240 + ], + "resnet_dt": true, + "seed": 2375417769 + }, + "type_map": [ + "Mg", + "Al", + "Cu" + ] + }, + "learning_rate": { + "type": "exp", + "start_lr": 0.001, + "decay_steps": 5000 + }, + "loss": { + "start_pref_e": 0.2, + "limit_pref_e": 2, + "start_pref_f": 100, + "limit_pref_f": 1, + "start_pref_v": 0, + "limit_pref_v": 0 + }, + "training": { + "stop_batch": 6000, + "seed": 3982377700, + "_comment": "that's all", + "disp_file": "lcurve.out", + "disp_freq": 2000, + "numb_test": 4, + "save_freq": 2000, + "save_ckpt": "model.ckpt", + "disp_training": true, + "time_training": true, + "profiling": false, + "profiling_file": "timeline.json", + "set_prefix": "set" + } + }, + "sys_configs":"", + "model_devi_dt": 0.002, + "model_devi_skip": 0, + "model_devi_f_trust_lo": 0.05, + "model_devi_f_trust_hi": 0.15, + "model_devi_e_trust_lo": 10000000000.0, + "model_devi_e_trust_hi": 10000000000.0, + "model_devi_clean_traj": true, + "model_devi_jobs": [ +{"times":[0],"NameOfAtoms":["Mg","Al","Cu"],"NumberOfAtoms":[1,1,1],"NumberOfFormula":[1,1],"Volume":[30],"DistanceOfIon":[[1.48,1.44,1.59],[1.44,1.41,1.56],[1.59,1.56,1.70]],"PsoRatio":[0.6],"PopSize":[500],"MaxStep":[3],"ICode":[1],"Split":"T","VSC":"T","MaxNumAtom":[31],"CtrlRange":[[1,10],[1,10],[1,10]]}, +{"times":[1],"NameOfAtoms":["Mg","Al"],"NumberOfAtoms":[1,1],"NumberOfFormula":[1,1],"Volume":[30],"DistanceOfIon":[[1.48,1.44],[1.44,1.41]],"PsoRatio":[0.6],"PopSize":[500],"MaxStep":[3],"ICode":[1],"Split":"T"}, +{"times":[3],"NameOfAtoms":["Al","Cu"],"NumberOfAtoms":[1,10],"NumberOfFormula":[1,2],"Volume":[300],"DistanceOfIon":[[1.48,1.44],[1.44,1.41]],"PsoRatio":[0.6],"PopSize":[5],"MaxStep":[3],"ICode":[1],"Split":"T"}, +{"times":[2],"NameOfAtoms":["Mg","Al","Cu"],"NumberOfAtoms":[1,1,1],"NumberOfFormula":[1,1],"Volume":[30],"DistanceOfIon":[[1.48,1.44,1.59],[1.44,1.41,1.56],[1.59,1.56,1.70]],"PsoRatio":[0.6],"PopSize":[5],"MaxStep":[1],"ICode":[1],"Split":"T","VSC":"T","MaxNumAtom":[31],"CtrlRange":[[1,10],[1,10],[1,10]],"PSTRESS":[0],"fmax":[0.01]}, +{"times":[4],"NameOfAtoms":["Mg","Al","Cu"],"NumberOfAtoms":[1,1,1],"NumberOfFormula":[1,1],"Volume":30,"DistanceOfIon":[[1.48,1.44,1.59],[1.44,1.41,1.56],[1.59,1.56,1.70]],"PsoRatio":0.6,"PopSize":5,"MaxStep":1,"ICode":1,"Split":"T","VSC":"T","MaxNumAtom":31,"CtrlRange":[[1,10],[1,10],[1,10]],"PSTRESS":[0, 400 ],"fmax":0.01} + ], + + "fp_style": "vasp", + "shuffle_poscar": false, + "fp_task_max": 10, + "fp_task_min": 1, + "fp_pp_path": "/home/zhenyu/workplace/dpgen/AA-2400/vasp_input", + "fp_pp_files": [ + "POTCAR.Mg", + "POTCAR.Al", + "POTCAR.Cu" + ], + "fp_incar":"/home/zhenyu/workplace/dpgen/AA-2400/vasp_input/INCAR" +} diff --git a/tests/generator/test_calypso.py b/tests/generator/test_calypso.py index b302cfca6..958b9e40e 100644 --- a/tests/generator/test_calypso.py +++ b/tests/generator/test_calypso.py @@ -46,9 +46,9 @@ def test_write_model_devi_out(self): os.remove('model_devi.out') def test_make_calypso_input(self): - ret = make_calypso_input(["Mg","Al","Cu"],[1,1,1],[1,4],[30],[ + ret = make_calypso_input(["Mg","Al","Cu"],[1,1,1],[1,4],30,[ [1.48,1.44,1.59],[1.44,1.41,1.56],[1.59,1.56,1.70] - ],[0.6],[5],[3],[13],"T","T",[31],[[1,10],[1,10],[1,10]],[0],[0.01]) + ],0.6,5,3,13,"T","T",31,[[1,10],[1,10],[1,10]],0,0.01) #with open('calypso_test_path/input.dat','w') as fin: with open('input.dat','w') as fin: fin.write(ret) @@ -69,9 +69,9 @@ def test_make_calypso_input(self): break def test_parse_calypso_input(self): - ret = make_calypso_input(["Mg","Al","Cu"],[1,1,1],[1,4],[30],[ + ret = make_calypso_input(["Mg","Al","Cu"],[1,1,1],[1,4],30,[ [1.48,1.44,1.59],[1.44,1.41,1.56],[1.59,1.56,1.70] - ],[0.6],[5],[3],[13],"T","T",[31],[[1,10],[1,10],[1,10]],[0],[0.01]) + ],0.6,5,3,13,"T","T",31,[[1,10],[1,10],[1,10]],0,0.01) #with open('calypso_test_path/input.dat','w') as fin: with open('input.dat','w') as fin: fin.write(ret)