"""Created on Sun Mar 19 11:47:30 2023.
@author: YuxiaoLan
"""
import shutil
from ruamel.yaml import YAML
from HTMACat.model.Substrate import substrate_from_input
from HTMACat.model.Ads import ads_from_input
from HTMACat.model.Species import species_from_input
from ase.io.vasp import write_vasp
from HTMACat.model.Structure import Structure
from pathlib import Path
from rich import print
import os
[docs]def read(filename):
substrate_dict,species_dict,ads_dict = yaml2dict(filename)
ads = dict2object(substrate_dict, species_dict, ads_dict)
return ads
[docs]def yaml2dict(filename):
yaml = YAML(typ="safe")
with open(filename, encoding="utf-8") as f:
result: dict = yaml.load(f.read())
substrate_dict = get_substrate_dict(result)
species_dict = get_species_dict(result)
ads_dict = get_ads_dict(result)
return substrate_dict,species_dict,ads_dict
[docs]def get_substrate_dict(result):
# preproces substrate dictionary
struct_Info = result["StrucInfo"]
file_default = []
struct_default = {
"element": "Pt",
"lattice_type": "fcc",
"lattice_constant": 3.92,
"facet": ["111"],
"dope": {},
"supercell": [3, 3],
"layer": 4
}
if "file" in struct_Info:
if isinstance(struct_Info["file"], list):
file_default = struct_Info["file"]
else:
file_default = [struct_Info["file"]]
if "struct" in struct_Info:
struct_default.update(struct_Info["struct"])
else:
struct_default = {}
substrate_init_dict = {"file": file_default, "struct": struct_default}
return substrate_init_dict
[docs]def get_species_dict(result):
if "Species" not in result.keys():
return {}
species_info = result["Species"]
return species_info
[docs]def get_ads_dict(result):
ads_model = result["Model"]
ads_default_dict = {"ads": [], "coads": []}
for key in ["ads", "coads"]:
if key not in ads_model:
ads_model[key] = ads_default_dict[key]
return ads_model
[docs]def dict2object(substrate_dict, species_dict, ads_dict):
substrates = substrate_from_input(substrate_dict)
species = species_from_input(species_dict)
ads = ads_from_input(ads_dict, substrates, species)
return ads
[docs]def get_templator():
templator = """#Templator[YAML-format] for HTMACat-kit input
StrucInfo:
# The followting two keywords should be chosen only one
file: POSCARfile #read substrate from POSCAR file
struct:
element: Au #bulk phase element
lattice_type: fcc #lattice type
lattice_constant: 4.16 #lattice parameter
facet: ['111','100'] #crystal plane
dope: #dopeing part
Cu: [3] #dopeing element and dope type
Ag: [1,2,3,'b1','1L']
Model:
SML: False #whether the species is in Smile style
ads: #single adsorption for one species
- ['NH3',1] #species name and adsorption sites
- ['NO', 2]
coads: #co-adsorption for one species
- ['NH3','O',1,1] #species name and adsorption sites"""
return templator
[docs]def print_templator():
templator = get_templator()
print(templator)
[docs]def out_templator_file():
templator = get_templator()
workdir = Path("./config.yaml")
if workdir.is_file():
while True:
choose = input("Warning: Replace config.yaml file in your folder? [y/n(default)]:")
if choose == "y":
break
elif choose == "n" or choose == "":
return
else:
continue
with open("config.yaml", "w") as f:
f.write(templator)
[docs]def generate_unique_filename(filename):
base_name, extension = os.path.splitext(filename)
counter = 1
unique_filename = filename
while os.path.exists(unique_filename):
unique_filename = f"{base_name}_{counter}{extension}"
counter += 1
return unique_filename
[docs]def write(struct_class: Structure):
file_name = struct_class.out_file_name()
print_str = struct_class.out_print()
structures = struct_class.construct()
if structures:
for i, structure in enumerate(structures):
unique_filename = generate_unique_filename(f"{file_name}_{i}.vasp")
write_vasp(f"{unique_filename}", structure, direct=True, sort=[""], vasp5=True)
print(
f"[i][u]{print_str}[/u][/i] are construct with [i][u]{i + 1}[/u][/i] configurations!"
)
else:
print(f"[i][u]{print_str}[/u][/i] are construct with !No! configurations!")