diff --git a/nexus/nexus/__init__.py b/nexus/nexus/__init__.py index 4099638c6a..43f6478c9a 100644 --- a/nexus/nexus/__init__.py +++ b/nexus/nexus/__init__.py @@ -27,14 +27,15 @@ import importlib from importlib.metadata import PackageNotFoundError from pathlib import Path +from collections.abc import Collection from .nexus_version import nexus_version from .generic import generic_settings -from .developer import obj, log, NexusError +from .developer import obj, log, NexusError, warn from .debug import ci from .utilities import path_string -from .nexus_base import NexusCore, nexus_core, nexus_noncore, nexus_core_noncore, restore_nexus_core_defaults, nexus_core_defaults, write_splash +from .nexus_base import NexusCore, NexusConfig, SimStage, ShowStatusMode, NEXUS_CONFIG, write_splash from .machines import Job, job, Machine, Supercomputer, get_machine, get_cpu_cores, Workstation from .simulation import generate_simulation, input_template, multi_input_template, generate_template_input, generate_multi_template_input, graph_sims, DynamicProcess from .project_manager import ProjectManager, DynamicWorkflowManager, workflow_manager @@ -82,7 +83,7 @@ # test needed def run_project(*args,**kwargs): - if nexus_core.graph_sims: + if NEXUS_CONFIG.graph_sims: graph_sims() #end if pm = ProjectManager() @@ -131,28 +132,13 @@ class Settings(NexusCore): 'interactive_cores', 'machine_info', 'machine', 'machine_mode', 'user', 'account' }) - 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', - 'local_directory', 'status_only' - }) - - core_process_vars = frozenset({'file_locations', 'status', 'mode'}) - - noncore_assign_vars = frozenset({'basis_dir'}) - - noncore_process_vars = frozenset() - gamess_vars = frozenset({'ericfmt', 'mcppath'}) pwscf_vars = frozenset({'vdw_table'}) qm_package_vars = frozenset({'qprc'}) - nexus_core_vars = core_assign_vars | core_process_vars - nexus_noncore_vars = noncore_assign_vars | noncore_process_vars - nexus_vars = nexus_core_vars | nexus_noncore_vars + nexus_vars = frozenset(NexusConfig.__slots__) allowed_vars = nexus_vars | machine_vars \ | gamess_vars | pwscf_vars | qm_package_vars @@ -205,13 +191,13 @@ def __call__(self,**kwargs): #end if # restore default core default settings - restore_nexus_core_defaults() + NEXUS_CONFIG.restore_defaults() # process command line inputs, if any if 'command_line' in kwargs: - nexus_core.command_line = kwargs.command_line + NEXUS_CONFIG.command_line = kwargs.command_line #end if - if nexus_core.command_line: + if NEXUS_CONFIG.command_line: self.process_command_line_settings(kwargs) #end if @@ -258,7 +244,7 @@ def __call__(self,**kwargs): nxs_deps = {k:v for k, v in sorted(nxs_deps.items(), key=lambda x: pkg_sort.get(x[0], 1000))} available_pkgs = {} - for module in nxs_deps.keys(): + for module in nxs_deps: if importlib.util.find_spec(module) is not None: available_pkgs[module] = importlib.metadata.version(module) else: @@ -266,7 +252,7 @@ def __call__(self,**kwargs): version_text = "" - name_align = max([len(i) for i in nxs_deps.keys()]) + name_align = max([len(i) for i in nxs_deps]) version_text += " Currently Available Nexus Dependencies:\n" version_text += f" {'Python':<{name_align}} = {sys.version.split()[0]}\n" for pkg_name, pkg_ver in available_pkgs.items(): @@ -279,7 +265,7 @@ def __call__(self,**kwargs): version_text += f" {pkg_name:<{name_align}} >= {pkg_info['min_ver']:<10} ({pkg_info['status']})\n" version_text += "\n" - missing_deps = set(nxs_deps) - set([i for i, a in available_pkgs.items() if a != "Unavailable"]) + missing_deps = set(nxs_deps) - {i for i, a in available_pkgs.items() if a != "Unavailable"} if len(missing_deps) > 0: version_text += " Required dependencies are met,\n" version_text += " however some optional dependencies are missing.\n" @@ -297,20 +283,6 @@ def __call__(self,**kwargs): self.log('Applying user settings') - # assign simple variables - for name in Settings.core_assign_vars: - if name in kwargs: - nexus_core[name] = kwargs[name] - #end if - #end for - - # assign simple variables - for name in Settings.noncore_assign_vars: - if name in kwargs: - nexus_noncore[name] = kwargs[name] - #end if - #end for - # extract settings based on keyword groups kw = Settings.kw_set(Settings.nexus_vars ,kwargs) mach_kw = Settings.kw_set(Settings.machine_vars ,kwargs) @@ -318,7 +290,11 @@ def __call__(self,**kwargs): pwscf_kw = Settings.kw_set(Settings.pwscf_vars ,kwargs) qm_pkg_kw = Settings.kw_set(Settings.qm_package_vars,kwargs) if len(kwargs)>0: - msg = f'some settings keywords have not been accounted for\nleftover keywords: {sorted(kwargs.keys())}\nthis is a developer error' + msg = ( + 'Some settings keywords have not been accounted for\n' + f'Leftover keywords: {sorted(kwargs.keys())}\n' + 'This is a developer error' + ) raise NexusError(msg) #end if @@ -331,21 +307,8 @@ def __call__(self,**kwargs): # process machine settings self.process_machine_settings(mach_kw) - # process nexus core settings - self.process_core_settings(kw) - - # process nexus noncore settings - self.process_noncore_settings(kw) - - # transfer select core data to the global namespace - for k in nexus_core_noncore.keys(): - nexus_core_noncore[k] = nexus_core[k] - nexus_noncore.update(**deepcopy(nexus_core_noncore)) # prevent write to core namespace - - # copy final core and noncore settings - self.update(**deepcopy(nexus_core)) - self.update(**deepcopy(nexus_noncore)) - + # process nexus config settings + self.process_config_settings(kw) # process gamess settings Gamess.restore_default_settings() @@ -358,8 +321,6 @@ def __call__(self,**kwargs): # process quantum package settings QuantumPackage.restore_default_settings() QuantumPackage.settings(**qm_pkg_kw) - - return #end def __call__ @@ -391,11 +352,11 @@ def process_command_line_settings(self,script_settings): ) parser.add_option('--sleep',dest='sleep', default='none', - help=f'Number of seconds between polls. At each poll, simulations are actually run provided all simulations they depend on have successfully completed (default={nexus_core_defaults.sleep}).' + help=f'Number of seconds between polls. At each poll, simulations are actually run provided all simulations they depend on have successfully completed (default={NEXUS_CONFIG.sleep}).' ) parser.add_option('--timeout',dest='timeout', default='none', - help=f'Number of seconds to wait for output and error files after a job exits the queue before marking the simulation as failed (default={nexus_core_defaults.timeout}).' + help=f'Number of seconds to wait for output and error files after a job exits the queue before marking the simulation as failed (default={NEXUS_CONFIG.timeout}).' ) parser.add_option('--machine',dest='machine', default='none', @@ -407,15 +368,15 @@ def process_command_line_settings(self,script_settings): ) parser.add_option('--runs',dest='runs', default='none', - help=f'Directory to perform all runs in. Simulation paths are appended to this directory (default={nexus_core_defaults.runs}).' + help=f'Directory to perform all runs in. Simulation paths are appended to this directory (default={NEXUS_CONFIG.runs}).' ) parser.add_option('--results',dest='results', default='none', - help=f"Directory to copy out lightweight results data. If set to '', results will not be stored outside of the runs directory (default={nexus_core_defaults.results})." + help=f"Directory to copy out lightweight results data. If set to '', results will not be stored outside of the runs directory (default={NEXUS_CONFIG.results})." ) parser.add_option('--local_directory',dest='local_directory', default='none', - help=f'Base path where runs and results directories will be created (default={nexus_core_defaults.local_directory}).' + help=f'Base path where runs and results directories will be created (default={NEXUS_CONFIG.local_directory}).' ) parser.add_option('--pseudo_dir',dest='pseudo_dir', default='none', @@ -449,20 +410,28 @@ def process_command_line_settings(self,script_settings): # check that all options are allowed (developer check) invalid = set(opt.keys())-Settings.allowed_vars if len(invalid)>0: - msg = f'invalid command line settings encountered\ninvalid settings: {sorted(invalid)}\nthis is a developer error' + msg = ( + 'Invalid command line settings encountered\n' + f'Invalid settings: {sorted(invalid)}\n' + 'This is a developer error' + ) raise NexusError(msg) #end if # pre-process options, full processing occurs upon return - boolean_options = set(['status_only','generate_only','progress_tty']) + boolean_options = {'status_only','generate_only','progress_tty'} real_options = {'sleep', 'timeout'} for ropt in real_options: if opt[ropt]!='none': try: opt[ropt] = float(opt[ropt]) - except: - msg = f"command line option '{ropt}' must be a real value\nyou provided: {opt[ropt]}\nplease try again" - raise ValueError(msg) + except ValueError as err: + msg = ( + f"Command line option '{ropt}' must be a real value\n" + f"You provided: {opt[ropt]}\n" + "Please try again" + ) + raise TypeError(msg) from err #end try #end if #end for @@ -474,7 +443,6 @@ def process_command_line_settings(self,script_settings): script_settings[name] = value #end if #end for - #end def process_command_line_settings @@ -484,7 +452,7 @@ def process_machine_settings(self,mset): mid_set = set() if 'machine_info' in mset: machine_info = mset.machine_info - if isinstance(machine_info,dict) or isinstance(machine_info,obj): + if isinstance(machine_info, dict | obj): for machine_name,minfo in machine_info.items(): mname = machine_name.lower() if Machine.exists(mname): @@ -493,12 +461,18 @@ def process_machine_settings(self,mset): machine.incorporate_user_info(minfo) mid_set.add(id(machine)) else: - msg = f'machine {machine_name} is unknown\n cannot set machine_info' + msg = ( + f'machine {machine_name} is unknown\n' + ' cannot set machine_info' + ) raise ValueError(msg) #end if #end for else: - msg = 'machine_info must be a dict or obj\n you provided type '+machine_info.__class__.__name__ + msg = ( + 'machine_info must be a dict or obj\n' + ' you provided type '+type(machine_info).__name__ + ) raise TypeError(msg) #end if #end if @@ -528,7 +502,10 @@ def process_machine_settings(self,mset): if 'account' in mset: account = mset.account if not isinstance(account,str): - msg = f'account for {machine_name} must be a string\nyou provided: {account}' + msg = ( + f'account for {machine_name} must be a string\n' + f'you provided: {account}' + ) raise TypeError(msg) #end if ProjectManager.machine.account = account @@ -536,7 +513,10 @@ def process_machine_settings(self,mset): if 'user' in mset: user = mset.user if not isinstance(user,str): - msg = f'user for {machine_name} must be a string\nyou provided: {user}' + msg = ( + f'user for {machine_name} must be a string\n' + f'you provided: {user}' + ) raise TypeError(msg) #end if ProjectManager.machine.user = user @@ -567,125 +547,120 @@ def process_machine_settings(self,mset): #end def process_machine_settings - 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 - elif kw.status==True: - nexus_core.status = nexus_core.status_modes.standard - elif kw.status in nexus_core.status_modes: - nexus_core.status = nexus_core.status_modes[kw.status] - else: - msg = f'invalid status mode specified: {kw.status}\nvalid status modes are: {sorted(nexus_core.status_modes.keys())}' - raise ValueError(msg) - #end if - #end if - 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 = f'invalid mode specified: {kw.mode}\nvalid modes are: {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)) + def process_config_settings(self, kw: dict): + # Deprecated variables + deprecated = ( + ("mode", "Please use `stages` instead!"), + ("verbose", "Please use `quiet` instead!"), + ("debug", "This variable was redundant, please remove from your script!"), + ("trace", "This variable was unused in Nexus, please remove from your script!"), + ("emulate", "This variable was unused in Nexus, please remove from your script!"), + ) + for var, extra in deprecated: + if var in kw: + del kw[var] + warn( + f"The setting '{var}' has been deprecated!\n" + f"{extra}" + ) + + match kw.pop("status", None): + case None | False: + pass + case True: + NEXUS_CONFIG.status = ShowStatusMode.ALL + case val: + val_str = str(val).upper() + if val_str not in ShowStatusMode.__members__: + msg = ( + f"Invalid status mode specified: {val}\n" + f"Valid status modes are: {[*ShowStatusMode.__members__]}" + ) + raise ValueError(msg) + NEXUS_CONFIG.status = ShowStatusMode[val_str] + + if status_only := kw.pop("status_only", None): + NEXUS_CONFIG.status_only = status_only + if NEXUS_CONFIG.status is ShowStatusMode.NONE: + NEXUS_CONFIG.status = ShowStatusMode.ALL + + stages = kw.pop("stages", None) + generate_only = kw.pop("generate_only", None) + if stages is not None and generate_only is not None: + msg = "Can not set both `stages` and `generate_only`!" + raise ValueError(msg) + elif isinstance(stages, SimStage): + NEXUS_CONFIG.stages = stages + elif isinstance(stages, str): + if stages.upper() not in SimStage.__members__: + msg = ( + f"Invalid stages specified: {val}\n" + f"Valid stages are: {[*SimStage.__members__]}" + ) 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: - nexus_core.file_locations.append(kw.local_directory) - #end if - if 'file_locations' in kw: - fl = kw.file_locations - if isinstance(fl,str): - nexus_core.file_locations.extend([path_string(fl)]) + NEXUS_CONFIG.stages = SimStage[stages.upper()] + elif isinstance(stages, Collection): + NEXUS_CONFIG.stages = SimStage.from_list(stages) + elif stages is not None: + msg = f"stages should be a SimStage, str, or list of str, but is {type(stages)}!" + raise TypeError(msg) + elif generate_only: + NEXUS_CONFIG.stages = SimStage.SETUP # Preferred new route + NEXUS_CONFIG.generate_only = True # Legacy, will replace + + if (loc_dir := kw.pop("local_directory", None)) is not None: + NEXUS_CONFIG.file_locations.append(loc_dir) + + if (file_locs := kw.pop("file_locations", None)) is not None: + if isinstance(file_locs, str | Path): + NEXUS_CONFIG.file_locations.append(path_string(file_locs)) else: - nexus_core.file_locations.extend([path_string(f) for f in fl]) - #end if - #end if - pseudo_dir = kw.get('pseudo_dir',None) - if pseudo_dir is not None: - if not os.path.isdir(pseudo_dir): - msg = f'pseudo_dir "{pseudo_dir}" does not exist or is not a directory' + NEXUS_CONFIG.file_locations.extend( + path_string(i) for i in file_locs + ) + + if (pseudo_dir := kw.pop("pseudo_dir", None)) is not None: + pseudo_dir = Path(pseudo_dir).resolve(strict=True) + if not pseudo_dir.is_dir(): + msg = f"pseudo_dir '{pseudo_dir}' is not a directory!" raise NotADirectoryError(msg) - #end if - pseudo_dir = os.path.abspath(pseudo_dir) - nexus_core.pseudo_dir = pseudo_dir - #end if + + NEXUS_CONFIG.pseudo_dir = path_string(pseudo_dir) + PseudoSet.pseudo_files.clear() PseudoSet.labeled_pseudosets.clear() - if pseudo_dir is not None: - for file in Path(pseudo_dir).iterdir(): + if NEXUS_CONFIG.pseudo_dir is not None: + for file in Path(NEXUS_CONFIG.pseudo_dir).iterdir(): if file.is_file(): - PseudoSet.pseudo_files[file.name] = str(file.resolve()) - #end if - #end for - #end if + PseudoSet.pseudo_files[file.name] = str(file) # backwards compatibility with prior results_dir default old_results_default = 'results' - old_results_dir = os.path.join(nexus_core.local_directory,old_results_default) + old_results_dir = os.path.join(NEXUS_CONFIG.local_directory,old_results_default) if 'results' not in kw and os.path.exists(old_results_dir): - nexus_core.results = old_results_default - #end if - #end def process_core_settings + NEXUS_CONFIG.results = old_results_default + if basis_dir := kw.pop("basis_dir", None): + basis_dir = Path(basis_dir).resolve(strict=True) + if not basis_dir.is_dir(): + msg = f"basis_dir '{basis_dir}' is not a directory!" + raise NotADirectoryError(msg) - def process_noncore_settings(self,kw): - if 'basis_dir' not in kw: - nexus_noncore.basissets = BasisSets() + NEXUS_CONFIG.file_locations.append(path_string(basis_dir)) + bs_files = [] + for file in basis_dir.iterdir(): + if file.is_file(): + bs_files.append(path_string(file)) + + NEXUS_CONFIG.basissets = BasisSets(bs_files) else: - basis_dir = kw.basis_dir - nexus_core.file_locations.append(basis_dir) - if not os.path.exists(basis_dir): - msg = f'basis_dir "{basis_dir}" does not exist' - raise FileNotFoundError(msg) - #end if - files = os.listdir(basis_dir) - bsfiles = [] - for f in files: - pf = os.path.join(basis_dir,f) - if os.path.isfile(pf): - bsfiles.append(pf) - #end if - #end for - nexus_noncore.basissets = BasisSets(bsfiles) - #end if - #end def process_noncore_settings + NEXUS_CONFIG.basissets = BasisSets() + + # Set remaining settings + for cfg_var in NexusConfig.__slots__: + if (cfg_val := kw.pop(cfg_var, None)) is not None: + setattr(NEXUS_CONFIG, cfg_var, cfg_val) + #end def process_core_settings #end class Settings diff --git a/nexus/nexus/examples/qmcpack/rsqmc_misc/c20/c20.py b/nexus/nexus/examples/qmcpack/rsqmc_misc/c20/c20.py index 6b3c142fc1..e74022dc46 100755 --- a/nexus/nexus/examples/qmcpack/rsqmc_misc/c20/c20.py +++ b/nexus/nexus/examples/qmcpack/rsqmc_misc/c20/c20.py @@ -1,6 +1,6 @@ #! /usr/bin/env python3 -from nexus import settings,job,run_project +from nexus import settings,job,run_project,NEXUS_CONFIG from nexus import read_structure from nexus import generate_physical_system from nexus import generate_pwscf @@ -153,7 +153,7 @@ # print out the total energy -performed_runs = not settings.generate_only and not settings.status_only +performed_runs = not NEXUS_CONFIG.generate_only and not NEXUS_CONFIG.status_only if performed_runs: # get the qmcpack analyzer object # it contains all of the statistically analyzed data from the run diff --git a/nexus/nexus/examples/qmcpack/rsqmc_misc/graphene/graphene.py b/nexus/nexus/examples/qmcpack/rsqmc_misc/graphene/graphene.py index 1760087f7c..5537e08399 100755 --- a/nexus/nexus/examples/qmcpack/rsqmc_misc/graphene/graphene.py +++ b/nexus/nexus/examples/qmcpack/rsqmc_misc/graphene/graphene.py @@ -1,6 +1,6 @@ #! /usr/bin/env python3 -from nexus import settings,job,run_project +from nexus import settings,job,run_project,NEXUS_CONFIG from nexus import generate_physical_system from nexus import generate_pwscf from nexus import generate_pw2qmcpack @@ -203,7 +203,7 @@ # print out the total energy -performed_runs = not settings.generate_only and not settings.status_only +performed_runs = not NEXUS_CONFIG.generate_only and not NEXUS_CONFIG.status_only if performed_runs: # get the qmcpack analyzer object # it contains all of the statistically analyzed data from the run diff --git a/nexus/nexus/examples/quantum_espresso/relax_Ge_T_vs_kpoints/relax_vs_kpoints_example.py b/nexus/nexus/examples/quantum_espresso/relax_Ge_T_vs_kpoints/relax_vs_kpoints_example.py index 74ae861f7b..eebf0509a5 100755 --- a/nexus/nexus/examples/quantum_espresso/relax_Ge_T_vs_kpoints/relax_vs_kpoints_example.py +++ b/nexus/nexus/examples/quantum_espresso/relax_Ge_T_vs_kpoints/relax_vs_kpoints_example.py @@ -1,6 +1,6 @@ #! /usr/bin/env python3 -from nexus import settings +from nexus import settings, NEXUS_CONFIG from nexus import generate_physical_system from nexus import generate_pwscf,job from nexus import run_project @@ -64,7 +64,7 @@ # analyze the results -performed_runs = not settings.generate_only and not settings.status_only +performed_runs = not NEXUS_CONFIG.generate_only and not NEXUS_CONFIG.status_only if performed_runs: print() print('Relaxation results:') diff --git a/nexus/nexus/gamess_input.py b/nexus/nexus/gamess_input.py index 54101e3098..b922bd8c4d 100644 --- a/nexus/nexus/gamess_input.py +++ b/nexus/nexus/gamess_input.py @@ -37,7 +37,7 @@ import numpy as np from .periodic_table import Elements from .developer import DevBase, obj, warn, FileFormatError -from .nexus_base import nexus_noncore +from .nexus_base import NEXUS_CONFIG from .pseudoset import pp_elem_label, PseudoSet from .simulation import SimulationInput from .utilities import path_string @@ -1253,7 +1253,7 @@ def generate_any_gamess_input(**kwargs): #end if if pskw.pseudos is None: if pskw.bases is not None: - bss = nexus_noncore.basissets.bases_by_atom(*pskw.bases) + bss = NEXUS_CONFIG.basissets.bases_by_atom(*pskw.bases) else: bss = obj() if 'coord' not in gi.contrl: diff --git a/nexus/nexus/machines.py b/nexus/nexus/machines.py index c1cebba0ee..05514b9c43 100644 --- a/nexus/nexus/machines.py +++ b/nexus/nexus/machines.py @@ -54,7 +54,7 @@ from subprocess import Popen, CalledProcessError import numpy as np from .developer import DevBase, obj, warn, NexusError -from .nexus_base import NexusCore, nexus_core +from .nexus_base import NexusCore, NEXUS_CONFIG from .execute import execute from .utilities import path_string import importlib.util @@ -637,7 +637,7 @@ def initialize(self,sim): #end if if self.subdir is None: if machine.local_directory is not None: - self.subdir = os.path.join(machine.local_directory,nexus_core.runs,sim.path) + self.subdir = os.path.join(machine.local_directory,NEXUS_CONFIG.runs,sim.path) self.abs_subdir = self.subdir else: self.subdir = self.directory @@ -759,7 +759,7 @@ def serial_only(self): # remove? def determine_end_status(self,status): - if not nexus_core.generate_only: + if not NEXUS_CONFIG.generate_only: self.successful = False # not really implemented yet #end if #end def determine_end_status @@ -1312,7 +1312,7 @@ def query_queue(self): self.validate() done = [] for pid,process in self.processes.items(): - if nexus_core.generate_only or not nexus_core.monitor: + if NEXUS_CONFIG.generate_only or not NEXUS_CONFIG.monitor: qpid,status = pid,0 else: qpid,status = os.waitpid(pid,os.WNOHANG) @@ -1326,7 +1326,7 @@ def query_queue(self): self.running.remove(iid) self.finished.add(iid) done.append(pid) - if not nexus_core.generate_only: + if not NEXUS_CONFIG.generate_only: job.out.close() job.err.close() #end if @@ -1369,7 +1369,7 @@ def submit_jobs(self): job_req = job_req[order] for job in job_req: - if job.cores>self.cores and not nexus_core.generate_only: + if job.cores>self.cores and not NEXUS_CONFIG.generate_only: msg = ( 'job '+str(job.internal_id)+' is too large to run on this machine\n' 'cores requested: '+str(job.cores)+'\n' @@ -1443,11 +1443,11 @@ def submit_job(self,job): job.status = job.states.running process = obj() process.job = job - if nexus_core.generate_only: + if NEXUS_CONFIG.generate_only: self.log(pad+'Would have executed: '+command) job.system_id = job.internal_id else: - if nexus_core.monitor: + if NEXUS_CONFIG.monitor: self.log(pad+'Executing: '+command) job.out = open(job.outfile,'w') job.err = open(job.errfile,'w') @@ -1747,7 +1747,7 @@ def requeue_job(self,job): #end if self.process_job(job) self.jobs[jid] = job - if not nexus_core.dynamic: + if not NEXUS_CONFIG.dynamic: self.running.add(jid) process = obj(job=job) self.processes[pid] = process @@ -2087,7 +2087,7 @@ def query_queue(self,out=None): #end if done = [] for pid,process in self.processes.items(): - if pid not in self.system_queue or self.system_queue[pid]=='complete' or nexus_core.generate_only: + if pid not in self.system_queue or self.system_queue[pid]=='complete' or NEXUS_CONFIG.generate_only: job = process.job job.status = job.states.finished job.finished = True @@ -2138,7 +2138,7 @@ def submit_job(self,job): raise FileNotFoundError(msg) #end if command = self.sub_command(job) - if nexus_core.generate_only: + if NEXUS_CONFIG.generate_only: self.log(pad+'Would have executed: '+command) job.status = job.states.running process = obj() diff --git a/nexus/nexus/nexus_base.py b/nexus/nexus/nexus_base.py index fc371a94eb..c81a7c9de7 100644 --- a/nexus/nexus/nexus_base.py +++ b/nexus/nexus/nexus_base.py @@ -23,111 +23,261 @@ # classes. # # # #====================================================================# - +from __future__ import annotations import os -from os import PathLike -from copy import deepcopy import pickle -from pickle import UnpicklingError +from collections.abc import Collection +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 pickle import UnpicklingError +from typing import TypeAlias + +from .basisset import BasisSets +from .developer import DevBase, log, obj from .memory import resident -from .developer import DevBase, obj, log - - -# Nexus namespaces -# nexus_core: to be used by NexusCore classes only -# nexus_noncore: allows read only access to some nexus_core data to non-core classes -nexus_core = obj() -nexus_noncore = obj() -nexus_core_noncore = obj() - -status_modes = obj( - none = 0, - standard = 1, - active = 2, - failed = 3, - ready = 4, - ) +from .nexus_version import nexus_version +from .utilities import path_string -modes = obj( - none = 0, - setup = 1, - send_files = 2, - submit = 3, - get_output = 4, - analyze = 5, - stages = 6, - all = 7 - ) +StrPath: TypeAlias = str -nexus_noncore_defaults = obj( - basis_dir = None, - basissets = None, - ) +class ShowStatusMode(Flag): + """Flags for controlling the output of a status report. -# core namespace elements that can be accessed by noncore classes -nexus_core_noncore_defaults = obj( - pseudo_dir = None, # used by: Settings, VaspInput - ) + See :meth:`~.project_manager.ProjectManager.write_simulation_status`. + """ -nexus_core_defaults = obj( - status_only = False, # used by: ProjectManager - generate_only = False, # used by: Simulation,Machine - sleep = 3, # used by: ProjectManager - timeout = 5*60, # used by: Simulation - runs = 'runs', # used by: Simulation,Machine - results = '', # used by: Simulation - local_directory = './', # used by: Simulation,Machine - remote_directory = './', # used by: Simulation - file_locations = ['./'], # used by: Simulation - 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 - dynamic = False, # used by: DynamicWorkflowManager - # Simulation - **nexus_core_noncore_defaults - ) + NONE = auto() + READY = auto() + ACTIVE = auto() + FAILED = auto() + ALL = READY | ACTIVE | FAILED +#end class ShowStatusMode -def restore_nexus_core_defaults(): - nexus_core.clear() - nexus_noncore.clear() - nexus_core_noncore.clear() - nexus_core.update(**deepcopy(nexus_core_defaults)) - nexus_noncore.update(**deepcopy(nexus_noncore_defaults)) - for k in nexus_core_noncore_defaults.keys(): - nexus_core_noncore[k] = nexus_core[k] -#end def restore_nexus_core_defaults +class SimStage(Flag): + """Flags for controlling which stages of a simulation should be run. -restore_nexus_core_defaults() + See :meth:`~.simulation.Simulation.progress`. + """ + WRITE_INPUT = auto() + SEND_FILES = auto() + SETUP = WRITE_INPUT | SEND_FILES + SUBMIT = auto() + GET_OUTPUT = auto() + ANALYZE = auto() + ALL = SETUP | SUBMIT | GET_OUTPUT | ANALYZE + + @classmethod + def from_list(cls, items: Collection[str]) -> SimStage: + if not all(isinstance(item, str) for item in items): + msg = f"Expected a collection of strs, but got {items}" + raise TypeError(msg) + + stages = cls(0) + for stage in items: + st_up = stage.upper() + if st_up not in cls.__members__: + msg = f"Encountered invalid stage '{stage}'" + raise ValueError(msg) + stages |= cls[st_up] + return stages +#end class SimStage + + +class NexusConfig: + """Singleton class that represents all of Nexus's configuration settings. + + Attributes + ---------- + status_only : bool + Show status only and exit. + + See :meth:`~.project_manager.ProjectManager.write_simulation_status`. + status : ShowStatusMode + Which jobs to show the status of. + + See :class:`~.ShowStatusMode`, :attr:`~.status_only`. + sleep : int + How long (in seconds) to sleep between polling the queue and checking memory consumption of subprocesses. + + See :meth:`~.project_manager.ProjectManager.run_project`. + timeout : int + Number of seconds to wait for output and error files after a job exits the queue before marking the simulation as failed. + + See :meth:`~.simulation.Simulation.check_status`. + runs : StrPath + Name of the directory that Nexus runs should be placed in. + + See :meth:`~.simulation.Simulation.set_directories`. + results : StrPath + Name of the directory that results from Nexus runs should be copied to. + + If not set (empty string), results will not be stored outside of the runs directory. + + See :meth:`~.simulation.Simulation.set_directories`. + local_directory : StrPath + Directory that Nexus will create files relative to. + + See :meth:`~.simulation.Simulation.set_directories`. + remote_directory : StrPath + Unknown purpose. + file_locations : list[StrPath] + List of paths to directories that Nexus will look in for files. + + See :meth:`~.simulation.Simulation.send_files`. + monitor : bool + Toggle whether or not Nexus should continue to monitor jobs after submission. + + See :meth:`~.project_manager.ProjectManager.run_project`. + skip_submit : bool + Toggle whether or not to skip actually submitting a job. + + See :meth:`~.simulation.Simulation.submit`. + + Also related to :class:`~.bundle.SimulationBundle`. + load_images : bool + Whether or not to load the simulation image saves to reconstruct the project state. + + See :meth:`~.project_manager.ProjectManager.load_cascades`. + stages : SimStage + Control which simulation stages Nexus should run. + + See :class:`~.SimStage` and :meth:`~.simulation.Simulation.progress`. + dependent_modes : SimStage + Set which stages are required for runtime execution. + quiet : bool + Disable all Nexus output after initialization. + indent : str + Indentation base level for Nexus output. + + See :meth:`~.nexus_base.NexusCore.log`. + progress_tty : bool + Toggle printing abbreviated polling messages.graph_sims: bool + Optionally create a graph of the simulations that maps their dependency trees. + + See :func:`~nexus.run_project` and :func:`~.simulation.graph_sims`. + command_line : bool + Toggle processing of command line arguments. + + See :meth:`nexus.Settings.__call__` + dynamic : bool + Toggle use of dynamic workflows. + + Used in various places. Some spots to look are in + :meth:`.simulation.Simulation.__init__`, :func:`~.pwscf.generate_pwscf`, + :func:`~.qmcpack_converters.generate_pw2qmcpack`, and + :func:`~.project_manager.workflow_manager`. + basis_dir : StrPath | None + Directory that basis sets are stored in. + + See :attr:`~.basissets`. + basissets : BasisSets + Basis sets found in ``basis_dir`` if it exists. + + See :func:`~.gamess_input.generate_any_gamess_input`. + pseudo_dir : StrPath | None + Directory that pseudopotentials are stored in. + + See :attr:`~.pseudoset.PseudoSet.pseudo_files`, + :meth:`~.vasp_input.VaspInput.set_potcar`. + generate_only : bool + (LEGACY) Toggle only generating inputs and sending files. + """ + + __slots__ = ( # noqa: RUF023 + "status_only", + "status", + "sleep", + "timeout", + "runs", + "results", + "local_directory", + "remote_directory", + "file_locations", + "monitor", + "skip_submit", + "load_images", + "stages", + "dependent_modes", + "quiet", + "indent", + "progress_tty", + "graph_sims", + "command_line", + "dynamic", + "basis_dir", + "basissets", + "pseudo_dir", + + "generate_only", # Legacy, will be replaced + ) + + status_only: bool + status: ShowStatusMode + sleep: int + timeout: int + runs: StrPath + results: StrPath + local_directory: StrPath + remote_directory: StrPath + file_locations: list[StrPath] + monitor: bool + skip_submit: bool + load_images: bool + stages: SimStage + dependent_modes: SimStage + quiet: bool + indent: str + progress_tty: bool + graph_sims: bool + command_line: bool + dynamic: bool + basis_dir: StrPath | None + basissets: BasisSets + pseudo_dir: StrPath | None + generate_only: bool + + def __init__(self): + self.restore_defaults() + + def restore_defaults(self) -> None: + self.status_only = False + self.status = ShowStatusMode.NONE + self.sleep = 3 + self.timeout = 5*60 + self.runs = 'runs' + self.results = '' + self.local_directory = './' + self.remote_directory = './' + self.file_locations = ['./'] + self.monitor = True + self.skip_submit = False + self.load_images = True + self.stages = SimStage.ALL + self.dependent_modes = SimStage.SUBMIT + self.quiet = False + self.indent = ' ' + self.progress_tty = False + self.graph_sims = False + self.command_line = True + self.dynamic = False + self.basis_dir = None + self.basissets = None + self.pseudo_dir = None + # Legacy + self.generate_only = False + +NEXUS_CONFIG = NexusConfig() -nexus_core_no_process = {'status_only', 'generate_only', 'sleep', 'timeout'} nexus_modules = [mod.stem for mod in Path(__file__).parent.iterdir() if mod.suffix == ".py"] class NexusUnpickler(pickle.Unpickler): """This class is designed for backwards compatibility with pickles generated - before Nexus was packaged (PR #5700, December 20, 2025). + before Nexus was packaged (PR #5700, December 20, 2025). It shouldn't touch anything but old Nexus pickles. """ def find_class(self, module, name): @@ -155,7 +305,7 @@ def write_splash(): J. T. Krogel Comput. Phys. Commun. 198 154 (2016) https://doi.org/10.1016/j.cpc.2015.08.012 _____________________________________________________ - + '''.format(*nexus_version) log(splash_text) write_splash.wrote_splash = True @@ -186,7 +336,7 @@ 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 not NEXUS_CONFIG.quiet: if len(kwargs)>0: n = kwargs['n'] else: @@ -197,9 +347,9 @@ def log(self,*texts,**kwargs): for t in texts: text+=str(t)+' ' #end for - pad = n*nexus_core.indent + pad = n*NEXUS_CONFIG.indent output_text = pad+text.replace('\n','\n'+pad) - if nexus_core.progress_tty and is_progress and self._logfile.isatty(): + if NEXUS_CONFIG.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() @@ -211,7 +361,7 @@ def log(self,*texts,**kwargs): def enter(self, directory: PathLike, *, changedir: bool = True, msg: str = ''): """Have Nexus enter a directory and change its current working directory. - + Parameters ---------- directory : PathLike @@ -249,7 +399,7 @@ def load(self, fpath: PathLike | None = None): fobj.seek(0) try: # Old pickles from before Nexus was packaged (PR #5700, December 20 2025) - # won't have the correct module path. The custom unpickler will handle this by + # won't have the correct module path. The custom unpickler will handle this by # prepending "nexus." to the module path tmp = NexusUnpickler(fobj).load() except UnpicklingError: diff --git a/nexus/nexus/project_manager.py b/nexus/nexus/project_manager.py index 255d558081..0f74ca62dc 100644 --- a/nexus/nexus/project_manager.py +++ b/nexus/nexus/project_manager.py @@ -22,7 +22,7 @@ from typing import ClassVar,Literal,TextIO from . import memory from .developer import obj, NexusError -from .nexus_base import NexusCore, nexus_core, dynamic_storage +from .nexus_base import NexusCore, ShowStatusMode, NEXUS_CONFIG, dynamic_storage from .simulation import Simulation, sim_err_handler from .machines import Machine,Job @@ -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() @@ -98,8 +96,8 @@ def add_cascade(self,cascade): def run_project(self,*,status=False,status_only=False): self.log('\nProject starting',n=0) self.init_cascades() - status_only = status_only or nexus_core.status_only - status = status or status_only or nexus_core.status!=nexus_core.status_modes.none + status_only = status_only or NEXUS_CONFIG.status_only + status = status or status_only or NEXUS_CONFIG.status is not ShowStatusMode.NONE if status: self.write_simulation_status() if status_only: @@ -107,8 +105,8 @@ 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: + if NEXUS_CONFIG.dependent_modes in NEXUS_CONFIG.stages: + if NEXUS_CONFIG.monitor: start_time = time.time() ipoll = 0 while len(self.progressing_cascades)>0: @@ -122,7 +120,7 @@ def run_project(self,*,status=False,status_only=False): self.progress_cascades() self.machine.submit_jobs() self.update_process_ids() - time.sleep(nexus_core.sleep) + time.sleep(NEXUS_CONFIG.sleep) if NexusCore.wrote_something: self.log() #end if @@ -145,7 +143,7 @@ def init_cascades(self): self.resolve_file_collisions() self.propagate_blockages() self.log('loading cascade images',n=1) - if nexus_core.load_images: + if NEXUS_CONFIG.load_images: self.load_cascades() else: self.log('cascades',n=1) @@ -286,18 +284,17 @@ def traverse_cascades(self,operation=trivial,*args,**kwargs): def write_simulation_status(self): - status = nexus_core.status - status_modes = nexus_core.status_modes + status = NEXUS_CONFIG.status self.log('\ncascade status',n=1) self.log('setup, sent_files, submitted, finished, got_output, analyzed, failed',n=2) all_sids = set() for sim in self.simulations.values(): add = False - if status==status_modes.active: + if status is ShowStatusMode.ACTIVE: add = sim.active() - elif status==status_modes.ready: + elif status is ShowStatusMode.READY: add = sim.ready() - elif status==status_modes.failed: + elif status is ShowStatusMode.FAILED: add = sim.failed else: add = True @@ -310,7 +307,7 @@ def write_simulation_status(self): for isim in sorted(all_sids): sim = self.simulations[isim] if not sim.bundled: - if status==status_modes.active and not sim.active(): + if status is ShowStatusMode.ACTIVE and not sim.active(): continue #end if self.status_line(sim) @@ -483,7 +480,7 @@ def add_new_dyn_procs(self): def poll(self,sleep=None): if sleep is None: - sleep = nexus_core.sleep + sleep = NEXUS_CONFIG.sleep # find and add newly created dynamic process objects self.add_new_dyn_procs() @@ -557,7 +554,7 @@ def workflow_manager(**kw): workflow_manager.first = True else: workflow_manager.first = False - if not nexus_core.dynamic: + if not NEXUS_CONFIG.dynamic: msg = ( 'workflow_manager is only compatible with dynamic workflows.\n' 'If you intend to use dynamic workflows, please set dynamic=True in settings.' diff --git a/nexus/nexus/pseudoset.py b/nexus/nexus/pseudoset.py index 11dc35ac1e..5e2bbfc846 100644 --- a/nexus/nexus/pseudoset.py +++ b/nexus/nexus/pseudoset.py @@ -17,7 +17,7 @@ from .periodic_table import Elements from .physical_system import PhysicalSystem from .utilities import is_valid_filename -from .nexus_base import nexus_core +from .nexus_base import NEXUS_CONFIG def pp_elem_label( @@ -1521,8 +1521,8 @@ def generate_pseudoset( H: /path/to/pseudo_dir/H.ccECP.gamess """ if pseudo_dir is None and len(codes_psps) == 0: - if nexus_core.pseudo_dir is not None: - pseudo_dir = Path(nexus_core.pseudo_dir).resolve() + if NEXUS_CONFIG.pseudo_dir is not None: + pseudo_dir = Path(NEXUS_CONFIG.pseudo_dir).resolve() else: msg = "Must supply `pseudo_dir` and/or `codes_psps`!" raise ValueError(msg) diff --git a/nexus/nexus/pwscf.py b/nexus/nexus/pwscf.py index ec816b40e4..18741d36b0 100644 --- a/nexus/nexus/pwscf.py +++ b/nexus/nexus/pwscf.py @@ -21,7 +21,7 @@ from copy import deepcopy import shutil import numpy as np -from .nexus_base import nexus_core +from .nexus_base import NEXUS_CONFIG from .developer import obj, NexusError from .physical_system import PhysicalSystem from .pseudoset import PseudoSet @@ -513,7 +513,7 @@ def receive_structure(self,struct): def generate_pwscf(**kwargs): - if nexus_core.dynamic: + if NEXUS_CONFIG.dynamic: dp,dyn_args = DynamicProcess.check_first_gen(kwargs) if dp is not None: return dp @@ -538,7 +538,7 @@ def generate_pwscf(**kwargs): #end if pwscf = Pwscf(**sim_args) - if nexus_core.dynamic: + if NEXUS_CONFIG.dynamic: pwscf = DynamicProcess(sim=pwscf,**dyn_args) return pwscf diff --git a/nexus/nexus/qmcpack.py b/nexus/nexus/qmcpack.py index d126bf5db1..77fadf32d9 100644 --- a/nexus/nexus/qmcpack.py +++ b/nexus/nexus/qmcpack.py @@ -56,7 +56,7 @@ from .qmcpack_converters import Pw2qmcpack, Convert4qmc, Convertpw4qmc, PyscfToAfqmc from .pyscf_sim import Pyscf from .developer import DevBase, obj, NexusError, FileFormatError -from .nexus_base import nexus_core +from .nexus_base import NEXUS_CONFIG from .pseudoset import PseudoSet from .hdfreader import read_hdf from .unit_converter import convert @@ -692,7 +692,7 @@ def pre_write_inputs(self,save_image): # fix to make twist averaged input file under generate_only if self.system is None: self.should_twist_average = False - elif nexus_core.generate_only: + elif NEXUS_CONFIG.generate_only: twistnums = list(range(len(self.system.structure.kpoints))) if self.should_twist_average: self.twist_average(twistnums) @@ -2059,7 +2059,7 @@ def generate_qmcpack(**kwargs): if 'input' not in sim_args: run_path = None if 'path' in sim_args: - run_path = os.path.join(nexus_core.local_directory,nexus_core.runs,sim_args.path) + run_path = os.path.join(NEXUS_CONFIG.local_directory,NEXUS_CONFIG.runs,sim_args.path) #end if inp_args.run_path = run_path sim_args.input = generate_qmcpack_input(**inp_args) diff --git a/nexus/nexus/qmcpack_converters.py b/nexus/nexus/qmcpack_converters.py index c03a0c9e31..dc28ddc0a3 100644 --- a/nexus/nexus/qmcpack_converters.py +++ b/nexus/nexus/qmcpack_converters.py @@ -47,7 +47,7 @@ from types import MappingProxyType import numpy as np from .developer import obj, FileFormatError -from .nexus_base import nexus_core +from .nexus_base import NEXUS_CONFIG from .simulation import Simulation, SimulationInput, SimulationAnalyzer from .simulation import DynamicProcess from .pwscf import Pwscf @@ -537,7 +537,7 @@ def receive_orbitals(self,orb_path): def generate_pw2qmcpack(**kwargs): - if nexus_core.dynamic: + if NEXUS_CONFIG.dynamic: dp,dyn_args = DynamicProcess.check_first_gen(kwargs) if dp is not None: return dp @@ -549,7 +549,7 @@ def generate_pw2qmcpack(**kwargs): #end if pw2qmcpack = Pw2qmcpack(**sim_args) - if nexus_core.dynamic: + if NEXUS_CONFIG.dynamic: pw2qmcpack = DynamicProcess(sim=pw2qmcpack,**dyn_args) return pw2qmcpack diff --git a/nexus/nexus/quantum_package.py b/nexus/nexus/quantum_package.py index 014917c5e5..15eef42856 100644 --- a/nexus/nexus/quantum_package.py +++ b/nexus/nexus/quantum_package.py @@ -21,7 +21,7 @@ from pathlib import Path from .developer import obj, NexusError from .execute import execute -from .nexus_base import nexus_core +from .nexus_base import NEXUS_CONFIG from .simulation import Simulation from .quantum_package_input import QuantumPackageInput, generate_quantum_package_input, read_qp_value from .quantum_package_analyzer import QuantumPackageAnalyzer @@ -54,7 +54,7 @@ def settings(qprc=None): else: QuantumPackage.qprc = qprc - if qprc is not None and not nexus_core.status_only: + if qprc is not None and not NEXUS_CONFIG.status_only: if not isinstance(qprc,str): msg = ( 'settings input "qprc" must be a path\n' diff --git a/nexus/nexus/simulation.py b/nexus/nexus/simulation.py index 9cf51d3845..f02cab528b 100644 --- a/nexus/nexus/simulation.py +++ b/nexus/nexus/simulation.py @@ -82,7 +82,7 @@ from .structure import Structure, read_structure from .physical_system import PhysicalSystem from .machines import Job, Workstation, get_machine -from .nexus_base import NexusCore, nexus_core, dynamic_storage +from .nexus_base import NexusCore, NEXUS_CONFIG, SimStage, dynamic_storage from .utilities import path_string @@ -389,7 +389,7 @@ def __init__(self,**kwargs): self.wait_ids = set() self.block = False self.block_subcascade = False - self.skip_submit = nexus_core.skip_submit + self.skip_submit = NEXUS_CONFIG.skip_submit self.force_write = False self.loaded = False self.ordered_dependencies = [] @@ -420,7 +420,7 @@ def __init__(self,**kwargs): Simulation.all_sims.append(self) # dynamic workflow support - if nexus_core.dynamic: + if NEXUS_CONFIG.dynamic: assert self.simid not in dynamic_storage.simulation_ids self.produces = set() self.products = obj() @@ -504,7 +504,7 @@ def set(self,**kw): if p.startswith('./'): p = p[2:] #end if - ld = nexus_core.local_directory + ld = NEXUS_CONFIG.local_directory if p.startswith(ld): p = p.split(ld)[1].lstrip('/') @@ -526,7 +526,7 @@ def set(self,**kw): self.system = deepcopy(self.system) consistent,msg = self.system.check_consistent(exit=False,message=True) if not consistent: - locdir = os.path.join(nexus_core.local_directory,nexus_core.runs,self.path) + locdir = os.path.join(NEXUS_CONFIG.local_directory,NEXUS_CONFIG.runs,self.path) msg = ( 'user provided physical system is not internally consistent\n' f'simulation identifier: {self.identifier}\n' @@ -552,9 +552,9 @@ def set(self,**kw): def set_directories(self): - self.locdir = os.path.join(nexus_core.local_directory,nexus_core.runs,self.path) - self.remdir = os.path.join(nexus_core.remote_directory,nexus_core.runs,self.path) - self.resdir = os.path.join(nexus_core.local_directory,nexus_core.results,nexus_core.runs,self.path) + self.locdir = os.path.join(NEXUS_CONFIG.local_directory,NEXUS_CONFIG.runs,self.path) + self.remdir = os.path.join(NEXUS_CONFIG.remote_directory,NEXUS_CONFIG.runs,self.path) + self.resdir = os.path.join(NEXUS_CONFIG.local_directory,NEXUS_CONFIG.results,NEXUS_CONFIG.runs,self.path) if not self.fake(): #print ' creating sim {0} in {1}'.format(self.simid,self.locdir) @@ -768,7 +768,7 @@ def create_directories(self): def depends(self,*dependencies): - if nexus_core.dynamic: + if NEXUS_CONFIG.dynamic: msg = 'dynamic workflows do not allow explicit dependencies between simulations' raise ValueError(msg) if len(dependencies)==0: @@ -906,7 +906,7 @@ def check_dependencies(self,result): def get_dependencies(self): - if nexus_core.generate_only or self.finished: + if NEXUS_CONFIG.generate_only or self.finished: for dep in self.dependencies.values(): for result_name in dep.result_names: dep.results[result_name] = result_name @@ -1117,7 +1117,7 @@ def send_files(self,*,enter=True): self.files.add(self.infile) #end if send_files = self.files - file_locations = [self.locdir]+nexus_core.file_locations + file_locations = [self.locdir]+NEXUS_CONFIG.file_locations remote = self.remdir for file in send_files: found_file = False @@ -1168,7 +1168,7 @@ def submit(self): #end if self.submitted = True self.record_timestamp('submitted') - if (self.job.batch_mode or not nexus_core.monitor) and not nexus_core.generate_only: + if (self.job.batch_mode or not NEXUS_CONFIG.monitor) and not NEXUS_CONFIG.generate_only: self.save_image() #end if elif not self.finished: @@ -1193,7 +1193,7 @@ def check_status(self): newly_exited_queue = 'exited_queue' not in self.timestamps self.record_timestamp('exited_queue') #end if - if nexus_core.generate_only: + if NEXUS_CONFIG.generate_only: self.finished = self.job.finished elif self.job.finished: should_check = True @@ -1210,7 +1210,7 @@ def check_status(self): elif not self.finished: exited_queue = datetime.fromisoformat(self.timestamps.exited_queue) elapsed = datetime.now().astimezone() - exited_queue - if elapsed.total_seconds()>nexus_core.timeout: + if elapsed.total_seconds()>NEXUS_CONFIG.timeout: self.record_timestamp('timed_out') self.failed = True #end if @@ -1252,7 +1252,7 @@ def get_output(self): if self.finished: self.enter(self.locdir,changedir=False,msg=self.simid) self.log('copying results'+self.idstr(),n=3) - if not nexus_core.generate_only: + if not NEXUS_CONFIG.generate_only: output_files = self.get_output_files() if self.infile is not None: output_files.append(self.infile) @@ -1293,7 +1293,7 @@ def analyze(self): if self.finished: self.enter(self.locdir,changedir=False,msg=self.simid) self.log('analyzing'+self.idstr(),n=3) - if not nexus_core.generate_only: + if not NEXUS_CONFIG.generate_only: analyzer = self.analyzer_type(self) analyzer.analyze() self.post_analyze(analyzer) @@ -1305,7 +1305,7 @@ def analyze(self): self.save_image() # support dynamic workflows - if nexus_core.dynamic: + if NEXUS_CONFIG.dynamic: self.fill_products() #end if #end def analyze @@ -1345,96 +1345,71 @@ 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: - self.get_output() - progress = self.finished - elif mode==modes.analyze: - 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 len(self.wait_ids) > 0: + return + + if self.block or self.failed: + if self.force_write: if not self.got_dependencies: self.get_dependencies() - #end if - if 'setup' in nexus_core.stages: + + if SimStage.WRITE_INPUT in NEXUS_CONFIG.stages: + # Wouldn't this fail if the directories haven't been created? self.write_inputs() - #end if - if not self.sent_files and 'send_files' in nexus_core.stages: + + if not self.sent_files and SimStage.SEND_FILES in NEXUS_CONFIG.stages: self.send_files() - #end if - #end if - #end if + return + + progress = True + if not self.created_directories: + self.create_directories() + + if not self.got_dependencies: + self.get_dependencies() + + if not ( + self.setup + and SimStage.WRITE_INPUT in NEXUS_CONFIG.stages + ): + self.write_inputs() + + if not ( + self.sent_files + and SimStage.SEND_FILES in NEXUS_CONFIG.stages + ): + self.send_files() + + if not ( + self.finished + and SimStage.SUBMIT in NEXUS_CONFIG.stages + ): + self.submit() + + if NEXUS_CONFIG.dependent_modes in NEXUS_CONFIG.stages: + progress_post = self.finished + progress = self.finished and self.analyzed + else: + progress_post = progress + + if progress_post: + if not ( + self.got_output + and SimStage.GET_OUTPUT in NEXUS_CONFIG.stages + ): + self.get_output() + + if not ( + self.analyzed + and SimStage.ANALYZE in NEXUS_CONFIG.stages + ): + self.analyze() + + 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 @@ -1444,7 +1419,7 @@ def reconstruct_cascade(self): self.load_image() # continue from interruption if self.submitted and not self.finished and self.process_id is not None: - if nexus_core.dynamic: + if NEXUS_CONFIG.dynamic: machine = get_machine(Job.machine) if isinstance(machine,Workstation): # fully rerun following interrupt @@ -1529,7 +1504,7 @@ def execute(self,run_command=None): else: env = job.env #end if - if nexus_core.generate_only: + if NEXUS_CONFIG.generate_only: self.log(pad+'Would have executed: '+command) else: self.log(pad+'Executing: '+command) @@ -2024,8 +1999,8 @@ class DynamicProcess(DevBase): @classmethod def check_first_gen(cls,kw): - nc_loc = nexus_core.local_directory - runs = nexus_core.runs + nc_loc = NEXUS_CONFIG.local_directory + runs = NEXUS_CONFIG.runs path = kw['path'] identifier = kw['identifier'] locdir = os.path.join(nc_loc,runs,path) diff --git a/nexus/nexus/testing.py b/nexus/nexus/testing.py index 2ed9a15549..098e2fed4e 100644 --- a/nexus/nexus/testing.py +++ b/nexus/nexus/testing.py @@ -327,18 +327,6 @@ def clear_all_sims(): def check_final_state(): - from .nexus_base import nexus_core,nexus_core_defaults - from .nexus_base import nexus_noncore,nexus_noncore_defaults - from .nexus_base import nexus_core_noncore,nexus_core_noncore_defaults - - assert('runs' in nexus_core_defaults) - assert('basis_dir' in nexus_noncore_defaults) - assert('pseudo_dir' in nexus_core_noncore_defaults) - - assert(object_eq(nexus_core,nexus_core_defaults)) - assert(object_eq(nexus_noncore,nexus_noncore_defaults)) - assert(object_eq(nexus_core_noncore,nexus_core_noncore_defaults)) - from .simulation import Simulation assert(Simulation.sim_count==0) diff --git a/nexus/nexus/tests/__init__.py b/nexus/nexus/tests/__init__.py index f35b7a13f9..6ecf8c3b0c 100644 --- a/nexus/nexus/tests/__init__.py +++ b/nexus/nexus/tests/__init__.py @@ -3,7 +3,7 @@ from pathlib import Path from copy import deepcopy import functools -from nexus.nexus_base import nexus_core, nexus_noncore, nexus_noncore_defaults +from nexus.nexus_base import NEXUS_CONFIG from nexus.generic import generic_settings from nexus.pseudoset import PseudoSet from nexus.simulation import Simulation @@ -11,60 +11,6 @@ # qmcpack/nexus/nexus/tests/ TEST_DIR = Path(__file__).resolve().parent -NEXUS_CORE_KEYS = ( - "local_directory", - "remote_directory", - "mode", - "stages", - "stages_set", - "status", - "sleep", - "timeout", - "file_locations", - "pseudo_dir", - "runs", - "results", - ) -NEXUS_NONCORE_KEYS = ( - "pseudo_dir", - ) - -def divert_nexus_core(): - """Store Nexus's core and noncore keys and return them.""" - nexus_core_storage = {} - for key in NEXUS_CORE_KEYS: - nexus_core_storage[key] = nexus_core[key] - nexus_core[key] = deepcopy(nexus_core[key]) - - nexus_noncore_storage = {} - for key in NEXUS_NONCORE_KEYS: - if key in nexus_noncore: - nexus_noncore_storage[key] = nexus_noncore[key] - nexus_noncore[key] = deepcopy(nexus_noncore[key]) - - return nexus_core_storage, nexus_noncore_storage - - -def restore_nexus_core(nexus_core_storage: dict, nexus_noncore_storage: dict): - """Use the keys in ``nexus_core_storage`` and ``nexus_noncore_storage`` to restore state.""" - - for key in NEXUS_CORE_KEYS: - nexus_core[key] = nexus_core_storage.pop(key) - - for key in NEXUS_NONCORE_KEYS: - if key in nexus_noncore_storage: - nexus_noncore[key] = nexus_noncore_storage.pop(key) - elif key in nexus_noncore: - del nexus_noncore[key] - - for key in list(nexus_noncore.keys()): - if key not in nexus_noncore_defaults: - del nexus_noncore[key] - - assert len(nexus_noncore_storage) == 0, "Nexus Core keys have not been properly reset!" - assert len(nexus_core_storage) == 0, "Nexus NonCore keys have not been properly reset!" - - class FakeLog: def __init__(self): self.reset() @@ -76,7 +22,7 @@ def write(self,s): self.s += s def close(self): - None + pass def contents(self): return self.s @@ -98,49 +44,37 @@ def restore_nexus_log(logging_storage: dict): def isolate_nexus_core(test_func = None): - """Isolate changes in ``nexus_core`` for a test function.""" + """Isolate changes in ``NEXUS_CONFIG`` for a test function.""" needs_tmp_path = "tmp_path" in str(signature(test_func)) @functools.wraps(test_func) def wrap_path(tmp_path): - nexus_core_storage, nexus_noncore_storage = divert_nexus_core() pseudo_files = deepcopy(PseudoSet.pseudo_files) labeled_pseudosets = deepcopy(PseudoSet.labeled_pseudosets) logfile, logging_storage = divert_nexus_log() try: test_func(tmp_path) - test_err = None - except Exception as err: - test_err = err - - restore_nexus_core(nexus_core_storage, nexus_noncore_storage) - PseudoSet.pseudo_files = pseudo_files - PseudoSet.labeled_pseudosets = labeled_pseudosets - restore_nexus_log(logging_storage) - Simulation.clear_all_sims() - if test_err is not None: - raise test_err + finally: + NEXUS_CONFIG.restore_defaults() + PseudoSet.pseudo_files = pseudo_files + PseudoSet.labeled_pseudosets = labeled_pseudosets + restore_nexus_log(logging_storage) + Simulation.clear_all_sims() @functools.wraps(test_func) def wrap(): - nexus_core_storage, nexus_noncore_storage = divert_nexus_core() pseudo_files = deepcopy(PseudoSet.pseudo_files) labeled_pseudosets = deepcopy(PseudoSet.labeled_pseudosets) logfile, logging_storage = divert_nexus_log() try: test_func() - test_err = None - except Exception as err: - test_err = err - - restore_nexus_core(nexus_core_storage, nexus_noncore_storage) - PseudoSet.pseudo_files = pseudo_files - PseudoSet.labeled_pseudosets = labeled_pseudosets - restore_nexus_log(logging_storage) - Simulation.clear_all_sims() - if test_err is not None: - raise test_err + finally: + NEXUS_CONFIG.restore_defaults() + PseudoSet.pseudo_files = pseudo_files + PseudoSet.labeled_pseudosets = labeled_pseudosets + restore_nexus_log(logging_storage) + Simulation.clear_all_sims() if needs_tmp_path: return wrap_path @@ -191,8 +125,7 @@ def create_pseudo_files( if pseudo.is_file() } PseudoSet.labeled_pseudosets = {} - nexus_core.pseudo_dir = str(pseudo_dir) - nexus_noncore.pseudo_dir = str(pseudo_dir) + NEXUS_CONFIG.pseudo_dir = str(pseudo_dir) def register_pseudo_files(pseudos: list[str]): diff --git a/nexus/nexus/tests/test_gamess_input.py b/nexus/nexus/tests/test_gamess_input.py index ebc60c373c..a486f260f9 100644 --- a/nexus/nexus/tests/test_gamess_input.py +++ b/nexus/nexus/tests/test_gamess_input.py @@ -6,7 +6,7 @@ import shutil from . import isolate_nexus_core, TEST_DIR -from nexus.nexus_base import nexus_core +from nexus.nexus_base import NEXUS_CONFIG from ..testing import object_eq,dict_serialize @@ -326,9 +326,9 @@ def test_generate(tmp_path): pp_dir = tmp_path / "pseudopotentials" pp_dir.mkdir() - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] for file in ppfiles: pp = TEST_FILES[file] shutil.copy( diff --git a/nexus/nexus/tests/test_gamess_simulation.py b/nexus/nexus/tests/test_gamess_simulation.py index 1b2821554d..d15bf7e9ff 100644 --- a/nexus/nexus/tests/test_gamess_simulation.py +++ b/nexus/nexus/tests/test_gamess_simulation.py @@ -80,12 +80,12 @@ def test_check_result(): @isolate_nexus_core def test_get_result(tmp_path): from ..developer import obj, NexusError - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] - nexus_core.runs = '' + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] + NEXUS_CONFIG.runs = '' sim = get_gamess_sim('rhf') @@ -160,12 +160,12 @@ def test_incorporate_result(): @isolate_nexus_core def test_check_sim_status(tmp_path): - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] - nexus_core.runs = '' + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] + NEXUS_CONFIG.runs = '' sim = get_gamess_sim('rhf') diff --git a/nexus/nexus/tests/test_nexus_base.py b/nexus/nexus/tests/test_nexus_base.py index ea821df9f0..af2695ee38 100644 --- a/nexus/nexus/tests/test_nexus_base.py +++ b/nexus/nexus/tests/test_nexus_base.py @@ -6,7 +6,6 @@ from ..testing import object_eq from ..generic import generic_settings - TEST_FILES = { "old_nxs_pwscf_input.p": (TEST_DIR / "test_generic_files/old_nxs_pwscf_input.p").resolve(), "old_nxs_sim.p": (TEST_DIR / "test_generic_files/old_nxs_sim.p").resolve(), @@ -14,22 +13,6 @@ "old_nxs_sim_numpy_1.p": (TEST_DIR / "test_generic_files/old_nxs_sim_numpy_1.p").resolve(), } -def test_namespaces(): - from ..nexus_base import nexus_core,nexus_core_defaults - from ..nexus_base import nexus_noncore,nexus_noncore_defaults - from ..nexus_base import nexus_core_noncore,nexus_core_noncore_defaults - - assert('runs' in nexus_core_defaults) - assert('basis_dir' in nexus_noncore_defaults) - assert('pseudo_dir' in nexus_core_noncore_defaults) - - assert(object_eq(nexus_core,nexus_core_defaults)) - assert(object_eq(nexus_noncore,nexus_noncore_defaults)) - assert(object_eq(nexus_core_noncore,nexus_core_noncore_defaults)) -#end def test_namespaces - - - def test_empty_init(): from ..nexus_base import NexusCore nc = NexusCore() diff --git a/nexus/nexus/tests/test_nxs_sim.py b/nexus/nexus/tests/test_nxs_sim.py index 6a8f545880..3880768eaf 100644 --- a/nexus/nexus/tests/test_nxs_sim.py +++ b/nexus/nexus/tests/test_nxs_sim.py @@ -10,15 +10,15 @@ @isolate_nexus_core def test_sim(tmp_path): - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG from .test_simulation_module import get_sim - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] - nexus_core.runs = '' - nexus_core.results = '' + NEXUS_CONFIG.runs = '' + NEXUS_CONFIG.results = '' exe = TEST_DIR.parent / "bin/nxs-sim" diff --git a/nexus/nexus/tests/test_project_manager.py b/nexus/nexus/tests/test_project_manager.py index b953d79d38..0dafa09308 100644 --- a/nexus/nexus/tests/test_project_manager.py +++ b/nexus/nexus/tests/test_project_manager.py @@ -5,17 +5,13 @@ from . import isolate_nexus_core from ..testing import value_eq from ..testing import failed,FailedTest - +from ..nexus_base import NEXUS_CONFIG, ShowStatusMode, SimStage 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 @@ -277,7 +273,6 @@ def test_check_dependencies(): @isolate_nexus_core def test_write_simulation_status(): from ..generic import generic_settings - from ..nexus_base import nexus_core from ..simulation import Simulation from ..project_manager import ProjectManager @@ -293,8 +288,6 @@ def test_write_simulation_status(): pm = ProjectManager() pm.add_simulations(list(sims.values())) - status_modes = nexus_core.status_modes - def status_log(): log.reset() pm.write_simulation_status() @@ -302,7 +295,7 @@ def status_log(): return '\n'.join(line.rstrip() for line in s.splitlines()) #end def status_log - assert(nexus_core.status==status_modes.none) + assert(NEXUS_CONFIG.status is ShowStatusMode.NONE) status_ref = ''' cascade status setup, sent_files, submitted, finished, got_output, analyzed, failed @@ -317,10 +310,10 @@ def status_log(): ''' assert(status_log().strip()==status_ref.strip()) - nexus_core.status = status_modes.standard + NEXUS_CONFIG.status = ShowStatusMode.ALL assert(status_log().strip()==status_ref.strip()) - nexus_core.status = status_modes.active + NEXUS_CONFIG.status = ShowStatusMode.ACTIVE status_ref = ''' cascade status setup, sent_files, submitted, finished, got_output, analyzed, failed @@ -330,10 +323,10 @@ def status_log(): ''' assert(status_log().strip()==status_ref.strip()) - nexus_core.status = status_modes.ready + NEXUS_CONFIG.status = ShowStatusMode.READY assert(status_log().strip()==status_ref.strip()) - nexus_core.status = status_modes.failed + NEXUS_CONFIG.status = ShowStatusMode.FAILED status_ref = ''' cascade status setup, sent_files, submitted, finished, got_output, analyzed, failed @@ -402,30 +395,20 @@ def isatty(self): @isolate_nexus_core def test_run_project(tmp_path): from ..generic import generic_settings - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG from ..simulation import Simulation,input_template from ..project_manager import ProjectManager from .test_simulation_module import get_test_workflow,n_test_workflows # divert_nexus() - nexus_core.local_directory = str(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_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] - nexus_core.stages = list(nexus_core.primary_modes) - nexus_core.stages_set = set(nexus_core.stages) + assert(NEXUS_CONFIG.stages is SimStage.ALL) - 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 + NEXUS_CONFIG.sleep = 0.1 flags = ['setup','sent_files','submitted','finished','got_output','analyzed'] diff --git a/nexus/nexus/tests/test_pseudoset.py b/nexus/nexus/tests/test_pseudoset.py index cbd3bf7949..dbfc4c6cdc 100644 --- a/nexus/nexus/tests/test_pseudoset.py +++ b/nexus/nexus/tests/test_pseudoset.py @@ -12,7 +12,7 @@ import numpy as np -from nexus.nexus_base import nexus_core +from nexus.nexus_base import NEXUS_CONFIG from nexus.physical_system import generate_physical_system from nexus.pseudoset import PseudoSet, ppset, generate_pseudoset from nexus.pseudoset import read_potcar_z_valence, read_qmcpack_xml_z_valence, read_upf_z_valence @@ -1903,7 +1903,7 @@ def test_legacy_ppset(tmp_path): psp_dir.mkdir() assert psp_dir.exists(), "Failed to create pseudo directory!" - nexus_core.file_locations += [str(psp_dir)] + NEXUS_CONFIG.file_locations += [str(psp_dir)] pseudo_list = [] for psp in pseudo_names: @@ -2014,7 +2014,7 @@ def test_get_pseudos(tmp_path): psp_dir.mkdir() assert psp_dir.exists(), "Failed to create pseudo directory!" - nexus_core.file_locations += [str(psp_dir)] + NEXUS_CONFIG.file_locations += [str(psp_dir)] pseudo_list = [] for psp in pseudo_names: diff --git a/nexus/nexus/tests/test_pwscf_simulation.py b/nexus/nexus/tests/test_pwscf_simulation.py index 45abdec825..810ec025b3 100644 --- a/nexus/nexus/tests/test_pwscf_simulation.py +++ b/nexus/nexus/tests/test_pwscf_simulation.py @@ -7,7 +7,7 @@ from copy import deepcopy from . import isolate_nexus_core, create_pseudo_files -from nexus.nexus_base import nexus_core +from nexus.nexus_base import NEXUS_CONFIG from ..testing import clear_all_sims from ..testing import failed,FailedTest from ..testing import value_eq,object_eq @@ -35,11 +35,11 @@ def get_system(): def get_pwscf_sim(type='scf'): - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG from ..machines import job from ..pwscf import Pwscf,generate_pwscf - nexus_core.runs = '' + NEXUS_CONFIG.runs = '' sim = None @@ -89,9 +89,9 @@ def test_minimal_init(): @isolate_nexus_core def test_check_result(tmp_path): - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] create_pseudo_files(tmp_path, ["C.BFD.upf"]) @@ -111,9 +111,9 @@ def test_check_result(tmp_path): def test_get_result(tmp_path): from ..developer import NexusError - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] create_pseudo_files(tmp_path, ["C.BFD.upf"]) @@ -164,9 +164,9 @@ def test_get_result(tmp_path): def test_incorporate_result(tmp_path): from ..developer import obj, to_obj - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] create_pseudo_files(tmp_path, ["C.BFD.upf"]) @@ -222,9 +222,9 @@ def test_incorporate_result(tmp_path): @isolate_nexus_core def test_check_sim_status(tmp_path): - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] create_pseudo_files(tmp_path, ["C.BFD.upf"]) diff --git a/nexus/nexus/tests/test_pyscf_simulation.py b/nexus/nexus/tests/test_pyscf_simulation.py index 99832a6a3c..abd2d8e40a 100644 --- a/nexus/nexus/tests/test_pyscf_simulation.py +++ b/nexus/nexus/tests/test_pyscf_simulation.py @@ -6,7 +6,7 @@ from pathlib import Path from . import isolate_nexus_core, TEST_DIR -from nexus.nexus_base import nexus_core +from nexus.nexus_base import NEXUS_CONFIG from nexus.physical_system import generate_physical_system from nexus.structure import generate_trimer_structure from ..testing import clear_all_sims @@ -75,13 +75,13 @@ def test_check_result(): @isolate_nexus_core def test_get_result(tmp_path): from ..developer import NexusError - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] - nexus_core.runs = '' + NEXUS_CONFIG.runs = '' template_file = 'scf_template.py' template_text = 'template $chkfile' @@ -121,10 +121,10 @@ def test_check_sim_status(tmp_path): installed ``pyscf-dispersion`` with it, then tries to import it. """ - nexus_core.runs = '' - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.runs = '' + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] # Water structure = generate_trimer_structure( diff --git a/nexus/nexus/tests/test_qmcpack_converter_simulations.py b/nexus/nexus/tests/test_qmcpack_converter_simulations.py index a6ea8ade28..cf14becc23 100644 --- a/nexus/nexus/tests/test_qmcpack_converter_simulations.py +++ b/nexus/nexus/tests/test_qmcpack_converter_simulations.py @@ -7,7 +7,7 @@ from pathlib import Path from . import isolate_nexus_core, create_pseudo_files -from nexus.nexus_base import nexus_core +from nexus.nexus_base import NEXUS_CONFIG from ..testing import clear_all_sims from ..testing import failed,FailedTest from ..testing import object_eq @@ -90,9 +90,9 @@ def test_pw2qmcpack_incorporate_result(tmp_path): from ..simulation import Simulation from .test_pwscf_simulation import get_pwscf_sim - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] create_pseudo_files(tmp_path, ["C.BFD.upf"]) @@ -116,12 +116,12 @@ def test_pw2qmcpack_incorporate_result(tmp_path): @isolate_nexus_core def test_pw2qmcpack_check_sim_status(tmp_path): - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG - nexus_core.runs = '' - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.runs = '' + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] sim = get_pw2qmcpack_sim() @@ -330,12 +330,12 @@ def test_convert4qmc_incorporate_result(): @isolate_nexus_core def test_convert4qmc_check_sim_status(tmp_path): - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG - nexus_core.runs = '' - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.runs = '' + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] sim = get_convert4qmc_sim() @@ -493,12 +493,12 @@ def test_pyscf_to_afqmc_incorporate_result(): @isolate_nexus_core def test_pyscf_to_afqmc_check_sim_status(tmp_path): - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG - nexus_core.runs = '' - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.runs = '' + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] sim = get_pyscf_to_afqmc_sim() diff --git a/nexus/nexus/tests/test_qmcpack_simulation.py b/nexus/nexus/tests/test_qmcpack_simulation.py index 2a99895aba..91a4e45618 100644 --- a/nexus/nexus/tests/test_qmcpack_simulation.py +++ b/nexus/nexus/tests/test_qmcpack_simulation.py @@ -131,15 +131,15 @@ def test_check_result(): @isolate_nexus_core def test_get_result(tmp_path): from ..developer import NexusError, obj - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG from ..qmcpack_analyzer import QmcpackAnalyzer from ..qmcpack_input import dmc,mcwalkerset - nexus_core.runs = '' - nexus_core.results = '' - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.runs = '' + NEXUS_CONFIG.results = '' + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] sim = get_qmcpack_sim() @@ -238,14 +238,14 @@ def test_get_result(tmp_path): @isolate_nexus_core def test_restart_twist_average(tmp_path): - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG from ..qmcpack_input import TracedQmcpackInput,dmc,mcwalkerset - nexus_core.runs = '' - nexus_core.results = '' - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.runs = '' + NEXUS_CONFIG.results = '' + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] source = get_qmcpack_sim( identifier = 'restart_source', @@ -304,18 +304,18 @@ def test_incorporate_result(tmp_path): import shutil from numpy import array from ..developer import obj - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG from ..qmcpack_input import dmc,mcwalkerset from .test_vasp_simulation import setup_vasp_sim as get_vasp_sim from .test_qmcpack_converter_simulations import get_pw2qmcpack_sim from .test_qmcpack_converter_simulations import get_convert4qmc_sim from .test_qmcpack_converter_simulations import get_pyscf_to_afqmc_sim - nexus_core.runs = '' - nexus_core.results = '' - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.runs = '' + NEXUS_CONFIG.results = '' + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] create_pseudo_files( tmp_dir=tmp_path, @@ -549,12 +549,12 @@ def test_incorporate_result(tmp_path): @isolate_nexus_core def test_check_sim_status(tmp_path): - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG - nexus_core.runs = '' - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.runs = '' + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] sim = get_qmcpack_sim(identifier='qmc') diff --git a/nexus/nexus/tests/test_quantum_package_simulation.py b/nexus/nexus/tests/test_quantum_package_simulation.py index c6c2cc247c..83cde9994f 100644 --- a/nexus/nexus/tests/test_quantum_package_simulation.py +++ b/nexus/nexus/tests/test_quantum_package_simulation.py @@ -134,12 +134,12 @@ def test_incorporate_result(): @isolate_nexus_core def test_check_sim_status(tmp_path): - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG - nexus_core.runs = '' - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.runs = '' + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] sim = get_quantum_package_sim() diff --git a/nexus/nexus/tests/test_settings.py b/nexus/nexus/tests/test_settings.py index 98afdda17e..0585800322 100644 --- a/nexus/nexus/tests/test_settings.py +++ b/nexus/nexus/tests/test_settings.py @@ -10,7 +10,7 @@ from . import isolate_nexus_core from .. import testing from ..testing import object_eq - +from ..nexus_base import NEXUS_CONFIG, SimStage, ShowStatusMode @isolate_nexus_core def test_settings(tmp_path): @@ -18,9 +18,7 @@ def test_settings(tmp_path): import os from nexus import settings,Settings from ..developer import DevBase - from ..nexus_base import nexus_core,nexus_core_defaults - from ..nexus_base import nexus_noncore,nexus_noncore_defaults - from ..nexus_base import nexus_core_noncore,nexus_core_noncore_defaults + from ..pseudoset import PseudoSet from ..basisset import BasisSets from ..machines import Job,Workstation @@ -43,89 +41,25 @@ def aux_defaults(): assert(QuantumPackage.qprc is None) #end def aux_defaults - def check_settings_core_noncore(): - nckeys_check = set([ - 'command_line','debug', 'dependent_modes', 'emulate', - 'file_locations', 'generate_only', 'graph_sims', 'indent', - 'load_images', 'local_directory', 'mode', 'modes', 'monitor', - 'primary_modes', '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([ - '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', - 'pseudo_dir', 'remote_directory', 'results', - 'runs', 'skip_submit', 'sleep', 'stages', 'stages_set', 'status', - 'timeout', - 'status_modes', 'status_only', 'trace', 'verbose', 'dynamic' - ]) - setkeys_allowed = setkeys_check | Settings.allowed_vars - - nckeys = set(nexus_core.keys()) - nnckeys = set(nexus_noncore.keys()) - setkeys = set(settings.keys()) - - assert(nckeys==nckeys_check) - assert(nnckeys==nnckeys_check) - assert(setkeys>=setkeys_check) - assert(setkeys<=setkeys_allowed) - - pairs = [(settings,nexus_core), - (settings,nexus_noncore), - (nexus_core,nexus_noncore) - ] - for o1,o2 in pairs: - shared_keys = set(o1.keys()) & set(o2.keys()) - for k in shared_keys: - v1 = o1[k] - v2 = o2[k] - if isinstance(v1,(obj,DevBase)): - assert(object_eq(v1,v2)) - else: - assert(v1 == v2) - #end if - #end for - #end for - #end check_settings_core_noncore - def check_empty_settings(): - settings( - command_line = False, - ) - 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)) + settings(command_line = False) + settings.command_line = True + NEXUS_CONFIG.command_line = True + # nexus config has basic run stages and PseudoSet registries are empty + assert(NEXUS_CONFIG.stages is SimStage.ALL) + 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)) - assert(len(nexus_noncore.basissets)==0) - nnc_defaults = obj(**nexus_noncore_defaults) - nnc_defaults.update(**nexus_core_noncore_defaults) - nexus_noncore.basissets = None - assert(object_eq(nexus_noncore,nnc_defaults)) + assert(isinstance(NEXUS_CONFIG.basissets,BasisSets)) + assert(len(NEXUS_CONFIG.basissets)==0) + NEXUS_CONFIG.restore_defaults() + assert(NEXUS_CONFIG.basissets is None) # other settings objects should be at default also aux_defaults() #end def_check_empty_settings - - - # check that core settings are at default values - assert(object_eq(nexus_core,nexus_core_defaults)) - assert(nexus_core.timeout==5*60) - assert(object_eq(nexus_noncore,nexus_noncore_defaults)) - assert(object_eq(nexus_core_noncore,nexus_core_noncore_defaults)) + + NEXUS_CONFIG.restore_defaults() + assert(NEXUS_CONFIG.timeout==5*60) aux_defaults() # core settings remain almost at default with empty settings @@ -155,12 +89,11 @@ def check_empty_settings(): machine = 'ws16', command_line = False, ) - check_settings_core_noncore() - assert(nexus_core.status_only==0) - assert(nexus_core.generate_only==1) - assert(nexus_core.timeout==10) + assert(NEXUS_CONFIG.status_only==0) + assert(NEXUS_CONFIG.generate_only==1) + assert(NEXUS_CONFIG.timeout==10) pseudo_path = str((tmp_path / 'pseudopotentials').resolve()) - assert(nexus_core.pseudo_dir==pseudo_path) + assert(NEXUS_CONFIG.pseudo_dir==pseudo_path) assert(PseudoSet.pseudo_files=={ pseudo:str((Path(pseudo_path)/pseudo).resolve()) for pseudo in pseudos }) diff --git a/nexus/nexus/tests/test_simulation_module.py b/nexus/nexus/tests/test_simulation_module.py index df50fe39ca..6504c902c8 100644 --- a/nexus/nexus/tests/test_simulation_module.py +++ b/nexus/nexus/tests/test_simulation_module.py @@ -7,7 +7,7 @@ from pathlib import Path from copy import deepcopy from . import isolate_nexus_core -from nexus.nexus_base import nexus_core +from nexus.nexus_base import NEXUS_CONFIG, SimStage from ..testing import value_eq,object_eq from ..testing import FailedTest,failed @@ -1002,9 +1002,9 @@ def test_create_directories(tmp_path): import os from ..simulation import Simulation - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] s = Simulation() @@ -1026,9 +1026,9 @@ def test_create_directories(tmp_path): def test_file_text(tmp_path): from ..simulation import Simulation - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] s = Simulation() s.create_directories() @@ -1687,9 +1687,9 @@ def test_save_load_image(tmp_path): from ..developer import obj, load from ..simulation import Simulation,SimulationImage - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] nsave = 31 nload = 23 @@ -1746,9 +1746,9 @@ def test_save_load_image(tmp_path): def test_load_analyzer_image(tmp_path): from ..simulation import Simulation - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] sim = get_test_sim() @@ -1778,9 +1778,9 @@ def test_load_analyzer_image(tmp_path): def test_save_attempt(tmp_path): from ..simulation import Simulation - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] sim = get_test_sim() @@ -1810,9 +1810,9 @@ def test_save_attempt(tmp_path): def test_write_inputs(tmp_path): from ..simulation import Simulation,input_template - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] template = ''' name = "$name" @@ -1861,12 +1861,12 @@ def test_write_inputs(tmp_path): @isolate_nexus_core def test_send_files(tmp_path): - from ..nexus_base import nexus_core + from ..nexus_base import NEXUS_CONFIG from ..simulation import Simulation - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] # make fake data files data_file1 = 'data_file1.txt' @@ -1917,9 +1917,9 @@ def test_submit(tmp_path): from ..machines import job from ..simulation import Simulation - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] s = get_test_sim( job = job(machine='ws1',app_command='echo run'), @@ -1951,9 +1951,9 @@ def test_submit(tmp_path): def test_update_process_id(tmp_path): from ..simulation import Simulation - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] s = get_test_sim() j = s.job @@ -1984,9 +1984,9 @@ def test_check_status(tmp_path): from datetime import datetime from ..simulation import Simulation - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] s = get_test_sim() j = s.job @@ -2028,10 +2028,10 @@ def test_check_status_timeout(tmp_path): from datetime import datetime,timedelta from ..simulation import Simulation - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] - nexus_core.timeout = 10 + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] + NEXUS_CONFIG.timeout = 10 # output files that arrive before the timeout are checked normally s = get_test_sim() @@ -2063,7 +2063,7 @@ def test_check_status_timeout(tmp_path): s = get_test_sim() s.create_directories() s.job.finished = True - nexus_core.timeout = 1 + NEXUS_CONFIG.timeout = 1 exited_queue = (datetime.now().astimezone()-timedelta(seconds=2)).isoformat() s.timestamps.exited_queue = exited_queue @@ -2085,9 +2085,9 @@ def test_check_status_timeout(tmp_path): def test_get_output(tmp_path): from ..simulation import Simulation - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] s = get_test_sim() @@ -2148,9 +2148,9 @@ def test_get_output(tmp_path): def test_analyze(tmp_path): from ..simulation import Simulation - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] s = get_test_sim() @@ -2180,23 +2180,13 @@ def test_analyze(tmp_path): @isolate_nexus_core def test_progress(tmp_path): - from ..nexus_base import nexus_core from ..simulation import Simulation,input_template - nexus_core.local_directory = str(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_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] + assert(NEXUS_CONFIG.stages is SimStage.ALL) template = ''' name = "$name" @@ -2370,9 +2360,9 @@ def test_execute(tmp_path): from ..machines import job from ..simulation import Simulation - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] import shutil serial = shutil.which('mpirun') is None @@ -2553,9 +2543,9 @@ def assert_blocked(sim): def test_reconstruct_cascade(tmp_path): from ..simulation import Simulation - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] sims = get_test_workflow(2) assert(len(sims)==7) diff --git a/nexus/nexus/tests/test_vasp_input.py b/nexus/nexus/tests/test_vasp_input.py index d327e391b7..1de22648ab 100644 --- a/nexus/nexus/tests/test_vasp_input.py +++ b/nexus/nexus/tests/test_vasp_input.py @@ -6,7 +6,7 @@ from ..generic import NexusError from ..pseudoset import PseudoSet -from nexus.nexus_base import nexus_core +from nexus.nexus_base import NEXUS_CONFIG from . import isolate_nexus_core, TEST_DIR from .. import testing from ..testing import object_eq,dict_serialize @@ -1002,17 +1002,16 @@ def test_write(tmp_path): @isolate_nexus_core def test_generate(tmp_path): import numpy as np - from ..nexus_base import nexus_noncore from ..physical_system import generate_physical_system from ..vasp_input import generate_vasp_input,VaspInput pseudo_dir = tmp_path / 'pseudopotentials' pseudo_dir.mkdir() - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] - nexus_noncore.pseudo_dir = pseudo_dir + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] + NEXUS_CONFIG.pseudo_dir = pseudo_dir (pseudo_dir / 'C.POTCAR').write_text(c_potcar_text) PseudoSet.pseudo_files = { diff --git a/nexus/nexus/tests/test_vasp_simulation.py b/nexus/nexus/tests/test_vasp_simulation.py index 6ed83d430f..744fcb83a0 100644 --- a/nexus/nexus/tests/test_vasp_simulation.py +++ b/nexus/nexus/tests/test_vasp_simulation.py @@ -5,7 +5,7 @@ from pathlib import Path from . import isolate_nexus_core, create_pseudo_files -from nexus.nexus_base import nexus_core +from nexus.nexus_base import NEXUS_CONFIG from ..testing import clear_all_sims from ..testing import failed,FailedTest from ..testing import value_eq,object_eq,check_object_eq @@ -15,12 +15,11 @@ def setup_vasp_sim(path,identifier='vasp',*,copy_files=False): import shutil - from ..nexus_base import nexus_core from ..machines import job from ..physical_system import generate_physical_system from ..vasp import generate_vasp,Vasp - nexus_core.runs = '' + NEXUS_CONFIG.runs = '' dia16 = generate_physical_system( structure = TEST_FILES['d16bulk.POSCAR'], @@ -81,9 +80,9 @@ def test_minimal_init(): @isolate_nexus_core def test_check_result(tmp_path): - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] create_pseudo_files( tmp_dir=tmp_path, pseudos=["C.POTCAR"], @@ -191,9 +190,9 @@ def test_incorporate_result(tmp_path): from numpy import array from ..developer import obj,to_obj - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] create_pseudo_files( tmp_dir=tmp_path, pseudos=["C.POTCAR"], @@ -262,9 +261,9 @@ def test_incorporate_result(tmp_path): @isolate_nexus_core def test_check_sim_status(tmp_path): - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] create_pseudo_files( tmp_dir=tmp_path, pseudos=["C.POTCAR"], @@ -300,9 +299,9 @@ def test_check_sim_status(tmp_path): @isolate_nexus_core def test_get_output_files(tmp_path): - nexus_core.local_directory = str(tmp_path) - nexus_core.remote_directory = str(tmp_path) - nexus_core.file_locations = nexus_core.file_locations + [str(tmp_path)] + NEXUS_CONFIG.local_directory = str(tmp_path) + NEXUS_CONFIG.remote_directory = str(tmp_path) + NEXUS_CONFIG.file_locations = NEXUS_CONFIG.file_locations + [str(tmp_path)] create_pseudo_files( tmp_dir=tmp_path, pseudos=["C.POTCAR"], diff --git a/nexus/nexus/vasp_input.py b/nexus/nexus/vasp_input.py index edca87cd4b..934144be8e 100644 --- a/nexus/nexus/vasp_input.py +++ b/nexus/nexus/vasp_input.py @@ -19,7 +19,7 @@ from types import MappingProxyType import numpy as np from .periodic_table import Elements -from .nexus_base import nexus_noncore +from .nexus_base import NEXUS_CONFIG from .simulation import SimulationInput from .structure import interpolate_structures, Structure from .physical_system import PhysicalSystem @@ -2627,7 +2627,7 @@ def set_potcar(self,pseudos,species=None): ordered_pseudos.append(pseudo_map[symbol]) #end for #end if - self.potcar = Potcar(nexus_noncore.pseudo_dir,ordered_pseudos) + self.potcar = Potcar(NEXUS_CONFIG.pseudo_dir,ordered_pseudos) #end def set_potcar