Skip to content

Commit

Permalink
Update funcionalities for ALMACE/MACE
Browse files Browse the repository at this point in the history
  • Loading branch information
rayhe88 authored and mjohnson541 committed Nov 21, 2024
1 parent 7ab60d6 commit 00132c4
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 29 deletions.
37 changes: 32 additions & 5 deletions pynta/calculator.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from xtb.ase.calculator import XTB
from pynta.wrapper_almace import wrapperALMACE
import numpy as np
import ase
from ase.atoms import Atoms
Expand Down Expand Up @@ -66,7 +67,33 @@ def get_energy_forces_site_bond(atoms,ind,site_pos,k,deq):
energy = k*(d-deq)**2
return energy,k*forces

class HarmonicallyForcedXTB(XTB):
class HarmonicallyForcedXTB(wrapperALMACE):
def get_energy_forces(self):
energy = 0.0
forces = np.zeros(self.atoms.positions.shape)
if hasattr(self.parameters,"atom_bond_potentials"):
for atom_bond_potential in self.parameters.atom_bond_potentials:
E,F = get_energy_forces_atom_bond(self.atoms,**atom_bond_potential)
energy += E
forces += F

if hasattr(self.parameters,"site_bond_potentials"):
for site_bond_potential in self.parameters.site_bond_potentials:
E,F = get_energy_forces_site_bond(self.atoms,**site_bond_potential)
energy += E
forces += F

return energy[0][0],forces

def calculate(self, atoms=None, properties=None, system_changes=calculator.all_changes):
wrapperALMACE.calculate(self,atoms=atoms,properties=properties,system_changes=system_changes)
energy,forces = self.get_energy_forces()
self.results["energy"] += energy
self.results["free_energy"] += energy
self.results["forces"] += forces


