Source code for dpgen.generator.lib.make_calypso
#!/usr/bin/env python3
import glob
import json
import os
import shutil
import numpy as np
[docs]
def make_calypso_input(
nameofatoms,
numberofatoms,
numberofformula,
volume,
distanceofion,
psoratio,
popsize,
maxstep,
icode,
split,
vsc,
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 is not None
ret += "SystemName = {}\n".format("".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 = {}\n".format(" ".join(nameofatoms))
ret += "# Number of atoms for each chemical species in one formula unit. \n"
assert numberofatoms is not None and len(numberofatoms) == len(nameofatoms)
ret += "NumberOfAtoms = {}\n".format(" ".join(list(map(str, numberofatoms))))
ret += "# The range of formula unit per cell in your simulation. \n"
assert (
numberofformula is not None
and len(numberofformula) == 2
and isinstance(numberofformula, list)
)
ret += "NumberOfFormula = {}\n".format(" ".join(list(map(str, numberofformula))))
ret += "# The volume per formula unit. Unit is in angstrom^3.\n"
if volume is None:
ret += "# volume not found, CALYPSO will set one!\n"
else:
ret += f"Volume = {volume}\n"
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)
ret += "@DistanceOfIon \n"
for temp in distanceofion:
ret += "%4s \n" % (" ".join(list(map(str, temp))))
ret += "@End\n"
ret += "# It determines which algorithm should be adopted in the simulation.\n"
ret += "Ialgo = 2\n"
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 <= 1
ret += f"PsoRatio = {psoratio}\n"
ret += (
"# The population size. Normally, it has a larger number for larger systems.\n"
)
assert popsize is not None and isinstance(popsize, int)
ret += "PopSize = %d\n" % (popsize)
assert maxstep is not None and isinstance(maxstep, int)
ret += "# The Max step for iteration\n"
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"
ret += "# 2 grid method for large system\n"
ret += "# 3 and 4 core grow method \n"
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 is not None and isinstance(icode, 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"
ret += "# The number of lbest for local PSO\n"
ret += "NumberOfLbest=4\n"
ret += "# The Number of local optimization for each structure.\n"
ret += "NumberOfLocalOptim= 3\n"
ret += "# The command to perform local optimiztion calculation (e.g., VASP, SIESTA) on your computer.\n"
ret += "Command = sh submit.sh\n"
ret += "MaxTime = 9000 \n"
ret += "# If True, a previous calculation will be continued.\n"
ret += "PickUp = F\n"
ret += "# At which step will the previous calculation be picked up.\n"
ret += "PickStep = 1\n"
ret += "# If True, the local optimizations performed by parallel\n"
ret += "Parallel = F\n"
ret += "# The number node for parallel \n"
ret += "NumberOfParallel = 4\n"
assert split is not None
ret += f"Split = {split}\n"
assert pstress is not None and (
isinstance(pstress, int) or isinstance(pstress, float)
)
ret += f"PSTRESS = {pstress:f}\n"
assert fmax is not None or isinstance(fmax, float)
ret += f"fmax = {fmax:f}\n"
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'
ret += "##### The Parameters For Variational Stoichiometry ##############\n"
ret += (
"## If True, Variational Stoichiometry structure prediction is performed\n"
)
ret += f"VSC = {vsc}\n"
ret += "# The Max Number of Atoms in unit cell\n"
ret += f"MaxNumAtom = {maxnumatom}\n"
ret += "# The Variation Range for each type atom \n"
ret += "@CtrlRange\n"
for ttemp in ctrlrange:
ret += "%4s \n" % (" ".join(list(map(str, ttemp))))
ret += "@end\n"
ret += "###################End Parameters for VSC ##########################\n"
return ret
def _make_model_devi_buffet(jdata, calypso_run_opt_path):
calypso_input_path = jdata.get("calypso_input_path")
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):
for iiidx, jobbs in enumerate(model_devi_jobs):
if iter_index in jobbs.get("times"):
cur_job = model_devi_jobs[iiidx]
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)
# Crystal Parameters
nameofatoms = cur_job.get("NameOfAtoms")
numberofatoms = cur_job.get("NumberOfAtoms")
numberofformula = cur_job.get("NumberOfFormula", [1, 1])
volume = cur_job.get("Volume")
distanceofion = cur_job.get("DistanceOfIon")
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
vsc = cur_job.get("VSC", "F")
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])
# 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,
cur_press,
fmax,
)
with open(os.path.join(temp_calypso_run_opt_path, "input.dat"), "w") as cin:
cin.write(file_c)
[docs]
def write_model_devi_out(devi, fname):
assert devi.shape[1] == 8
# assert devi.shape[1] == 7
header = "%5s" % "step"
for item in "vf":
header += "%16s%16s%16s" % (
f"max_devi_{item}",
f"min_devi_{item}",
f"avg_devi_{item}",
)
header += "%16s" % "min_dis"
np.savetxt(
fname,
devi,
fmt=["%5d"] + ["%17.6e" for _ in range(7)],
delimiter="",
header=header,
)
return devi