1414 pass
1515
1616import numpy as np
17+ import time , datetime
1718
1819from ase .units import Rydberg , Bohr
1920import ase , ase .io
@@ -179,6 +180,10 @@ def __init__(self, hostname=None, pwd=None, extra_options="", workdir = "",
179180 self .timeout = 1000
180181 self .use_timeout = False
181182
183+ # Check the status of the job every TOT seconds
184+ self .check_timeout = 300
185+ self .nonblocking_command = False # True if you use a different version of slurm that does not accept blocking commands
186+
182187 # This is the number of configurations to be computed for each jub submitted
183188 # This times the self.batch_size is the total amount of configurations submitted toghether
184189 self .job_number = 1
@@ -277,7 +282,7 @@ def __setattr__(self, name, value):
277282
278283
279284
280- def ExecuteCMD (self , cmd , raise_error = True , return_output = False ):
285+ def ExecuteCMD (self , cmd , raise_error = True , return_output = False , on_cluster = False ):
281286 """
282287 EXECUTE THE CMD ON THE CLUSTER
283288 ==============================
@@ -294,6 +299,8 @@ def ExecuteCMD(self, cmd, raise_error = True, return_output = False):
294299 return_output : bool, optional
295300 If True (default False) the output of the command is
296301 returned as second value.
302+ on_cluster : bool
303+ If true, the command is executed directly on the cluster through ssh
297304
298305 Returns
299306 -------
@@ -303,6 +310,9 @@ def ExecuteCMD(self, cmd, raise_error = True, return_output = False):
303310 output : string
304311 Returned only if return_output is True
305312 """
313+
314+ if on_cluster :
315+ cmd = self .sshcmd + " {} '{}'" .format (self .hostname , cmd )
306316
307317 success = False
308318 output = ""
@@ -335,6 +345,8 @@ def ExecuteCMD(self, cmd, raise_error = True, return_output = False):
335345 if return_output :
336346 return success , output
337347 return success
348+
349+
338350
339351
340352 def set_timeout (self , timeout ):
@@ -661,6 +673,7 @@ def batch_submission(self, list_of_structures, calc, indices,
661673# sys.stderr.write(cmd + ": exit with code " + str(cp_res) + "\n")
662674# return results #[None] * N_structs
663675
676+
664677 submission = self .create_submission_script (submission_labels )
665678
666679 # Copy the submission script
@@ -674,11 +687,12 @@ def batch_submission(self, list_of_structures, calc, indices,
674687 if not cp_res :
675688 print ("Error while executing:" , cmd )
676689 print ("Return code:" , cp_res )
677- sys .stderr .write (cmd + ": exit with code " + str (cp_res ))
690+ sys .stderr .write (cmd + ": exit with code " + str (cp_res ) + " \n " )
678691 return results #[None] * N_structs
679692
680693
681694 # Run the simulation
695+
682696 sub_script_loc = os .path .join (self .workdir , label + "_" + str (indices [0 ]) + ".sh" )
683697 cp_res , submission_output = self .submit (sub_script_loc )
684698
@@ -720,7 +734,58 @@ def batch_submission(self, list_of_structures, calc, indices,
720734 pass
721735
722736 return results
737+
738+ def get_job_id_from_submission_output (self , output ):
739+ """
740+ GET THE JOB ID
741+
742+ Retreive the job id from the output of the submission.
743+ This depends on the software employed. It works for slurm.
744+
745+ Returns None if the output contains an error
746+ """
747+
748+ try :
749+ id = output .split ()[- 1 ]
750+ return id
751+ except :
752+ print ("Error, expected a standard output, but the result of the submission was: {}" .format (output ))
753+ return None
723754
755+ def check_job_finished (self , job_id , verbose = True ):
756+ """
757+ Check if the job identified by the job_id is finished
758+
759+ Parameters
760+ ----------
761+ job_id : string
762+ The string that identifies uniquely the job
763+ """
764+
765+ status , output = self .ExecuteCMD ("squeue -u $USER" , False , return_output = True , on_cluster = True , )
766+ lines = output .split ("\n " )
767+ if len (lines ):
768+ for l in lines :
769+ data = l .strip ().split ()
770+ if data [0 ] == job_id :
771+ if verbose :
772+ now = datetime .datetime .now ()
773+ sys .stderr .write ("{}/{}/{} - {}:{}:{} | job {} still running\n " .format (now .year , now .month , now .day , now .hour , now .minute , now .second , job_id ))
774+ sys .stderr .flush ()
775+ return False
776+
777+ # If I'm here it means I did not find the job, but the command returned at least 1 line (so it was correctly executed).
778+ if verbose :
779+ now = datetime .datetime .now ()
780+ sys .stderr .write ("{}/{}/{} - {}:{}:{} | job {} finished\n " .format (now .year , now .month , now .day , now .hour , now .minute , now .second , job_id ))
781+ sys .stderr .flush ()
782+ return True
783+ if verbose :
784+ now = datetime .datetime .now ()
785+ sys .stderr .write ("{}/{}/{} - {}:{}:{} | error while interrogating the cluster for job {}\n " .format (now .year , now .month , now .day , now .hour , now .minute , now .second , job_id ))
786+ sys .stderr .flush ()
787+ return False
788+
724789
725790 def run_atoms (self , ase_calc , ase_atoms , label = "ESP" ,
726791 in_extension = ".pwi" , out_extension = ".pwo" ,
0 commit comments