diff --git a/nexus/nexus/__init__.py b/nexus/nexus/__init__.py index 80a2b2a3fc..eb4c29e68c 100644 --- a/nexus/nexus/__init__.py +++ b/nexus/nexus/__init__.py @@ -132,13 +132,13 @@ class Settings(NexusCore): }) core_assign_vars = frozenset({ - 'results', 'load_images', 'remote_directory', 'verbose', 'progress_tty', - 'command_line', 'sleep', 'timeout', 'monitor', 'debug', 'skip_submit', 'dynamic', 'runs', - 'stages', 'pseudo_dir', 'graph_sims', 'generate_only', 'trace', + 'results', 'load_images', 'remote_directory', 'progress_tty', + 'command_line', 'sleep', 'timeout', 'monitor', 'skip_submit', 'dynamic', 'runs', + 'pseudo_dir', 'graph_sims', 'generate_only', 'local_directory', 'status_only' }) - core_process_vars = frozenset({'file_locations', 'status', 'mode'}) + core_process_vars = frozenset({'file_locations'}) noncore_assign_vars = frozenset({'basis_dir'}) @@ -373,10 +373,6 @@ def process_command_line_settings(self,script_settings): action='store_true',default=False, help='Report status of all simulations and then exit.' ) - parser.add_option('--status',dest='status', - default='none', - help="Controls displayed simulation status information. May be set to one of 'standard', 'active', 'failed', or 'ready'." - ) parser.add_option('--generate_only',dest='generate_only', action='store_true',default=False, help='Write inputs to all simulations and then exit. Note that no dependencies are processed, e.g. if one simulation depends on another for an orbital file location or for a relaxed structure, this information will not be present in the generated input file for that simulation since no simulations are actually run with this option.' @@ -568,10 +564,6 @@ def process_machine_settings(self,mset): def process_core_settings(self,kw): - # process project manager settings - if nexus_core.debug: - nexus_core.verbose = True - #end if if 'status' in kw: if kw.status==None or kw.status==False: nexus_core.status = nexus_core.status_modes.none @@ -587,43 +579,6 @@ def process_core_settings(self,kw): if nexus_core.status_only and nexus_core.status==nexus_core.status_modes.none: nexus_core.status = nexus_core.status_modes.standard #end if - if 'mode' in kw: - if kw.mode in nexus_core.modes: - nexus_core.mode = kw.mode - else: - msg = 'invalid mode specified: {0}\nvalid modes are: {1}'.format(kw.mode,sorted(nexus_core.modes.keys())) - raise ValueError(msg) - #end if - #end if - mode = nexus_core.mode - modes = nexus_core.modes - if mode==modes.stages: - stages = nexus_core.stages - elif mode==modes.all: - stages = list(nexus_core.primary_modes) - else: - stages = [kw.mode] - #end if - allowed_stages = set(nexus_core.primary_modes) - if isinstance(stages,str): - stages = [stages] - #end if - if len(stages)==0: - stages = list(nexus_core.primary_modes) - elif 'all' in stages: - stages = list(nexus_core.primary_modes) - else: - forbidden = set(nexus_core.stages)-allowed_stages - if len(forbidden)>0: - msg = 'some stages provided are not primary stages.\n You provided '+str(list(forbidden))+'\n Options are '+str(list(allowed_stages)) - raise ValueError(msg) - #end if - #end if - # overide user input and always use stages mode - # keep processing code above in case a change is desired in the future - nexus_core.mode = modes.stages - nexus_core.stages = stages - nexus_core.stages_set = set(nexus_core.stages) # process simulation settings if 'local_directory' in kw: diff --git a/nexus/nexus/nexus_base.py b/nexus/nexus/nexus_base.py index fc371a94eb..8ff8f14aae 100644 --- a/nexus/nexus/nexus_base.py +++ b/nexus/nexus/nexus_base.py @@ -26,16 +26,17 @@ import os -from os import PathLike -from copy import deepcopy import pickle -from pickle import UnpicklingError +from copy import deepcopy +from enum import Flag, auto +from os import PathLike from pathlib import Path -from .utilities import path_string -from .nexus_version import nexus_version -from .memory import resident -from .developer import DevBase, obj, log +from pickle import UnpicklingError +from .developer import DevBase, log, obj +from .memory import resident +from .nexus_version import nexus_version +from .utilities import path_string # Nexus namespaces # nexus_core: to be used by NexusCore classes only @@ -52,17 +53,6 @@ ready = 4, ) -modes = obj( - none = 0, - setup = 1, - send_files = 2, - submit = 3, - get_output = 4, - analyze = 5, - stages = 6, - all = 7 - ) - nexus_noncore_defaults = obj( basis_dir = None, basissets = None, @@ -86,19 +76,9 @@ monitor = True, # used by: ProjectManager,Simulation,Machine skip_submit = False, # used by: Simulation load_images = True, # used by: ProjectManager - modes = modes, # used by: ProjectManager,Simulation - mode = modes.stages, # used by: Simulation - stages_set = set(), # used by: ProjectManager,Simulation - stages = [], # used by: Simulation - primary_modes = ['setup','send_files','submit','get_output','analyze'], # used by: Settings - dependent_modes = set(['submit']), # used by: ProjectManager,Simulation - verbose = True, # used by: NexusCore - debug = False, # used by: NexusCore - trace = False, # used by: NexusCore indent = ' ', # used by: NexusCore status_modes = status_modes, # used by: ProjectManager status = status_modes.none, # used by: ProjectManager - emulate = False, # unused progress_tty = False, # used by: ProjectManager graph_sims = False, # used by: ProjectManager command_line = True, # used by: Settings @@ -186,26 +166,25 @@ def log(self,*texts,**kwargs): If ``True`` and output is to a terminal, overwrite and update the last line, rather than scrolling. """ - if nexus_core.verbose: - if len(kwargs)>0: - n = kwargs['n'] - else: - n=0 - #end if - is_progress = kwargs.get('progress',False) - text='' - for t in texts: - text+=str(t)+' ' - #end for - pad = n*nexus_core.indent - output_text = pad+text.replace('\n','\n'+pad) - if nexus_core.progress_tty and is_progress and self._logfile.isatty(): - # spaces to ensure previous line is overwritten. Need better solution. - self._logfile.write(output_text+' \r') - self._logfile.flush() - else: - self._logfile.write(output_text+'\n') + if len(kwargs)>0: + n = kwargs['n'] + else: + n=0 #end if + is_progress = kwargs.get('progress',False) + text='' + for t in texts: + text+=str(t)+' ' + #end for + pad = n*nexus_core.indent + output_text = pad+text.replace('\n','\n'+pad) + if nexus_core.progress_tty and is_progress and self._logfile.isatty(): + # spaces to ensure previous line is overwritten. Need better solution. + self._logfile.write(output_text+' \r') + self._logfile.flush() + else: + self._logfile.write(output_text+'\n') + NexusCore.wrote_something = True #end def log diff --git a/nexus/nexus/project_manager.py b/nexus/nexus/project_manager.py index b07da096ff..0f5c716baa 100644 --- a/nexus/nexus/project_manager.py +++ b/nexus/nexus/project_manager.py @@ -62,8 +62,6 @@ def restore_default_settings(): #end def restore_default_settings def __init__(self): - modes = nexus_core.modes - self.persistent_modes = set([modes.submit,modes.all]) self.simulations = obj() self.cascades = obj() self.progressing_cascades = obj() @@ -107,35 +105,32 @@ def run_project(self,*,status=False,status_only=False): #end if #end if self.log('\nstarting runs:\n'+30*'~',n=1) - if nexus_core.dependent_modes <= nexus_core.stages_set: - if nexus_core.monitor: - start_time = time.time() - ipoll = 0 - while len(self.progressing_cascades)>0: - elapsed_time = time.time() - start_time - self.log('elapsed time %.1f s'%elapsed_time, - ' memory %3.2f MB'%(memory.resident(children=True)/1e6), - n=1,progress=True) - NexusCore.wrote_something = False - ipoll+=1 - self.machine.query_queue() - self.progress_cascades() - self.machine.submit_jobs() - self.update_process_ids() - time.sleep(nexus_core.sleep) - if NexusCore.wrote_something: - self.log() - #end if - #end while - elif len(self.progressing_cascades)>0: + + if nexus_core.monitor: + start_time = time.time() + while len(self.progressing_cascades)>0: + elapsed_time = time.time() - start_time + self.log( + f'elapsed time {elapsed_time:.1f} s', + f' memory {(memory.resident(children=True)/1e6):3.2f} MB', + n=1, + progress=True, + ) + NexusCore.wrote_something = False self.machine.query_queue() self.progress_cascades() self.machine.submit_jobs() self.update_process_ids() - #end if - else: + time.sleep(nexus_core.sleep) + if NexusCore.wrote_something: + self.log() + + elif len(self.progressing_cascades)>0: + self.machine.query_queue() self.progress_cascades() - #end if + self.machine.submit_jobs() + self.update_process_ids() + self.log('Project finished\n') #end def run_project diff --git a/nexus/nexus/simulation.py b/nexus/nexus/simulation.py index f1990e250e..863010f102 100644 --- a/nexus/nexus/simulation.py +++ b/nexus/nexus/simulation.py @@ -65,27 +65,26 @@ #====================================================================# -import contextlib import os -import sys import shutil +import sys import tempfile import traceback -from functools import partial from copy import deepcopy from datetime import datetime from pathlib import Path from string import Template from subprocess import Popen from typing import ClassVar -from .developer import DevBase, obj, unavailable, FileFormatError, NexusError -from .structure import Structure, read_structure -from .physical_system import PhysicalSystem + +from .developer import DevBase, FileFormatError, NexusError, obj, unavailable from .machines import Job, Workstation, get_machine -from .nexus_base import NexusCore, nexus_core, dynamic_storage +from .nexus_base import NexusCore, dynamic_storage, nexus_core +from .physical_system import PhysicalSystem +from .structure import Structure, read_structure from .utilities import path_string - + class SimulationInput(NexusCore): def is_valid(self): raise NotImplementedError @@ -279,7 +278,7 @@ class Simulation(NexusCore): 'identifier','path','infile','outfile','errfile','imagefile', 'input','job','files','dependencies','analysis_request', 'block','block_subcascade','app_name','app_props','system', - 'skip_submit','force_write','simlabel','fake_sim', + 'skip_submit','simlabel','fake_sim', 'restartable','force_restart' }) sim_imagefile = 'sim.p' @@ -390,7 +389,6 @@ def __init__(self,**kwargs): self.block = False self.block_subcascade = False self.skip_submit = nexus_core.skip_submit - self.force_write = False self.loaded = False self.ordered_dependencies = [] self.process_id = None @@ -1374,96 +1372,36 @@ def block_dependents(self,*,block_self=True): def progress(self,dependency_id=None): if dependency_id is not None: self.wait_ids.remove(dependency_id) - #end if - if len(self.wait_ids)==0 and not self.block and not self.failed: - modes = nexus_core.modes - mode = nexus_core.mode - progress = True - if mode==modes.none: - return - elif mode==modes.setup: - self.write_inputs() - elif mode==modes.send_files: - self.send_files() - elif mode==modes.submit: - self.submit() - progress = self.finished - elif mode==modes.get_output: + + if len(self.wait_ids) > 0 or self.block or self.failed: + return # No progression if we are waiting or blocked or failed + + progress = True + conds_ops = ( + (self.created_directories, self.create_directories), + (self.got_dependencies, self.get_dependencies), + (self.setup, self.write_inputs), + (self.sent_files, self.send_files), + (self.finished, self.submit), + ) + for cond, op in conds_ops: + if not cond: + op() + + progress_post = self.finished + progress = self.finished and self.analyzed + + if progress_post: + if not self.got_output: self.get_output() - progress = self.finished - elif mode==modes.analyze: + + if not self.analyzed: self.analyze() - progress = self.finished - elif mode==modes.stages: - if not self.created_directories: - self.create_directories() - #end if - if not self.got_dependencies: - self.get_dependencies() - #end if - if not self.setup and 'setup' in nexus_core.stages: - self.write_inputs() - #end if - if not self.sent_files and 'send_files' in nexus_core.stages: - self.send_files() - #end if - if not self.finished and 'submit' in nexus_core.stages: - self.submit() - #end if - if nexus_core.dependent_modes <= nexus_core.stages_set: - progress_post = self.finished - progress = self.finished and self.analyzed - else: - progress_post = progress - #end if - if progress_post: - if not self.got_output and 'get_output' in nexus_core.stages: - self.get_output() - #end if - if not self.analyzed and 'analyze' in nexus_core.stages: - self.analyze() - #end if - #end if - elif mode==modes.all: - if not self.setup: - self.write_inputs() - self.send_files(enter=False) - #end if - if not self.finished: - self.submit() - #end if - if self.finished: - if not self.got_output: - self.get_output() - #end if - if not self.analyzed: - self.analyze() - #end if - #end if - progress = self.finished - #end if - if progress and not self.block_subcascade and not self.failed: - for sim in self.dependents.values(): - if not sim.bundled: - sim.progress(self.simid) - #end if - #end for - #end if - elif len(self.wait_ids)==0 and self.force_write: - modes = nexus_core.modes - mode = nexus_core.mode - if mode==modes.stages: - if not self.got_dependencies: - self.get_dependencies() - #end if - if 'setup' in nexus_core.stages: - self.write_inputs() - #end if - if not self.sent_files and 'send_files' in nexus_core.stages: - self.send_files() - #end if - #end if - #end if + + if progress and not (self.block_subcascade or self.failed): + for sim in self.dependents.values(): + if not sim.bundled: + sim.progress(self.simid) #end def progress diff --git a/nexus/nexus/tests/__init__.py b/nexus/nexus/tests/__init__.py index f35b7a13f9..6b55b53003 100644 --- a/nexus/nexus/tests/__init__.py +++ b/nexus/nexus/tests/__init__.py @@ -14,9 +14,6 @@ NEXUS_CORE_KEYS = ( "local_directory", "remote_directory", - "mode", - "stages", - "stages_set", "status", "sleep", "timeout", diff --git a/nexus/nexus/tests/test_project_manager.py b/nexus/nexus/tests/test_project_manager.py index b953d79d38..c0b396a686 100644 --- a/nexus/nexus/tests/test_project_manager.py +++ b/nexus/nexus/tests/test_project_manager.py @@ -9,13 +9,10 @@ def test_init(): from ..developer import obj - from ..nexus_base import nexus_core from ..project_manager import ProjectManager pm = ProjectManager() - modes = nexus_core.modes - assert(pm.persistent_modes==set([modes.submit,modes.all])) def check(v): assert isinstance(v,obj) assert len(v)==0 @@ -413,20 +410,8 @@ def test_run_project(tmp_path): nexus_core.remote_directory = str(tmp_path) nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] - assert(nexus_core.mode==nexus_core.modes.stages) - assert(len(nexus_core.stages)==0) - - nexus_core.stages = list(nexus_core.primary_modes) - nexus_core.stages_set = set(nexus_core.stages) - - primary_modes = ['setup','send_files','submit','get_output','analyze'] - assert(value_eq(nexus_core.stages,primary_modes)) - assert(value_eq(nexus_core.stages_set,set(primary_modes))) - nexus_core.sleep = 0.1 - log = generic_settings.devlog - flags = ['setup','sent_files','submitted','finished','got_output','analyzed'] def finished(s): diff --git a/nexus/nexus/tests/test_settings.py b/nexus/nexus/tests/test_settings.py index 98afdda17e..d2c0b53323 100644 --- a/nexus/nexus/tests/test_settings.py +++ b/nexus/nexus/tests/test_settings.py @@ -44,28 +44,28 @@ def aux_defaults(): #end def aux_defaults def check_settings_core_noncore(): - nckeys_check = set([ - 'command_line','debug', 'dependent_modes', 'emulate', + nckeys_check = { + 'command_line', 'file_locations', 'generate_only', 'graph_sims', 'indent', - 'load_images', 'local_directory', 'mode', 'modes', 'monitor', - 'primary_modes', 'progress_tty', 'pseudo_dir', + 'load_images', 'local_directory', 'monitor', + 'progress_tty', 'pseudo_dir', 'remote_directory', 'results', 'runs', - 'skip_submit', 'sleep', 'stages', 'stages_set', 'status', 'timeout', - 'status_modes', 'status_only', 'trace', 'verbose', 'dynamic' - ]) - nnckeys_check = set([ + 'skip_submit', 'sleep', 'status', 'timeout', + 'status_modes', 'status_only', 'dynamic' + } + nnckeys_check = { 'basis_dir', 'basissets', 'pseudo_dir' - ]) - setkeys_check = set([ - 'command_line','basis_dir', 'basissets', 'debug', - 'dependent_modes', 'emulate', 'file_locations', 'generate_only', - 'graph_sims', 'indent', 'load_images', 'local_directory', 'mode', - 'modes', 'monitor', 'primary_modes', 'progress_tty', + } + setkeys_check = { + 'command_line', 'basis_dir', 'basissets', + 'file_locations', 'generate_only', + 'graph_sims', 'indent', 'load_images', 'local_directory', + 'monitor', 'progress_tty', 'pseudo_dir', 'remote_directory', 'results', - 'runs', 'skip_submit', 'sleep', 'stages', 'stages_set', 'status', + 'runs', 'skip_submit', 'sleep', 'status', 'timeout', - 'status_modes', 'status_only', 'trace', 'verbose', 'dynamic' - ]) + 'status_modes', 'status_only', 'dynamic' + } setkeys_allowed = setkeys_check | Settings.allowed_vars nckeys = set(nexus_core.keys()) @@ -102,12 +102,9 @@ def check_empty_settings(): settings.command_line = True nexus_core.command_line = True check_settings_core_noncore() - # nexus core sets basic run stages and PseudoSet registries are empty - assert(nexus_core.stages_set==set(nexus_core_defaults.primary_modes)) + # PseudoSet registries are empty assert(len(PseudoSet.pseudo_files)==0) assert(len(PseudoSet.labeled_pseudosets)==0) - nexus_core.stages_set = set() - nexus_core.stages = [] assert(object_eq(nexus_core,nexus_core_defaults)) # nexus noncore sets a BasisSets object assert(isinstance(nexus_noncore.basissets,BasisSets)) diff --git a/nexus/nexus/tests/test_simulation_module.py b/nexus/nexus/tests/test_simulation_module.py index df50fe39ca..a0cb9b8791 100644 --- a/nexus/nexus/tests/test_simulation_module.py +++ b/nexus/nexus/tests/test_simulation_module.py @@ -743,7 +743,6 @@ def test_init(): files = set([]), finished = False, force_restart = False, - force_write = False, got_dependencies = False, got_output = False, identifier = 'sim', @@ -2187,16 +2186,6 @@ def test_progress(tmp_path): nexus_core.remote_directory = str(tmp_path) nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] - assert(nexus_core.mode==nexus_core.modes.stages) - assert(len(nexus_core.stages)==0) - - nexus_core.stages = list(nexus_core.primary_modes) - nexus_core.stages_set = set(nexus_core.stages) - - primary_modes = ['setup','send_files','submit','get_output','analyze'] - assert(value_eq(nexus_core.stages,primary_modes)) - assert(value_eq(nexus_core.stages_set,set(primary_modes))) - template = ''' name = "$name"