class HarmonicallyForcedXTB2(XTB):
def get_energy_forces(self):
energy = 0.0
forces = np.zeros(self.atoms.positions.shape)
Expand Down Expand Up @@ -119,9 +146,9 @@ def run_harmonically_forced_xtb(atoms,atom_bond_potentials,site_bond_potentials,
out_constraints.append(FixAtoms(
indices=list(range(n))
))

atoms.set_constraint(out_constraints)

hfxtb = HarmonicallyForcedXTB(method="GFN1-xTB",
atom_bond_potentials=atom_bond_potentials,
site_bond_potentials=site_bond_potentials)
Expand Down Expand Up @@ -258,7 +285,7 @@ def run_harmonically_forced_xtb_no_pbc(atoms,atom_bond_potentials,site_bond_pote
if "a2" in c:
c["a2"] += new_nslab-nslab
new_constraints.append(c)

out_constraints = []
for c in new_constraints:
if isinstance(c,dict):
Expand All @@ -282,7 +309,7 @@ def run_harmonically_forced_xtb_no_pbc(atoms,atom_bond_potentials,site_bond_pote
out_constraints.append(FixAtoms(
indices=list(range(n))
))

hfxtb = HarmonicallyForcedXTB(method="GFN1-xTB",
atom_bond_potentials=new_atom_bond_potentials,
site_bond_potentials=new_site_potentials)
Expand Down
68 changes: 46 additions & 22 deletions pynta/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,9 +549,10 @@ def launch(self,single_job=False):
"""
if self.queue:
rapidfirequeue(self.launchpad,self.fworker,self.qadapter,njobs_queue=self.njobs_queue,nlaunches="infinite")
elif not self.queue and (self.num_jobs == 1 or single_job):
rapidfire(self.launchpad,self.fworker,nlaunches="infinite")
#elif not self.queue and (self.num_jobs == 1 or single_job):
# rapidfire(self.launchpad,self.fworker,nlaunches="infinite")
else:
print(" my own multilauncher")
listfworkers = createFWorkers(self.num_jobs)
launch_multiprocess2(self.launchpad,listfworkers,"INFO",0,self.num_jobs,5)

Expand Down Expand Up @@ -613,6 +614,7 @@ def execute_from_initial_ad_guesses(self):

#restart option: RHE
def reset(self):
print(" >> Restarting ")
# Get the information of the workflow
wf1 = self.launchpad.get_wf_summary_dict(1, mode='more')

Expand All @@ -638,6 +640,8 @@ def reset(self):
'{{pynta.tasks.MolecularVibrationsTask}}',
'{{pynta.tasks.MolecularIRC}}']

print('TaskID:{2:5d} Name task {0:^20s} {1:^12s}'.format(task_name, task_state, task_id))

#if nameTask in nameTasks:
# opt_method = newd['_tasks'][0]['opt_method'] if 'opt_method' in newd['_tasks'][0] else None

Expand All @@ -651,35 +655,55 @@ def reset(self):
# We load the trajectory file and save this structure in the
# tree of each uncompleted task

if 'opt' in task_name:
dirs = wf_launchers[task_name]
if dirs != []:
src = dirs[0]
print(' Name task {0:^20s} {1:^12s} {2}'.format(task_name, task_state, src))
file_traj = [name for name in os.listdir(src) if name.endswith(".traj")]
if len(file_traj) > 1:
file_traj = file_traj[0]
base, ext = os.path.splitext(file_traj)
#if 'opt' in task_name:
# dirs = wf_launchers[task_name]
# if dirs != []:
# src = dirs[0]
# print(' Name task {0:^20s} {1:^12s} {2}'.format(task_name, task_state, src))
# file_traj = [name for name in os.listdir(src) if name.endswith(".traj")]
# if len(file_traj) > 1:
# file_traj = file_traj[0]
# base, ext = os.path.splitext(file_traj)

with open (os.path.join(src, "FW.json")) as file:
filejson = json.load(file)
# with open (os.path.join(src, "FW.json")) as file:
# filejson = json.load(file)

if opt_method == 'QuasiNewton':
namexyz = f'weakopt_{base}.xyz'
else:
namexyz = f'{base}_init.xyz'
# if opt_method == 'QuasiNewton':
# namexyz = f'weakopt_{base}.xyz'
# else:
# namexyz = f'{base}_init.xyz'

atoms = read(os.path.join(src, file_traj), index=-1)
dst = os.path.dirname(filejson['spec']['_tasks'][0]['xyz'])
# atoms = read(os.path.join(src, file_traj), index=-1)
# dst = os.path.dirname(filejson['spec']['_tasks'][0]['xyz'])

write(f'{src}/{namexyz}', atoms, format='xyz')
# write(f'{src}/{namexyz}', atoms, format='xyz')

copyDataAndSave(src, dst, namexyz)
copyDataAndSave(src, dst, f'{base}.traj')
# copyDataAndSave(src, dst, namexyz)
# copyDataAndSave(src, dst, f'{base}.traj')

# Keep on with the task_state != 'COMPLETED'
self.launchpad.rerun_fw(task_id)
self.launchpad.update_spec([task_id], newd)
else:
task_id = int(task_name.split('--')[-1])
if task_id in [3, 5, 7, 9, 12, 14, 16, 18]:
d = self.launchpad.get_fw_dict_by_id(task_id)
newd = deepcopy(d['spec'])
from pprint import pprint
nameTask = newd['_tasks'][0]['_fw_name']
print(" TASKID ",task_id)
pprint(newd)

nameTasks = ['{{pynta.tasks.MolecularOptimizationTask}}',
'{{pynta.tasks.MolecularVibrationsTask}}',
'{{pynta.tasks.MolecularIRC}}']

print('TaskID:{2:5d} Name task {0:^20s} {1:^12s}'.format(task_name, task_state, task_id))

self.launchpad.rerun_fw(task_id)
self.launchpad.update_spec([task_id], newd)




self.launch()
4 changes: 3 additions & 1 deletion pynta/polaris.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
def createCommand(node, software):
binary = os.environ.get("EXE")
if binary is None:
binary = '/lus/eagle/projects/catalysis_aesp/raymundo/soft/qe-7.1/build_cuda_nompiaware/bin/pw.x'
binary = '/soft/applications/quantum_espresso/7.3.1-nvhpc23.1-libxc610/bin/pw.x'

if software == 'Espresso':
command = 'mpiexec --hosts {} -n 4 --ppn 4 --depth=8 --cpu-bind depth --env OMP_NUM_THREADS=8 --env CUDA_VISIBLE_DEVICES=0,1,2,3 {} -nk 4 -in PREFIX.pwi > PREFIX.pwo'.format(node, binary)
Expand All @@ -32,6 +32,8 @@ def createFWorkers(num_jobs):
for line in f:
nodes_list.append(line.strip('\n'))

#nodes_list.pop(0) # delete the first node for dispatch

fworkers = []

for i in range(num_jobs):
Expand Down
44 changes: 43 additions & 1 deletion pynta/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def optimize_firework(xyz,software,label,opt_method=None,sella=None,socket=False
if opt_method: d["opt_method"] = opt_method
if software_kwargs: d["software_kwargs"] = software_kwargs
if opt_kwargs: d["opt_kwargs"] = opt_kwargs
print("opt kwargs", opt_kwargs)
if run_kwargs: d["run_kwargs"] = run_kwargs
if constraints: d["constraints"] = constraints
sella = True if sella or (sella is None and order != 0) else False
Expand All @@ -80,9 +81,16 @@ def optimize_firework(xyz,software,label,opt_method=None,sella=None,socket=False
d["facet"] = facet
t1 = MolecularOptimizationTask(d)
directory = os.path.dirname(xyz)
subname = directory.split('/')
if out_path is None: out_path = os.path.join(directory,label+".xyz")
t2 = FileTransferTask({'files': [{'src': label+'.xyz', 'dest': out_path}, {'src': label+'.traj', 'dest': os.path.join(directory,label+".traj")}],
'mode': 'copy', 'ignore_errors' : ignore_errors})
if software == 'ALMACE' and opt_method == 'MDMin':
storage = d['software_kwargs']['storage']
t2 = FileTransferTask({'files': [{'src': label+'.xyz', 'dest': out_path}, {'src': label+'.traj', 'dest': os.path.join(directory,label+".traj")},
{'src':label+'.traj', 'dest':os.path.join(storage,subname[-2]+'_'+label+'.traj')},
],
'mode': 'copy', 'ignore_errors' : ignore_errors})
return Firework([t1,t2],parents=parents,name=label+"opt",spec={"_allow_fizzled_parents": allow_fizzled_parents,"_priority": priority})

@explicit_serialize
Expand All @@ -97,6 +105,14 @@ def run_task(self, fw_spec):
if self["software"] == "Espresso" or self["software"] == "PWDFT":
software_kwargs["command"] = createCommand(fw_spec["_fw_env"]["host"], self["software"])

if self["software"] == "MACE" :
software_kwargs["host"] = fw_spec["_fw_env"]["host"] # RHE

if self["software"] == "ALMACE" :
software_kwargs["host"] = fw_spec["_fw_env"]["host"] # RHE
software_kwargs['sub_software_kwargs']['command'] = createCommand(fw_spec['_fw_env']['host'], software_kwargs['sub_software'])
software_kwargs['opt_method'] = name_to_ase_opt(self["opt_method"]) if "opt_method" in self.keys() else BFGS

socket = self["socket"] if "socket" in self.keys() else False
if socket:
unixsocket = "ase_"+self["software"].lower()+"_"+self["label"]+"_"+self["xyz"].replace("/","_").replace(".","_")
Expand All @@ -121,6 +137,7 @@ def run_task(self, fw_spec):
label = self["label"]
xyz = self['xyz']
suffix = os.path.split(xyz)[-1].split(".")[-1]
print("\033[31m xyz: {0}\033[0m".format(xyz))

try:
if suffix == "xyz":
Expand Down Expand Up @@ -312,6 +329,10 @@ def run_task(self, fw_spec):
# Mapping nodes to fworkers
if self["software"] == "Espresso" or self["software"] == "PWDFT":
software_kwargs["command"] = createCommand(fw_spec["_fw_env"]["host"], self["software"])

if self["software"] == "MACE" :
software_kwargs["host"] = fw_spec["_fw_env"]["host"]

software = name_to_ase_software(self["software"])(**software_kwargs)

opt_kwargs = deepcopy(self["opt_kwargs"]) if "opt_kwargs" in self.keys() else dict()
Expand Down Expand Up @@ -360,6 +381,10 @@ def run_task(self, fw_spec):
if self["software"] == "Espresso" or self["software"] == "PWDFT":
software_kwargs["command"] = createCommand(fw_spec["_fw_env"]["host"], self["software"])

if self["software"] == "MACE" :
software_kwargs["host"] = fw_spec["_fw_env"]["host"]


try:
sp = read(xyz)
sp.calc = software(**software_kwargs)
Expand Down Expand Up @@ -405,6 +430,15 @@ def run_task(self, fw_spec):
# Mapping nodes to fworkers
if self["software"] == "Espresso" or self["software"] == "PWDFT":
software_kwargs["command"] = createCommand(fw_spec["_fw_env"]["host"], self["software"])

if self["software"] == "MACE" :
software_kwargs["host"] = fw_spec["_fw_env"]["host"]

if self["software"] == "ALMACE" :
software_kwargs["host"] = fw_spec["_fw_env"]["host"] # RHE
software_kwargs['opt_method'] = name_to_ase_opt(self["opt_method"]) if "opt_method" in self.keys() else BFGS #RHE
software_kwargs['sub_software_kwargs']['command'] = createCommand(fw_spec['_fw_env']['host'], software_kwargs['sub_software'])

software = name_to_ase_software(self["software"])(**software_kwargs)
ignore_errors = deepcopy(self["ignore_errors"]) if "ignore_errors" in self.keys() else False
socket = self["socket"] if "socket" in self.keys() else False
Expand Down Expand Up @@ -516,7 +550,7 @@ def run_task(self, fw_spec):

cas = SlabAdsorptionSites(slab,facet,allow_6fold=False,composition_effect=False,
label_sites=True,tol=0.5,
surrogate_metal='Pt')
surrogate_metal=metal)

adsorbates_path = self["adsorbates_path"]

Expand Down Expand Up @@ -781,6 +815,14 @@ def run_task(self, fw_spec):
# Mapping nodes to fworkers
if self["software"] == "Espresso" or self["software"] == "PWDFT":
software_kwargs["command"] = createCommand(fw_spec["_fw_env"]["host"], self["software"])

if self["software"] == "MACE" :
software_kwargs["host"] = fw_spec["_fw_env"]["host"]

if self["software"] == "ALMACE" :
software_kwargs["host"] = fw_spec["_fw_env"]["host"] # RHE
software_kwargs['sub_software_kwargs']['command'] = createCommand(fw_spec['_fw_env']['host'], software_kwargs['sub_software'])

socket = self["socket"] if "socket" in self.keys() else False
if socket:
unixsocket = "ase_"+self["software"].lower()+"_"+self["label"]+"_"+self["xyz"].replace("/","_").replace(".","_")
Expand Down
6 changes: 6 additions & 0 deletions pynta/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@ def name_to_ase_software(software_name):
elif software_name == "PWDFT":
module = import_module("pynta.ase_pwdft.pwdft")
return getattr(module, software_name)
elif software_name == "ALMACE":
module = import_module("pynta.wrapper_almace")
return getattr(module,"wrapperALMACE")
elif software_name == "MACE":
module = import_module("pynta.wrapper_mace")
return getattr(module,"wrapperMACE")
else:
module = import_module("ase.calculators."+software_name.lower())
return getattr(module, software_name)
Expand Down

0 comments on commit 00132c4

Please sign in to comment.