From 461c3a63e927d644d3012f0bbccc994738a267b9 Mon Sep 17 00:00:00 2001 From: Jaron Krogel Date: Wed, 11 Nov 2015 19:39:04 +0000 Subject: [PATCH] Major updates to Nexus: see full text of message Changes made to render core of Nexus more robust, a couple of bug fixes, several additions to functionality, and several files relegated to "legacy". ================= new functionality ================= -added support for templated input for qmcpack generation is no longer required should also work for all supported codes now also allows driving of generic simulation codes lacking detailed nexus interface -added basic interfaces to drive CRYSTAL and properties -added support to convert to CASINO pseudopotential format for semilocal PPs can convert from GAMESS/CRYSTAL to QMCPACK/CASINO also convert between QMCPACK and CASINO -improved handling of gamma point calculations for pwscf better autodetection of gamma point explicit user override to forbid "KPOINTS gamma" -added support for head node/local job submission useful for lightweight serial tools or scripts in workflows -added "execute" function to Simulation will later enable use generation/running of simulations directly within user script will allow for dynamic workflows, rather than dynamic execution of static workflows -added enum class to developer.py -added general formatted read to TextFile class in fileio.py ========= bug fixes ========= -dependents of failed simulations now guaranteed not to run following interruption and restart of user script -run directory creation now guaranteed to occur prior to simulation dependency processing ================ added robustness ================ -restructured global base class (obj) in generic.py remove dependence on abilities.py classes streamline and expand base class functions move to "new-style" Python classes (inherit from object) -added nexuscore "namespace" and NexusCore base class better control of core vs. noncore information propagation less chance of downstream breakage (e.g. for derived Simulation classes) classes inheriting from NexusCore: Settings ProjectManager Machine Job Simulation SimulationImage SimulationInput SimulationAnalyzer -added separate SimulationImage class for save/load of Simulation state ensures only central information is saved/loaded prevents interaction with derived Simulation classes -improved organization for Settings class -removed debug log cruft from ProjectManager -improved definition of SimulationTemplateInput now uses string.Template rather than custom code -replaced dynamic type detection functionality from types module with inspect -simplified UnitConverter class -made periodic_table process symbols consistently ============ housekeeping ============ -removed unused files converters.py auxilliary.py -relegated several superseded/less used files to new legacy directory abilities.py differences.py qmcpack_pp_validation.py cascade.py eos_fit.py qmcpack_variations.py density_analyzer.py generator.py qmc.py dft.py qmcpack_calculations.py -consolidated orbital converters for qmcpack into qmcpack_converters.py replaces convert4qmc.py, pw2qmcpack.py, wfconvert.py -consolidated numerical functionality into numerics.py extended_numpy.py is removed along with ill-advised "from numpy import *" -consolidated files associated with QmcpackAnalyzer plotter.py qaobject.py spacegrid.py -renamed project.py as nexus.py, removing vacuous nexus.py also renamed project_base.py as nexus_base.py -separated processing of basis sets to basissets.py -removed outdated BundledQmcpack class git-svn-id: https://subversion.assembla.com/svn/qmcdev/trunk@6616 e5b18d87-469d-4833-9cc0-8cdfa06e9491 --- nexus/library/atomscf.py | 36 +- nexus/library/auxiliary.py | 8 - nexus/library/bundle.py | 3 - nexus/library/convert4qmc.py | 238 --- nexus/library/converters.py | 14 - nexus/library/crystal.py | 178 +++ nexus/library/debug.py | 9 +- nexus/library/developer.py | 166 +- nexus/library/execute.py | 2 +- nexus/library/extended_numpy.py | 699 --------- nexus/library/fileio.py | 34 +- nexus/library/gamess.py | 20 + nexus/library/gamess_analyzer.py | 1 - nexus/library/gamess_input.py | 29 +- nexus/library/generic.py | 1335 +++++++++------- nexus/library/graph.py | 4 +- nexus/library/{ => legacy}/abilities.py | 0 nexus/library/{ => legacy}/cascade.py | 0 .../library/{ => legacy}/density_analyzer.py | 0 nexus/library/{ => legacy}/dft.py | 4 +- nexus/library/{ => legacy}/differences.py | 0 nexus/library/{ => legacy}/eos_fit.py | 0 nexus/library/{ => legacy}/generator.py | 0 nexus/library/{ => legacy}/qmc.py | 8 +- .../{ => legacy}/qmcpack_calculations.py | 0 .../{ => legacy}/qmcpack_pp_validation.py | 6 +- .../{ => legacy}/qmcpack_variations.py | 6 +- nexus/library/machines.py | 94 +- nexus/library/memory.py | 2 +- nexus/library/nexus.py | 343 +++- nexus/library/nexus_base.py | 195 +++ nexus/library/numerics.py | 698 ++++++++- nexus/library/opium.py | 14 +- nexus/library/periodic_table.py | 10 +- nexus/library/plotter.py | 88 -- nexus/library/project.py | 271 ---- nexus/library/project_base.py | 161 -- nexus/library/project_manager.py | 48 +- nexus/library/pseudopotential.py | 894 ++--------- nexus/library/pw2casino.py | 9 +- nexus/library/pw2qmcpack.py | 360 ----- nexus/library/pwscf.py | 2 +- nexus/library/pwscf_input.py | 146 +- nexus/library/qaobject.py | 149 -- nexus/library/qmcpack.py | 240 +-- nexus/library/qmcpack_analyzer.py | 15 +- nexus/library/qmcpack_analyzer_base.py | 280 +++- nexus/library/qmcpack_converters.py | 786 ++++++++++ nexus/library/qmcpack_input.py | 69 +- nexus/library/qmcpack_method_analyzers.py | 3 +- nexus/library/qmcpack_property_analyzers.py | 3 +- nexus/library/qmcpack_quantity_analyzers.py | 1373 ++++++++++++++++- nexus/library/qmcpack_result_analyzers.py | 121 +- nexus/library/simulation.py | 752 +++++---- nexus/library/spacegrid.py | 1335 ---------------- nexus/library/sqd_input.py | 55 +- nexus/library/structure.py | 22 +- nexus/library/template_simulation.py | 32 +- nexus/library/unit_converter.py | 245 +-- nexus/library/vasp.py | 8 +- nexus/library/vasp_input.py | 17 +- nexus/library/wfconvert.py | 206 --- nexus/library/xmlreader.py | 6 +- 63 files changed, 5698 insertions(+), 6154 deletions(-) delete mode 100644 nexus/library/auxiliary.py delete mode 100644 nexus/library/convert4qmc.py delete mode 100644 nexus/library/converters.py delete mode 100644 nexus/library/extended_numpy.py rename nexus/library/{ => legacy}/abilities.py (100%) rename nexus/library/{ => legacy}/cascade.py (100%) rename nexus/library/{ => legacy}/density_analyzer.py (100%) rename nexus/library/{ => legacy}/dft.py (93%) rename nexus/library/{ => legacy}/differences.py (100%) rename nexus/library/{ => legacy}/eos_fit.py (100%) rename nexus/library/{ => legacy}/generator.py (100%) rename nexus/library/{ => legacy}/qmc.py (87%) rename nexus/library/{ => legacy}/qmcpack_calculations.py (100%) rename nexus/library/{ => legacy}/qmcpack_pp_validation.py (99%) rename nexus/library/{ => legacy}/qmcpack_variations.py (98%) mode change 100644 => 100755 nexus/library/nexus.py create mode 100644 nexus/library/nexus_base.py delete mode 100644 nexus/library/plotter.py delete mode 100755 nexus/library/project.py delete mode 100644 nexus/library/project_base.py delete mode 100644 nexus/library/pw2qmcpack.py delete mode 100644 nexus/library/qaobject.py create mode 100644 nexus/library/qmcpack_converters.py delete mode 100644 nexus/library/spacegrid.py delete mode 100644 nexus/library/wfconvert.py diff --git a/nexus/library/atomscf.py b/nexus/library/atomscf.py index 131932829..c96c569e3 100644 --- a/nexus/library/atomscf.py +++ b/nexus/library/atomscf.py @@ -1329,7 +1329,7 @@ class AtomscfInput(SimulationInput): #end def __init__ - def read_contents(self,text): + def read_text(self,text,filepath=None): raw_lines = text.splitlines() lines = [] for rline in raw_lines: @@ -1447,10 +1447,10 @@ class AtomscfInput(SimulationInput): del self.lines del self.n del self.cur_section - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self,filepath=None): self.text = '' self.cur_section = None self.text += '{0}\n'.format(self.lim) @@ -1546,7 +1546,7 @@ class AtomscfInput(SimulationInput): del self.text del self.cur_section return text - #end def write_contents + #end def write_text def nonzero(self,name): @@ -1688,21 +1688,21 @@ class AtomscfInput(SimulationInput): if len(kwargs)>0: kw = obj(**kwargs) - element = kw.delete_option('element') - state = kw.delete_option('state') - jcoeff = kw.delete_option('jcoeff') - kcoeff = kw.delete_option('kcoeff') - coeff = kw.delete_option('coeff') - pseudo = kw.delete_option('pseudo') - ppformat = kw.delete_option('ppformat') - basis = kw.delete_option('basis') - guess = kw.delete_option('guess') + element = kw.delete_optional('element') + state = kw.delete_optional('state') + jcoeff = kw.delete_optional('jcoeff') + kcoeff = kw.delete_optional('kcoeff') + coeff = kw.delete_optional('coeff') + pseudo = kw.delete_optional('pseudo') + ppformat = kw.delete_optional('ppformat') + basis = kw.delete_optional('basis') + guess = kw.delete_optional('guess') - use_none = kw.delete_option('use_none' ,False) - use_defaults = kw.delete_option('use_defaults',True) - use_state = kw.delete_option('use_state' ,True) - use_pseudo = kw.delete_option('use_pseudo' ,True) - use_basis = kw.delete_option('use_basis' ,True) + use_none = kw.delete_optional('use_none' ,False) + use_defaults = kw.delete_optional('use_defaults',True) + use_state = kw.delete_optional('use_state' ,True) + use_pseudo = kw.delete_optional('use_pseudo' ,True) + use_basis = kw.delete_optional('use_basis' ,True) if use_none: use_defaults = False use_state = False diff --git a/nexus/library/auxiliary.py b/nexus/library/auxiliary.py deleted file mode 100644 index 466705e79..000000000 --- a/nexus/library/auxiliary.py +++ /dev/null @@ -1,8 +0,0 @@ -################################################################## -## (c) Copyright 2015- by Jaron T. Krogel ## -################################################################## - - - - - diff --git a/nexus/library/bundle.py b/nexus/library/bundle.py index 461682ce0..2ab1ba1ca 100644 --- a/nexus/library/bundle.py +++ b/nexus/library/bundle.py @@ -46,9 +46,6 @@ class SimulationBundle(Simulation): generic_identifier = 'bundle' image_directory = 'bundle' - preserve = Simulation.preserve & set(['sims']) - - def __init__(self,*sims,**kwargs): if len(sims)==1 and isinstance(sims[0],list): sims = sims[0] diff --git a/nexus/library/convert4qmc.py b/nexus/library/convert4qmc.py deleted file mode 100644 index bc8d5a020..000000000 --- a/nexus/library/convert4qmc.py +++ /dev/null @@ -1,238 +0,0 @@ -################################################################## -## (c) Copyright 2015- by Jaron T. Krogel ## -################################################################## - - -#====================================================================# -# convert4qmc.py # -# Interface to convert4qmc tool (associated with QMCPACK). # -# # -# Content summary: # -# Convert4qmcInput # -# Class representing command line interface of convert4qmc. # -# # -# Convert4qmcAnalyzer # -# Placeholder class for output analysis. # -# # -# Convert4qmc # -# Class representing conver4qmc instance. # -# # -# generate_convert4qmc_input # -# Function to generate arbitrary convert4qmc input. # -# # -# generate_convert4qmc # -# Function to generate Convert4qmc simulation object. # -# # -#====================================================================# - - - -import os -from generic import obj -from simulation import Simulation,SimulationInput,SimulationAnalyzer -from debug import * - - -class Convert4qmcInput(SimulationInput): - def __init__(self, - app_name = 'convert4qmc', - prefix = None, - gamess_ascii = None, - ci = None, - read_initial_guess = None, - natural_orbitals = None, - threshold = None, - zero_ci = False, - add_3body_J = False - ): - self.prefix = prefix - self.app_name = app_name - self.gamess_ascii = gamess_ascii - self.ci = ci - self.read_initial_guess = read_initial_guess - self.natural_orbitals = natural_orbitals - self.threshold = threshold - self.zero_ci = zero_ci - self.add_3body_J = add_3body_J - #end def __init__ - - def set_app_name(self,app_name): - self.app_name = app_name - #end def set_app_name - - def app_command(self): - c = self.app_name - if self.prefix!=None: - c += ' -prefix '+self.prefix - #end if - if self.gamess_ascii!=None: - c += ' -gamessAscii '+self.gamess_ascii - #end if - if self.ci!=None: - c += ' -ci '+self.ci - #end if - if self.threshold!=None: - c += ' -threshold '+str(self.threshold) - #end if - if self.zero_ci: - c += ' -zeroCi' - #end if - if self.read_initial_guess!=None: - c += ' -readInitialGuess '+str(self.read_initial_guess) - #end if - if self.natural_orbitals!=None: - c += ' -NaturalOrbitals '+str(self.natural_orbitals) - #end if - if self.add_3body_J: - c += ' -add3BodyJ' - #end if - return c - #end def app_command - - def read(self,filepath): - None - #end def read - - def write_contents(self): - return self.app_command() - #end def write_contents - - def output_files(self): - prefix = 'sample' - if self.prefix!=None: - prefix = self.prefix - #end if - wfn_file = prefix+'.Gaussian-G2.xml' - ptcl_file = prefix+'.Gaussian-G2.ptcl.xml' - return wfn_file,ptcl_file - #end def output_files -#end class Convert4qmcInput - - -def generate_convert4qmc_input(**kwargs): - return Convert4qmcInput(**kwargs) -#end def generate_convert4qmc_input - - -class Convert4qmcAnalyzer(SimulationAnalyzer): - def __init__(self,arg0): - if isinstance(arg0,Simulation): - self.infile = arg0.infile - else: - self.infile = arg0 - #end if - #end def __init__ - - def analyze(self): - None - #end def analyze -#end class Convert4qmcAnalyzer - - - -class Convert4qmc(Simulation): - input_type = Convert4qmcInput - analyzer_type = Convert4qmcAnalyzer - generic_identifier = 'convert4qmc' - application = 'convert4qmc' - application_properties = set(['serial']) - application_results = set(['orbitals']) - - def set_app_name(self,app_name): - self.app_name = app_name - self.input.set_app_name(app_name) - #end def set_app_name - - def propagate_identifier(self): - None - #self.input.prefix = self.identifier - #end def propagate_identifier - - def check_result(self,result_name,sim): - calculating_result = False - if result_name=='orbitals': - calculating_result = True - else: - calculating_result = False - self.error('ability to check for result '+result_name+' has not been implemented') - #end if - return calculating_result - #end def check_result - - def get_result(self,result_name,sim): - result = obj() - input = self.input - if result_name=='orbitals': - wfn_file,ptcl_file = input.output_files() - result.location = os.path.join(self.locdir,wfn_file) - else: - self.error('ability to get result '+result_name+' has not been implemented') - #end if - return result - #end def get_result - - def incorporate_result(self,result_name,result,sim): - if result_name=='orbitals': - orbpath = os.path.relpath(result.location,self.locdir) - if result.scftyp=='mcscf': - self.input.gamess_ascii = orbpath - self.input.ci = orbpath - elif result.scftyp=='none': # cisd, etc - self.input.gamess_ascii = orbpath - self.input.ci = orbpath - if result.mos>0: - self.input.read_initial_guess = result.mos - elif result.norbitals>0: - self.input.read_initial_guess = result.norbitals - #end if - else: - self.input.gamess_ascii = orbpath - #end if - self.job.app_command = self.input.app_command() - else: - self.error('ability to incorporate result '+result_name+' has not been implemented') - #end if - #end def incorporate_result - - def check_sim_status(self): - output = open(os.path.join(self.locdir,self.outfile),'r').read() - #errors = open(os.path.join(self.locdir,self.errfile),'r').read() - - success = 'QMCGaussianParserBase::dump' in output - for filename in self.input.output_files(): - success &= os.path.exists(os.path.join(self.locdir,filename)) - #end for - - self.failed = not success - self.finished = self.job.finished - #end def check_sim_status - - def get_output_files(self): - output_files = [] - return output_files - #end def get_output_files - - def app_command(self): - return self.input.app_command() - #end def app_command -#end class Convert4qmc - - - - - - - -def generate_convert4qmc(**kwargs): - sim_args,inp_args = Simulation.separate_inputs(kwargs) - if 'identifier' in sim_args and not 'prefix' in inp_args: - inp_args.prefix = sim_args.identifier - #end if - - if not 'input' in sim_args: - sim_args.input = generate_convert4qmc_input(**inp_args) - #end if - convert4qmc = Convert4qmc(**sim_args) - - return convert4qmc -#end def generate_convert4qmc diff --git a/nexus/library/converters.py b/nexus/library/converters.py deleted file mode 100644 index 06d633b3f..000000000 --- a/nexus/library/converters.py +++ /dev/null @@ -1,14 +0,0 @@ -################################################################## -## (c) Copyright 2015- by Jaron T. Krogel ## -################################################################## - - -#====================================================================# -# converters.py # -# Collection of converters for QMCPACK. # -# # -#====================================================================# - - -from pw2qmcpack import Pw2qmcpack,Pw2qmcpackInput,Pw2qmcpackAnalyzer -from wfconvert import Wfconvert,WfconvertInput,WfconvertAnalyzer diff --git a/nexus/library/crystal.py b/nexus/library/crystal.py index d9c9198a7..d3d6b0ca2 100644 --- a/nexus/library/crystal.py +++ b/nexus/library/crystal.py @@ -3,9 +3,12 @@ ################################################################## +import os from generic import obj from periodic_table import pt as ptable from pseudopotential import GaussianPP +from nexus_base import nexus_noncore +from simulation import Simulation from developer import error @@ -170,4 +173,179 @@ def write_hamiltonian(theory = None, #end def write_hamiltonian +class CrystalSim: None +class PropertiesSim: None + +from simulation import GenericSimulation +class Crystal_1(GenericSimulation,CrystalSim): + generic_identifier = 'crystal' + application = 'crystal' + infile_extension = '.d12' + application_results = set(['orbitals']) + + def check_result(self,result_name,sim): + return result_name=='orbitals' + #end def check_result + + def get_result(self,result_name,sim): + result = obj() # its up to the other application how to handle crystal + if result_name!='orbitals': + self.error('ability to get result '+result_name+' has not been implemented') + #end if + return result + #end def get_result + + def incorporate_result(self,result_name,result,sim): + self.error('ability to incorporate result '+result_name+' has not been implemented') + #end def incorporate_result + + def app_command(self): + return self.app_name+'<'+self.infile + #end def app_command +#end class Crystal_1 + + + +from simulation import generate_simulation,input_template_dev +def gen_crystal_molecule_sim( + identifier = 'crystal', + path = None, + job = None, + title = 'atom', + system = None, + pseudos = None, + occupations = None, + formats = None, + theory = None, + levshift = None, + maxcycle = None, + ): + required = obj(path=path,system=system,pseudos=pseudos,occupations=occupations,formats=formats,theory=theory,job=job) + for k,v in required.iteritems(): + if v is None: + error(k+' is a required input','gen_crystal_molecule_sim') + #end if + #end for + pseudos_in = pseudos + pseudos = [] + for pp in pseudos_in: + pseudos.append(os.path.join(nexus_noncore.pseudo_dir,pp)) + #end for + + crys_input = input_template_dev() + crys_input.read_text( + write_geometry( + title = title, + bcond = 'molecule', + system = system + )+ + write_basis( + pseudos = pseudos, + occupations = occupations, + formats = formats, + )+ + write_hamiltonian( + theory = theory, + system = system, + levshift = levshift, + maxcycle = maxcycle + ) + ) + + #crys = generate_simulation( + # identifier = identifier, + # path = path, + # job = job(cores=1,serial=True,app_command='crystal<{0}.d12>&{0}.out&'.format(identifier)), + # input = crys_input, + # infile = '{0}.d12'.format(identifier), + # outfile = '{0}.out'.format(identifier), + # ) + + + crys = Crystal_1( + identifier = identifier, + path = path, + job = job, + input = crys_input, + ) + + + return crys +#end def gen_crystal_molecule_sim + + + + + + +class Properties_1(GenericSimulation,PropertiesSim): # same implementation, not 'is a' + generic_identifier = 'properties' + application = 'properties' + infile_extension = '.d3' + application_results = set(['orbitals']) + + def check_result(self,result_name,sim): + return result_name=='orbitals' + #end def check_result + + def get_result(self,result_name,sim): + result = obj() # its up to the other application how to handle crystal + if result_name!='orbitals': + self.error('ability to get result '+result_name+' has not been implemented') + #end if + return result + #end def get_result + + def incorporate_result(self,result_name,result,sim): + if result_name!='orbitals' or not isinstance(sim,Crystal_1): + self.error('ability to incorporate result '+result_name+' has not been implemented') + #end if + #end def incorporate_result + + def app_command(self): + return self.app_name+'<'+self.infile + #end def app_command +#end class Properties_1 + + +molecule_text = ''' +NEWK +1 0 +CRYAPI_OUT +END +''' +periodic_text = ''' +NEWK +0 0 +1 0 +CRYAPI_OUT +END +''' + +def gen_properties(**kwargs): + + if 'systype' not in kwargs: + error('systype is a required input','gen_properties') + #end if + systype = kwargs['systype'] + del kwargs['systype'] + + if systype=='molecule_qmc': + text = molecule_text + elif systype=='periodic_qmc': + text = periodic_text + else: + error('invalid systype encountered\nsystype provided: {0}\nvalid options are: molecule_qmc, periodic_qmc'.format(systype)) + #end if + + sim_args,inp_args = Simulation.separate_inputs(kwargs) + if len(inp_args)>0: + error('invalid arguments encountered\ninvalid keywords: {0}'.format(sorted(inp_args.keys())),'gen_properties') + #end if + if not 'input' in sim_args: + sim_args.input = input_template_dev(text=text.strip()) + #end if + prop = Properties_1(**sim_args) + return prop +#end def gen_properties diff --git a/nexus/library/debug.py b/nexus/library/debug.py index 616b955e4..52dc2e740 100644 --- a/nexus/library/debug.py +++ b/nexus/library/debug.py @@ -23,8 +23,15 @@ import code +import inspect -def ci(locs,globs): +def ci(locs=None,globs=None): + if locs is None or globs is None: + cur_frame = inspect.currentframe() + caller_frame = cur_frame.f_back + locs = caller_frame.f_locals + globs = caller_frame.f_globals + #end if code.interact(local=dict(globs,**locs)) #end def ci diff --git a/nexus/library/developer.py b/nexus/library/developer.py index 6cdbd696f..8327fb99b 100644 --- a/nexus/library/developer.py +++ b/nexus/library/developer.py @@ -27,151 +27,51 @@ # non-existent entities are used during runtime execution. # # This enables the maximum amount of Nexus functionality to be # # accessed given the available modules. # -# # +# # #====================================================================# -import sys -import traceback -from generic import obj - -exit_call = exit -devlog = sys.stdout - -def log(*items): - s='' - for item in items: - s+=str(item)+' ' - #end for - s+='\n' - devlog.write(s) -#end def log - - -def warn(message,location,header=None,post_header=' Warning:'): - pad = 4*' ' - if location is None: - header = 'warning:' - else: - header = location+' warning:' - #end if - log('\n '+header) - log(pad+message.replace('\n','\n'+pad)) -#end def warn - - -def error(message,location=None,exit=True,trace=True): - pad = 4*' ' - if location is None: - header = 'error:' - else: - header = location+' error:' - #end if - log('\n '+header) - log(pad+message.replace('\n','\n'+pad)) - if exit: - log(' exiting.\n') - if trace: - traceback.print_stack() - #end if - exit_call() - #end if -#end def error +from generic import obj,object_interface,log,error,warn +from debug import ci,interact class DevBase(obj): - user_interface_data = obj() - dev_instructions_data = obj() - def not_implemented(self): - #self.error('a base class function has not been implemented','Developer') self.error('a base class function has not been implemented',trace=True) #end def not_implemented - - @classmethod - def set_user_interface(cls,class_variables=None,class_functions=None,member_variables=None,member_functions=None): - if class_variables is None: - class_variables = [] - if class_functions is None: - class_functions = [] - if member_variables is None: - member_variables = [] - if member_functions is None: - member_functions = [] - ui = cls.user_interface_data - ui.class_variables = class_variables - ui.class_functions = class_functions - ui.member_variables= member_variables - ui.member_functions= member_functions - #end def set_user_interface - - @classmethod - def set_dev_instruction(cls,situation='writing a derived class',class_variables=None,class_functions=None,member_variables=None,member_functions=None): - if class_variables is None: - class_variables = [] - if class_functions is None: - class_functions = [] - if member_variables is None: - member_variables = [] - if member_functions is None: - member_functions = [] - ins = obj() - cls.dev_instructions_data[situation] = ins - ins.class_variables = class_variables - ins.class_functions = class_functions - ins.member_variables= member_variables - ins.member_functions= member_functions - #end def set_dev_instruction - - @classmethod - def write_dev_data(cls,s,dev_data,indent=''): - p1 = ' ' - p2 = 2*p1 - p3 = 3*p1 - dpad = indent+p3 - for name,value in dev_data.iteritems(): - s+=indent+p1+name+'\n' - if isinstance(value,list): - for v in value: - s+=indent+p2+v+'\n' - #end for - else: - for v,description in value.iteritems(): - s+=indent+p2+v+'\n' - s+=dpad+description.replace('\n','\n'+dpad) - #end for - #end for - #end for - return s - #end def write_dev_data - - @classmethod - def user_interface(cls): - s='User Interface for '+cls.__name__+' Class\n' - s+= (len(s)-1)*'='+'\n' - s+=cls.write_dev_data(cls.user_interface_data) - return s - #end def user_interface - - @classmethod - def developer_instructions(cls): - s='Developer Instructions for '+cls.__name__+' Class\n' - s+= (len(s)-1)*'='+'\n' - i1=' ' - i2=2*i1 - i3=3*i1 - for situation,instruction in cls.developer_instructions.iteritems(): - s+=i1+'situation: '+situation+'\n' - s+=i2+'define the following variables and functions:' - s+=cls.write_dev_data(instructions,i3) - #end for - return s - #end def developer_instructions #end class DevBase +class enum(object_interface): + def __init__(self,*keys): + if len(keys)==1 and isinstance(keys[0],(list,tuple)): + keys = keys[0] + #end if + n=0 + for key in keys: + self[key] = n + n+=1 + #end for + #end def __init__ + + # override some object interface methods + # specifically forbid modification + def __setitem__(self,name,value): + self._error('attempted to modify immutable enum object') + #end def __setitem__ + def __delitem__(self,name): + self._error('attempted to modify immutable enum object') + #end def __delitem__ + def clear(self): + self._error('attempted to modify immutable enum object') + #end def clear + + def _clear(self): + enum.clear(self) + #end def _clear +#end class enum class Void: @@ -220,8 +120,10 @@ class Void: @classmethod def __instancecheck__(cls,*args,**kwargs): Void._class_unavailable() + @classmethod def __subclasscheck__(cls,*args,**kwargs): Void._class_unavailable() + @classmethod def __subclasshook__(cls,*args,**kwargs): Void._class_unavailable() @@ -441,8 +343,6 @@ class Void: Void._unavailable(self) def __setstate__(self,*args,**kwargs): Void._unavailable(self) - def __hash__(self,*args,**kwargs): - Void._unavailable(self) def __bytes__(self,*args,**kwargs): Void._unavailable(self) def __format__(self,*args,**kwargs): diff --git a/nexus/library/execute.py b/nexus/library/execute.py index a6df4ba59..3594a8fdd 100644 --- a/nexus/library/execute.py +++ b/nexus/library/execute.py @@ -11,7 +11,7 @@ # execute # # Execute an arbitrary shell command within the user # # environment of the local machine and wait for its completion. # -# # +# # #====================================================================# diff --git a/nexus/library/extended_numpy.py b/nexus/library/extended_numpy.py deleted file mode 100644 index cb19c08d0..000000000 --- a/nexus/library/extended_numpy.py +++ /dev/null @@ -1,699 +0,0 @@ -################################################################## -## (c) Copyright 2015- by Jaron T. Krogel ## -################################################################## - - -#====================================================================# -# extended_numpy.py # -# Extension of functionality available in numpy plus various # -# numerical functions. To be merged into numerics.py # -# # -# Content summary: # -# ndgrid # -# Function to construct an arbitrary N-dimensional grid. # -# Similar to ndgrid from MATLAB. # -# # -# simstats # -# Compute statistics of N-dimensional Monte Carlo simulation # -# data, including mean, variance, error, and autocorrelation. # -# # -# simplestats # -# Compute error assuming uncorrelated data. # -# # -# equilibration_length # -# Estimate equilibration point of Monte Carlo time series data # -# using a heuristic algorithm. # -# # -# ttest # -# Implementation of Student's T-test # -# # -# surface_normals # -# Compute vectors normal to a parametric surface. # -# # -# simple_surface # -# Create a parametric surface in Cartesian, cylindrical, or # -# spherical coordinates. # -# # -# func_fit # -# Perform a fit to an arbitrary function using an arbitrary # -# cost metric (e.g. least squares). # -# # -# distance_table # -# Calculate all N^2 pair distances for a set of N points. # -# # -# nearest_neighbors # -# Find k nearest neighbors of N points using a fast algorithm. # -# # -# voronoi_neighbors # -# Find nearest neighbors in the Voronoi sense, that is for # -# each point, find the points whose Voronoi polyhedra contact # -# the Voronoi polyhedron of that point. # -# # -# convex_hull # -# Find the convex hull of a set of points in N dimensions. # -# # -#====================================================================# - - -import sys - -from numpy import * -from numpy.linalg import * - -from developer import unavailable -try: - from scipy.special import betainc - from scipy.optimize import fmin - from scipy.spatial import KDTree,Delaunay,Voronoi - scipy_unavailable = False -except ImportError: - betainc = unavailable('scipy.special' ,'betainc') - fmin = unavailable('scipy.optimize','fmin') - KDTree,Delaunay,Voronoi = unavailable('scipy.spatial' ,'KDTree','Delaunay','Voronoi') - scipy_unavailable = True -#end try - - -######################################################################## -############ ndgrid -######################################################################## - -# retrieved from -# http://www.mailinglistarchive.com/html/matplotlib-users@lists.sourceforge.net/2010-05/msg00055.html - -#""" -#n-dimensional gridding like Matlab's NDGRID -# -#Typical usage: -#>>> x, y, z = [0, 1], [2, 3, 4], [5, 6, 7, 8] -#>>> X, Y, Z = ndgrid(x, y, z) -# -#See ?ndgrid for details. -#""" - -def ndgrid(*args, **kwargs): - """ - n-dimensional gridding like Matlab's NDGRID - - The input *args are an arbitrary number of numerical sequences, - e.g. lists, arrays, or tuples. - The i-th dimension of the i-th output argument - has copies of the i-th input argument. - - Optional keyword argument: - same_dtype : If False (default), the result is an ndarray. - If True, the result is a lists of ndarrays, possibly with - different dtype. This can save space if some *args - have a smaller dtype than others. - - Typical usage: - >>> x, y, z = [0, 1], [2, 3, 4], [5, 6, 7, 8] - >>> X, Y, Z = ndgrid(x, y, z) # unpacking the returned ndarray into X, Y, Z - - Each of X, Y, Z has shape [len(v) for v in x, y, z]. - >>> X.shape == Y.shape == Z.shape == (2, 3, 4) - True - >>> X - array([[[0, 0, 0, 0], - [0, 0, 0, 0], - [0, 0, 0, 0]], - [[1, 1, 1, 1], - [1, 1, 1, 1], - [1, 1, 1, 1]]]) - >>> Y - array([[[2, 2, 2, 2], - [3, 3, 3, 3], - [4, 4, 4, 4]], - [[2, 2, 2, 2], - [3, 3, 3, 3], - [4, 4, 4, 4]]]) - >>> Z - array([[[5, 6, 7, 8], - [5, 6, 7, 8], - [5, 6, 7, 8]], - [[5, 6, 7, 8], - [5, 6, 7, 8], - [5, 6, 7, 8]]]) - - With an unpacked argument list: - >>> V = [[0, 1], [2, 3, 4]] - >>> ndgrid(*V) # an array of two arrays with shape (2, 3) - array([[[0, 0, 0], - [1, 1, 1]], - [[2, 3, 4], - [2, 3, 4]]]) - - For input vectors of different data types, same_dtype=False makes ndgrid() - return a list of arrays with the respective dtype. - >>> ndgrid([0, 1], [1.0, 1.1, 1.2], same_dtype=False) - [array([[0, 0, 0], [1, 1, 1]]), - array([[ 1. , 1.1, 1.2], [ 1. , 1.1, 1.2]])] - - Default is to return a single array. - >>> ndgrid([0, 1], [1.0, 1.1, 1.2]) - array([[[ 0. , 0. , 0. ], [ 1. , 1. , 1. ]], - [[ 1. , 1.1, 1.2], [ 1. , 1.1, 1.2]]]) - """ - same_dtype = kwargs.get("same_dtype", True) - V = [array(v) for v in args] # ensure all input vectors are arrays - shape = [len(v) for v in args] # common shape of the outputs - result = [] - for i, v in enumerate(V): - # reshape v so it can broadcast to the common shape - # http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html - zero = zeros(shape, dtype=v.dtype) - thisshape = ones_like(shape) - thisshape[i] = shape[i] - result.append(zero + v.reshape(thisshape)) - if same_dtype: - return array(result) # converts to a common dtype - else: - return result # keeps separate dtype for each output - -#if __name__ == "__main__": -# import doctest -# doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE) - - -######################################################################## -############ End ndgrid -######################################################################## - - -def simstats(x,dim=None): - shape = x.shape - ndim = len(shape) - if dim==None: - dim=ndim-1 - #end if - permute = dim!=ndim-1 - reshape = ndim>2 - nblocks = shape[dim] - if permute: - r = range(ndim) - r.pop(dim) - r.append(dim) - permutation = tuple(r) - r = range(ndim) - r.pop(ndim-1) - r.insert(dim,ndim-1) - invperm = tuple(r) - x=x.transpose(permutation) - shape = tuple(array(shape)[array(permutation)]) - dim = ndim-1 - #end if - if reshape: - nvars = prod(shape[0:dim]) - x=x.reshape(nvars,nblocks) - rdim=dim - dim=1 - else: - nvars = shape[0] - #end if - - mean = x.mean(dim) - var = x.var(dim) - - N=nblocks - - if ndim==1: - i=0 - tempC=0.5 - kappa=0.0 - mtmp=mean - if abs(var)<1e-15: - kappa = 1.0 - else: - ovar=1.0/var - while (tempC>0 and i<(N-1)): - kappa=kappa+2.0*tempC - i=i+1 - #tempC=corr(i,x,mean,var) - tempC = ovar/(N-i)*sum((x[0:N-i]-mtmp)*(x[i:N]-mtmp)) - #end while - if kappa == 0.0: - kappa = 1.0 - #end if - #end if - Neff=(N+0.0)/(kappa+0.0) - if (Neff == 0.0): - Neff = 1.0 - #end if - error=sqrt(var/Neff) - else: - error = zeros(mean.shape) - kappa = zeros(mean.shape) - for v in xrange(nvars): - i=0 - tempC=0.5 - kap=0.0 - vtmp = var[v] - mtmp = mean[v] - if abs(vtmp)<1e-15: - kap = 1.0 - else: - ovar = 1.0/vtmp - while (tempC>0 and i<(N-1)): - i += 1 - kap += 2.0*tempC - tempC = ovar/(N-i)*sum((x[v,0:N-i]-mtmp)*(x[v,i:N]-mtmp)) - #end while - if kap == 0.0: - kap = 1.0 - #end if - #end if - Neff=(N+0.0)/(kap+0.0) - if (Neff == 0.0): - Neff = 1.0 - #end if - kappa[v]=kap - error[v]=sqrt(vtmp/Neff) - #end for - #end if - - if reshape: - x = x.reshape(shape) - mean = mean.reshape(shape[0:rdim]) - var = var.reshape(shape[0:rdim]) - error = error.reshape(shape[0:rdim]) - kappa = kappa.reshape(shape[0:rdim]) - #end if - if permute: - x=x.transpose(invperm) - #end if - - return (mean,var,error,kappa) -#end def simstats - - - -def simplestats(x,dim=None): - if dim==None: - dim=len(x.shape)-1 - #end if - osqrtN = 1.0/sqrt(1.0*x.shape[dim]) - mean = x.mean(dim) - error = x.var(dim)*osqrtN - return (mean,error) -#end def simplestats - - -def equilibration_length(x,tail=.5,plot=False,xlim=None,bounces=2): - bounces = max(1,bounces) - eqlen = 0 - nx = len(x) - xt = x[int((1.-tail)*nx+.5):] - nxt = len(xt) - if nxt<10: - return eqlen - #end if - #mean = xh.mean() - #sigma = sqrt(xh.var()) - xs = array(xt) - xs.sort() - mean = xs[int(.5*(nxt-1)+.5)] - sigma = (abs(xs[int((.5-.341)*nxt+.5)]-mean)+abs(xs[int((.5+.341)*nxt+.5)]-mean))/2 - crossings = bounces*[0,0] - if abs(x[0]-mean)>sigma: - s = -sign(x[0]-mean) - ncrossings = 0 - for i in range(nx): - dist = s*(x[i]-mean) - if dist>sigma and dist<5*sigma: - crossings[ncrossings]=i - s*=-1 - ncrossings+=1 - if ncrossings==2*bounces: - break - #end if - #end if - #end for - bounce = crossings[-2:] - bounce[1] = max(bounce[1],bounce[0]) - #print len(x),crossings,crossings[1]-crossings[0]+1 - eqlen = bounce[0]+random.randint(bounce[1]-bounce[0]+1) - #end if - if plot: - xlims = xlim - del plot,xlim - from matplotlib.pyplot import plot,figure,show,xlim - figure() - ix = arange(nx) - plot(ix,x,'b.-') - plot([0,nx],[mean,mean],'k-') - plot([0,nx],[mean+sigma,mean+sigma],'r-') - plot([0,nx],[mean-sigma,mean-sigma],'r-') - plot(ix[crossings],x[crossings],'r.') - plot(ix[bounce],x[bounce],'ro') - plot([ix[eqlen],ix[eqlen]],[x.min(),x.max()],'g-') - plot(ix[eqlen],x[eqlen],'go') - if xlims!=None: - xlim(xlims) - #end if - show() - #end if - return eqlen -#end def equilibration_length - - -def ttest(m1,e1,n1,m2,e2,n2): - m1 = float(m1) - e1 = float(e1) - m2 = float(m2) - e2 = float(e2) - v1 = e1**2 - v2 = e2**2 - t = (m1-m2)/sqrt(v1+v2) - nu = (v1+v2)**2/(v1**2/(n1-1)+v2**2/(n2-1)) - x = nu/(nu+t**2) - p = 1.-betainc(nu/2,.5,x) - return p -#end def ttest - - - -def surface_normals(x,y,z): - nu,nv = x.shape - normals = empty((nu,nv,3)) - mi=nu-1 - mj=nv-1 - v1 = empty((3,)) - v2 = empty((3,)) - v3 = empty((3,)) - dr = empty((3,)) - dr[0] = x[0,0]-x[1,0] - dr[1] = y[0,0]-y[1,0] - dr[2] = z[0,0]-z[1,0] - drtol = 1e-4 - for i in xrange(nu): - for j in xrange(nv): - iedge = i==0 or i==mi - jedge = j==0 or j==mj - if iedge: - dr[0] = x[0,j]-x[mi,j] - dr[1] = y[0,j]-y[mi,j] - dr[2] = z[0,j]-z[mi,j] - if norm(dr)1.00000000001: - print 'Error in simple surface: '+k+' cannot be more than 1' - print ' actual maximum: '+str(max(v)) - sys.exit() - #end if - #end if - u=empty((3,)) - r=empty((3,)) - if coord==0: - xl = grid['x'] - yl = grid['y'] - zl = grid['z'] - dim = (len(xl),len(yl),len(zl)) - npoints = prod(dim) - points = empty((npoints,3)) - n=0 - for i in xrange(dim[0]): - for j in xrange(dim[1]): - for k in xrange(dim[2]): - r[0] = xl[i] - r[1] = yl[j] - r[2] = zl[k] - points[n,:] = dot(axes,r) + origin - n+=1 - #end for - #end for - #end for - elif coord==1: - rl = grid['r'] - phil = 2.*pi*grid['phi'] - zl = grid['z'] - dim = (len(rl),len(phil),len(zl)) - npoints = prod(dim) - points = empty((npoints,3)) - n=0 - for i in xrange(dim[0]): - for j in xrange(dim[1]): - for k in xrange(dim[2]): - u[0] = rl[i] - u[1] = phil[j] - u[2] = zl[k] - r[0] = u[0]*cos(u[1]) - r[1] = u[0]*sin(u[1]) - r[2] = u[2] - points[n,:] = dot(axes,r) + origin - n+=1 - #end for - #end for - #end for - elif coord==2: - rl = grid['r'] - phil = 2.*pi*grid['phi'] - thetal = pi*grid['theta'] - dim = (len(rl),len(phil),len(thetal)) - if dim[0]==1: - sgn = -1. #this is to 'fix' surface normals - #sgn = 1. #this is to 'fix' surface normals - else: - sgn = 1. - #end if - npoints = prod(dim) - points = empty((npoints,3)) - n=0 - for i in xrange(dim[0]): - for j in xrange(dim[1]): - for k in xrange(dim[2]): - u[0] = rl[i] - u[1] = phil[j] - u[2] = thetal[k] - r[0] = sgn*u[0]*sin(u[2])*cos(u[1]) - r[1] = sgn*u[0]*sin(u[2])*sin(u[1]) - r[2] = sgn*u[0]*cos(u[2]) - points[n,:] = dot(axes,r) + origin - n+=1 - #end for - #end for - #end for - #end if - - if min(dim)!=1: - print 'Error in simple_surface: minimum dimension must be 1' - print ' actual minimum dimension:',str(min(dim)) - sys.exit() - #end if - - dm = [] - for d in dim: - if d>1: - dm.append(d) - #end if - #end for - dm=tuple(dm) - - x = points[:,0].reshape(dm) - y = points[:,1].reshape(dm) - z = points[:,2].reshape(dm) - - return x,y,z -#end def simple_surface - - - -least_squares = lambda p,x,y,f: ((f(p,x)-y)**2).sum() - -def func_fit(x,y,fitting_function,p0,minimizer=least_squares): - f = fitting_function - p = fmin(minimizer,p0,args=(x,y,f),maxiter=10000,maxfun=10000) - return p -#end def func_fit - - -def distance_table(p1,p2,ordering=0): - n1 = len(p1) - n2 = len(p2) - if not isinstance(p1,ndarray): - p1=array(p1) - #end if - if not isinstance(p2,ndarray): - p2=array(p2) - #end if - dt = zeros((n1,n2)) - for i1 in xrange(n1): - for i2 in xrange(n2): - dt[i1,i2] = norm(p1[i1]-p2[i2]) - #end for - #end for - if ordering==0: - return dt - else: - if ordering==1: - n=n1 - elif ordering==2: - n=n2 - dt=dt.T - else: - print 'distance_table Error: ordering must be 1 or 2,\n you provided '+str(ordering)+'\nexiting.' - exit() - #end if - order = empty(dt.shape,dtype=int) - for i in xrange(n): - o = dt[i].argsort() - order[i] = o - dt[i,:] = dt[i,o] - #end for - return dt,order - #end if -#end def distance_table - - - -def nearest_neighbors(n,points,qpoints=None,return_distances=False,slow=False): - extra = 0 - if qpoints==None: - qpoints=points - if len(points)>1: - extra=1 - elif return_distances: - return array([]),array([]) - else: - return array([]) - #end if - #end if - if n>len(qpoints)-extra: - print 'nearest_neighbors Error: requested more than the total number of neighbors\n maximum is: {0}\n you requested: {1}\nexiting.'.format(len(qpoints)-extra,n) - exit() - #end if - slow = slow or scipy_unavailable - if not slow: - kt = KDTree(points) - dist,ind = kt.query(qpoints,n+extra) - else: - dtable,order = distance_table(points,qpoints,ordering=2) - dist = dtable[:,0:n+extra] - ind = order[:,0:n+extra] - #end if - if extra==0 and n==1 and not slow: - nn = atleast_2d(ind).T - else: - nn = ind[:,extra:] - #end if - if not return_distances: - return nn - else: - return nn,dist - #end if -#end def nearest_neighbors - - -def voronoi_neighbors(points): - vor = Voronoi(points) - neighbor_pairs = vor.ridge_points - return neighbor_pairs -#end def voronoi_neighbors - - -def convex_hull(points,dimension=None,tol=None): - if dimension is None: - np,dimension = points.shape - #end if - d1 = dimension+1 - tri = Delaunay(points) - all_inds = empty((d1,),dtype=bool) - all_inds[:] = True - verts = [] - have_tol = tol!=None - for ni in range(len(tri.neighbors)): - n = tri.neighbors[ni] - ns = list(n) - if -1 in ns: - i = ns.index(-1) - inds = all_inds.copy() - inds[i] = False - v = tri.vertices[ni] - if have_tol: - iv = range(d1) - iv.pop(i) - c = points[v[iv[1]]] - a = points[v[i]]-c - b = points[v[iv[0]]]-c - bn = norm(b) - d = norm(a-dot(a,b)/(bn*bn)*b) - if d1: + format = formats[0] + all_same = True + elif len(formats)>len(stokens): + self.error('formatted line read failed\nnumber of tokens and provided number of formats do not match\nline: {0}\nnumber of tokens: {1}\nnumber of formats provided: {2}'.format(line,len(stokens),len(formats))) + #end if + tokens = [] + if all_same: + for stoken in stokens: + tokens.append(format(stoken)) + #end for + else: + for i in xrange(len(formats)): + tokens.append(formats[i](stokens[i])) + #end for + #end if + if len(tokens)==1: + return tokens[0] + else: + return tokens + #end if + #end def readtokensf # extended mmap interface below def close(self): @@ -464,7 +494,7 @@ class XsfFile(DevBase): i+=1 #end while if check and not self.is_valid(): - self.error('read failed, not a valid xsf file'.format(filepath)) + self.error('read failed, not a valid xsf file') #end if #end def read_text diff --git a/nexus/library/gamess.py b/nexus/library/gamess.py index 9468e0d82..3fd78c440 100644 --- a/nexus/library/gamess.py +++ b/nexus/library/gamess.py @@ -96,6 +96,7 @@ class Gamess(Simulation): analyzer = self.load_analyzer_image() if result_name=='orbitals': result.location = os.path.join(self.locdir,self.outfile) + result.outfile = result.location result.vec = None # vec from punch result.norbitals = 0 # orbital count in punch result.mos = 0 # orbital count (MO's) from log file @@ -154,6 +155,25 @@ class Gamess(Simulation): output_files = [] return output_files #end def get_output_files + + + def output_filename(self,name): + name = name.upper() + if name not in GamessInput.file_units: + self.error('gamess does not produce a file matching the requested description: {0}'.format(name)) + #end if + unit = GamessInput.file_units[name] + filename = '{0}.F{1}'.format(self.identifier,str(unit).zfill(2)) + return filename + #end def output_filename + + + def output_filepath(self,name): + filename = self.output_filename(name) + filepath = os.path.join(self.locdir,filename) + filepath = os.path.abspath(filepath) + return filepath + #end def #end class Gamess diff --git a/nexus/library/gamess_analyzer.py b/nexus/library/gamess_analyzer.py index eb7418b7b..15e7a2f69 100644 --- a/nexus/library/gamess_analyzer.py +++ b/nexus/library/gamess_analyzer.py @@ -185,7 +185,6 @@ class GamessAnalyzer(SimulationAnalyzer): # try to get the mulliken/lowdin populations in each ao if 'counts' in self: ao_populations = obj() - self.read_ao_populations(log,ao_populations) try: self.read_ao_populations(log,ao_populations) except: diff --git a/nexus/library/gamess_input.py b/nexus/library/gamess_input.py index 36756e900..5fb2ad45c 100644 --- a/nexus/library/gamess_input.py +++ b/nexus/library/gamess_input.py @@ -37,6 +37,7 @@ from numpy import array,ndarray,abs from generic import obj from periodic_table import pt from developer import DevBase +from nexus_base import nexus_noncore from simulation import SimulationInput from debug import * @@ -386,7 +387,7 @@ class ContrlGroup(KeywordSpecGroup): 'coord' ,'units' ,'nzvar' ,'pp' ,'local' ,'ispher','qmttol', 'maxit' ,'molplt','pltorb','aimpac','friend','nfflvl','nprint', 'nosym' ,'etollz','inttyp','grdtyp','normf' ,'normp' ,'itol' , - 'icut' ,'iskprp','irest' ,'geom' ,'ecp' + 'icut' ,'iskprp','irest' ,'geom' ,'ecp' ,'casino' ]) integers = set([ 'mplevl','icharg','mult' ,'nzvar' ,'ispher','maxit' ,'nfflvl', @@ -394,7 +395,7 @@ class ContrlGroup(KeywordSpecGroup): 'irest' ]) reals = set(['qmttol' ,'etollz']) - bools = set(['numgrd' ,'molplt','pltorb','aimpac']) + bools = set(['numgrd' ,'molplt','pltorb','aimpac','casino']) strings = set([ 'scftyp','dfttyp','tddft' ,'vbtyp' ,'cityp' ,'cctyp' ,'cimtyp', 'relwfn','runtyp','exetyp','coord' ,'units' ,'pp' ,'local' , @@ -812,7 +813,7 @@ class GamessInput(SimulationInput,GIbase): #end def __init__ - def read_contents(self,contents): + def read_text(self,contents,filepath=None): #print 8*'\n' #print contents @@ -929,7 +930,7 @@ class GamessInput(SimulationInput,GIbase): #print self #exit() - #end def read_contents + #end def read_text def process_line(self,ls): @@ -951,7 +952,7 @@ class GamessInput(SimulationInput,GIbase): #end def process_line - def write_contents(self): + def write_text(self,filepath=None): contents = '' extra_groups = set(self.keys())-set(self.group_order) if len(extra_groups)>0: @@ -968,7 +969,7 @@ class GamessInput(SimulationInput,GIbase): #end if #end for return contents - #end def write_contents + #end def write_text def incorporate_system(self,system): @@ -997,7 +998,7 @@ def generate_gamess_input(**kwargs): -ps_inputs = set('descriptor symmetry system pseudos pseudo_bases'.split()) +ps_inputs = set('descriptor symmetry system pseudos pseudo_bases bases'.split()) ps_defaults = obj() for var in ps_inputs: ps_defaults[var]=None @@ -1032,7 +1033,7 @@ def generate_any_gamess_input(**kwargs): invalid_names = kwset-GamessInput.all_name_aliases if len(invalid_names)>0: - GamessInput.class_error('invalid group names or keywords encountered\n invalid names/keywords provided: {0}\n please check if these group names or keywords are actually valid GAMESS inputs\n if so, unsupported groups can be generated by providing the keywords as a single argument:\n generate_gamess_input(\n ...,\n group_name = obj(assign keywords),\n ...,\n )'.format(sorted(invalid_names)),'generate_gamess_input') + GamessInput.class_error('invalid group names or keywords encountered\ninvalid names/keywords provided: {0}\nplease check if these group names or keywords are actually valid GAMESS inputs\nif so, unsupported groups can be generated by providing the keywords as a single argument:\n generate_gamess_input(\n ...,\n group_name = obj(assign keywords),\n ...,\n )'.format(sorted(invalid_names)),'generate_gamess_input') #end if gi = GamessInput() @@ -1113,11 +1114,19 @@ def generate_any_gamess_input(**kwargs): data+='\n' #end if if pskw.pseudos is None: - gi.contrl.coord = 'cart' + if pskw.bases!=None: + bss = nexus_noncore.basissets.bases_by_atom(*pskw.bases) + else: + bss = obj() + gi.contrl.coord = 'cart' + #end if for i in range(len(elem)): a = elem[i] Z = pt[a].atomic_number data+='{0} {1:3.2f} {2:16.8f} {3:16.8f} {4:16.8f}\n'.format(a,Z,*pos[i]) + if a in bss: + data+=bss[a].text+'\n\n' + #end if #end for else: gi.contrl.set( @@ -1125,7 +1134,7 @@ def generate_any_gamess_input(**kwargs): ecp = 'read' ) ecp = '' - pps = GamessInput.pseudopotentials.pseudos_by_atom(*pskw.pseudos) + pps = nexus_noncore.pseudopotentials.pseudos_by_atom(*pskw.pseudos) atoms = set() for i in range(len(elem)): a = elem[i] diff --git a/nexus/library/generic.py b/nexus/library/generic.py index 139d28920..19d7e575f 100644 --- a/nexus/library/generic.py +++ b/nexus/library/generic.py @@ -33,345 +33,138 @@ import sys import traceback from copy import deepcopy +import cPickle from random import randint -from abilities import AllAbilities,genbase exit_call = exit +devlog = sys.stdout -class obj(AllAbilities): - logfile = sys.stdout - - def copy(self): - return self._copy() - def copies(self,count): - return self._copies(count) - def iteritems(self): - return self._iteritems() - def keys(self): - return self._keys() - def values(self): - return self._values() - def inverse(self): - return self._inverse() - def set(self,**variables): - return self._set(**variables) - def clear(self): - self._clear() - def add_attribute(self,name,value=None): - self._add_attribute(name,value) - def add_attributes(self,*names,**attributes): - self._add_attributes(*names,**attributes) - #def transfer_from(self,other,copy=False): - # self._transfer_from(other,copy) - #def transfer_to(self,other,copy=False): - # self._transfer_to(other,copy) - def append(self,value): - self._append(value) - def save(self,fpath=None,fast=True): - self._save(fpath,fast) - def load(self,fpath,fast=True): - self._load(fpath,fast) +def nocopy(value): + return value +#end def nocopy - def list(self,*names): - if len(names)==0: - names = list(self.keys()) - names.sort() +def log(*items,**kwargs): + indent=None + logfile=devlog + if len(kwargs)>0: + n=0 + if 'indent' in kwargs: + indent = kwargs['indent'] + n+=1 #end if - values = [] - for name in names: - values.append(self[name]) + if 'logfile' in kwargs: + logfile = kwargs['logfile'] + n+=1 #end if - return values - #end def list - - def tuple(self,*names): - return tuple(self.list(*names)) - #end def tuple - - def obj(self,*names): - o = obj() - o.transfer_from(self,keys=names,copy=False) - return o - #end def obj - - def first(self): - return self[min(self.keys())] - #end def first - - def last(self): - return self[max(self.keys())] - #end def last - - def open_log(self,filepath): - self.logfile = open(filepath,'w') - #end def open_log - - def close_log(self): - self.logfile.close() - #end def close_log - - def _write(self,s): - self.logfile.write(s) - #end def _write - - def write(self,s): - self._write(s) - #end def write - - def logna(self,*items): + if n!=len(kwargs): + valid = 'indent logfile'.split() + invalid = set(kwargs.keys())-set(valid) + error('invalid keyword arguments provided\ninvalid keywords: {0}\nvalid options are: {1}'.format(sorted(invalid),valid)) + #end if + #end if + if len(items)==1 and isinstance(items[0],str): + s = items[0] + else: s='' for item in items: s+=str(item)+' ' #end for - self.logfile.write(s) - #end def logna - - def log(self,*items): - s='' - for item in items: - s+=str(item)+' ' - #end for - s+='\n' - self.logfile.write(s) - #end def log - - def error(self,message,header=None,exit=True,trace=True,post_header=' Error:'): - pad = 4*' ' - if header==None: - header = self.__class__.__name__ + #end if + if len(s)>0: + if isinstance(indent,str): + s=indent+s.replace('\n','\n'+indent) #end if - self.log('\n'+header+post_header) - self.log(pad+message.replace('\n','\n'+pad)) - if exit: - self.log(' exiting.\n') - if trace: - traceback.print_stack() - #end if - exit_call() + s += '\n' + #end if + logfile.write(s) +#end def log + + +def message(msg,header=None,post_header=' message:',indent=' ',logfile=devlog): + if header is None: + header = post_header.lstrip() + else: + header += post_header + #end if + log('\n '+header) + log(msg.rstrip(),indent=indent,logfile=logfile) +#end def message + + +def warn(msg,header=None,indent=' ',logfile=devlog): + post_header=' warning:' + message(msg,header,post_header,indent,logfile) +#end def warn + + +def error(msg,header=None,exit=True,trace=True,indent=' ',logfile=devlog): + post_header=' error:' + message(msg,header,post_header,indent,logfile) + if exit: + log(' exiting.\n') + if trace: + traceback.print_stack() #end if - #end def error - - def warn(self,message,header=None,post_header=' Warning:'): - pad = 4*' ' - if header==None: - header=self.__class__.__name__ - #end if - self.log('\n'+header+post_header) - self.log(pad+message.replace('\n','\n'+pad)) - #end def warn - - @classmethod - def class_error(cls,message,header=None,exit=True,trace=True,post_header=' Error:'): - pad = 4*' ' - if header==None: - header = cls.__name__ - #end if - cls.logfile.write('\n'+header+post_header+'\n') - cls.logfile.write((pad+message).replace('\n','\n'+pad)+'\n') - if exit: - cls.logfile.write(' exiting.\n\n') - if trace: - traceback.print_stack() - #end if - exit_call() - #end if - #end def class_error - - @classmethod - def class_warn(cls,message,header=None,post_header=' Warning:'): - pad = 4*' ' - if header==None: - header=cls.__name__ - #end if - cls.logfile.write(header+post_header+'\n') - cls.logfile.write(('\n'+message).replace('\n','\n'+pad)+'\n') - #end def error - - def transfer_from(self,other,keys=None,copy=False): - if keys==None: - keys = other.keys() - #end if - if not copy: - for k in keys: - self[k]=other[k] - #end for - else: - for k in keys: - self[k]=deepcopy(other[k]) - #end for - #end if - #end def transfer_from - - def transfer_to(self,other,keys=None,copy=False): - if keys==None: - keys = self.keys() - #end if - if not copy: - for k in keys: - other[k]=self[k] - #end for - else: - for k in keys: - other[k]=deepcopy(self[k]) - #end for - #end if - #end def transfer_to - - def move_from(self,other,keys=None): - if keys==None: - keys = other.keys() - #end if - for k in keys: - self[k]=other[k] - del other[k] - #end for - #end def move_from - - def move_to(self,other,keys=None): - other.move_from(self,keys) - #end def move_to - - def copy_from(self,other,keys=None,deep=False): - self.transfer_from(other,keys,copy=deep) - #end def copy_from - - def copy_to(self,other,keys=None,deep=False): - self.transfer_to(other,keys,copy=deep) - #end def copy_to - - def delete(self,*names): - if len(names)==1: - name = names[0] - value = self[name] - del self[name] - return value - else: - if len(names)==0: - names = sorted(obj.keys(self)) - #end if - values = [] - for name in names: - values.append(self[name]) - del self[name] - #end for - return values - #end if - #end def delete - - def delete_option(self,name,value=None): - if name in self: - value = self[name] - del self[name] - #end if - return value - #end def delete_option - - def add_option(self,name,value): - added = False - if name not in self: - self[name] = value - added = True - #end if - return added - #end def add_option - - def add_attribute_path(self,path,value=None): - o = self - for p in path[0:-1]: - if not p in o: - o[p] = obj() - #end if - o = o[p] - #end for - o[path[-1]] = value - #end def add_attribute_path - - def select_random(self): # intended for list-like objects - return self[randint(0,len(self)-1)] - #end def select_random -#end class obj + exit_call() + #end if +#end def error - -import copy -import cPickle - -class generic(genbase): - logfile = sys.stdout - - def __init__(self,*vals,**kwargs): - if len(vals)==1 and isinstance(vals[0],(dict,generic)): - self.add_attributes(**vals[0]) - self.add_attributes(**kwargs) - else: - self.add_attributes(*vals,**kwargs) - #end for - #end def __init__ - - def _dict(self): - return self.__dict__ - #end def __get_dict - - def _alt(self): - return self.__dict__ - #end def __alt +class object_interface(object): + _logfile = sys.stdout def __len__(self): - return len(self._dict()) + return len(self.__dict__) #end def __len__ def __contains__(self,name): - return name in self._dict() - #end def __contains__ + return name in self.__dict__ + #end def def __getitem__(self,name): - return self._dict()[name] + return self.__dict__[name] #end def __getitem__ def __setitem__(self,name,value): - self._dict()[name] = value + self.__dict__[name]=value #end def __setitem__ def __delitem__(self,name): - del self._dict()[name] + del self.__dict__[name] #end def __delitem__ - def __repr__(self): - s='' - stype = type(s) - d = self._dict() - mem = list(d.keys()) - mem.sort() - for m in mem: - v=d[m] - if hasattr(v,'__class__'): - s+=' {0:<20} {1:<20}\n'.format(m,v.__class__.__name__) - else: - s+=' {0:<20} {1:<20}\n'.format(m,type(v)) + def __iter__(self): + for item in self.__dict__: + yield self.__dict__[item] + #end for + #end def __iter__ + + def __repr__(self): + s='' + for k in sorted(self._keys()): + if not isinstance(k,str) or k[0]!='_': + v=self.__dict__[k] + if hasattr(v,'__class__'): + s+=' {0:<20} {1:<20}\n'.format(k,v.__class__.__name__) + else: + s+=' {0:<20} {1:<20}\n'.format(k,type(v)) + #end if #end if #end for return s - #end def __repr__ - - def __iter__(self): - d = self._dict() - for item in d.__dict__: - yield d[item] - #end for - #end def __iter__ + #end def __repr__ def __str__(self,nindent=1): pad = ' ' npad = nindent*pad s='' - stype = type(s) normal = [] qable = [] - for k,v in self._dict().iteritems(): - if type(k)!=stype or k[0]!='_': - if isinstance(v,(generic,obj)): + for k,v in self._iteritems(): + if not isinstance(k,str) or k[0]!='_': + if isinstance(v,object_interface): qable.append(k) else: normal.append(k) @@ -380,9 +173,9 @@ class generic(genbase): #end for normal.sort() qable.sort() + indent = npad+18*' ' for k in normal: v = self[k] - indent = npad+18*' ' vstr = str(v).replace('\n','\n'+indent) s+=npad+'{0:<15} = '.format(k)+vstr+'\n' #end for @@ -397,59 +190,72 @@ class generic(genbase): return s #end def __str__ + def __eq__(self,other): + if not hasattr(other,'__dict__'): + return False + #end if + eq = True + for sname in self.__dict__: + if sname not in other.__dict__: + return False + #end if + svar = self.__dict__[sname] + ovar = other.__dict__[sname] + stype = type(svar) + otype = type(ovar) + if stype!=otype: + return False + #end if + eqval = svar==ovar + if isinstance(eqval,bool): + eq &= eqval + else: + try: # accomodate numpy arrays implicitly + eq &= eqval.all() + except: + return False + #end try + #end if + #end for + return eq + #end def __eq__ - def copy(self): - return copy.deepcopy(self) - #end def copy - - def iteritems(self): - return self._dict().iteritems() - #end def iteritems - + # dict interface def keys(self): - return self._dict().keys() + return self.__dict__.keys() #end def keys def values(self): - return self._dict().values() - #end def keys + return self.__dict__.values() + #end def values - def inverse(self): - new = self.__class__() - d = dict((v,k) for k, v in self.iteritems()) - new.add_attributes(**d) - return new - #end def inverse + def items(self): + return self.__dict__.items() + #end def items - def set(self,**variables): - for name,value in variables.iteritems(): - self[name]=value - #end for - return self - #end def set + def iterkeys(self): + return self.__dict__.iterkeys() + #end def iterkeys + + def itervalues(self): + return self.__dict__.itervalues() + #end def itervalues + + def iteritems(self): + return self.__dict__.iteritems() + #end def iteritems + + def copy(self): + return deepcopy(self) + #end def copy def clear(self): - self._dict().clear() + self.__dict__.clear() #end def clear - def add_attribute(self,name,value=None): - self[name] = value - #end def add_attribute - - def add_attributes(self,*names,**attributes): - for name in names: - self[name] = None - #end for - for name,value in attributes.iteritems(): - self[name]=value - #end for - #end def add_attributes - - def append(self,value): - self[len(self)] = value - #end def append + # save/load def save(self,fpath=None): if fpath==None: fpath='./'+self.__class__.__name__+'.p' @@ -480,39 +286,416 @@ class generic(genbase): return #end def load - def transfer_from(self,other,keys=None,copy=False): - if keys==None: - keys = other.keys() + + + # log, warning, and error messages + def open_log(self,filepath): + self._logfile = open(filepath,'w') + #end def open_log + + def close_log(self): + self._logfile.close() + #end def close_log + + def write(self,s): + self._logfile.write(s) + #end def write + + def log(self,*items,**kwargs): + if 'logfile' not in kwargs: + kwargs['logfile'] = self._logfile #end if - if not copy: + log(*items,**kwargs) + #end def log + + def warn(self,message,header=None): + if header is None: + header=self.__class__.__name__ + #end if + warn(message,header,logfile=self._logfile) + #end def warn + + def error(self,message,header=None,exit=True,trace=True): + if header==None: + header = self.__class__.__name__ + #end if + error(message,header,exit,trace,logfile=self._logfile) + #end def error + + @classmethod + def class_warn(cls,message,header=None,post_header=' Warning:'): + if header==None: + header=cls.__name__ + #end if + warn(message,header,logfile=cls._logfile) + #end def error + + @classmethod + def class_error(cls,message,header=None,exit=True,trace=True,post_header=' Error:'): + if header==None: + header = cls.__name__ + #end if + error(message,header,exit,trace,logfile=cls._logfile) + #end def class_error + + @classmethod + def class_has(cls,k): + return hasattr(cls,k) + #end def classmethod + + @classmethod + def class_keys(cls): + return cls.__dict__.keys() + #end def class_keys + + @classmethod + def class_iteritems(cls): + return cls.__dict__.iteritems() + #end def class_iteritems + + @classmethod + def class_get(cls,k): + return getattr(cls,k) + #end def class_set + + @classmethod + def class_set(cls,**kwargs): + for k,v in kwargs.iteritems(): + setattr(cls,k,v) + #end for + #end def class_set + + @classmethod + def class_set_single(cls,k,v): + setattr(cls,k,v) + #end def class_set_single + + @classmethod + def class_set_optional(cls,**kwargs): + for k,v in kwargs.iteritems(): + if not hasattr(cls,k): + setattr(cls,k,v) + #end if + #end for + #end def class_set_optional + + + # access preserving functions + # dict interface + def _keys(self,*args,**kwargs): + return object_interface.keys(self,*args,**kwargs) + def _values(self,*args,**kwargs): + object_interface.values(self,*args,**kwargs) + def _items(self,*args,**kwargs): + return object_interface.items(self,*args,**kwargs) + def _iterkeys(self,*args,**kwargs): + return object_interface.iterkeys(self,*args,**kwargs) + def _itervalues(self,*args,**kwargs): + object_interface.itervalues(self,*args,**kwargs) + def _iteritems(self,*args,**kwargs): + return object_interface.iteritems(self,*args,**kwargs) + def _copy(self,*args,**kwargs): + return object_interface.copy(self,*args,**kwargs) + def _clear(self,*args,**kwargs): + object_interface.clear(self,*args,**kwargs) + # save/load + def _save(self,*args,**kwargs): + object_interface.save(self,*args,**kwargs) + def _load(self,*args,**kwargs): + object_interface.load(self,*args,**kwargs) + # log, warning, and error messages + def _open_log(self,*args,**kwargs): + object_interface.open_log(self,*args,**kwargs) + def _close_log(self,*args,**kwargs): + object_interface.close_log(self,*args,**kwargs) + def _write(self,*args,**kwargs): + object_interface.write(self,*args,**kwargs) + def _log(self,*args,**kwargs): + object_interface.log(self,*args,**kwargs) + def _error(self,*args,**kwargs): + object_interface.error(self,*args,**kwargs) + def _warn(self,*args,**kwargs): + object_interface.warn(self,*args,**kwargs) + +#end class object_interface + + + +class obj(object_interface): + + def __init__(self,*vars,**kwargs): + for var in vars: + if isinstance(var,(dict,object_interface)): + for k,v in var.iteritems(): + self[k] = v + #end for + else: + self[var] = None + #end if + #end for + for k,v in kwargs.iteritems(): + self[k] = v + #end for + #end def __init__ + + + # list interface + def append(self,value): + self[len(self)] = value + #end def append + + + # return representations + def list(self,*keys): + nkeys = len(keys) + if nkeys==0: + keys = sorted(self._keys()) + elif nkeys==1 and isinstance(keys[0],(list,tuple)): + keys = keys[0] + #end if + values = [] + for key in keys: + values.append(self[key]) + #end if + return values + #end def list + + def list_optional(self,*keys): + nkeys = len(keys) + if nkeys==0: + keys = sorted(self._keys()) + elif nkeys==1 and isinstance(keys[0],(list,tuple)): + keys = keys[0] + #end if + values = [] + for key in keys: + if key in self: + values.append(self[key]) + else: + values.append(None) + #end if + #end if + return values + #end def list_optional + + def tuple(self,*keys): + return tuple(obj.list(self,*keys)) + #end def tuple + + def dict(self,*keys): + nkeys = len(keys) + if nkeys==0: + keys = sorted(self._keys()) + elif nkeys==1 and isinstance(keys[0],(list,tuple)): + keys = keys[0] + #end if + d = dict() + for k in keys: + d[k] = self[k] + #end for + return d + #end def dict + + def to_dict(self): + d = dict() + for k,v in self: + if isinstance(v,obj): + d[k] = v.to_dict() + else: + d[k] = v + #end if + #end for + return d + #end def to_dict + + def obj(self,*keys): + nkeys = len(keys) + if nkeys==0: + keys = sorted(self._keys()) + elif nkeys==1 and isinstance(keys[0],(list,tuple)): + keys = keys[0] + #end if + o = obj() + for k in keys: + o[k] = self[k] + #end for + return o + #end def obj + + + # list extensions + def first(self): + return self[min(self._keys())] + #end def first + + def last(self): + return self[max(self._keys())] + #end def last + + def select_random(self): + return self[randint(0,len(self)-1)] + #end def select_random + + + # dict extensions + def set(self,*objs,**kwargs): + for key,value in kwargs.iteritems(): + self[key]=value + #end for + if len(objs)>0: + for o in objs: + for k,v in o.iteritems(): + self[k] = v + #end for + #end for + #end if + return self + #end def set + + def set_optional(self,*objs,**kwargs): + for key,value in kwargs.iteritems(): + if key not in self: + self[key]=value + #end if + #end for + if len(objs)>0: + for o in objs: + for k,v in o.iteritems(): + if k not in self: + self[k] = v + #end if + #end for + #end for + #end if + return self + #end def set_optional + + def set_path(self,path,value=None): + o = self + cls = self.__class__ + if isinstance(path,str): + path = path.split('/') + #end if + for p in path[0:-1]: + if not p in o: + o[p] = cls() + #end if + o = o[p] + #end for + o[path[-1]] = value + #end def set_path + + def get(self,key,value=None): # follow dict interface, no plural + if key in self: + value = self[key] + #end if + return value + #end def get + + def get_optional(self,key,value=None): + if key in self: + value = self[key] + #end if + return value + #end def get_optional + + def get_required(self,key): + if key in self: + value = self[key] + else: + obj.error(self,'a required key is not present\nkey required: {0}\nkey present: {1}'.format(key,sorted(self._keys()))) + #end if + return value + #end def get_required + + def delete(self,*keys): + nkeys = len(keys) + if nkeys==0: + keys = sorted(self._keys()) + elif nkeys==1 and isinstance(keys[0],(list,tuple)): + keys = keys[0] + #end if + values = [] + for key in keys: + values.append(self[key]) + del self[key] + #end for + return values + #end def delete + + def delete_optional(self,key,value=None): + if key in self: + value = self[key] + del self[key] + #end if + return value + #end def delete_optional + + def delete_required(self,key): + if key in self: + value = self[key] + del self[key] + else: + obj.error(self,'a required key is not present\nkey required: {0}\nkeys present: {1}'.format(key,sorted(self._keys()))) + #end if + return value + #end def delete_required + + def transfer_from(self,other,keys=None,copy=False,overwrite=True): + if keys==None: + if isinstance(other,object_interface): + keys = other._keys() + else: + keys = other.keys() + #end if + #end if + if copy: + copier = deepcopy + else: + copier = nocopy + #end if + if overwrite: for k in keys: - self[k]=other[k] + self[k]=copier(other[k]) #end for else: for k in keys: - self[k]=deepcopy(other[k]) - #end for + if k not in self: + self[k]=copier(other[k]) + #end if + #end for #end if #end def transfer_from - def transfer_to(self,other,keys=None,copy=False): + def transfer_to(self,other,keys=None,copy=False,overwrite=True): if keys==None: - keys = self.keys() + keys = self._keys() #end if - if not copy: + if copy: + copier = deepcopy + else: + copier = nocopy + #end if + if overwrite: for k in keys: - other[k]=self[k] + other[k]=copier(self[k]) #end for else: for k in keys: - other[k]=deepcopy(self[k]) - #end for + if k not in self: + other[k]=copier(self[k]) + #end if + #end for #end if #end def transfer_to def move_from(self,other,keys=None): if keys==None: - keys = other.keys() + if isinstance(other,object_interface): + keys = other._keys() + else: + keys = other.keys() + #end if #end if for k in keys: self[k]=other[k] @@ -521,218 +704,193 @@ class generic(genbase): #end def move_from def move_to(self,other,keys=None): - other.move_from(self,keys) + if keys==None: + keys = self._keys() + #end if + for k in keys: + other[k]=self[k] + del self[k] + #end for #end def move_to - def copy_from(self,other,keys=None,deep=False): - self.transfer_from(other,keys,copy=deep) + def copy_from(self,other,keys=None,deep=True): + obj.transfer_from(self,other,keys,copy=deep) #end def copy_from - def copy_to(self,other,keys=None,deep=False): - self.transfer_to(other,keys,copy=deep) + def copy_to(self,other,keys=None,deep=True): + obj.transfer_to(self,other,keys,copy=deep) #end def copy_to - def delete(self,*names): - if len(names)==1: - name = names[0] - value = self[name] - del self[name] - return value - else: - if len(names)==0: - names = sorted(generic.keys(self)) - #end if - values = [] - for name in names: - values.append(self[name]) - del self[name] - #end for - return values - #end if - #end def delete - - def list(self,*names): - if len(names)==0: - names = list(generic.keys(self)) - names.sort() - #end if - values = [] - for name in names: - values.append(self[name]) - #end if - return values - #end def list - - def tuple(self,*names): - return tuple(self.list(*names)) - #end def tuple - - def obj(self,*names): - o = obj() - o.transfer_from(self,keys=names,copy=False) - return o - #end def obj - - def first(self): - return self[min(self.keys())] - #end def first - - def last(self): - return self[max(self.keys())] - #end def last - - def open_log(self,filepath): - self._alt().logfile = open(filepath,'w') - #end def open_log - - def close_log(self): - self._alt().logfile.close() - #end def close_log - - def write(self,s): - self._alt().logfile.write(s) - #end def write - - def logna(self,*items): - s='' - for item in items: - s+=str(item)+' ' + def shallow_copy(self): + new = self.__class__() + for k,v in self._iteritems(): + self[k] = v #end for - self._alt().logfile.write(s) - #end def logna + return new + #end def shallow_copy - def log(self,*items): - s='' - for item in items: - s+=str(item)+' ' + def inverse(self): + new = self.__class__() + for k,v in self._iteritems(): + new[v] = k #end for - s+='\n' - self._alt().logfile.write(s) - #end def log - - def error(self,message,header=None,exit=True,trace=True,post_header=' Error:'): - pad = 4*' ' - if header==None: - header = self.__class__.__name__ - #end if - self.log(header+post_header) - self.log(pad+message.replace('\n','\n'+pad)) - if exit: - self.log(' exiting.\n') - if trace: - traceback.print_stack() - #end if - exit_call() - #end if - #end def error - - def warn(self,message,header=None,post_header=' Warning:'): - pad = 4*' ' - if header==None: - header=self.__class__.__name__ - #end if - self.log(header+post_header) - self.log(pad+message.replace('\n','\n'+pad)) - #end def error - - @classmethod - def class_error(cls,message,header=None,exit=True,trace=True,post_header=' Error:'): - pad = 4*' ' - if header==None: - header = cls.__name__ - #end if - cls.logfile.write(header+post_header) - cls.logfile.write(pad+message.replace('\n','\n'+pad)+'\n') - if exit: - cls.logfile.write(' exiting.\n\n') - if trace: - traceback.print_stack() - #end if - exit_call() - #end if - #end def class_error + return new + #end def inverse - def _copy(self,*args,**kwargs): - return generic.copy(self,*args,**kwargs) - def _iteritems(self,*args,**kwargs): - return generic.iteritems(self,*args,**kwargs) - def _keys(self,*args,**kwargs): - return generic.keys(self,*args,**kwargs) - def _values(self,*args,**kwargs): - generic.values(self,*args,**kwargs) - def _inverse(self,*args,**kwargs): - return generic.inverse(self,*args,**kwargs) - def _set(self,*args,**kwargs): - generic.set(self,*args,**kwargs) - def _clear(self,*args,**kwargs): - generic.clear(self,*args,**kwargs) - def _add_attribute(self,*args,**kwargs): - generic.add_attribute(self,*args,**kwargs) - def _add_attributes(self,*args,**kwargs): - generic.add_attributes(self,*args,**kwargs) + # access preserving functions + # list interface def _append(self,*args,**kwargs): - generic.append(self,*args,**kwargs) - def _save(self,*args,**kwargs): - generic.save(self,*args,**kwargs) - def _load(self,*args,**kwargs): - generic.load(self,*args,**kwargs) - def _transfer_from(self,*args,**kwargs): - generic.transfer_from(self,*args,**kwargs) - def _transfer_to(self,*args,**kwargs): - generic.transfer_to(self,*args,**kwargs) - def _move_from(self,*args,**kwargs): - generic.move_from(self,*args,**kwargs) - def _move_to(self,*args,**kwargs): - generic.move_to(self,*args,**kwargs) - def _copy_from(self,*args,**kwargs): - generic.copy_from(self,*args,**kwargs) - def _copy_to(self,*args,**kwargs): - generic.copy_to(self,*args,**kwargs) - def _delete(self,*args,**kwargs): - generic.delete(self,*args,**kwargs) + obj.append(self,*args,**kwargs) + # return representations def _list(self,*args,**kwargs): - return generic.list(self,*args,**kwargs) + return obj.list(self,*args,**kwargs) + def _list_optional(self,*args,**kwargs): + return obj.list_optional(self,*args,**kwargs) def _tuple(self,*args,**kwargs): - return generic.tuple(self,*args,**kwargs) + return obj.tuple(self,*args,**kwargs) + def _dict(self,*args,**kwargs): + return obj.dict(self,*args,**kwargs) + def _to_dict(self,*args,**kwargs): + return obj.to_dict(self,*args,**kwargs) def _obj(self,*args,**kwargs): - return generic.obj(self,*args,**kwargs) + return obj.obj(self,*args,**kwargs) + # list extensions def _first(self,*args,**kwargs): - return generic.first(self,*args,**kwargs) + return obj.first(self,*args,**kwargs) def _last(self,*args,**kwargs): - return generic.last(self,*args,**kwargs) - def _open_log(self,*args,**kwargs): - generic.open_log(self,*args,**kwargs) - def _close_log(self,*args,**kwargs): - generic.close_log(self,*args,**kwargs) - def _write(self,*args,**kwargs): - generic.write(self,*args,**kwargs) - def _logna(self,*args,**kwargs): - generic.logna(self,*args,**kwargs) - def _log(self,*args,**kwargs): - generic.log(self,*args,**kwargs) - def _error(self,*args,**kwargs): - generic.error(self,*args,**kwargs) - def _warn(self,*args,**kwargs): - generic.warn(self,*args,**kwargs) -#end class generic + return obj.last(self,*args,**kwargs) + def _select_random(self,*args,**kwargs): + return obj.select_random(self,*args,**kwargs) + # dict extensions + def _set(self,*args,**kwargs): + obj.set(self,*args,**kwargs) + def _set_optional(self,*args,**kwargs): + obj.set_optional(self,*args,**kwargs) + def _set_path(self,*args,**kwargs): + obj.set_path(self,*args,**kwargs) + def _get(self,*args,**kwargs): + obj.get(self,*args,**kwargs) + def _get_optional(self,*args,**kwargs): + obj.get_optional(self,*args,**kwargs) + def _get_required(self,*args,**kwargs): + obj.get_required(self,*args,**kwargs) + def _delete(self,*args,**kwargs): + obj.delete(self,*args,**kwargs) + def _delete_optional(self,*args,**kwargs): + obj.delete_optional(self,*args,**kwargs) + def _delete_required(self,*args,**kwargs): + obj.delete_required(self,*args,**kwargs) + def _transfer_from(self,*args,**kwargs): + obj.transfer_from(self,*args,**kwargs) + def _transfer_to(self,*args,**kwargs): + obj.transfer_to(self,*args,**kwargs) + def _move_from(self,*args,**kwargs): + obj.move_from(self,*args,**kwargs) + def _move_to(self,*args,**kwargs): + obj.move_to(self,*args,**kwargs) + def _copy_from(self,*args,**kwargs): + obj.copy_from(self,*args,**kwargs) + def _copy_to(self,*args,**kwargs): + obj.copy_to(self,*args,**kwargs) + def _shallow_copy(self,*args,**kwargs): + obj.shallow_copy(self,*args,**kwargs) + def _inverse(self,*args,**kwargs): + return obj.inverse(self,*args,**kwargs) + +#end class obj -class hidden(generic): - def __init__(self,*vals,**kwargs): - d = object.__getattribute__(self,'__dict__') - d['_hidden_'] = generic() - d['_public_'] = generic() - d = self._dict() - generic.__init__(self,*vals,**kwargs) + + +class hobj(obj): + def __init__(self,*args,**kwargs): + obj.__init__(self,*args,**kwargs) #end def __init__ + @property + def _dict(self): + return self.__dict__ + #end def __get_dict + + @property + def _alt(self): + return self.__dict__ + #end def __alt + + def __len__(self): + return len(self._dict) + #end def __len__ + + def __contains__(self,name): + return name in self._dict + #end def __contains__ + + def __getitem__(self,name): + return self._dict[name] + #end def __getitem__ + + def __setitem__(self,name,value): + self._dict[name] = value + #end def __setitem__ + + def __delitem__(self,name): + del self._dict[name] + #end def __delitem__ + + def __iter__(self): + d = self._dict + for item in d.__dict__: + yield d[item] + #end for + #end def __iter__ + + def iteritems(self): + return self._dict.iteritems() + #end def iteritems + + def keys(self): + return self._dict.keys() + #end def keys + + def values(self): + return self._dict.values() + #end def keys + + def clear(self): + self._dict.clear() + #end def clear + + # access preserving functions + # dict interface + def _iteritems(self,*args,**kwargs): + return hobj.iteritems(self,*args,**kwargs) + def _keys(self,*args,**kwargs): + return hobj.keys(self,*args,**kwargs) + def _values(self,*args,**kwargs): + hobj.values(self,*args,**kwargs) + def _clear(self,*args,**kwargs): + hobj.clear(self,*args,**kwargs) +#end class hobj + + + +class hidden(hobj): + def __init__(self,*vals,**kwargs): + d = object.__getattribute__(self,'__dict__') + d['_hidden_'] = hobj() + d['_public_'] = hobj() + hobj.__init__(self,*vals,**kwargs) + #end def __init__ + + @property def _dict(self): return self.__dict__['_public_'] #end def __get_dict + @property def _alt(self): return self.__dict__['_hidden_'] #end def __alt @@ -752,11 +910,11 @@ class hidden(generic): #end def __getattribute__ def __setattr__(self,name,value): - self._dict()[name] = value + self._dict[name] = value #end def __setattr__ def __delattr__(self,name): - del self._dict()[name] + del self._dict[name] #end def __delattr__ def hidden(self): @@ -774,4 +932,103 @@ class hidden(generic): def _public(self): return hidden.public(self) #end def _public + + def open_log(self,filepath): + self._alt._open_log(filepath) + #end def open_log + + def close_log(self): + self._alt._close_log() + #end def close_log + + def write(self,s): + self._alt._write(s) + #end def write + + def log(self,*items,**kwargs): + self._alt._log(*items,**kwargs) + #end def log + + # log, warning, and error messages + def _open_log(self,*args,**kwargs): + hidden.open_log(self,*args,**kwargs) + def _close_log(self,*args,**kwargs): + hidden.close_log(self,*args,**kwargs) + def _write(self,*args,**kwargs): + hidden.write(self,*args,**kwargs) + def _log(self,*args,**kwargs): + hidden.log(self,*args,**kwargs) + #end class hidden + + + +if __name__=='__main__': + o = obj(a=1,b=2,c=3) + o[0]='d' + o.o = obj('something','else') + + print repr(o) + print o + print 'o' in o + del o.a + print 'a' not in o + print len(o)==4 + o2 = o.copy() + print id(o2)!=id(o) + o2.clear() + print len(o2)==0 + o.append(6) + print len(o)==5 and 4 in o + #o.save('obj.p') + #o.clear() + #o.load('obj.p') + #print o + o.write('True\n') + o.log('True') + del o.o + print o + print o.list() + print o.tuple() + print o.obj() + print o.first() + print o.last() + print o.shallow_copy() + print o.inverse() + o2 = obj() + o2.clear() + o.transfer_to(o2) + o2.clear() + o2.transfer_from(o) + o2.clear() + o.move_to(o2) + o.move_from(o2) + #print 'o' + #print o + #print 'o2' + #print o2 + o2.clear() + o.copy_to(o2) + o2.clear() + o2.copy_from(o) + print o + o2.delete('b','c') + print o2 + print o.get_optional('b') + print o.get_required('b') + o2 = o.copy() + print o2.delete_optional('b') + o2 = o.copy() + print o2.delete_required('b') + o2.set_path('one fine day is'.split(),'here') + print o2 + o.warn('this is a warning') + o.warn('this is another warning') + o.warn('this\nis\na\nmultiline\nwarning') + o.warn('final warning') + print 'printing normally' + message('this is a message') + print 'printing normally' + log('this is log output') + print 'printing normally' +#end if diff --git a/nexus/library/graph.py b/nexus/library/graph.py index 40f7d3492..60e074e79 100644 --- a/nexus/library/graph.py +++ b/nexus/library/graph.py @@ -10,7 +10,7 @@ # Content summary: # # Graph # # Wrapper class for pydot functionality # -# # +# # #====================================================================# @@ -168,7 +168,7 @@ class Graph(DevBase): graphs = graphs[0] #end if for graph in graphs: - self.add_graph(graph) + self.add_subgraph(graph) #end for #end def add_subgraphs diff --git a/nexus/library/abilities.py b/nexus/library/legacy/abilities.py similarity index 100% rename from nexus/library/abilities.py rename to nexus/library/legacy/abilities.py diff --git a/nexus/library/cascade.py b/nexus/library/legacy/cascade.py similarity index 100% rename from nexus/library/cascade.py rename to nexus/library/legacy/cascade.py diff --git a/nexus/library/density_analyzer.py b/nexus/library/legacy/density_analyzer.py similarity index 100% rename from nexus/library/density_analyzer.py rename to nexus/library/legacy/density_analyzer.py diff --git a/nexus/library/dft.py b/nexus/library/legacy/dft.py similarity index 93% rename from nexus/library/dft.py rename to nexus/library/legacy/dft.py index 51f5e4bf4..8623688ec 100644 --- a/nexus/library/dft.py +++ b/nexus/library/legacy/dft.py @@ -13,11 +13,11 @@ -from project_base import Pobj +from developer import DevBase import pwscf -class DFTDescriptor(Pobj): +class DFTDescriptor(DevBase): #general description of a dft simulation # information transferred to pwscf or abinit input None diff --git a/nexus/library/differences.py b/nexus/library/legacy/differences.py similarity index 100% rename from nexus/library/differences.py rename to nexus/library/legacy/differences.py diff --git a/nexus/library/eos_fit.py b/nexus/library/legacy/eos_fit.py similarity index 100% rename from nexus/library/eos_fit.py rename to nexus/library/legacy/eos_fit.py diff --git a/nexus/library/generator.py b/nexus/library/legacy/generator.py similarity index 100% rename from nexus/library/generator.py rename to nexus/library/legacy/generator.py diff --git a/nexus/library/qmc.py b/nexus/library/legacy/qmc.py similarity index 87% rename from nexus/library/qmc.py rename to nexus/library/legacy/qmc.py index 0128914b0..98b505720 100644 --- a/nexus/library/qmc.py +++ b/nexus/library/legacy/qmc.py @@ -12,19 +12,19 @@ #====================================================================# -from project_base import Pobj +from developer import DevBase import qmcpack -class HamiltonianDescriptor(Pobj): +class HamiltonianDescriptor(DevBase): None #end class HamiltonianDescriptor -class WavefunctionDescriptor(Pobj): +class WavefunctionDescriptor(DevBase): None #end class WavefunctionDescriptor -class QMCDescriptor(Pobj): +class QMCDescriptor(DevBase): #general description of a qmc simulation # information transferred to qmcpack or casino input None diff --git a/nexus/library/qmcpack_calculations.py b/nexus/library/legacy/qmcpack_calculations.py similarity index 100% rename from nexus/library/qmcpack_calculations.py rename to nexus/library/legacy/qmcpack_calculations.py diff --git a/nexus/library/qmcpack_pp_validation.py b/nexus/library/legacy/qmcpack_pp_validation.py similarity index 99% rename from nexus/library/qmcpack_pp_validation.py rename to nexus/library/legacy/qmcpack_pp_validation.py index 520265431..7d8122441 100755 --- a/nexus/library/qmcpack_pp_validation.py +++ b/nexus/library/legacy/qmcpack_pp_validation.py @@ -26,7 +26,7 @@ from project import generate_pw2casino,generate_pw2qmcpack from project import generate_sqd from project import generate_qmcpack,generate_jastrow from project import loop,vmc,dmc,linear,cslinear -from project import settings,ProjectManager,Job,Pobj +from project import settings,ProjectManager,Job,Settings from qmcpack_calculations import basic_qmc,standard_qmc @@ -2778,8 +2778,8 @@ class ValidatePPs(ValidatePPBase): test_order = ['atoms','dimers'] def __init__(self,settings=None,atoms=None,dimers=None): - if not isinstance(settings,Pobj): - self.error('input variable settings must be the settings object from the Project Suite') + if not isinstance(settings,Settings): + self.error('input variable settings must be the settings object from Nexus') #end if ValidatePPBase.settings = settings if atoms!=None: diff --git a/nexus/library/qmcpack_variations.py b/nexus/library/legacy/qmcpack_variations.py similarity index 98% rename from nexus/library/qmcpack_variations.py rename to nexus/library/legacy/qmcpack_variations.py index 5fe72aa91..3d806adfb 100644 --- a/nexus/library/qmcpack_variations.py +++ b/nexus/library/legacy/qmcpack_variations.py @@ -16,7 +16,7 @@ from datetime import datetime # jtk library imports from generic import obj # generic.py from project import Qmcpack,QmcpackInput,QmcpackAnalyzer # project.py -from project import Job,Pobj +from project import Job,nexus_core from developer import DevBase # developer.py from debug import * # debug.py @@ -258,7 +258,7 @@ class QmcpackVariations(DevBase): input.assign(**assignments) # add the relative path location of the wavefunction file - runpath = os.path.join(Pobj.local_directory,Pobj.runs,path) + runpath = os.path.join(nexus_core.local_directory,nexus_core.runs,path) wftmp = os.path.join(source_path,wf_h5file) wfpath = os.path.relpath(wftmp,runpath) @@ -270,7 +270,7 @@ class QmcpackVariations(DevBase): # check that the build exists app_loc = os.path.join(self.build_path,build_dir,self.app_loc) - if not os.path.exists(app_loc) and not self.generate_only: + if not os.path.exists(app_loc) and not nexus_core.generate_only: print ' Error: no qmcapp at '+app_loc error = True #end if diff --git a/nexus/library/machines.py b/nexus/library/machines.py index 86c84a417..4c6317806 100644 --- a/nexus/library/machines.py +++ b/nexus/library/machines.py @@ -39,7 +39,7 @@ # including arguments to the simulation executable, # # the run launcher (aprun/mpirun, etc), and the job submitter # # (e.g. qsub). # -# # +# # #====================================================================# @@ -50,7 +50,8 @@ from socket import gethostname from subprocess import Popen,PIPE from numpy import array,mod,floor,ceil,round,log from generic import obj -from project_base import Pobj +from developer import DevBase +from nexus_base import NexusCore,nexus_core from debug import * @@ -79,7 +80,7 @@ def cpu_count(): -class Options(Pobj): +class Options(DevBase): def __init__(self,**kwargs): self.add(**kwargs) #end def __init__ @@ -130,7 +131,7 @@ class Options(Pobj): -class Job(Pobj): +class Job(NexusCore): machine = None #default machine if none is specified in settings @@ -170,15 +171,15 @@ class Job(Pobj): name = 'jobname', directory = None, sub_dir = None, - app_name = None, + app_name = None, # name of/path to application app_flags = None, app_command = None, app_props = None, - app = None, + app = None, # name of/path to application env = None, - user_env = True, - presub = '', - postsub = '', + user_env = True, # import user environment + presub = '', # shell text executed just prior to submission + postsub = '', # shell text executed just after submission outfile = None, errfile = None, mode = None, @@ -187,9 +188,9 @@ class Job(Pobj): queue = None, bundled_jobs = None, relative = False, - cores = None, - nodes = None, - threads = 1, + cores = None, # number of cores for the job + nodes = None, # number of nodes for the job + threads = 1, # number of openmp threads for the job ppn = None, compiler = None, override = None, @@ -197,7 +198,8 @@ class Job(Pobj): app_options = None, run_options = None, sub_options = None, - serial = False, + serial = False, # run job serially, no mpi + local = False, # run job locally, no queue submission days = 0, hours = 0, minutes = 0, @@ -234,6 +236,7 @@ class Job(Pobj): self.run_options = Options() self.sub_options = Options() self.serial = serial + self.local = local self.days = days self.hours = hours self.minutes = minutes @@ -295,6 +298,11 @@ class Job(Pobj): #end if #end if + if self.serial: + self.cores = 1 + self.nodes = None + #end if + if machine!=None: self.machine = machine #end if @@ -308,6 +316,9 @@ class Job(Pobj): if not machine.batch_capable: self.error('running batched/bundled jobs on {0} is either not possible or not yet implemented, sorry.'.format(machine.name)) #end if + for job in bundled_jobs: # Paul Young's fix for jobs + machine.process_job(job) # with differing node counts + #end for #end if self.normalize_time() @@ -335,7 +346,7 @@ class Job(Pobj): #end if if self.subdir is None: if machine.local_directory!=None: - self.subdir = os.path.join(machine.local_directory,sim.runs,sim.path) + self.subdir = os.path.join(machine.local_directory,nexus_core.runs,sim.path) self.abs_subdir = self.subdir else: self.subdir = self.directory @@ -439,7 +450,7 @@ class Job(Pobj): def determine_end_status(self,status): - if not self.generate_only: + if not nexus_core.generate_only: self.successful = False # not really implemented yet #errfile = os.path.join(self.directory,self.errfile) #if os.path.exists(errfile): @@ -569,7 +580,7 @@ class Job(Pobj): -class Machine(Pobj): +class Machine(NexusCore): machines = obj() @@ -830,13 +841,11 @@ class Workstation(Machine): #end def write_job_states def query_queue(self): - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~query queue',n=1) #self.write_job_states('query queue') self.validate() done = [] - self.dlog('qq',self.processes.keys(),n=2) for pid,process in self.processes.iteritems(): - if self.generate_only or not self.monitor: + if nexus_core.generate_only or not nexus_core.monitor: qpid,status = pid,0 else: qpid,status = os.waitpid(pid,os.WNOHANG) @@ -850,7 +859,7 @@ class Workstation(Machine): self.running.remove(iid) self.finished.add(iid) done.append(pid) - if not self.generate_only: + if not nexus_core.generate_only: job.out.close() job.err.close() #end if @@ -859,14 +868,11 @@ class Workstation(Machine): for pid in done: del self.processes[pid] #end for - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~end query queue',n=1) #end def query_queue def submit_jobs(self): - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~submit jobs',n=1) - self.dlog('sj',self.waiting,n=2) cores_used = 0 for process in self.processes: cores_used += process.job.cores @@ -880,14 +886,13 @@ class Workstation(Machine): job_req.append(job) core_req.append(job.cores) #end for - core_req = array(core_req) - job_req = array(job_req) - order = core_req.argsort() - job_req = job_req[order] + core_req = array(core_req,dtype=int) + job_req = array(job_req ,dtype=object) + order = core_req.argsort() + job_req = job_req[order] - self.dlog('cores available:',cores_available,n=2) for job in job_req: - if job.cores>self.cores and not self.generate_only: + if job.cores>self.cores and not nexus_core.generate_only: self.error('job '+str(job.internal_id)+' is too large to run on this machine\n cores requested: '+str(job.cores)+'\n machine cores: '+str(self.cores)) #end if if job.cores<=cores_available: @@ -902,7 +907,6 @@ class Workstation(Machine): break #end if #end for - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~end submit jobs',n=1) #end def submit_jobs @@ -925,11 +929,11 @@ class Workstation(Machine): job.status = job.states.running process = obj() process.job = job - if self.generate_only: + if nexus_core.generate_only: self.log(pad+'Would have executed: '+command) job.system_id = job.internal_id else: - if self.monitor: + if nexus_core.monitor: self.log(pad+'Executing: '+command) job.out = open(job.outfile,'w') job.err = open(job.errfile,'w') @@ -1246,18 +1250,11 @@ class Supercomputer(Machine): def query_queue(self): - -# print -# print 'in query queue' - self.system_queue.clear() if self.queue_querier=='qstat': out,err = Popen('qstat -a',shell=True,stdout=PIPE,stderr=PIPE,close_fds=True).communicate() lines = out.splitlines() for line in lines: - -# print line - tokens=line.split() if len(tokens)>0: if '.' in tokens[0]: @@ -1327,8 +1324,6 @@ class Supercomputer(Machine): else: spid = tokens[0] #endif - #print tokens - #print '----------' if spid.isdigit() and len(tokens)==6: #if account is empty, only 6 tokens. pid = int(spid) @@ -1354,14 +1349,9 @@ class Supercomputer(Machine): else: self.error('ability to query queue with '+self.queue_querier+' has not yet been implemented') #end if - -# print -# print 'system_queue' -# print self.system_queue - done = [] for pid,process in self.processes.iteritems(): - if not pid in self.system_queue or self.system_queue[pid]=='complete' or self.generate_only: + if not pid in self.system_queue or self.system_queue[pid]=='complete' or nexus_core.generate_only: job = process.job job.status = job.states.finished job.finished = True @@ -1374,10 +1364,6 @@ class Supercomputer(Machine): for pid in done: del self.processes[pid] #end for - -# print -# print 'processes' -# print self.processes #end def query_queue @@ -1410,7 +1396,7 @@ class Supercomputer(Machine): self.error('job submission file was not written prior to submission\n submission file: '+os.path.join(job.directory,job.subfile)) #end if command = self.sub_launcher+job.sub_options.write()+' '+job.subfile - if self.generate_only: + if nexus_core.generate_only: self.log(pad+'Would have executed: '+command) job.status = job.states.running process = obj() @@ -2074,14 +2060,14 @@ class Amos(Supercomputer): job.seconds =0 #end if if job.nodesmax_partition: self.warn('!!! ATTENTION !!!\n number of nodes in {0} should not be more than {1}\n you requested: {2}'.format(job.queue,max_partition,job.nodes)) else: if job.queue != 'verylarge': partition = log(float(job.nodes)/base_partition)/log(2.) if abs(partition-int(partition))>1e-6: - self.warn('!!! ATTENTION !!!\n number of nodes on {0} must be {1} times a power of two\n you requested: {2}\n nearby valid node count: {3}'.format(self.name,self.base_partition,job.nodes,self.base_partition*2**int(round(partition)))) + self.warn('!!! ATTENTION !!!\n number of nodes on {0} must be {1} times a power of two\n you requested: {2}\n nearby valid node count: {3}'.format(self.name,base_partition,job.nodes,base_partition*2**int(round(partition)))) elif job.nodes != 3072 and job.nodes != 4096: self.warn('!!! ATTENTION !!!\n number of nodes on {0} must be 3072 or 4096 you requested {1}'.format(self.name,job.nodes)) #end if diff --git a/nexus/library/memory.py b/nexus/library/memory.py index 6d0eef705..ff3571307 100644 --- a/nexus/library/memory.py +++ b/nexus/library/memory.py @@ -16,7 +16,7 @@ # # # stacksize # # Return stack size. # -# # +# # #====================================================================# diff --git a/nexus/library/nexus.py b/nexus/library/nexus.py old mode 100644 new mode 100755 index 30e913ded..3a4578fe5 --- a/nexus/library/nexus.py +++ b/nexus/library/nexus.py @@ -5,10 +5,349 @@ #====================================================================# # nexus.py # -# The sum of all user-facing Nexus components. # +# Gathering place for user-facing Nexus functions. Management # +# of user-provided settings. # +# # +# Content summary: # +# Settings # +# Class to set 'global' Nexus data. # +# # +# settings # +# A single Settings instance users interact with as a function. # +# # +# run_project # +# User interface to the ProjectManager. # +# Runs all simulations generated by the user. # # # #====================================================================# -from project import * +import os +from generic import obj + +from nexus_base import NexusCore,nexus_core,nexus_noncore,nexus_core_noncore +from machines import Job,job,Machine,Supercomputer,get_machine +from simulation import generate_simulation,input_template,multi_input_template,generate_template_input,generate_multi_template_input +from project_manager import ProjectManager + +from structure import Structure,generate_structure,generate_cell,read_structure +from physical_system import PhysicalSystem,generate_physical_system +from pseudopotential import Pseudopotential,Pseudopotentials +from basisset import BasisSets +from bundle import bundle + +from opium import Opium , OpiumInput , OpiumAnalyzer +from sqd import Sqd , SqdInput , SqdAnalyzer , generate_sqd_input , generate_sqd, hunds_rule_filling +from pwscf import Pwscf , PwscfInput , PwscfAnalyzer , generate_pwscf_input , generate_pwscf +from gamess import Gamess , GamessInput , GamessAnalyzer , generate_gamess_input , generate_gamess, FormattedGroup +from vasp import Vasp , VaspInput , VaspAnalyzer , generate_vasp_input , generate_vasp +from qmcpack import Qmcpack, QmcpackInput, QmcpackAnalyzer, generate_qmcpack_input, generate_qmcpack + +from qmcpack_converters import Pw2qmcpack , Pw2qmcpackInput , Pw2qmcpackAnalyzer , generate_pw2qmcpack_input , generate_pw2qmcpack +from qmcpack_converters import Wfconvert , WfconvertInput , WfconvertAnalyzer , generate_wfconvert_input , generate_wfconvert +from qmcpack_converters import Convert4qmc, Convert4qmcInput, Convert4qmcAnalyzer, generate_convert4qmc_input, generate_convert4qmc +from pw2casino import Pw2casino , Pw2casinoInput , Pw2casinoAnalyzer , generate_pw2casino_input , generate_pw2casino + +from qmcpack import loop,linear,cslinear,vmc,dmc +from qmcpack import generate_jastrows,generate_jastrow,generate_jastrow1,generate_jastrow2,generate_jastrow3,generate_opt,generate_opts +from qmcpack import generate_cusp_correction + +from debug import * + + +#set the machine if known, otherwise user will provide +hostmachine = Machine.get_hostname() +if Machine.exists(hostmachine): + Job.machine = hostmachine + ProjectManager.machine = Machine.get(hostmachine) +#end if + + + +class Settings(NexusCore): + singleton = None + + machine_vars = set(''' + machine account machine_info interactive_cores + machine_mode + '''.split()) + + core_assign_vars = set(''' + status_only generate_only runs results + pseudo_dir sleep local_directory remote_directory + monitor skip_submit load_images stages + verbose debug trace + '''.split()) + + core_process_vars = set(''' + file_locations mode + '''.split()) + + noncore_assign_vars = set(''' + basis_dir + '''.split()) + + noncore_process_vars = set() + + gamess_vars = set(''' + ericfmt mcppath + '''.split()) + + 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 + allowed_vars = nexus_vars | machine_vars | gamess_vars + + + @staticmethod + def kw_set(vars,source=None): + kw = obj() + if source!=None: + for n in vars: + if n in source: + kw[n]=source[n] + del source[n] + #end if + #end for + #end if + return kw + #end def null_kw_set + + + def __init__(self): + if Settings.singleton is None: + Settings.singleton = self + else: + self.error('attempted to create a second Settings object\n please just use the original') + #end if + #end def __init__ + + + def error(self,message,header='settings',exit=True,trace=True): + NexusCore.error(self,message,header,exit,trace) + #end def error + + + # sets up Nexus core class behavior and passes information to broader class structure + def __call__(self,**kwargs): + + NexusCore.write_splash() + + self.log('Applying user settings') + + # guard against invalid settings + not_allowed = set(kwargs.keys()) - Settings.allowed_vars + if len(not_allowed)>0: + self.error('unrecognized variables provided.\nYou provided: {0}\nAllowed variables are: {1}'.format(sorted(not_allowed),sorted(Settings.allowed_vars))) + #end if + + # 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) + gamess_kw = Settings.kw_set(Settings.gamess_vars ,kwargs) + if len(kwargs)>0: + self.error('some settings keywords have not been accounted for\nleftover keywords: {0}\nthis is a developer error'.format(sorted(kwargs.keys()))) + #end if + + + # copy input settings + self.transfer_from(mach_kw.copy()) + self.transfer_from(gamess_kw.copy()) + + # 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 + nexus_core_noncore.transfer_from(nexus_core,nexus_core_noncore.keys()) + nexus_noncore.set(**nexus_core_noncore.copy()) # prevent write to core namespace + + # copy final core and noncore settings + self.transfer_from(nexus_core.copy()) + self.transfer_from(nexus_noncore.copy()) + + + # process gamess settings + Gamess.settings(**gamess_kw) + + return + #end def __call__ + + + def process_machine_settings(self,mset): + if 'machine_info' in mset: + machine_info = mset.machine_info + if isinstance(machine_info,dict) or isinstance(machine_info,obj): + for machine_name,minfo in machine_info.iteritems(): + mname = machine_name.lower() + if Machine.exists(mname): + machine = Machine.get(mname) + machine.incorporate_user_info(minfo) + else: + self.error('machine {0} is unknown\n cannot set machine_info'.format(machine_name)) + #end if + #end for + else: + self.error('machine_info must be a dict or obj\n you provided type '+machine_info.__class__.__name__) + #end if + #end if + if 'machine' in mset: + machine_name = mset.machine + if not Machine.exists(machine_name): + self.error('machine {0} is unknown'.format(machine_name)) + #end if + Job.machine = machine_name + ProjectManager.machine = Machine.get(machine_name) + if 'account' in mset: + account = mset.account + if not isinstance(account,str): + self.error('account for {0} must be a string\n you provided: {1}'.format(machine_name,account)) + #end if + ProjectManager.machine.account = account + #end if + if 'machine_mode' in mset: + machine_mode = mset.machine_mode + if machine_mode in Machine.modes: + machine_mode = Machine.modes[machine_mode] + #end if + if machine_mode==Machine.modes.interactive: + if ProjectManager.machine==None: + ProjectManager.class_error('no machine specified for interactive mode') + #end if + if not isinstance(ProjectManager.machine,Supercomputer): + self.error('interactive mode is not supported for machine type '+ProjectManager.machine.__class__.__name__) + #end if + if not 'interactive_cores' in mset: + self.error('interactive mode requested, but interactive_cores not set') + #end if + ProjectManager.machine = ProjectManager.machine.interactive_representation(mset.interactive_cores) + #end if + #end if + #end if + #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 'mode' in kw: + if kw.mode in nexus_core.modes: + nexus_core.mode = kw.mode + else: + self.error('invalid mode specified: {0}\nvalid modes are {1}'.format(kw.mode,sorted(nexus_core.modes.keys()))) + #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: + self.error('some stages provided are not primary stages.\n You provided '+str(list(forbidden))+'\n Options are '+str(list(allowed_stages))) + #end if + #end if + 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([fl]) + else: + nexus_core.file_locations.extend(list(fl)) + #end if + #end if + if not 'pseudo_dir' in kw: + nexus_core.pseudopotentials = Pseudopotentials() + else: + pseudo_dir = kw.pseudo_dir + nexus_core.file_locations.append(pseudo_dir) + if not os.path.exists(pseudo_dir): + self.error('pseudo_dir "{0}" does not exist'.format(pseudo_dir),trace=False) + #end if + files = os.listdir(pseudo_dir) + ppfiles = [] + for f in files: + pf = os.path.join(pseudo_dir,f) + if os.path.isfile(pf): + ppfiles.append(pf) + #end if + #end for + nexus_core.pseudopotentials = Pseudopotentials(ppfiles) + #end if + #end def process_core_settings + + + def process_noncore_settings(self,kw): + if not 'basis_dir' in kw: + nexus_noncore.basissets = BasisSets() + else: + basis_dir = kw.basis_dir + nexus_core.file_locations.append(basis_dir) + if not os.path.exists(basis_dir): + self.error('basis_dir "{0}" does not exist'.format(basis_dir),trace=False) + #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 +#end class Settings + + +# create settings functor for UI +settings = Settings() + + +def run_project(*args,**kwargs): + pm = ProjectManager() + pm.add_simulations(*args,**kwargs) + pm.run_project() +#end def run_project diff --git a/nexus/library/nexus_base.py b/nexus/library/nexus_base.py new file mode 100644 index 000000000..84bed071d --- /dev/null +++ b/nexus/library/nexus_base.py @@ -0,0 +1,195 @@ +################################################################## +## (c) Copyright 2015- by Jaron T. Krogel ## +################################################################## + + +#====================================================================# +# nexus_base.py # +# Provides base class functionality and access to 'global' data # +# for core Nexus classes. # +# # +# Content summary: # +# NexusCore # +# Base class for core Nexus classes. # +# Data intended to be 'global' among core classes is assigned # +# by the Settings class. # +# # +# nexus_core # +# Namespace to be accessed by core Nexus classes. # +# These are classes that inherit from NexusCore directly. # +# # +# nexus_noncore # +# Namespace to be accessed in read-only fashion by non-core # +# classes. # +# # +#====================================================================# + + +import os +import traceback +import gc as garbage_collector +from memory import resident +from generic import obj +from developer import DevBase + + +# 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() + + +modes = obj( + none = 0, + setup = 1, + send_files = 2, + submit = 3, + get_output = 4, + analyze = 5, + stages = 6, + all = 7 + ) + +garbage_collector.enable() + + +nexus_noncore.set( + basis_dir = None, + basissets = None, + ) + +# core namespace elements that can be accessed by noncore classes +nexus_core_noncore = obj( + pseudo_dir = None, # used by: Settings, VaspInput + pseudopotentials = None, # used by: Simulation, GamessInput + ) + +nexus_core.set( + status_only = False, # used by: ProjectManager + generate_only = False, # used by: Simulation,Machine + sleep = 3, # used by: ProjectManager + runs = 'runs', # used by: Simulation,Machine + results = '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 + emulate = False, # unused + **nexus_core_noncore + ) + +nexus_core_no_process = set(''' + status_only generate_only sleep + '''.split()) + + +class NexusCore(DevBase): + + # garbage collector + gc = garbage_collector + + # mutable/dynamic nexus core data + wrote_something = False # for pretty printing + working_directory = None + wrote_splash = False + + @staticmethod + def write_splash(): + return # don't do this yet + if not NexusCore.wrote_splash: + splash_text = ''' +_____________________________________________________ + _ _______ _______ + | \ /| | ____ \ |\ /| |\ /| | ____ \ + | \ | | | | \/ | \ / | | | | | | | \/ + | \ | | | |__ \ \_/ / | | | | | |_____ + | |\ \| | | __| | _ | | | | | |_____ | + | | \ | | | / / \ \ | | | | | | + | | \ | | |____/\ | / \ | | |___| | /\____| | + |/ \_| |_______/ |/ \| |_______| \_______| +_____________________________________________________ + + Main author: Jaron T. Krogel + ____________________________ + + ''' + print splash_text + NexusCore.wrote_splash = True + #end if + #end def write_splash + + @staticmethod + def write_end_splash(): + return # don't do this yet + splash_text = ''' +_____________________________________________________ +_____________________________________________________ + ''' + print splash_text + #end def write_end_splash + + def mem_usage(self): + return int(resident()/1e6) + #end def mem_usage + + def log(self,*texts,**kwargs): + if nexus_core.verbose: + if len(kwargs)>0: + n = kwargs['n'] + else: + n=0 + #end if + text='' + for t in texts: + text+=str(t)+' ' + #end for + pad = n*nexus_core.indent + self._logfile.write(pad+text.replace('\n','\n'+pad)+'\n') + #end if + NexusCore.wrote_something = True + #end def log + + def dlog(self,*texts,**kwargs): + if nexus_core.debug: + #self.log('mem_usage',self.mem_usage(),n=5) + self.log(*texts,**kwargs) + #end if + #end def dlog + + def tlog(self,*texts,**kwargs): + if nexus_core.trace: + self.log(*texts,**kwargs) + w,s,j,f,g,a=int(self.setup),int(self.submitted),int(self.job.finished),int(self.finished),int(self.got_output),int(self.analyzed) + self.log('w,s,j,f,g,a',w,s,j,f,g,a,n=kwargs['n']+1) + #self.log('dependencies',self.dependencies.keys(),n=kwargs['n']+1) + #self.log('dependents ',self.dependents.keys(),n=kwargs['n']+1) + #end if + #end def tlog + + def enter(self,directory,changedir=True,msg=''): + NexusCore.working_directory = os.getcwd() + self.log(' Entering '+directory,msg) + if changedir: + os.chdir(directory) + #end if + pad = ' ' + return pad + #end def enter + + def leave(self): + os.chdir(NexusCore.working_directory) + #end def leave +#end class NexusCore diff --git a/nexus/library/numerics.py b/nexus/library/numerics.py index 38698fced..b8fa36cfd 100644 --- a/nexus/library/numerics.py +++ b/nexus/library/numerics.py @@ -6,8 +6,8 @@ #====================================================================# # numerics.py # # A collection of useful numerical functions, currently # -# including specialized curve fitting and jack-knife statistical # -# analysis. # +# including specialized curve fitting, statistical analysis, # +# and spatial analysis. # # # # Content summary: # # morse_spect_fit # @@ -34,21 +34,73 @@ # Can be used to obtain error bars of fit parameters, # # eigenvalues, and other statistical results that depend on # # the input data in a non-linear fashion. # -# # +# # +# ndgrid # +# Function to construct an arbitrary N-dimensional grid. # +# Similar to ndgrid from MATLAB. # +# # +# simstats # +# Compute statistics of N-dimensional Monte Carlo simulation # +# data, including mean, variance, error, and autocorrelation. # +# # +# simplestats # +# Compute error assuming uncorrelated data. # +# # +# equilibration_length # +# Estimate equilibration point of Monte Carlo time series data # +# using a heuristic algorithm. # +# # +# ttest # +# Implementation of Student's T-test # +# # +# surface_normals # +# Compute vectors normal to a parametric surface. # +# # +# simple_surface # +# Create a parametric surface in Cartesian, cylindrical, or # +# spherical coordinates. # +# # +# func_fit # +# Perform a fit to an arbitrary function using an arbitrary # +# cost metric (e.g. least squares). # +# # +# distance_table # +# Calculate all N^2 pair distances for a set of N points. # +# # +# nearest_neighbors # +# Find k nearest neighbors of N points using a fast algorithm. # +# # +# voronoi_neighbors # +# Find nearest neighbors in the Voronoi sense, that is for # +# each point, find the points whose Voronoi polyhedra contact # +# the Voronoi polyhedron of that point. # +# # +# convex_hull # +# Find the convex hull of a set of points in N dimensions. # +# # #====================================================================# -import types as pytypes +import sys +import inspect from numpy import array,ndarray,zeros,linspace,pi,exp,sqrt,polyfit,polyval +from numpy import sum,abs,arange,empty,sin,cos,dot,atleast_2d,ogrid +from numpy import ones_like,sign,random,cross,prod +from numpy.linalg import norm from generic import obj from developer import unavailable,warn,error from unit_converter import convert from periodic_table import pt as ptable -from debug import * try: + from scipy.special import betainc from scipy.optimize import fmin + from scipy.spatial import KDTree,Delaunay,Voronoi + scipy_unavailable = False except ImportError: - fmin = unavailable('scipy.optimize','fmin') + betainc = unavailable('scipy.special' ,'betainc') + fmin = unavailable('scipy.optimize','fmin') + KDTree,Delaunay,Voronoi = unavailable('scipy.spatial' ,'KDTree','Delaunay','Voronoi') + scipy_unavailable = True #end try @@ -443,7 +495,7 @@ numerics_jackknife = jackknife # auxfunc is an additional function to get a jackknife sample of a derived quantity def jackknife_aux(jsamples,auxfunc,args=None,kwargs=None,position=None,capture=None): # unpack the argument list if compressed - if type(auxfunc)!=pytypes.FunctionType: + if not inspect.isfunction(auxfunc): if len(auxfunc)==1: auxfunc = auxfunc[0] elif len(auxfunc)==2: @@ -536,3 +588,635 @@ def check_jackknife_inputs(args,kwargs,position): #end if return argpos,kwargpos,args,kwargs,position #end def check_jackknife_inputs + + + + + + + + + +######################################################################## +############ ndgrid +######################################################################## + +# retrieved from +# http://www.mailinglistarchive.com/html/matplotlib-users@lists.sourceforge.net/2010-05/msg00055.html + +#""" +#n-dimensional gridding like Matlab's NDGRID +# +#Typical usage: +#>>> x, y, z = [0, 1], [2, 3, 4], [5, 6, 7, 8] +#>>> X, Y, Z = ndgrid(x, y, z) +# +#See ?ndgrid for details. +#""" + +def ndgrid(*args, **kwargs): + """ + n-dimensional gridding like Matlab's NDGRID + + The input *args are an arbitrary number of numerical sequences, + e.g. lists, arrays, or tuples. + The i-th dimension of the i-th output argument + has copies of the i-th input argument. + + Optional keyword argument: + same_dtype : If False (default), the result is an ndarray. + If True, the result is a lists of ndarrays, possibly with + different dtype. This can save space if some *args + have a smaller dtype than others. + + Typical usage: + >>> x, y, z = [0, 1], [2, 3, 4], [5, 6, 7, 8] + >>> X, Y, Z = ndgrid(x, y, z) # unpacking the returned ndarray into X, Y, Z + + Each of X, Y, Z has shape [len(v) for v in x, y, z]. + >>> X.shape == Y.shape == Z.shape == (2, 3, 4) + True + >>> X + array([[[0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0]], + [[1, 1, 1, 1], + [1, 1, 1, 1], + [1, 1, 1, 1]]]) + >>> Y + array([[[2, 2, 2, 2], + [3, 3, 3, 3], + [4, 4, 4, 4]], + [[2, 2, 2, 2], + [3, 3, 3, 3], + [4, 4, 4, 4]]]) + >>> Z + array([[[5, 6, 7, 8], + [5, 6, 7, 8], + [5, 6, 7, 8]], + [[5, 6, 7, 8], + [5, 6, 7, 8], + [5, 6, 7, 8]]]) + + With an unpacked argument list: + >>> V = [[0, 1], [2, 3, 4]] + >>> ndgrid(*V) # an array of two arrays with shape (2, 3) + array([[[0, 0, 0], + [1, 1, 1]], + [[2, 3, 4], + [2, 3, 4]]]) + + For input vectors of different data types, same_dtype=False makes ndgrid() + return a list of arrays with the respective dtype. + >>> ndgrid([0, 1], [1.0, 1.1, 1.2], same_dtype=False) + [array([[0, 0, 0], [1, 1, 1]]), + array([[ 1. , 1.1, 1.2], [ 1. , 1.1, 1.2]])] + + Default is to return a single array. + >>> ndgrid([0, 1], [1.0, 1.1, 1.2]) + array([[[ 0. , 0. , 0. ], [ 1. , 1. , 1. ]], + [[ 1. , 1.1, 1.2], [ 1. , 1.1, 1.2]]]) + """ + same_dtype = kwargs.get("same_dtype", True) + V = [array(v) for v in args] # ensure all input vectors are arrays + shape = [len(v) for v in args] # common shape of the outputs + result = [] + for i, v in enumerate(V): + # reshape v so it can broadcast to the common shape + # http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html + zero = zeros(shape, dtype=v.dtype) + thisshape = ones_like(shape) + thisshape[i] = shape[i] + result.append(zero + v.reshape(thisshape)) + if same_dtype: + return array(result) # converts to a common dtype + else: + return result # keeps separate dtype for each output + +#if __name__ == "__main__": +# import doctest +# doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE) + + +######################################################################## +############ End ndgrid +######################################################################## + + +def simstats(x,dim=None): + shape = x.shape + ndim = len(shape) + if dim==None: + dim=ndim-1 + #end if + permute = dim!=ndim-1 + reshape = ndim>2 + nblocks = shape[dim] + if permute: + r = range(ndim) + r.pop(dim) + r.append(dim) + permutation = tuple(r) + r = range(ndim) + r.pop(ndim-1) + r.insert(dim,ndim-1) + invperm = tuple(r) + x=x.transpose(permutation) + shape = tuple(array(shape)[array(permutation)]) + dim = ndim-1 + #end if + if reshape: + nvars = prod(shape[0:dim]) + x=x.reshape(nvars,nblocks) + rdim=dim + dim=1 + else: + nvars = shape[0] + #end if + + mean = x.mean(dim) + var = x.var(dim) + + N=nblocks + + if ndim==1: + i=0 + tempC=0.5 + kappa=0.0 + mtmp=mean + if abs(var)<1e-15: + kappa = 1.0 + else: + ovar=1.0/var + while (tempC>0 and i<(N-1)): + kappa=kappa+2.0*tempC + i=i+1 + #tempC=corr(i,x,mean,var) + tempC = ovar/(N-i)*sum((x[0:N-i]-mtmp)*(x[i:N]-mtmp)) + #end while + if kappa == 0.0: + kappa = 1.0 + #end if + #end if + Neff=(N+0.0)/(kappa+0.0) + if (Neff == 0.0): + Neff = 1.0 + #end if + error=sqrt(var/Neff) + else: + error = zeros(mean.shape) + kappa = zeros(mean.shape) + for v in xrange(nvars): + i=0 + tempC=0.5 + kap=0.0 + vtmp = var[v] + mtmp = mean[v] + if abs(vtmp)<1e-15: + kap = 1.0 + else: + ovar = 1.0/vtmp + while (tempC>0 and i<(N-1)): + i += 1 + kap += 2.0*tempC + tempC = ovar/(N-i)*sum((x[v,0:N-i]-mtmp)*(x[v,i:N]-mtmp)) + #end while + if kap == 0.0: + kap = 1.0 + #end if + #end if + Neff=(N+0.0)/(kap+0.0) + if (Neff == 0.0): + Neff = 1.0 + #end if + kappa[v]=kap + error[v]=sqrt(vtmp/Neff) + #end for + #end if + + if reshape: + x = x.reshape(shape) + mean = mean.reshape(shape[0:rdim]) + var = var.reshape(shape[0:rdim]) + error = error.reshape(shape[0:rdim]) + kappa = kappa.reshape(shape[0:rdim]) + #end if + if permute: + x=x.transpose(invperm) + #end if + + return (mean,var,error,kappa) +#end def simstats + + + +def simplestats(x,dim=None): + if dim==None: + dim=len(x.shape)-1 + #end if + osqrtN = 1.0/sqrt(1.0*x.shape[dim]) + mean = x.mean(dim) + error = x.var(dim)*osqrtN + return (mean,error) +#end def simplestats + + +def equilibration_length(x,tail=.5,plot=False,xlim=None,bounces=2): + bounces = max(1,bounces) + eqlen = 0 + nx = len(x) + xt = x[int((1.-tail)*nx+.5):] + nxt = len(xt) + if nxt<10: + return eqlen + #end if + #mean = xh.mean() + #sigma = sqrt(xh.var()) + xs = array(xt) + xs.sort() + mean = xs[int(.5*(nxt-1)+.5)] + sigma = (abs(xs[int((.5-.341)*nxt+.5)]-mean)+abs(xs[int((.5+.341)*nxt+.5)]-mean))/2 + crossings = bounces*[0,0] + if abs(x[0]-mean)>sigma: + s = -sign(x[0]-mean) + ncrossings = 0 + for i in range(nx): + dist = s*(x[i]-mean) + if dist>sigma and dist<5*sigma: + crossings[ncrossings]=i + s*=-1 + ncrossings+=1 + if ncrossings==2*bounces: + break + #end if + #end if + #end for + bounce = crossings[-2:] + bounce[1] = max(bounce[1],bounce[0]) + #print len(x),crossings,crossings[1]-crossings[0]+1 + eqlen = bounce[0]+random.randint(bounce[1]-bounce[0]+1) + #end if + if plot: + xlims = xlim + del plot,xlim + from matplotlib.pyplot import plot,figure,show,xlim + figure() + ix = arange(nx) + plot(ix,x,'b.-') + plot([0,nx],[mean,mean],'k-') + plot([0,nx],[mean+sigma,mean+sigma],'r-') + plot([0,nx],[mean-sigma,mean-sigma],'r-') + plot(ix[crossings],x[crossings],'r.') + plot(ix[bounce],x[bounce],'ro') + plot([ix[eqlen],ix[eqlen]],[x.min(),x.max()],'g-') + plot(ix[eqlen],x[eqlen],'go') + if xlims!=None: + xlim(xlims) + #end if + show() + #end if + return eqlen +#end def equilibration_length + + +def ttest(m1,e1,n1,m2,e2,n2): + m1 = float(m1) + e1 = float(e1) + m2 = float(m2) + e2 = float(e2) + v1 = e1**2 + v2 = e2**2 + t = (m1-m2)/sqrt(v1+v2) + nu = (v1+v2)**2/(v1**2/(n1-1)+v2**2/(n2-1)) + x = nu/(nu+t**2) + p = 1.-betainc(nu/2,.5,x) + return p +#end def ttest + + + +def surface_normals(x,y,z): + nu,nv = x.shape + normals = empty((nu,nv,3)) + mi=nu-1 + mj=nv-1 + v1 = empty((3,)) + v2 = empty((3,)) + v3 = empty((3,)) + dr = empty((3,)) + dr[0] = x[0,0]-x[1,0] + dr[1] = y[0,0]-y[1,0] + dr[2] = z[0,0]-z[1,0] + drtol = 1e-4 + for i in xrange(nu): + for j in xrange(nv): + iedge = i==0 or i==mi + jedge = j==0 or j==mj + if iedge: + dr[0] = x[0,j]-x[mi,j] + dr[1] = y[0,j]-y[mi,j] + dr[2] = z[0,j]-z[mi,j] + if norm(dr)1.00000000001: + print 'Error in simple surface: '+k+' cannot be more than 1' + print ' actual maximum: '+str(max(v)) + sys.exit() + #end if + #end if + u=empty((3,)) + r=empty((3,)) + if coord==0: + xl = grid['x'] + yl = grid['y'] + zl = grid['z'] + dim = (len(xl),len(yl),len(zl)) + npoints = prod(dim) + points = empty((npoints,3)) + n=0 + for i in xrange(dim[0]): + for j in xrange(dim[1]): + for k in xrange(dim[2]): + r[0] = xl[i] + r[1] = yl[j] + r[2] = zl[k] + points[n,:] = dot(axes,r) + origin + n+=1 + #end for + #end for + #end for + elif coord==1: + rl = grid['r'] + phil = 2.*pi*grid['phi'] + zl = grid['z'] + dim = (len(rl),len(phil),len(zl)) + npoints = prod(dim) + points = empty((npoints,3)) + n=0 + for i in xrange(dim[0]): + for j in xrange(dim[1]): + for k in xrange(dim[2]): + u[0] = rl[i] + u[1] = phil[j] + u[2] = zl[k] + r[0] = u[0]*cos(u[1]) + r[1] = u[0]*sin(u[1]) + r[2] = u[2] + points[n,:] = dot(axes,r) + origin + n+=1 + #end for + #end for + #end for + elif coord==2: + rl = grid['r'] + phil = 2.*pi*grid['phi'] + thetal = pi*grid['theta'] + dim = (len(rl),len(phil),len(thetal)) + if dim[0]==1: + sgn = -1. #this is to 'fix' surface normals + #sgn = 1. #this is to 'fix' surface normals + else: + sgn = 1. + #end if + npoints = prod(dim) + points = empty((npoints,3)) + n=0 + for i in xrange(dim[0]): + for j in xrange(dim[1]): + for k in xrange(dim[2]): + u[0] = rl[i] + u[1] = phil[j] + u[2] = thetal[k] + r[0] = sgn*u[0]*sin(u[2])*cos(u[1]) + r[1] = sgn*u[0]*sin(u[2])*sin(u[1]) + r[2] = sgn*u[0]*cos(u[2]) + points[n,:] = dot(axes,r) + origin + n+=1 + #end for + #end for + #end for + #end if + + if min(dim)!=1: + print 'Error in simple_surface: minimum dimension must be 1' + print ' actual minimum dimension:',str(min(dim)) + sys.exit() + #end if + + dm = [] + for d in dim: + if d>1: + dm.append(d) + #end if + #end for + dm=tuple(dm) + + x = points[:,0].reshape(dm) + y = points[:,1].reshape(dm) + z = points[:,2].reshape(dm) + + return x,y,z +#end def simple_surface + + + +#least_squares = lambda p,x,y,f: ((f(p,x)-y)**2).sum() + +def func_fit(x,y,fitting_function,p0,minimizer=least_squares): + f = fitting_function + p = fmin(minimizer,p0,args=(x,y,f),maxiter=10000,maxfun=10000) + return p +#end def func_fit + + +def distance_table(p1,p2,ordering=0): + n1 = len(p1) + n2 = len(p2) + if not isinstance(p1,ndarray): + p1=array(p1) + #end if + if not isinstance(p2,ndarray): + p2=array(p2) + #end if + dt = zeros((n1,n2)) + for i1 in xrange(n1): + for i2 in xrange(n2): + dt[i1,i2] = norm(p1[i1]-p2[i2]) + #end for + #end for + if ordering==0: + return dt + else: + if ordering==1: + n=n1 + elif ordering==2: + n=n2 + dt=dt.T + else: + print 'distance_table Error: ordering must be 1 or 2,\n you provided '+str(ordering)+'\nexiting.' + exit() + #end if + order = empty(dt.shape,dtype=int) + for i in xrange(n): + o = dt[i].argsort() + order[i] = o + dt[i,:] = dt[i,o] + #end for + return dt,order + #end if +#end def distance_table + + + +def nearest_neighbors(n,points,qpoints=None,return_distances=False,slow=False): + extra = 0 + if qpoints==None: + qpoints=points + if len(points)>1: + extra=1 + elif return_distances: + return array([]),array([]) + else: + return array([]) + #end if + #end if + if n>len(qpoints)-extra: + print 'nearest_neighbors Error: requested more than the total number of neighbors\n maximum is: {0}\n you requested: {1}\nexiting.'.format(len(qpoints)-extra,n) + exit() + #end if + slow = slow or scipy_unavailable + if not slow: + kt = KDTree(points) + dist,ind = kt.query(qpoints,n+extra) + else: + dtable,order = distance_table(points,qpoints,ordering=2) + dist = dtable[:,0:n+extra] + ind = order[:,0:n+extra] + #end if + if extra==0 and n==1 and not slow: + nn = atleast_2d(ind).T + else: + nn = ind[:,extra:] + #end if + if not return_distances: + return nn + else: + return nn,dist + #end if +#end def nearest_neighbors + + +def voronoi_neighbors(points): + vor = Voronoi(points) + neighbor_pairs = vor.ridge_points + return neighbor_pairs +#end def voronoi_neighbors + + +def convex_hull(points,dimension=None,tol=None): + if dimension is None: + np,dimension = points.shape + #end if + d1 = dimension+1 + tri = Delaunay(points) + all_inds = empty((d1,),dtype=bool) + all_inds[:] = True + verts = [] + have_tol = tol!=None + for ni in range(len(tri.neighbors)): + n = tri.neighbors[ni] + ns = list(n) + if -1 in ns: + i = ns.index(-1) + inds = all_inds.copy() + inds[i] = False + v = tri.vertices[ni] + if have_tol: + iv = range(d1) + iv.pop(i) + c = points[v[iv[1]]] + a = points[v[i]]-c + b = points[v[iv[0]]]-c + bn = norm(b) + d = norm(a-dot(a,b)/(bn*bn)*b) + if d1 and name[1:].isdigit(): s = name[0:1] - iselem = s in periodic_table.elements elif nlen>2 and name[2:].isdigit(): s = name[0:2] - iselem = s in periodic_table.elements #end if + if len(s)==1: + s = s.upper() + elif len(s)==2: + s = s[0].upper()+s[1].lower() + #end if + iselem = s in periodic_table.elements #end if #end if if symbol: diff --git a/nexus/library/plotter.py b/nexus/library/plotter.py deleted file mode 100644 index 00e3a988c..000000000 --- a/nexus/library/plotter.py +++ /dev/null @@ -1,88 +0,0 @@ -################################################################## -## (c) Copyright 2015- by Jaron T. Krogel ## -################################################################## - - -#====================================================================# -# plotter.py # -# Interface with mayavi to plot isosurfaces and surfaces slices # -# of volume data. Used in the past to visualize energy densities.# -# See qmcpack_quantity_analyzers.py and spacegrid.py. # -# # -# Content summary: # -# Plotter # -# Wrapper class for mayavi visualization. # -# # -#====================================================================# - - -from abilities import AllAbilities - -import numpy as np - -class Plotter(AllAbilities): - def __init__(self): - self.initialized = False - return - #end def __init__ - - def ensure_init(self): - if not self.initialized: - from enthought.mayavi import mlab - from enthought.tvtk.api import tvtk - self.mlab = mlab - self.tvtk = tvtk - - self.show = mlab.show - self.plot3d = mlab.plot3d - self.mesh = mlab.mesh - - self.initialized = True - #end if - #end def ensure_init - - def isosurface(self,points,scalars,contours,dimensions,name='val'): - self.ensure_init() - mlab = self.mlab - tvtk = self.tvtk - sg=tvtk.StructuredGrid(dimensions=dimensions,points=points) - sg.point_data.scalars = scalars - sg.point_data.scalars.name = name - d = mlab.pipeline.add_dataset(sg) - iso = mlab.pipeline.iso_surface(d) - if isinstance(contours,int): - iso.contour.number_of_contours = contours - elif isinstance(contours,list): - iso.contour.auto_contours = False - iso.contour.contours = contours - else: - self.error('isosurface contours must be an int or list\n a '+str(type(contours))+' was provided instead') - #end if - return - #end def isosurface - - def surface_slice(self,x,y,z,scalars,options=None): - scale = 1.0 - opacity= 1.0 - if options!=None: - if 'norm_height' in options: - scale = options.norm_height/abs(scalars.max()) - if 'scale' in options: - scale = options.scale - if 'opacity' in options: - opacity = options.opacity - #end if - self.ensure_init() - from extended_numpy import surface_normals - self.mesh(x,y,z,opacity=.2) - surfnorm = scale*surface_normals(x,y,z) - xs=x.copy() - ys=y.copy() - zs=z.copy() - xs[...] = x[...] + surfnorm[...,0]*scalars[...] - ys[...] = y[...] + surfnorm[...,1]*scalars[...] - zs[...] = z[...] + surfnorm[...,2]*scalars[...] - self.mesh(xs,ys,zs,scalars=scalars,opacity=opacity) - return - #end def surface_slice -#end class Plotter diff --git a/nexus/library/project.py b/nexus/library/project.py deleted file mode 100755 index c6efb9016..000000000 --- a/nexus/library/project.py +++ /dev/null @@ -1,271 +0,0 @@ -################################################################## -## (c) Copyright 2015- by Jaron T. Krogel ## -################################################################## - - -#====================================================================# -# project.py # -# Gathering place for user-facing Nexus functions. Management # -# of user-provided settings. # -# # -# Content summary: # -# Settings # -# Class to set 'global' Nexus data. # -# # -# settings # -# A single Settings instance users interact with as a function. # -# # -# run_project # -# User interface to the ProjectManager. # -# Runs all simulations generated by the user. # -# # -#====================================================================# - - -import os - -from generic import obj -from project_base import Pobj,modes - -from project_manager import ProjectManager -from machines import Job,job,Machine,Supercomputer,get_machine - -from structure import Structure,generate_structure,generate_cell,read_structure -from physical_system import PhysicalSystem,generate_physical_system -from pseudopotential import Pseudopotential,Pseudopotentials -from simulation import generate_simulation,input_template,multi_input_template,generate_template_input,generate_multi_template_input -from bundle import bundle -from opium import Opium , OpiumInput , OpiumAnalyzer -from sqd import Sqd , SqdInput , SqdAnalyzer , generate_sqd_input , generate_sqd, hunds_rule_filling -from pwscf import Pwscf , PwscfInput , PwscfAnalyzer , generate_pwscf_input , generate_pwscf -from pw2casino import Pw2casino , Pw2casinoInput , Pw2casinoAnalyzer , generate_pw2casino_input , generate_pw2casino -from pw2qmcpack import Pw2qmcpack , Pw2qmcpackInput , Pw2qmcpackAnalyzer , generate_pw2qmcpack_input , generate_pw2qmcpack -from wfconvert import Wfconvert , WfconvertInput , WfconvertAnalyzer , generate_wfconvert_input , generate_wfconvert -from gamess import Gamess , GamessInput , GamessAnalyzer , generate_gamess_input , generate_gamess, FormattedGroup -from convert4qmc import Convert4qmc, Convert4qmcInput, Convert4qmcAnalyzer, generate_convert4qmc_input, generate_convert4qmc -from qmcpack import Qmcpack , QmcpackInput , QmcpackAnalyzer , generate_qmcpack_input , generate_qmcpack -from vasp import Vasp , VaspInput , VaspAnalyzer , generate_vasp_input , generate_vasp -from qmcpack import loop,linear,cslinear,vmc,dmc -from qmcpack import generate_jastrows,generate_jastrow,generate_jastrow1,generate_jastrow2,generate_jastrow3,generate_opt,generate_opts -from qmcpack import generate_cusp_correction -from auxiliary import * -from debug import * - - -#set the machine if known, otherwise user will provide -hostmachine = Machine.get_hostname() -if Machine.exists(hostmachine): - Job.machine = hostmachine - ProjectManager.machine = Machine.get(hostmachine) -#end if - - - -class Settings(Pobj): - singleton = None - - project_vars = set([ - 'machine','account','generate_only','verbose','debug','mode', - 'local_directory','remote_directory','runs','results','sleep', - 'file_locations','load_images','trace','machine_mode','stages', - 'pseudo_dir','skip_submit','interactive_cores','monitor', - 'status_only','machine_info', - ]) - - gamess_vars = set('ericfmt mcppath'.split()) - - all_vars = project_vars | gamess_vars - - @staticmethod - def kw_set(vars,source=None): - kw = obj() - if source!=None: - for n in vars: - if n in source: - kw[n]=source[n] - del source[n] - #end if - #end for - #end if - return kw - #end def null_kw_set - - - def __init__(self): - if Settings.singleton is None: - Settings.singleton = self - else: - self.error('attempted to create a second Settings object\n please just use the original') - #end if - #end def __init__ - - - def error(self,message,header='settings',exit=True,trace=True): - Pobj.error(self,message,header,exit,trace) - #end def error - - - def __call__(self,**kwargs): - - # guard against invalid settings - not_allowed = set(kwargs.keys()) - self.all_vars - if len(not_allowed)>0: - self.error('unrecognized variables provided.\n You provided: '+str(list(not_allowed))+'\n Allowed variables are: '+str(list(vars))) - #end if - - # extract settings based on keyword groups - kw = Settings.kw_set(self.project_vars,kwargs) # project settings - gamess_kw = Settings.kw_set(self.gamess_vars,kwargs) # gamess settings - if len(kwargs)>0: - self.error('some settings keywords have not been accounted for\nleftover keywords: {0}\nthis is a developer error'.format(sorted(kwargs.keys()))) - #end if - - # transfer project variables to project base class - for name,value in kw.iteritems(): - Pobj.__dict__[name] = value - #end for - - # process project manager settings - if 'debug' in kw and kw.debug: - Pobj.verbose = True - #end if - if 'mode' in kw: - Pobj.set_mode(kw.mode) - #end if - - # process machine settings - if 'machine_info' in kw: - machine_info = Pobj.machine_info - del Pobj.machine_info - if isinstance(machine_info,dict) or isinstance(machine_info,obj): - for machine_name,minfo in machine_info.iteritems(): - mname = machine_name.lower() - if Machine.exists(mname): - machine = Machine.get(mname) - machine.incorporate_user_info(minfo) - else: - self.error('machine {0} is unknown\n cannot set machine_info'.format(machine_name)) - #end if - #end for - else: - self.error('machine_info must be a dict or obj\n you provided type '+machine_info.__class__.__name__) - #end if - #end if - if 'machine' in kw: - machine_name = kw.machine - if not Machine.exists(machine_name): - Pobj.class_error('machine {0} is unknown'.format(machine_name)) - #end if - Job.machine = machine_name - ProjectManager.machine = Machine.get(machine_name) - #del Pobj.machine - if 'account' in kw: - account = Pobj.account - #del Pobj.account - if not isinstance(account,str): - self.error('account for {0} must be a string\n you provided: {1}'.format(machine_name,account)) - #end if - ProjectManager.machine.account = account - #end if - if 'machine_mode' in kw: - machine_mode = kw.machine_mode - if machine_mode in Machine.modes: - machine_mode = Machine.modes[machine_mode] - #end if - if machine_mode==Machine.modes.interactive: - if ProjectManager.machine==None: - ProjectManager.class_error('no machine specified for interactive mode') - #end if - if not isinstance(ProjectManager.machine,Supercomputer): - self.error('interactive mode is not supported for machine type '+ProjectManager.machine.__class__.__name__) - #end if - if not 'interactive_cores' in kw: - self.error('interactive mode requested, but interactive_cores not set') - #end if - ProjectManager.machine = ProjectManager.machine.interactive_representation(Pobj.interactive_cores) - del Pobj.interactive_cores - #end if - del Pobj.machine_mode - #end if - #end if - - # process simulation settings - if 'local_directory' in kw: - Pobj.file_locations.append(kw.local_directory) - #end if - if 'skip_submit' in kw: - Pobj.skip_submission = Pobj.skip_submit - del Pobj.skip_submit - #end if - if 'file_locations' in kw: - fl = kw.file_locations - if isinstance(fl,str): - Pobj.file_locations.extend([fl]) - else: - Pobj.file_locations.extend(list(fl)) - #end if - #end if - if not 'pseudo_dir' in kw: - Pobj.pseudopotentials = Pseudopotentials() - else: - pseudo_dir = kw.pseudo_dir - Pobj.file_locations.append(pseudo_dir) - if not os.path.exists(pseudo_dir): - self.error('pseudo_dir "{0}" does not exist'.format(pseudo_dir),trace=False) - #end if - files = os.listdir(pseudo_dir) - ppfiles = [] - for f in files: - pf = os.path.join(pseudo_dir,f) - if os.path.isfile(pf): - ppfiles.append(pf) - #end if - #end for - Pobj.pseudopotentials = Pseudopotentials(ppfiles) - #end if - - # more simulation/project manager settings processing - mode = Pobj.mode - modes = Pobj.modes - if mode==modes.stages: - stages = Pobj.stages - elif mode==modes.all: - stages = list(Pobj.primary_modes) - else: - stages = [kw.mode] - #end if - allowed_stages = set(Pobj.primary_modes) - if isinstance(stages,str): - stages = [stages] - #end if - if len(stages)==0: - stages = list(Pobj.primary_modes) - #self.error('variable stages must be a list of primary modes.\n Options are '+str(list(allowed_stages))) - elif 'all' in stages: - stages = list(Pobj.primary_modes) - else: - forbidden = set(Pobj.stages)-allowed_stages - if len(forbidden)>0: - self.error('some stages provided are not primary stages.\n You provided '+str(list(forbidden))+'\n Options are '+str(list(allowed_stages))) - #end if - #end if - Pobj.mode = modes.stages - Pobj.stages = stages - Pobj.stages_set = set(Pobj.stages) - - # process gamess settings - Gamess.settings(**gamess_kw) - - return - #end def __call__ -#end class Settings - - -settings = Settings() - - -def run_project(*args,**kwargs): - pm = ProjectManager() - pm.add_simulations(*args,**kwargs) - pm.run_project() -#end def run_project diff --git a/nexus/library/project_base.py b/nexus/library/project_base.py deleted file mode 100644 index d84a81e28..000000000 --- a/nexus/library/project_base.py +++ /dev/null @@ -1,161 +0,0 @@ -################################################################## -## (c) Copyright 2015- by Jaron T. Krogel ## -################################################################## - - -#====================================================================# -# project_base.py # -# Provides base class functionality and access to 'global' data # -# for core Nexus classes. # -# # -# Content summary: # -# Pobj # -# Base class for core Nexus classes. # -# 'Global' data is assigned by the Settings class. # -# # -#====================================================================# - - -import os -import traceback -import gc as garbage_collector -from memory import resident -from generic import obj -from developer import DevBase - -modes = obj( - none = 0, - setup = 1, - send_files = 2, - submit = 3, - get_output = 4, - analyze = 5, - stages = 6, - all = 7 - ) - - -class Pobj(DevBase): - gc = garbage_collector - gc.enable() - mode = modes.stages - generate_only = False - status_only = False - monitor = True - skip_submission = False - emulate = False #override application and use application_emulator - verbose = True - debug = False - trace = False - load_images = True - - sleep = 3 - local_directory = './' - remote_directory = local_directory - file_locations = [local_directory] - runs = 'runs' - results = 'results' - #pseudo_dir = os.path.join(local_directory,'pseudopotentials') - pseudo_dir = None - pseudopotentials = None - - modes = modes - - primary_modes = ['setup','send_files','submit','get_output','analyze'] - dependent_modes = set(['submit']) - stages = [] - stages_set = set(stages) - - - wrote_something = False # for pretty printing - - @staticmethod - def set_mode(mode): - if mode in Pobj.modes: - Pobj.mode = Pobj.modes[mode] - else: - print 'settings Error: invalid mode specified: '+mode+'\n valid modes are '+str(Pobj.modes.keys()) - #end if - #end def set_mode - - def mem_usage(self): - return int(resident()/1e6) - #end def mem_usage - - indent = ' ' - def log(self,*texts,**kwargs): - if self.verbose: - if len(kwargs)>0: - n = kwargs['n'] - else: - n=0 - #end if - text='' - for t in texts: - text+=str(t)+' ' - #end for - pad = n*self.indent - self.logfile.write(pad+text.replace('\n','\n'+pad)+'\n') - #end if - Pobj.wrote_something = True - #end def log - - #@classmethod - #def class_error(cls,msg,source=None,n=0,trace=True): - # if source==None: - # source = cls.__name__ - # #end if - # pad = n*cls.indent - # text=pad+source+' Error: '+msg - # text = '\n'+text.replace('\n','\n'+pad)+'\n\n' - # cls.logfile.write(text) - # if trace: - # traceback.print_stack() - # #end if - # exit() - ##end def class_error - # - #@classmethod - #def class_warn(cls,msg,source=None,n=0): - # if source==None: - # source = cls.__name__ - # #end if - # pad = n*cls.indent - # text=pad+source+' Warning: '+msg - # cls.logfile.write(text.replace('\n','\n'+pad)+'\n') - ##end def class_warn - - def dlog(self,*texts,**kwargs): - if self.debug: - #self.log('mem_usage',self.mem_usage(),n=5) - self.log(*texts,**kwargs) - #end if - #end def dlog - - def tlog(self,*texts,**kwargs): - if self.trace: - self.log(*texts,**kwargs) - w,s,j,f,g,a=int(self.setup),int(self.submitted),int(self.job.finished),int(self.finished),int(self.got_output),int(self.analyzed) - self.log('w,s,j,f,g,a',w,s,j,f,g,a,n=kwargs['n']+1) - #self.log('dependencies',self.dependencies.keys(),n=kwargs['n']+1) - #self.log('dependents ',self.dependents.keys(),n=kwargs['n']+1) - #end if - #end def tlog - - working_directory = None - def enter(self,directory,changedir=True,msg=''): - self.working_directory = os.getcwd() - self.log(' Entering '+directory,msg) - if changedir: - os.chdir(directory) - #end if - pad = ' ' - return pad - #end def enter - - def leave(self): - os.chdir(self.working_directory) - #end def leave -#end class Pobj - - diff --git a/nexus/library/project_manager.py b/nexus/library/project_manager.py index b25e81907..fc8ee2db2 100644 --- a/nexus/library/project_manager.py +++ b/nexus/library/project_manager.py @@ -20,7 +20,7 @@ import os import time import memory from generic import obj -from project_base import Pobj +from nexus_base import NexusCore,nexus_core from simulation import Simulation @@ -29,10 +29,9 @@ def trivial(sim,*args,**kwargs): #end def trivial -class ProjectManager(Pobj): +class ProjectManager(NexusCore): def __init__(self): - #variables determined by self - modes = self.modes + modes = nexus_core.modes self.persistent_modes = set([modes.submit,modes.all]) self.simulations = obj() self.cascades = obj() @@ -63,7 +62,7 @@ class ProjectManager(Pobj): self.resolve_file_collisions() self.propagate_blockages() self.log('loading cascade images',n=1) - if self.load_images: + if nexus_core.load_images: self.load_cascades() else: self.log('cascades',n=1) @@ -80,32 +79,29 @@ class ProjectManager(Pobj): def run_project(self,status=False,status_only=False): self.log('\nProject starting',n=0) self.init_cascades() - status_only = status_only or self.status_only + status_only = status_only or nexus_core.status_only status = status or status_only if status: self.write_simulation_status() if status_only: + NexusCore.write_end_splash() return #end if #end if self.log('\nstarting runs:\n'+30*'~',n=1) - if self.dependent_modes <= self.stages_set: - if self.monitor: + if nexus_core.dependent_modes <= nexus_core.stages_set: + if nexus_core.monitor: ipoll = 0 while len(self.progressing_cascades)>0: - self.dlog('\n\n\n'+70*'=',n=1) self.log('poll',ipoll,' memory %3.2f MB'%(memory.resident()/1e6),n=1) - Pobj.wrote_something = False - self.dlog('cascades',self.progressing_cascades.keys(),n=2) + NexusCore.wrote_something = False ipoll+=1 self.machine.query_queue() self.progress_cascades() self.machine.submit_jobs() self.update_process_ids() - self.dlog('sleeping',self.sleep,n=2) - time.sleep(self.sleep) - self.dlog('awake',n=2) - if Pobj.wrote_something: + time.sleep(nexus_core.sleep) + if NexusCore.wrote_something: self.log() #end if #end while @@ -119,23 +115,20 @@ class ProjectManager(Pobj): self.progress_cascades() #end if self.log('Project finished\n') + NexusCore.write_end_splash() #end def run_project def load_cascades(self): - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~load cascades',n=1) cascades = obj() progressing_cascades = obj() for cid,cascade in self.cascades.iteritems(): - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~reconstruct cascade',n=1) rc = cascade.reconstruct_cascade() - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~end reconstruct cascade',n=1) cascades[rc.simid] = rc progressing_cascades[rc.simid] = rc #end for self.cascades = cascades self.progressing_cascades = progressing_cascades - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~end load cascades',n=1) #end def load_cascades @@ -204,7 +197,7 @@ class ProjectManager(Pobj): def write_simulation_status(self): - self.log('cascade status',n=1) + self.log('\ncascade status',n=1) self.log('setup, sent_files, submitted, finished, got_output, analyzed',n=2) indicators = ('setup','sent_files','submitted','finished','got_output','analyzed') for isim in self.simulations.keys(): @@ -214,14 +207,14 @@ class ProjectManager(Pobj): for stat in stats: status+=str(int(stat)) #end for - self.log('{0} {1} {2}'.format(status,sim.identifier,sim.locdir),n=2) + self.log('{0} {1:<6} {2}'.format(status,sim.identifier,sim.locdir),n=2) #end for self.log('setup, sent_files, submitted, finished, got_output, analyzed',n=2) #end def write_simulation_status def write_cascade_status(self): - self.log('cascade status',n=1) + self.log('\ncascade status',n=1) self.log('setup, sent_files, submitted, finished, got_output, analyzed',n=2) def write_status(sim): @@ -319,31 +312,22 @@ class ProjectManager(Pobj): #end def check_dependencies def progress_cascades(self): - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~progress cascades',n=1) - self.gc.collect() + NexusCore.gc.collect() finished = [] progressing_cascades = self.progressing_cascades - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~reset wait ids',n=1) for cid,cascade in progressing_cascades.iteritems(): cascade.reset_wait_ids() #end for - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~end reset wait ids',n=1) for cid,cascade in progressing_cascades.iteritems(): - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~progress',n=1) cascade.progress() - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~end progress',n=1) - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~check subcascade',n=1) cascade.check_subcascade() - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~end check subcascade',n=1) if cascade.subcascade_finished: finished.append(cid) #end if #end for for cid in finished: - self.dlog('removing cascade:',cid,n=1) del progressing_cascades[cid] #end for - self.dlog('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~end progress cascades',n=1) #end def progress_cascades diff --git a/nexus/library/pseudopotential.py b/nexus/library/pseudopotential.py index cfd805d9f..067be7b29 100644 --- a/nexus/library/pseudopotential.py +++ b/nexus/library/pseudopotential.py @@ -43,22 +43,16 @@ import os from subprocess import Popen from execute import execute from numpy import linspace,array,zeros,append,mgrid,empty,exp,minimum,maximum,sqrt,arange +from fileio import TextFile from xmlreader import readxml from superstring import string2val,split_delims from periodic_table import pt,is_element from unit_converter import convert from generic import obj from developer import DevBase,unavailable,error +from basisset import process_gaussian_text,GaussianBasisSet +from plotting import * from debug import * -try: - from matplotlib.pyplot import figure,plot,xlabel,ylabel,title,show,ylim,legend,xlim,rcParams,savefig,bar,xticks,subplot,grid,setp,errorbar,loglog,semilogx,semilogy - - params = {'legend.fontsize':14,'figure.facecolor':'white','figure.subplot.hspace':0., - 'axes.labelsize':16,'xtick.labelsize':14,'ytick.labelsize':14} - rcParams.update(params) -except (ImportError,RuntimeError): - figure,plot,xlabel,ylabel,title,show,ylim,legend,xlim,rcParams,savefig,bar,xticks,subplot,grid,setp,errorbar,loglog,semilogx,semilogy = unavailable('matplotlib.pyplot','figure','plot','xlabel','ylabel','title','show','ylim','legend','xlim','rcParams','savefig','bar','xticks','subplot','grid','setp','errorbar','loglog','semilogx','semilogy') -#end try try: from scipy.optimize import curve_fit except: @@ -81,7 +75,7 @@ class PseudoFile(DevBase): elem_label = self.filename.split('.')[0] is_elem,symbol = is_element(elem_label,symbol=True) if not is_elem: - self.error('cannot determine element for pseudopotential file: {0}\npseudopotential file names must be prefixed by an atomic symbol or label\n(e.g. Si, Si1, etc)'.format(filename)) + self.error('cannot determine element for pseudopotential file: {0}\npseudopotential file names must be prefixed by an atomic symbol or label\n(e.g. Si, Si1, etc)'.format(filepath)) #end if self.element = symbol self.element_label = elem_label @@ -159,7 +153,6 @@ class Pseudopotentials(DevBase): ppfiles = [] pps = [] errors = False - print for pp in pseudopotentials: if isinstance(pp,PseudoFile): pps.append(pp) @@ -173,7 +166,6 @@ class Pseudopotentials(DevBase): if errors: self.error('cannot create Pseudopotentials object') #end if - if len(pps)>0: self.addpp(pps) #end if @@ -198,6 +190,7 @@ class Pseudopotentials(DevBase): ppfiles = ppfiles[0] #end if pps = [] + print print ' Pseudopotentials' for filepath in ppfiles: print ' reading pp: ',filepath @@ -209,6 +202,7 @@ class Pseudopotentials(DevBase): #end if pps.append(pp) #end for + print self.addpp(pps) #end def readpp @@ -219,6 +213,8 @@ class Pseudopotentials(DevBase): if ppfile in self: pp = self[ppfile] pps[pp.element_label] = pp + else: + self.error('pseudopotential file not found\nmissing file: {0}'.format(ppfile)) #end if #end for return pps @@ -281,7 +277,7 @@ class Pseudopotential(DevBase): #end if self.element = split_delims(os.path.split(filepath)[1])[0] text = open(filepath,'r').read() - self.read_text(text,format) + self.read_text(text,format,filepath=filepath) #end def read @@ -301,7 +297,7 @@ class Pseudopotential(DevBase): #end def write - def read_text(self,text,format=None): + def read_text(self,text,format=None,filepath=None): self.not_implemented() #end def read_text @@ -321,7 +317,7 @@ class Pseudopotential(DevBase): class SemilocalPP(Pseudopotential): - l_channels = tuple('spdfgh') + l_channels = tuple('spdfghi') all_channels = ['loc']+list(l_channels) channel_colors = obj(s='g',p='r',d='b',f='m',g='c',h='k') @@ -396,7 +392,7 @@ class SemilocalPP(Pseudopotential): def l_int_from_text(self,ltext): - lint = 'spdfgh'.find(ltext) + lint = 'spdfghi'.find(ltext) return lint #end def l_int_from_text @@ -647,9 +643,9 @@ class SemilocalPP(Pseudopotential): symbol = self.element atomic_number = self.Zcore+self.Zval zval = self.Zval - creator = 'nexus' + creator = 'Nexus' npots_down = len(self.channels) - l_local = 'spdfg'.find(self.local) + l_local = 'spdfgi'.find(self.local) rmin = 1e99 rmax = -1e99 @@ -704,6 +700,67 @@ class SemilocalPP(Pseudopotential): #end if return text #end def write_qmcpack + + + def write_casino(self,filepath=None): + name = self.name + symbol = self.element + atomic_number = self.Zcore+self.Zval + zval = float(self.Zval) + l_local = 'spdfgi'.find(self.local) + + if name is None: + name = '{0} pseudopotential converted by Nexus'.format(symbol) + #end if + + rmin = 1e99 + rmax = -1e99 + npts = 0 + vps = obj() + for l in self.channels.keys(): + r,v = self.numeric_channel(l,rpow=1,with_local=True) + rmin = min(rmin,r.min()) + rmax = max(rmax,r.max()) + npts = len(r) + vps[l] = v + #end for + + header = '''{0} +Atomic number and pseudo-charge + {1} {2} +Energy units (rydberg/hartree/ev): + hartree +Angular momentum of local component (0=s,1=p,2=d..) + {3} +NLRULE override (1) VMC/DMC (2) config gen (0 ==> input/default value) + 0 0 +Number of grid points + {4} +'''.format(name,atomic_number,zval,l_local,npts) + + grid = 'R(i) in atomic units\n' + for d in r: + grid += ' {0:20.14e}\n'.format(d) + #end for + + channels = '' + for l in self.l_channels: + if l in vps: + channels += 'r*potential (L={0}) in Ha\n'.format('spdfgi'.find(l)) + v = vps[l] + for d in v: + channels += ' {0:20.14e}\n'.format(d) + #end for + #end if + #end for + text = header+grid+channels + + if filepath!=None: + open(filepath,'w').write(text) + #end if + return text + #end def write_casino + #end class SemilocalPP @@ -756,713 +813,8 @@ class GFit(DevBase): #end if #end def report #end class GFit - - -def process_gaussian_text(text,format,pp=True,basis=True): - if format=='gamess' or format=='gaussian' or format=='atomscf': - rawlines = text.splitlines() - sections = [] - last_empty = True - for rline in rawlines: - line = rline.strip() - if (not line.startswith('!')) and (not line.startswith('#')) and len(line)>0: - if last_empty: - lines = [] - sections.append(lines) - #end if - lines.append(line) - last_empty = False - else: - last_empty = True - #end if - #end for - del lines - if len(sections)==2: - basis_lines = sections[0] - pp_lines = sections[1] - elif pp: - basis_lines = None - pp_lines = sections[0] - elif basis: - basis_lines = sections[0] - pp_lines = None - #end if - elif format=='crystal': - rawlines = text.splitlines() - pp_lines = [] - basis_lines = [] - foundpp = False - for line in rawlines: - if not foundpp: - foundpp = len(line.split())==5 - #end if - if not foundpp: - pp_lines.append(line) - else: - basis_lines.append(line) - #end if - #end for - if len(pp_lines)==0: - pp_lines = None - #end if - if len(basis_lines)==0: - basis_lines = None - #end if - else: - error('{0} format is unknown'.format(format),'process_gaussian_text') - #end if - if pp and basis: - return pp_lines,basis_lines - elif pp: - return pp_lines - elif basis: - return basis_lines - else: - error('must request pp or basis') - #end if -#end def process_gaussian_text -class GaussianBasisSet(DevBase): - lset_full = tuple('spdfghijk') - lstyles = obj(s='g-',p='r-',d='b-',f='m-',g='c-',h='k-',i='g-.',j='r-.',k='b-.') - formats = 'gaussian gamess'.split() - - crystal_lmap = {0:'s',1:'sp',2:'p',3:'d',4:'f'} - crystal_lmap_reverse = dict(s=0,sp=1,p=2,d=3,f=4) - - @staticmethod - def process_float(s): - return float(s.replace('D','e').replace('d','e')) - #end def process_float - - - def __init__(self,filepath=None,format=None): - self.name = None - self.basis = obj() - if filepath!=None: - self.read(filepath,format) - #end if - #end def __init__ - - - def read(self,filepath,format=None): - if format is None: - self.error('format keyword must be specified to read file {0}\nvalid options are: {1}'.format(filepath,self.formats)) - elif not format in self.formats: - self.error('incorrect format requested: {0}\nvalid options are: {1}'.format(format,self.formats)) - #end if - if not os.path.exists(filepath): - self.error('cannot read {0}, file does not exist'.format(filepath)) - #end if - #self.name = split_delims(os.path.split(filepath)[1])[0] - self.name = os.path.split(filepath)[1].split('.')[0] - text = open(filepath,'r').read() - self.read_text(text,format) - #end def read - - - def write(self,filepath=None,format=None): - if format is None: - self.error('format keyword must be specified to write file {0}\nvalid options are: {1}'.format(filepath,self.formats)) - elif not format in self.formats: - self.error('incorrect format requested: {0}\nvalid options are: {1}'.format(format,self.formats)) - #end if - text = self.write_text(format) - if filepath!=None: - open(filepath,'w').write(text) - #end if - return text - #end def write - - - def read_text(self,text,format=None): - basis_lines = process_gaussian_text(text,format,pp=False) - self.read_lines(basis_lines,format) - #end def read_text - - - def read_lines(self,basis_lines,format=None): - basis = self.basis - basis.clear() - if format=='gamess': - i=1 - while itol: - exponents = array(list(exponents)+[expon],dtype=float) - #end if - #end for - #end for - for expon in exponents: - cterms = obj() - cterms.append(obj(expon=expon,coeff=1.0)) - bf = obj(l=l,scale=array([1.0]),terms=cterms) - self.basis.append(bf) - #end for - #end if - #end for - #end def uncontract - - - def contracted_basis_size(self): - bcount = obj() - for bf in self.basis: - l = bf.l - if l not in bcount: - bcount[l]=0 - #end if - bcount[l] += 1 - #end for - bs = '' - for l in self.lset_full: - if l in bcount: - bs += str(bcount[l])+l - #end if - #end for - return bs - #end def contracted_basis_size - - - def uncontracted_basis_size(self): - if self.uncontracted(): - return self.contracted_basis_size() - #end if - uc = self.copy() - uc.uncontract() - return uc.contracted_basis_size() - #end def uncontracted_basis_size - - - def basis_size(self): - us = self.uncontracted_basis_size() - cs = self.contracted_basis_size() - return '({0})/[{1}]'.format(us,cs) - #end def basis_size - - - def prim_expons(self): - if self.contracted(): - self.error('cannot find primitive gaussian expons because basis is contracted') - #end if - lbasis = self.lbasis() - gexpon = obj() - for l,lbas in lbasis.iteritems(): - e = [] - for n in range(len(lbas)): - e.append(lbas[n].terms[0].expon) - #end for - gexpon[l] = array(e,dtype=float) - #end for - return gexpon - #end def prim_expons - - - def prim_widths(self): - if self.contracted(): - self.error('cannot find primitive gaussian widths because basis is contracted') - #end if - lbasis = self.lbasis() - gwidth = obj() - for l,lbas in lbasis.iteritems(): - w = [] - for n in range(len(lbas)): - w.append(1./sqrt(2.*lbas[n].terms[0].expon)) - #end for - gwidth[l] = array(w,dtype=float) - #end for - return gwidth - #end def prim_widths - - - def remove_prims(self,comp=None,keep=None,**lselectors): - lbasis = self.lbasis() - if comp!=None: - gwidths = self.prim_widths() - #end if - for l,lsel in lselectors.iteritems(): - if l not in lbasis: - self.error('cannot remove basis functions from channel {0}, channel not present'.format(l)) - #end if - lbas = lbasis[l] - if isinstance(lsel,float): - rcut = lsel - less = False - if comp=='<': - less = True - elif comp=='>': - less = False - elif comp is None: - self.error('comp argument must be provided (< or >)') - else: - self.error('comp must be < or >, you provided: {0}'.format(comp)) - #end if - gw = gwidths[l] - iw = arange(len(gw)) - nkeep = 0 - if keep!=None and l in keep: - nkeep = keep[l] - #end if - if less: - rem = iw[gwrcut] - for i in xrange(nkeep,len(rem)): - del lbas[rem[i]] - #end for - #end if - elif isinstance(lsel,int): - if comp=='<': - if lsel>len(lbas): - self.error('cannot remove {0} basis functions from channel {1} as it only has {2}'.format(lsel,l,len(lbas))) - #end if - for i in xrange(lsel): - del lbas[i] - #end for - elif comp=='>': - if lsel>len(lbas): - self.error('cannot remove {0} basis functions from channel {1} as it only has {2}'.format(lsel,l,len(lbas))) - #end if - for i in xrange(len(lbas)-lsel,len(lbas)): - del lbas[i] - #end for - else: - if lsel>=len(lbas): - self.error('cannot remove basis function {0} from channel {1} as it only has {2}'.format(lsel,l,len(lbas))) - #end if - del lbas[lsel] - #end if - else: - for ind in lsel: - del lbas[ind] - #end for - #end if - #end for - self.basis.clear() - for l in self.lset_full: - if l in lbasis: - lbas = lbasis[l] - for k in sorted(lbas.keys()): - self.basis.append(lbas[k]) - #end for - #end if - #end for - #end def remove_prims - - - def remove_small_prims(self,**keep): - lsel = obj() - for l,lbas in self.lbasis().iteritems(): - if l in keep: - lsel[l] = len(lbas)-keep[l] - #end if - #end for - self.remove_prims(comp='<',**lsel) - #end def remove_small_prims - - - def remove_large_prims(self,**keep): - lsel = obj() - for l,lbas in self.lbasis().iteritems(): - if l in keep: - lsel[l] = len(lbas)-keep[l] - #end if - #end for - self.remove_prims(comp='>',**lsel) - #end def remove_large_prims - - - def remove_small_prims_rel(self,other,**keep): - gwidths = other.prim_widths() - lsel = obj() - for l,gw in gwidths.iteritems(): - lsel[l] = gw.min() - #end for - self.remove_prims(comp='<',keep=keep,**lsel) - #end def remove_small_prims_rel - - - def remove_large_prims_rel(self,other,**keep): - gwidths = other.prim_widths() - lsel = obj() - for l,gw in gwidths.iteritems(): - lsel[l] = gw.max() - #end for - self.remove_prims(comp='>',keep=keep,**lsel) - #end def remove_large_prims_rel - - - def remove_channels(self,llist): - lbasis = self.lbasis() - for l in llist: - if l in lbasis: - del lbasis[l] - #end if - #end for - self.basis.clear() - for l in self.lset_full: - if l in lbasis: - lbas = lbasis[l] - for n in range(len(lbas)): - bf = lbas[n] - self.basis.append(bf) - #end for - #end if - #end for - #end def remove_channels - - - def incorporate(self,other,tol=1e-3): - uncontracted = self.uncontracted() and other.uncontracted() - lbasis = self.lbasis() - lbasis_other = other.lbasis() - if uncontracted: - gwidths = self.prim_widths() - gwidths_other = other.prim_widths() - #end if - self.basis.clear() - if not uncontracted: # simple, direct merge of basis sets - for l in self.lset_full: - if l in lbasis: - lbas = lbasis[l] - for n in range(len(lbas)): - bf = lbas[n] - self.basis.append(bf) - #end for - #end if - if l in lbasis_other: - lbas = lbasis_other[l] - for n in range(len(lbas)): - bf = lbas[n] - self.basis.append(bf) - #end for - #end if - #end for - else: # merge uncontracted basis sets preserving order - for l in self.lset_full: - primitives = [] - widths = [] - orig_widths = array([]) - if l in lbasis: - primitives.extend(lbasis[l].list()) - widths.extend(gwidths[l]) - orig_widths = gwidths[l] - #end if - if l in lbasis_other: - prims = lbasis_other[l].list() - owidths = gwidths_other[l] - for n in range(len(prims)): - w = owidths[n] - if len(orig_widths)==0 or abs(orig_widths-w).min()>tol: - primitives.append(prims[n]) - widths.append(w) - #end if - #end if - #end if - primitives = array(primitives,dtype=object)[array(widths).argsort()] - for bf in primitives: - self.basis.append(bf) - #end for - #end for - #end if - #end def incorporate - - - def plot(self,r=None,rmin=0.01,rmax=8.0,show=True,fig=True,sep=False,prim=False,style=None,fmt=None,nsub=None): - if r is None: - r = linspace(rmin,rmax,1000) - #end if - if not prim: - ptitle = '{0} {1} basis'.format(self.name,self.basis_size()) - else: - ptitle = '{0} {1} primitives'.format(self.name,self.basis_size()) - #end if - if fig: - figure() - #end if - r2 = r**2 - lcount = self.lcount() - if nsub!=None: - lcount = max(lcount,nsub) - #end if - lbasis = self.lbasis() - lc = 0 - for l in self.lset_full: - if l in lbasis: - lc+=1 - if sep: - subplot(lcount,1,lc) - ylabel(l) - if lc==1: - title(ptitle) - #end if - #end if - lstyle=self.lstyles[l] - if style!=None: - lstyle = lstyle[0]+style - #end if - if fmt!=None: - lstyle=fmt - #end if - lbas = lbasis[l] - for n in range(len(lbas)): - bf = lbas[n] - br = zeros(r.shape) - s = bf.scale[0] - for pf in bf.terms: - c = pf.coeff - a = -pf.expon*s**2 - pr = exp(a*r2) - if not prim: - br += c*pr - else: - plot(r,pr,lstyle,label=l) - #end if - #end for - if not prim: - plot(r,br,lstyle,label=l) - #end if - #end for - #end if - #end for - if fig: - if not sep: - if self.name!=None: - title(ptitle) - #end if - ylabel('basis functions') - legend() - else: - xlabel('r') - #end if - if show: - show_plots() - #end if - #end if - #end def plot - - - def plot_primitives(self): - None - #end def plot_primitives - -#end class GaussianBasisSet @@ -1481,7 +833,7 @@ class GaussianPP(SemilocalPP): #end def __init__ - def read_text(self,text,format=None): + def read_text(self,text,format=None,filepath=None): lines,basis_lines = process_gaussian_text(text,format) format=format.lower() @@ -1858,7 +1210,7 @@ class QmcpackPP(SemilocalPP): if self.Zcore==0: self.core = '0' else: - self.core = pt.simple_elements[self.Zcore].symbol + self.core = pt.simple_elements[self.Zcore].symbol #end if g = pp.grid @@ -1879,6 +1231,7 @@ class QmcpackPP(SemilocalPP): if not isinstance(vps,list): vps = [vps] #end if + self.lmax = len(vps)-1 for vp in vps: self.channels[vp.l] = vp.radfunc.data.copy() #end for @@ -1906,9 +1259,12 @@ class QmcpackPP(SemilocalPP): def v_at_zero(self,l): - r = self.r - v = self.get_channel(l)/r - vz = (v[1]*r[2]**2-v[2]*r[1]**2)/(r[2]**2-r[1]**2) + #r = self.r + #v = self.get_channel(l)/r + #vz = (v[1]*r[2]**2-v[2]*r[1]**2)/(r[2]**2-r[1]**2) + r = self.r[1:3] + v = self.get_channel(l)[1:3]/r + vz = (v[0]*r[1]**2-v[1]*r[0]**2)/(r[1]**2-r[0]**2) return vz #end def v_at_zero #end class QmcpackPP @@ -1916,6 +1272,86 @@ class QmcpackPP(SemilocalPP): +class CasinoPP(SemilocalPP): + requires_format = False + numeric = True + interpolatable = False + + unitmap = dict(rydberg='Ry',hartree='Ha',ev='eV') + + def read(self,filepath,format=None): + if not os.path.exists(filepath): + self.error('cannot read {0}, file does not exist'.format(filepath)) + #end if + # open the file + file = TextFile(filepath) + # read scalar values at the top + Zatom,Z = file.readtokensf('Atomic number and pseudo-charge',int,float) + if Zatom>len(pt.simple_elements): + self.error('element {0} is not in the periodic table') + #end if + element = pt.simple_elements[Zatom].symbol + units = file.readtokensf('Energy units',str) + if not units in self.unitmap: + self.error('units {0} unrecognized from casino PP file {1}'.format(units,filepath)) + #end if + lloc = file.readtokensf('Angular momentum of local component',int) + lloc = self.l_channels[lloc] + ngrid = file.readtokensf('Number of grid points',int) + # read the radial grid + file.seek('R(i)',1) + file.readline() + r = empty((ngrid,),dtype=float) + for ir in xrange(ngrid): + r[ir] = float(file.readline()) + #end for + # read each channel, convert to hartree units + lmax = -1 + lvals = [] + lpots = [] + while(file.seek('pot',1)!=-1): + lmax += 1 + potline = file.readline() # read the r*potential line + eqloc = potline.find('=') + if eqloc==-1: + self.error('"=" not found in potential line\nline: {0}'.format(potline)) + #end if + l = self.l_channels[int(potline[eqloc+1])] # get the l value + lvals.append(l) + v = empty((ngrid,),dtype=float) + for ir in xrange(ngrid): + v[ir] = float(file.readline()) + #end for + lpots.append(convert(v,self.unitmap[units],'Ha')) + #end while + + # fill in SemilocalPP class data obtained from read + self.element = element + self.Zval = int(Z) + self.Zcore = Zatom-self.Zval + if self.Zcore==0: + self.core = '0' + else: + self.core = pt.simple_elements[self.Zcore].symbol + #end if + self.lmax = lmax + self.local = lloc + self.r = r + for i in range(len(lpots)): + self.channels[lvals[i]] = lpots[i] + #end for + for l in self.channels.keys(): + if l!=self.local: + self.channels[l] -= self.channels[self.local] + #end if + #end for + #end def read_file +#end class CasinoPP + + + + + # functions for gaussing fitting @@ -1931,7 +1367,7 @@ def get_gf_channel(ns,np,params,Zval=None): nparam += 2 #end if if nparam!=len(params): - raise RuntimeError('wrong number of parameters given to get_gf_coeff_rpow_expon\nparameters expected: {0}\nparameters given: {1}'.format(nparams,len(params))) + raise RuntimeError('wrong number of parameters given to get_gf_coeff_rpow_expon\nparameters expected: {0}\nparameters given: {1}'.format(nparam,len(params))) #end if pcur = 0 if loc: diff --git a/nexus/library/pw2casino.py b/nexus/library/pw2casino.py index 0bc4beb84..d98b65d8b 100644 --- a/nexus/library/pw2casino.py +++ b/nexus/library/pw2casino.py @@ -30,6 +30,7 @@ import os from generic import obj +from unit_converter import convert from simulation import Simulation,SimulationInput,SimulationAnalyzer @@ -88,7 +89,7 @@ class Pw2casinoInput(SimulationInput): allowed = set(ints+floats+strs+bools) - def read_contents(self,contents): + def read_text(self,contents,filepath=None): lines = contents.split('\n') inside = False for l in lines: @@ -120,9 +121,9 @@ class Pw2casinoInput(SimulationInput): inside=False #end if #end for - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self,filepath=None): contents = '' for sname,section in self.iteritems(): contents+='&'+sname+'\n' @@ -133,7 +134,7 @@ class Pw2casinoInput(SimulationInput): contents+='/\n' #end for return contents - #end def write_contents + #end def write_text def __init__(self,filepath=None,**vars): diff --git a/nexus/library/pw2qmcpack.py b/nexus/library/pw2qmcpack.py deleted file mode 100644 index 583aacc8a..000000000 --- a/nexus/library/pw2qmcpack.py +++ /dev/null @@ -1,360 +0,0 @@ -################################################################## -## (c) Copyright 2015- by Jaron T. Krogel ## -################################################################## - - -#====================================================================# -# pw2qmcpack.py # -# Nexus interface for the pw2qmcpack tool distributed with PWSCF. # -# pseudopotentials between file formats. # -# # -# Content summary: # -# generate_pw2qmcpack # -# User-facing function to create pw2qmcpack simulation objects. # -# # -# generate_pw2qmcpack_input # -# User-facing funcion to create input for pw2qmcpack. # -# # -# Pw2qmcpack # -# Simulation class for pw2qmcpack. # -# # -# Pw2qmcpackInput # -# SimulationInput class for pw2qmcpack. # -# # -# Pw2qmcpackAnalyzer # -# SimulationAnalyzer class for pw2qmcpack. # -# # -#====================================================================# - - -import os -from generic import obj -from simulation import Simulation,SimulationInput,SimulationAnalyzer - - -def read_str(sv): - return sv.strip('"').strip("'") -#end def read_str - -def read_int(sv): - return int(sv) -#end def read_int - -def read_float(sv): - return float(sv.replace('d','e').replace('D','e')) -#end def read_float - -bconv = {'.true.':True,'.false.':False} -def read_bool(sv): - return bconv[sv] -#end def read_bool - -def write_str(val): - return "'"+val+"'" -#end def write_str - -def write_int(val): - return str(val) -#end def write_int - -def write_float(val): - return str(val) -#end def write_float - -def write_bool(val): - return '.'+str(val).lower()+'.' -#end def write_bool - -readval={str:read_str,int:read_int,float:read_float,bool:read_bool} -writeval={str:write_str,int:write_int,float:write_float,bool:write_bool} - - -class Pw2qmcpackInput(SimulationInput): - ints = [] - floats = [] - strs = ['outdir','prefix'] - bools = ['write_psir'] - - var_types = dict() - for v in ints: - var_types[v]=int - for v in floats: - var_types[v]=float - for v in strs: - var_types[v]=str - for v in bools: - var_types[v]=bool - - allowed = set(ints+floats+strs+bools) - - def read_contents(self,contents): - lines = contents.split('\n') - inside = False - for l in lines: - if inside: - tokens = l.split(',') - for t in tokens: - ts = t.strip() - if ts!='' and ts!='/': - name,value = ts.split('=') - name = name.strip() - value= value.strip() - if name in self.allowed: - vtype = self.var_types[name] - value = readval[vtype](value) - sobj[name]=value - else: - self.error('encountered unknown variable: '+name) - #end if - #end if - #end for - #end if - if '&' in l: - inside=True - section = l.lstrip('&').lower() - sobj = obj() - self[section]=sobj - elif l.strip()=='/': - inside=False - #end if - #end for - #end def read_contents - - def write_contents(self): - contents = '' - for sname,section in self.iteritems(): - contents+='&'+sname+'\n' - for name,value in section.iteritems(): - vtype = type(value) - contents += ' '+name+' = '+writeval[vtype](value)+'\n' - #end for - contents+='/\n' - #end for - return contents - #end def write_contents - - - def __init__(self,filepath=None,**vars): - if filepath!=None: - self.read(filepath) - else: - inputpp = obj() - for name,value in vars.iteritems(): - inputpp[name] = value - #end for - self.inputpp = inputpp - #end if - #end def __init__ -#end class Pw2qmcpackInput - - -def generate_pw2qmcpack_input(prefix='pwscf',outdir='pwscf_output',write_psir=True): - pw = Pw2qmcpackInput( - prefix = prefix, - outdir = outdir, - write_psir = write_psir - ) - return pw -#end def generate_pw2qmcpack_input - - - -class Pw2qmcpackAnalyzer(SimulationAnalyzer): - def __init__(self,arg0): - if isinstance(arg0,Simulation): - sim = arg0 - self.infile = sim.infile - prefix,outdir = sim.input.inputpp.tuple('prefix','outdir') - self.dir = sim.locdir - self.h5file = os.path.join(sim.locdir,outdir,prefix+'.pwscf.h5') - else: - self.infile = arg0 - #end if - #end def __init__ - - def analyze(self): - if False: - import h5py - self.log('Fixing h5 file',n=5) - - path = os.path.split(self.h5file)[0] - print os.getcwd() - print os.listdir('./') - if os.path.exists(path): - print os.listdir(path) - #end if - print self.h5file - - h = h5py.File(self.h5file) - if 'electrons' in h: - elec = h['electrons'] - nkpoints = 0 - for name,val in elec.iteritems(): - if name.startswith('kpoint'): - nkpoints+=1 - #end for - #end if - nkold = elec['number_of_kpoints'][0] - self.log('Were',nkold,'kpoints, now',nkpoints,'kpoints',n=6) - elec['number_of_kpoints'][0] = nkpoints - #end for - #end if - #end def analyze - - def get_result(self,result_name): - self.not_implemented() - #end def get_result -#end class Pw2qmcpackAnalyzer - - -class Pw2qmcpack(Simulation): - input_type = Pw2qmcpackInput - analyzer_type = Pw2qmcpackAnalyzer - generic_identifier = 'pw2qmcpack' - application = 'pw2qmcpack.x' - application_properties = set(['serial']) - application_results = set(['orbitals']) - - def check_result(self,result_name,sim): - calculating_result = False - inputpp = self.input.inputpp - if result_name=='orbitals': - calculating_result = True - else: - calculating_result = False - self.error('ability to check for result '+result_name+' has not been implemented') - #end if - return calculating_result - #end def check_result - - def get_result(self,result_name,sim): - result = obj() - inputpp = self.input.inputpp - prefix = 'pwscf' - outdir = './' - if 'prefix' in inputpp: - prefix = inputpp.prefix - #end if - if 'outdir' in inputpp: - outdir = inputpp.outdir - #end if - if outdir.startswith('./'): - outdir = outdir[2:] - #end if - if result_name=='orbitals': - result.h5file = os.path.join(self.locdir,outdir,prefix+'.pwscf.h5') - result.ptcl_xml = os.path.join(self.locdir,outdir,prefix+'.ptcl.xml') - result.wfs_xml = os.path.join(self.locdir,outdir,prefix+'.wfs.xml') - else: - self.error('ability to get result '+result_name+' has not been implemented') - #end if - return result - #end def get_result - - def incorporate_result(self,result_name,result,sim): - if result_name=='orbitals': - pwin = sim.input.control - p2in = self.input.inputpp - pwprefix = 'pwscf' - p2prefix = 'pwscf' - pwoutdir = './' - p2outdir = './' - if 'prefix' in pwin: - pwprefix = pwin.prefix - if 'prefix' in p2in: - p2prefix = p2in.prefix - if 'outdir' in pwin: - pwoutdir = pwin.outdir - if 'outdir' in p2in: - p2outdir = p2in.outdir - if pwoutdir.startswith('./'): - pwoutdir = pwoutdir[2:] - if p2outdir.startswith('./'): - p2outdir = p2outdir[2:] - pwdir = os.path.abspath(os.path.join(sim.locdir ,pwoutdir)) - p2dir = os.path.abspath(os.path.join(self.locdir,p2outdir)) - errors = False - if pwdir!=p2dir: - self.error('to use orbitals, '+self.generic_identifier+' must have the same outdir as pwscf\n pwscf outdir: '+pwdir+'\n '+self.generic_identifier+' outdir: '+p2dir,exit=False) - errors = True - #end if - if pwprefix!=p2prefix: - self.error('to use orbitals, '+self.generic_identifier+' must have the same prefix as pwscf\n pwscf prefix: '+pwprefix+'\n '+self.generic_identifier+' prefix: '+p2prefix,exit=False) - errors = True - #end if - if errors: - self.error(self.generic_identifier+' cannot use orbitals from pwscf') - #end if - else: - self.error('ability to incorporate result '+result_name+' has not been implemented') - #end if - #end def incorporate_result - - def check_sim_status(self): - outfile = os.path.join(self.locdir,self.outfile) - fobj = open(outfile,'r') - output = fobj.read() - fobj.close() - inputpp = self.input.inputpp - prefix = 'pwscf' - outdir = './' - if 'prefix' in inputpp: - prefix = inputpp.prefix - #end if - if 'outdir' in inputpp: - outdir = inputpp.outdir - #end if - if outdir.startswith('./'): - outdir = outdir[2:] - #end if - h5file = os.path.join(self.locdir,outdir,prefix+'.pwscf.h5') - ptcl_xml = os.path.join(self.locdir,outdir,prefix+'.ptcl.xml') - wfs_xml = os.path.join(self.locdir,outdir,prefix+'.wfs.xml') - must_exist = [h5file,ptcl_xml,wfs_xml] - - files_exist = True - for file in must_exist: - files_exist = files_exist and os.path.exists(file) - #end for - outfin = True - #outfin = outfin and 'esh5 create' in output - #outfin = outfin and 'Creating electrons' in output - outfin = outfin and 'npw=' in output - outfin = outfin and 'ik=' in output - - outfin = outfin or 'JOB DONE' in output - - success = files_exist and outfin - - #self.finished = success and self.job.finished - - # pw2qmcpack has too many variants to assess completion based on log output - # assume (optimistically) that job completion indicates success - self.finished = files_exist and self.job.finished - #end def check_sim_status - - def get_output_files(self): - output_files = [] - return output_files - #end def get_output_files - - def app_command(self): - return self.app_name+'<'+self.infile - #end def app_command -#end class Pw2qmcpack - - - - -def generate_pw2qmcpack(**kwargs): - sim_args,inp_args = Simulation.separate_inputs(kwargs) - - if not 'input' in sim_args: - sim_args.input = generate_pw2qmcpack_input(**inp_args) - #end if - pw2qmcpack = Pw2qmcpack(**sim_args) - - return pw2qmcpack -#end def generate_pw2qmcpack - - diff --git a/nexus/library/pwscf.py b/nexus/library/pwscf.py index 1488ed4dd..bc8dbb44e 100644 --- a/nexus/library/pwscf.py +++ b/nexus/library/pwscf.py @@ -21,7 +21,7 @@ import os from numpy import array from generic import obj from physical_system import PhysicalSystem -from converters import Pw2qmcpack +from qmcpack_converters import Pw2qmcpack from simulation import Simulation from pwscf_input import PwscfInput,generate_pwscf_input from pwscf_analyzer import PwscfAnalyzer diff --git a/nexus/library/pwscf_input.py b/nexus/library/pwscf_input.py index 8cd3a6037..7e07fc2b0 100644 --- a/nexus/library/pwscf_input.py +++ b/nexus/library/pwscf_input.py @@ -45,7 +45,7 @@ import os -import types as pytypes +import inspect from copy import deepcopy from superstring import string2val from numpy import fromstring,empty,array,float64,ones,pi,dot @@ -54,7 +54,7 @@ from unit_converter import convert from generic import obj from structure import Structure,kmesh from physical_system import PhysicalSystem -from project_base import Pobj +from developer import DevBase,warn from simulation import SimulationInput from debug import * @@ -153,7 +153,7 @@ def array_to_string(a,pad=' ',format=pwscf_array_format,converter=noconv,rowse -class PwscfInputBase(Pobj): +class PwscfInputBase(DevBase): ints=['nstep','iprint','gdir','nppstr','nberrycyc','ibrav','nat','ntyp','nbnd','tot_charge','nr1','nr2','nr3','nr1s','nr2s','nr3s','nspin','multiplicity','tot_magnetization','edir','report','electron_maxstep','mixing_ndim','mixing_fixed_ns','ortho_para','diago_cg_maxiter','diago_david_ndim','nraise','bfgs_ndim','num_of_images','fe_nstep','sw_nstep','modenum','n_charge_compensation','nlev','lda_plus_u_kind'] floats=['dt','max_seconds','etot_conv_thr','forc_conv_thr','celldm','A','B','C','cosAB','cosAC','cosBC','nelec','ecutwfc','ecutrho','degauss','starting_magnetization','nelup','neldw','ecfixed','qcutz','q2sigma','Hubbard_alpha','Hubbard_U','Hubbard_J','starting_ns_eigenvalue','emaxpos','eopreg','eamp','angle1','angle2','fixed_magnetization','lambda','london_s6','london_rcut','conv_thr','mixing_beta','diago_thr_init','efield','tempw','tolp','delta_t','upscale','trust_radius_max','trust_radius_min','trust_radius_ini','w_1','w_2','temp_req','ds','k_max','k_min','path_thr','fe_step','g_amplitude','press','wmass','cell_factor','press_conv_thr','xqq','ecutcoarse','mixing_charge_compensation','comp_thr','exx_fraction','ecutfock'] strs=['calculation','title','verbosity','restart_mode','outdir','wfcdir','prefix','disk_io','pseudo_dir','occupations','smearing','input_dft','U_projection_type','constrained_magnetization','mixing_mode','diagonalization','startingpot','startingwfc','ion_dynamics','ion_positions','phase_space','pot_extrapolation','wfc_extrapolation','ion_temperature','opt_scheme','CI_scheme','cell_dynamics','cell_dofree','which_compensation','assume_isolated','exxdiv_treatment'] @@ -285,22 +285,22 @@ class Card(Element): def read(self,lines): self.get_specifier(lines[0]) - self.read_contents(lines[1:]) + self.read_text(lines[1:]) #end def read def write(self,parent): c = self.name.upper()+' '+self.specifier+'\n' - c += self.write_contents()+'\n' + c += self.write_text()+'\n' return c #end def write - def read_contents(self,lines): + def read_text(self,lines): self.not_implemented() - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self): self.not_implemented() - #end def write_contents + #end def write_text def change_specifier(self,new_specifier): self.not_implemented() @@ -513,7 +513,7 @@ def check_section_classes(*sections): class atomic_species(Card): name = 'atomic_species' - def read_contents(self,lines): + def read_text(self,lines): atoms = [] masses = obj() pseudopotentials = obj() @@ -525,22 +525,22 @@ class atomic_species(Card): pseudopotentials[atom] = tokens[2] #end for self.add(atoms=atoms,masses=masses,pseudopotentials=pseudopotentials) - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self): c = '' for at in self.atoms: c += ' '+'{0:2}'.format(at)+' '+str(self.masses[at])+' '+self.pseudopotentials[at]+'\n' #end for return c - #end def write_contents + #end def write_text #end class atomic_species class atomic_positions(Card): name = 'atomic_positions' - def read_contents(self,lines): + def read_text(self,lines): npos = len(lines) dim = 3 atoms = [] @@ -562,10 +562,10 @@ class atomic_positions(Card): if has_relax_directions: self.add(relax_directions=relax_directions) #end if - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self): c = '' has_relax_directions = 'relax_directions' in self if has_relax_directions: @@ -581,7 +581,7 @@ class atomic_positions(Card): #end if #end for return c - #end def write_contents + #end def write_text def change_specifier(self,new_specifier,pwi): @@ -627,7 +627,7 @@ class atomic_positions(Card): class k_points(Card): name = 'k_points' - def read_contents(self,lines): + def read_text(self,lines): if self.specifier in ['tpiba','crystal','tpiba_b','crystal_b','']: self.nkpoints = int(lines[0]) a = array_from_lines(lines[1:]) @@ -643,10 +643,10 @@ class k_points(Card): else: self.error('k_points specifier '+self.specifier+' is unrecognized') #end if - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self): c = '' if self.specifier in ('tpiba','crystal','tpiba_b','crystal_b',''): self.nkpoints = len(self.kpoints) @@ -665,7 +665,7 @@ class k_points(Card): self.error('k_points specifier '+self.specifier+' is unrecognized') #end if return c - #end def write_contents + #end def write_text def change_specifier(self,new_specifier,pwi): @@ -716,13 +716,13 @@ class k_points(Card): class cell_parameters(Card): name = 'cell_parameters' - def read_contents(self,lines): + def read_text(self,lines): self.vectors = array_from_lines(lines) - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self): return array_to_string(self.vectors) - #end def write_contents + #end def write_text #end class cell_parameters @@ -731,17 +731,17 @@ class cell_parameters(Card): class climbing_images(Card): name = 'climbing_images' - def read_contents(self,lines): + def read_text(self,lines): self.images = array_from_lines(lines) - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self): c=' ' for n in self.images: c+=str(int(n))+' ' #end for return c - #end def write_contents + #end def write_text #end class climbing_images @@ -750,7 +750,7 @@ class climbing_images(Card): class constraints(Card): name = 'constraints' - def read_contents(self,lines): + def read_text(self,lines): tokens = lines[0].split() self.ncontraints = int(tokens[0]) if len(tokens)>1: @@ -764,9 +764,9 @@ class constraints(Card): cons.parameters = array(tokens[1:],dtype=float64) self.constraints[i] = cons #end for - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self): c = ' '+str(self.nconstraints) if 'tolerance' in self: c+=' '+str(self.tolerance) @@ -775,7 +775,7 @@ class constraints(Card): c+=' '+cons.type+' '+array_to_string(cons.parameters,pad='') #end for return c - #end def write_contents + #end def write_text #end class constraints @@ -784,7 +784,7 @@ class constraints(Card): class collective_vars(Card): name = 'collective_vars' - def read_contents(self,lines): + def read_text(self,lines): tokens = lines[0].split() self.ncontraints = int(tokens[0]) if len(tokens)>1: @@ -798,9 +798,9 @@ class collective_vars(Card): collv.parameters = array(tokens[1:],dtype=float64) self.collective_vars[i] = collv #end for - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self): c= ' '+str(self.ncollective_vars) if 'tolerance' in self: c+=' '+str(self.tolerance) @@ -809,7 +809,7 @@ class collective_vars(Card): c+=' '+collv.type+' '+array_to_string(collv.parameters,pad='') #end for return c - #end def write_contents + #end def write_text #end class collective_vars @@ -818,13 +818,13 @@ class collective_vars(Card): class occupations(Card): name = 'occupations' - def read_contents(self,lines): + def read_text(self,lines): self.occupations = array_from_lines(lines) - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self): return array_to_string(self.occupations) - #end def write_contents + #end def write_text #end class occupations @@ -893,7 +893,7 @@ class PwscfInput(SimulationInput): #end def __init__ - def read_contents(self,contents): + def read_text(self,contents,filepath=None): lines = contents.splitlines() in_element = False elem_type = None @@ -948,10 +948,10 @@ class PwscfInput(SimulationInput): for element in self: element.post_process_read(self) #end for - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self,filepath=None): contents = '' for s in self.sections: if s in self: @@ -966,7 +966,7 @@ class PwscfInput(SimulationInput): #end for contents+='\n' return contents - #end def write_contents + #end def write_text def get_common_vars(self,*vars): @@ -1225,22 +1225,6 @@ class PwscfInput(SimulationInput): ion_charge += atoms.count(atom)*valency[atom] #end for - #ion_charge = 0 - #valency = dict() - #atoms = list(self.atomic_positions.atoms) - #for atom in self.atomic_species.atoms: - # pseudo_file = self.atomic_species.pseudopotentials[atom] - # if self.pseudopotentials!=None and pseudo_file in self.pseudopotentials: - # pseudopot = self.pseudopotentials[pseudo_file] - # element = pseudopot.element - # valence = int(pseudopot.Z) - # ion_charge += atoms.count(atom)*valence - # valency[atom] = valence - # else: - # self.error('file '+pseudo_file+' was not listed in Pseudopotentials object\n please specify pseudopotentials with the settings function',trace=False) - # #end if - ##end for - if 'nelup' in self.system: nup = self.system.nelup ndn = self.system.neldw @@ -1392,7 +1376,7 @@ def generate_any_pwscf_input(**kwargs): for name,default in defaults.iteritems(): if not name in kwargs: deftype = type(default) - if deftype==pytypes.ClassType or deftype==pytypes.FunctionType: + if inspect.isclass(default) or inspect.isfunction(default): kwargs[name] = default() else: kwargs[name] = default @@ -1427,13 +1411,14 @@ def generate_any_pwscf_input(**kwargs): #end for #process other keywords - pseudos = kwargs.delete('pseudos') - system = kwargs.delete('system') - use_folded = kwargs.delete('use_folded') - hubbard_u = kwargs.delete('hubbard_u') - start_mag = kwargs.delete('start_mag') - kgrid = kwargs.delete('kgrid') - kshift = kwargs.delete('kshift') + pseudos = kwargs.delete_required('pseudos') + system = kwargs.delete_required('system') + use_folded = kwargs.delete_required('use_folded') + hubbard_u = kwargs.delete_required('hubbard_u') + start_mag = kwargs.delete_required('start_mag') + kgrid = kwargs.delete_required('kgrid') + kshift = kwargs.delete_required('kshift') + nogamma = kwargs.delete_optional('nogamma',False) # pseudopotentials pseudopotentials = obj() @@ -1507,17 +1492,32 @@ def generate_any_pwscf_input(**kwargs): else: zero_shift = tuple(kshift)==(0,0,0) #end if - if zero_shift and (kgrid!=None and tuple(kgrid)==(1,1,1) or kgrid is None and system is None): + + single_point = kgrid != None and tuple(kgrid)==(1,1,1) + no_info = kgrid is None and system is None + at_gamma = zero_shift and (single_point or no_info) + at_gamma |= 'specifier' in pw.k_points and pw.k_points.specifier=='gamma' + auto = kgrid!=None and kshift!=None + shifted = not zero_shift and kshift!=None + + if at_gamma and not nogamma: pw.k_points.clear() pw.k_points.specifier = 'gamma' - elif kgrid!=None and kshift!=None: + elif at_gamma and nogamma: + pw.k_points.clear() + pw.k_points.set( + specifier = 'automatic', + grid = (1,1,1), + shift = (0,0,0) + ) + elif auto: pw.k_points.clear() pw.k_points.set( specifier = 'automatic', grid = kgrid, shift = kshift ) - elif not zero_shift and kshift!=None: + elif shifted: pw.k_points.clear() pw.k_points.set( specifier = 'automatic', @@ -1897,7 +1897,7 @@ def generate_relax_input(prefix = 'pwscf', if system is not None: structure = system.structure if group_atoms: - self.warn('requested grouping by atomic species, but pwscf does not group atoms anymore!') + warn('requested grouping by atomic species, but pwscf does not group atoms anymore!','generate_relax_input') #end if #if group_atoms: #don't group atoms for pwscf, any downstream consequences? # structure.group_atoms() diff --git a/nexus/library/qaobject.py b/nexus/library/qaobject.py deleted file mode 100644 index a6a446907..000000000 --- a/nexus/library/qaobject.py +++ /dev/null @@ -1,149 +0,0 @@ -################################################################## -## (c) Copyright 2015- by Jaron T. Krogel ## -################################################################## - - -#====================================================================# -# qaobject.py # -# Provides base class functionality for all classes associated # -# with the QmcpackAnalyzer class. Maintains data global to # -# these classes. # -# # -# Content summary: # -# QAobject # -# Base class for all QMCPACK analyzer components. # -# Exposes settings options to the user. # -# # -# Checks # -# Class to assess overall validity based on stored results of # -# many checks (boolean values). Only use so far is to validate # -# the structure of Trace files. See qmcpack_method_analyzers.py.# -# # -#====================================================================# - - -from generic import obj -from developer import DevBase -from project_base import Pobj -from plotter import Plotter - - -class QAobj_base(Pobj): - None -#end class QAobj_base - - -class QAobject(QAobj_base): - - _global = obj() - _global.dynamic_methods_objects=[] - - plotter = Plotter() - - opt_methods = set(['opt','linear','cslinear']) - - def __init__(self): - return - #end def __init__ - - @staticmethod - def condense_name(name): - return name.strip().lower().replace(' ','_').replace('-','_').replace('__','_') - #end def condense_name - - - def _register_dynamic_methods(self): - QAobject._global.dynamic_methods_objects.append(self) - return - #end def _register_dynamic_methods - - def _unlink_dynamic_methods(self): - for o in QAobject._global.dynamic_methods_objects: - o._unset_dynamic_methods() - #end for - return - #end def _unlink_dynamic_methods - - def _relink_dynamic_methods(self): - for o in QAobject._global.dynamic_methods_objects: - o._reset_dynamic_methods() - #end for - return - #end def _relink_dynamic_methods - - - _allowed_settings = set(['optimize']) - _default_settings = obj( - #optimize = 'variance' - optimize = 'lastcost' - ) - for var,val in _default_settings.iteritems(): - QAobj_base.__dict__[var] = val - #end for - - @classmethod - def settings(cls,**kwargs): - vars = set(kwargs.keys()) - invalid = vars-cls._allowed_settings - if len(invalid)>0: - allowed = list(cls._allowed_settings) - allowed.sort() - invalid = list(invalid) - invalid.sort() - cls.class_error('attempted to set unknown variables\n unknown variables: {0}\n valid options are: {1}'.format(invalid,allowed)) - #end if - for var,val in kwargs.iteritems(): - QAobj_base.__dict__[var] = val - #end for - #end settings -#end class QAobject - - - -class Checks(Pobj): - def __init__(self,label=''): - self._label = label - self._exclusions = set() - #end def __init__ - - def exclude(self,value): - self._exclusions.add(value) - #end def exclude - - def valid(self): - valid = True - for name,value in self.iteritems(): - if not (isinstance(name,str) and name.startswith('_')): - if not value in self._exclusions: - valid = valid and value - #end if - #end if - #end if - self._valid = valid - return valid - #end def valid - - def write(self,pad=''): - pad2 = pad+' ' - if not '_valid' in self: - self.valid() - #end if - valid = self._valid - if valid: - self.log(pad+self._label+' is valid') - else: - self.log(pad+self._label+' is invalid') - for name,value in self.iteritems(): - if not (isinstance(name,str) and name.startswith('_')): - if value in self._exclusions: - self.log(pad2+name+' could not be checked') - elif value: - self.log(pad2+name+' is valid') - else: - self.log(pad2+name+' is invalid') - #end if - #end if - #end for - #end if - #end def write -#end class Checks diff --git a/nexus/library/qmcpack.py b/nexus/library/qmcpack.py index d2d2200ee..9f495ee9e 100644 --- a/nexus/library/qmcpack.py +++ b/nexus/library/qmcpack.py @@ -32,14 +32,12 @@ from periodic_table import periodic_table from physical_system import PhysicalSystem from simulation import Simulation from qmcpack_input import QmcpackInput,generate_qmcpack_input -from qmcpack_input import BundledQmcpackInput,TracedQmcpackInput -from qmcpack_input import QmcpackInputTemplate +from qmcpack_input import TracedQmcpackInput from qmcpack_input import loop,linear,cslinear,vmc,dmc,collection,determinantset,hamiltonian,init,pairpot,bspline_builder from qmcpack_input import generate_jastrows,generate_jastrow,generate_jastrow1,generate_jastrow2,generate_jastrow3 from qmcpack_input import generate_opt,generate_opts from qmcpack_analyzer import QmcpackAnalyzer -from converters import Pw2qmcpack,Wfconvert -from convert4qmc import Convert4qmc +from qmcpack_converters import Pw2qmcpack,Wfconvert,Convert4qmc from sqd import Sqd from debug import ci,ls,gs from developer import unavailable @@ -60,7 +58,6 @@ class Qmcpack(Simulation): application = 'qmcapp_complex' # always use complex version until kpoint handling is fixed application_properties = set(['serial','omp','mpi']) application_results = set(['jastrow','cuspcorr','wavefunction']) - preserve = Simulation.preserve | set(['should_twist_average']) def post_init(self): @@ -71,12 +68,19 @@ class Qmcpack(Simulation): #if self.system is None: # self.error('system must be specified to determine type of run') ##end if + + generic_input = self.has_generic_input() + if self.system is None: - if not isinstance(self.input,QmcpackInputTemplate): + if not generic_input: self.warn('system must be specified to determine whether to twist average\n proceeding under the assumption of no twist averaging') #end if self.should_twist_average = False else: + if generic_input: + cls = self.__class__ + self.error('cannot twist average generic or templated input\nplease provide {0} instead of {1} for input'.format(cls.input_type.__class__.__name__,self.input.__class__.__name__)) + #end if self.system.group_atoms() self.system.change_units('B') twh = self.input.get_host('twist') @@ -91,7 +95,7 @@ class Qmcpack(Simulation): def propagate_identifier(self): - if not isinstance(self.input,QmcpackInputTemplate): + if not self.has_generic_input(): self.input.simulation.project.id = self.identifier #end if #end def propagate_identifier @@ -356,45 +360,43 @@ class Qmcpack(Simulation): def check_sim_status(self): - outfile = os.path.join(self.locdir,self.outfile) - errfile = os.path.join(self.locdir,self.errfile) - fobj = open(outfile,'r') - output = fobj.read() - fobj.close() - fobj = open(errfile,'r') - errors = fobj.read() - fobj.close() - - cusp_run = self.input.cusp_correction() - if cusp_run: - sd = self.input.get('slaterdeterminant') - if sd!=None: - cuspfiles = [] - for d in sd.determinants: - cuspfiles.append(d.id+'.cuspInfo.xml') - #end for - else: # assume multideterminant sposet names - cuspfiles = ['spo-up.cuspInfo.xml','spo-dn.cuspInfo.xml'] - #end if - outfiles = cuspfiles - else: - outfiles = self.input.get_output_info('outfiles') - #end if + output = self.outfile_text() + errors = self.errfile_text() ran_to_end = 'Total Execution' in output + aborted = 'Fatal Error' in errors files_exist = True - for file in outfiles: - file_loc = os.path.join(self.locdir,file) - files_exist = files_exist and os.path.exists(file_loc) - #end for - - if ran_to_end and not files_exist: - self.warn('run finished successfully, but output files do not seem to exist') - print outfiles - print os.listdir(self.locdir) + cusp_run = False + + if not self.has_generic_input(): + cusp_run = self.input.cusp_correction() + if cusp_run: + sd = self.input.get('slaterdeterminant') + if sd!=None: + cuspfiles = [] + for d in sd.determinants: + cuspfiles.append(d.id+'.cuspInfo.xml') + #end for + else: # assume multideterminant sposet names + cuspfiles = ['spo-up.cuspInfo.xml','spo-dn.cuspInfo.xml'] + #end if + outfiles = cuspfiles + else: + outfiles = self.input.get_output_info('outfiles') + #end if + + for file in outfiles: + file_loc = os.path.join(self.locdir,file) + files_exist = files_exist and os.path.exists(file_loc) + #end for + + if ran_to_end and not files_exist: + self.warn('run finished successfully, but output files do not seem to exist') + print outfiles + print os.listdir(self.locdir) + #end if #end if - aborted = 'Fatal Error' in errors self.succeeded = ran_to_end self.failed = aborted @@ -408,30 +410,22 @@ class Qmcpack(Simulation): #end for #end if - #print - #print self.__class__.__name__ - #print 'identifier ',self.identifier - #print 'ran_to_end ',ran_to_end - #print 'files_exist',files_exist - #print 'aborted ',aborted - #print 'job done ',self.job.finished - #print 'finished ',self.finished - #print - #end def check_sim_status def get_output_files(self): - if self.should_twist_average and not isinstance(self.input,TracedQmcpackInput): - self.twist_average(range(len(self.system.structure.kpoints))) - br = self.bundle_request - input = self.input.trace(br.quantity,br.values) - input.generate_filenames(self.infile) - self.input = input + if self.has_generic_input(): + output_files = [] + else: + if self.should_twist_average and not isinstance(self.input,TracedQmcpackInput): + self.twist_average(range(len(self.system.structure.kpoints))) + br = self.bundle_request + input = self.input.trace(br.quantity,br.values) + input.generate_filenames(self.infile) + self.input = input + #end if + output_files = self.input.get_output_info('outfiles') #end if - - output_files = self.input.get_output_info('outfiles') - return output_files #end def get_output_files @@ -446,16 +440,14 @@ class Qmcpack(Simulation): br.quantity = 'twistnum' br.values = list(twistnums) self.bundle_request = br - #self.app_name = 'qmcapp_complex' - #print 'twist_average' - #print ' setting bundle request:' - #print self.bundle_request #end def twist_average def write_prep(self): if self.got_dependencies: - if 'bundle_request' in self and not isinstance(self.input,TracedQmcpackInput): + traced_input = isinstance(self.input,TracedQmcpackInput) + generic_input = self.has_generic_input() + if 'bundle_request' in self and not traced_input and not generic_input: br = self.bundle_request input = self.input.trace(br.quantity,br.values) input.generate_filenames(self.infile) @@ -475,124 +467,6 @@ class Qmcpack(Simulation): - -class BundledQmcpack(Qmcpack): - infile_extension = '.in' - application_results = set([]) - - preserve = set(Simulation.preserve) - preserve.add('sims') - - def __init__(self,**kwargs): - if not 'sims' in kwargs: - self.error('sims must be provided') - #end if - sims = kwargs['sims'] - self.sims = sims - del kwargs['sims'] - files = set() - for sim in sims: - files = files | sim.files - #end for - kwargs['files'] = files - - inputs = [] - filenames = [] - for sim in sims: - inputs.append(sim.input) - filenames.append(sim.infile) - #end for - kwargs['input'] = BundledQmcpackInput(inputs=inputs,filenames=filenames) - - Simulation.__init__(self,**kwargs) - deps = [] - for sim in sims: - for dep in sim.dependencies: - deps.append((dep.sim,'other')) - #end for - #end for - self.depends(*deps) - #end def __init__ - - def propagate_identifier(self): - for sim in self.sims: - sim.propagate_identifier() - #end for - #end def propagate_identifier - - def check_result(self,result_name,sim): - return False - #end def check_result - - def get_result(self,result_name,sim): - self.error(result_name+' is not calculated by BundledQmcpack') - #end def get_result - - def check_dependencies(self,result): - for sim in self.sims: - sim.check_dependencies(results) - #end for - Simulation.check_dependencies(self,result) - #end def check_dependencies - - def get_dependencies(self): - for sim in self.sims: - sim.get_dependencies() - #end for - Simulation.get_dependencies(self) - #end def get_dependencies - - - - def check_sim_status(self): - outfile = os.path.join(self.locdir,self.outfile) - errfile = os.path.join(self.locdir,self.errfile) - fobj = open(outfile,'r') - output = fobj.read() - fobj.close() - fobj = open(errfile,'r') - errors = fobj.read() - fobj.close() - - ran_to_end = 'Total Execution' in output - files_exist = True - outfiles = self.input.get_output_info('outfiles') - for file in outfiles: - file_loc = os.path.join(self.locdir,file) - files_exist = files_exist and os.path.exists(file_loc) - #end for - - if ran_to_end and not files_exist: - self.warn('run finished successfully, but output files do not seem to exist') - print outfiles - print os.listdir(self.locdir) - #end if - - aborted = 'Fatal Error' in errors - - self.failed = aborted - self.finished = files_exist and self.job.finished and not aborted - - #print - #print self.__class__.__name__ - #print 'identifier ',self.identifier - #print 'ran_to_end ',ran_to_end - #print 'files_exist',files_exist - #print 'aborted ',aborted - #print 'job done ',self.job.finished - #print 'finished ',self.finished - #print - # - #import code - #code.interact(local=dict(locals(),**globals())) - - #end def check_sim_status - -#end class BundledQmcpack - - - - def generate_qmcpack(**kwargs): sim_args,inp_args = Simulation.separate_inputs(kwargs) diff --git a/nexus/library/qmcpack_analyzer.py b/nexus/library/qmcpack_analyzer.py index d2a17f315..76a5c5592 100644 --- a/nexus/library/qmcpack_analyzer.py +++ b/nexus/library/qmcpack_analyzer.py @@ -21,18 +21,6 @@ #====================================================================# -# -# bugs -# -equilibration length algorithm incorrectly picks first crossing of -# mean+sigma as starting place -# it should be the last crossing of mean+sigma preceeding the first -# crossing of mean-sigma -# -twist averaging energy density gets information from the first twist only -# -integral(Edens) /= E_tot for twist -# -generalized data averaging algorithm must not be finding all the data -# see /oahu/home/projects/project6_germanium/ed_paper_wrapup/final_analysis/data/pure/tile611_kg133/qmc/* -# -# from time import time @@ -48,8 +36,7 @@ from developer import unavailable from xmlreader import XMLreader from plotting import * #QmcpackAnalyzer classes imports -from qaobject import QAobject -from qmcpack_analyzer_base import QAanalyzer,QAanalyzerCollection +from qmcpack_analyzer_base import QAobject,QAanalyzer,QAanalyzerCollection from qmcpack_property_analyzers \ import WavefunctionAnalyzer from qmcpack_quantity_analyzers \ diff --git a/nexus/library/qmcpack_analyzer_base.py b/nexus/library/qmcpack_analyzer_base.py index 43ba6fd0d..2c1e81db3 100644 --- a/nexus/library/qmcpack_analyzer_base.py +++ b/nexus/library/qmcpack_analyzer_base.py @@ -6,8 +6,23 @@ #====================================================================# # qmcpack_analyzer_base.py # # Data object and analyzer base classes for QmcpackAnalyzer. # +# Maintains data global to these classes. # # # # Content summary: # +# QAobject # +# Base class for all QMCPACK analyzer components. # +# Exposes settings options to the user. # +# # +# Checks # +# Class to assess overall validity based on stored results of # +# many checks (boolean values). Only use so far is to validate # +# the structure of Trace files. See qmcpack_method_analyzers.py.# +# # +# Plotter # +# Wrapper class for mayavi visualization of isosurfaces and # +# surface slices. Previously used to visualize energy densities.# +# See qmcpack_quantity_analyzers.py and spacegrid.py. # +# # # QAdata # # Represents stored data from QMCPACK's output files. # # Classification marks it as a target for potential merging, # @@ -17,22 +32,214 @@ # Specialization of QAdata for data from HDF files. # # # # QAanalyzer # -# Base class for analyzer classes. # -# Analyzers load and analyze data. # -# Base class functionality includes recursive traversal of # -# nested analyzer object structures for loading and analyzing # -# data. # +# Base class for analyzer classes. Analyzers load and analyze # +# data. Base class functionality includes recursive traversal # +# of nested analyzer object structures for loading and # +# analyzing data. # # # #====================================================================# from numpy import minimum,resize from generic import obj +from developer import DevBase from hdfreader import HDFgroup -from qaobject import QAobject from debug import * + + +import numpy as np + +class Plotter(DevBase): + def __init__(self): + self.initialized = False + return + #end def __init__ + + def ensure_init(self): + if not self.initialized: + from enthought.mayavi import mlab + from enthought.tvtk.api import tvtk + self.mlab = mlab + self.tvtk = tvtk + + self.show = mlab.show + self.plot3d = mlab.plot3d + self.mesh = mlab.mesh + + self.initialized = True + #end if + #end def ensure_init + + def isosurface(self,points,scalars,contours,dimensions,name='val'): + self.ensure_init() + mlab = self.mlab + tvtk = self.tvtk + sg=tvtk.StructuredGrid(dimensions=dimensions,points=points) + sg.point_data.scalars = scalars + sg.point_data.scalars.name = name + d = mlab.pipeline.add_dataset(sg) + iso = mlab.pipeline.iso_surface(d) + if isinstance(contours,int): + iso.contour.number_of_contours = contours + elif isinstance(contours,list): + iso.contour.auto_contours = False + iso.contour.contours = contours + else: + self.error('isosurface contours must be an int or list\n a '+str(type(contours))+' was provided instead') + #end if + return + #end def isosurface + + def surface_slice(self,x,y,z,scalars,options=None): + scale = 1.0 + opacity= 1.0 + if options!=None: + if 'norm_height' in options: + scale = options.norm_height/abs(scalars.max()) + if 'scale' in options: + scale = options.scale + if 'opacity' in options: + opacity = options.opacity + #end if + self.ensure_init() + from numerics import surface_normals + self.mesh(x,y,z,opacity=.2) + surfnorm = scale*surface_normals(x,y,z) + xs=x.copy() + ys=y.copy() + zs=z.copy() + xs[...] = x[...] + surfnorm[...,0]*scalars[...] + ys[...] = y[...] + surfnorm[...,1]*scalars[...] + zs[...] = z[...] + surfnorm[...,2]*scalars[...] + self.mesh(xs,ys,zs,scalars=scalars,opacity=opacity) + return + #end def surface_slice +#end class Plotter + + + +class QAobj_base(DevBase): + None +#end class QAobj_base + + +class QAobject(QAobj_base): + + _global = obj() + _global.dynamic_methods_objects=[] + + plotter = Plotter() + + opt_methods = set(['opt','linear','cslinear']) + + def __init__(self): + return + #end def __init__ + + @staticmethod + def condense_name(name): + return name.strip().lower().replace(' ','_').replace('-','_').replace('__','_') + #end def condense_name + + + def _register_dynamic_methods(self): + QAobject._global.dynamic_methods_objects.append(self) + return + #end def _register_dynamic_methods + + def _unlink_dynamic_methods(self): + for o in QAobject._global.dynamic_methods_objects: + o._unset_dynamic_methods() + #end for + return + #end def _unlink_dynamic_methods + + def _relink_dynamic_methods(self): + for o in QAobject._global.dynamic_methods_objects: + o._reset_dynamic_methods() + #end for + return + #end def _relink_dynamic_methods + + + _allowed_settings = set(['optimize']) + _default_settings = obj( + #optimize = 'variance' + optimize = 'lastcost' + #optimize = 'energy_within_variance_tol' # also ewvt + ) + QAobj_base.class_set(**_default_settings) + + @classmethod + def settings(cls,**kwargs): + vars = set(kwargs.keys()) + invalid = vars-cls._allowed_settings + if len(invalid)>0: + allowed = list(cls._allowed_settings) + allowed.sort() + invalid = list(invalid) + invalid.sort() + cls.class_error('attempted to set unknown variables\n unknown variables: {0}\n valid options are: {1}'.format(invalid,allowed)) + #end if + QAobj_base.class_set(**kwargs) + #end settings +#end class QAobject + + + +class Checks(DevBase): + def __init__(self,label=''): + self._label = label + self._exclusions = set() + #end def __init__ + + def exclude(self,value): + self._exclusions.add(value) + #end def exclude + + def valid(self): + valid = True + for name,value in self.iteritems(): + if not (isinstance(name,str) and name.startswith('_')): + if not value in self._exclusions: + valid = valid and value + #end if + #end if + #end if + self._valid = valid + return valid + #end def valid + + def write(self,pad=''): + pad2 = pad+' ' + if not '_valid' in self: + self.valid() + #end if + valid = self._valid + if valid: + self.log(pad+self._label+' is valid') + else: + self.log(pad+self._label+' is invalid') + for name,value in self.iteritems(): + if not (isinstance(name,str) and name.startswith('_')): + if value in self._exclusions: + self.log(pad2+name+' could not be checked') + elif value: + self.log(pad2+name+' is valid') + else: + self.log(pad2+name+' is invalid') + #end if + #end if + #end for + #end if + #end def write +#end class Checks + + + + class QAinformation(obj): None #end class QAinformation @@ -147,19 +354,6 @@ class QAanalyzer(QAobject): dmc_methods = set(['dmc']) - allowed_settings = [] - @classmethod - def settings(cls,**kwargs): - invalid = list(set(kwargs.keys())-set(allowed_settings)) - if len(invalid)>0: - cls.class_error('invalid variable names encountered in settings\n invalid names: {0}\n valid options are: {1}'.format(invalid,allowed_settings)) - #end if - for name,value in kwargs.iteritems(): - cls.__dict__[name] = value - #end for - #end def settings - - def __init__(self,nindent=0): self.info = QAinformation( initialized = False, @@ -218,30 +412,30 @@ class QAanalyzer(QAobject): None #end def unset_global_info - def traverse(self,function,block_name=None,callpost=True,**kwargs): - if not callpost: - cls.__dict__[func_name](self,**kwargs) - #end if - if block_name is None or not self.info[block_name]: - for name,value in self.iteritems(): - if isinstance(value,QAanalyzer): - value.traverse(value,func_name,block_name,callpost,**kwargs) - elif isinstance(value,QAanalyzerCollection): - for n,v in value.iteritems(): - if isinstance(v,QAanalyzer): - v.traverse(v,func_name,block_name,callpost,**kwargs) - #end if - #end for - #end if - #end for - #end if - if block_name!=None: - self.info[block_name] = True - #end if - if callpost: - cls.__dict__[func_name](self,**kwargs) - #end if - #end def traverse + #def traverse(self,function,block_name=None,callpost=True,**kwargs): + # if not callpost: + # cls.__dict__[func_name](self,**kwargs) + # #end if + # if block_name is None or not self.info[block_name]: + # for name,value in self.iteritems(): + # if isinstance(value,QAanalyzer): + # value.traverse(value,func_name,block_name,callpost,**kwargs) + # elif isinstance(value,QAanalyzerCollection): + # for n,v in value.iteritems(): + # if isinstance(v,QAanalyzer): + # v.traverse(v,func_name,block_name,callpost,**kwargs) + # #end if + # #end for + # #end if + # #end for + # #end if + # if block_name!=None: + # self.info[block_name] = True + # #end if + # if callpost: + # cls.__dict__[func_name](self,**kwargs) + # #end if + ##end def traverse def propagate_indicators(self,**kwargs): self.reset_indicators(**kwargs) diff --git a/nexus/library/qmcpack_converters.py b/nexus/library/qmcpack_converters.py new file mode 100644 index 000000000..dc39ce976 --- /dev/null +++ b/nexus/library/qmcpack_converters.py @@ -0,0 +1,786 @@ +################################################################## +## (c) Copyright 2015- by Jaron T. Krogel ## +################################################################## + + +#====================================================================# +# qmcpack_converters.py # +# Nexus interfaces for orbital converter tools of QMCPACK: # +# pw2qmcpack, wfconvert, and convert4qmc # +# # +# Content summary: # +# generate_pw2qmcpack # +# User-facing function to create pw2qmcpack simulation objects. # +# # +# generate_pw2qmcpack_input # +# User-facing funcion to create input for pw2qmcpack. # +# # +# Pw2qmcpack # +# Simulation class for pw2qmcpack. # +# # +# Pw2qmcpackInput # +# SimulationInput class for pw2qmcpack. # +# # +# Pw2qmcpackAnalyzer # +# SimulationAnalyzer class for pw2qmcpack. # +# # +# # +# WfconvertInput # +# SimulationInput class for wfconvert. # +# # +# WfconvertAnalyzer # +# SimulationAnalyzer class for wfconvert. # +# # +# Wfconvert # +# Simulation class for wfconvert. # +# # +# generate_wfconvert # +# User-facing function to generate wfconvert simulation objects.# +# # +# # +# Convert4qmcInput # +# Class representing command line interface of convert4qmc. # +# # +# Convert4qmcAnalyzer # +# Placeholder class for output analysis. # +# # +# Convert4qmc # +# Class representing conver4qmc instance. # +# # +# generate_convert4qmc_input # +# Function to generate arbitrary convert4qmc input. # +# # +# generate_convert4qmc # +# Function to generate Convert4qmc simulation object. # +# # +#====================================================================# + + + +import os +from generic import obj +from simulation import Simulation,SimulationInput,SimulationAnalyzer + + +# read/write functions associated with pw2qmcpack only +def read_str(sv): + return sv.strip('"').strip("'") +#end def read_str + +def read_int(sv): + return int(sv) +#end def read_int + +def read_float(sv): + return float(sv.replace('d','e').replace('D','e')) +#end def read_float + +bconv = {'.true.':True,'.false.':False} +def read_bool(sv): + return bconv[sv] +#end def read_bool + +def write_str(val): + return "'"+val+"'" +#end def write_str + +def write_int(val): + return str(val) +#end def write_int + +def write_float(val): + return str(val) +#end def write_float + +def write_bool(val): + return '.'+str(val).lower()+'.' +#end def write_bool + +readval={str:read_str,int:read_int,float:read_float,bool:read_bool} +writeval={str:write_str,int:write_int,float:write_float,bool:write_bool} + + +class Pw2qmcpackInput(SimulationInput): + ints = [] + floats = [] + strs = ['outdir','prefix'] + bools = ['write_psir'] + + var_types = dict() + for v in ints: + var_types[v]=int + for v in floats: + var_types[v]=float + for v in strs: + var_types[v]=str + for v in bools: + var_types[v]=bool + + allowed = set(ints+floats+strs+bools) + + def read_text(self,contents,filepath=None): + lines = contents.split('\n') + inside = False + for l in lines: + if inside: + tokens = l.split(',') + for t in tokens: + ts = t.strip() + if ts!='' and ts!='/': + name,value = ts.split('=') + name = name.strip() + value= value.strip() + if name in self.allowed: + vtype = self.var_types[name] + value = readval[vtype](value) + sobj[name]=value + else: + self.error('encountered unknown variable: '+name) + #end if + #end if + #end for + #end if + if '&' in l: + inside=True + section = l.lstrip('&').lower() + sobj = obj() + self[section]=sobj + elif l.strip()=='/': + inside=False + #end if + #end for + #end def read_text + + def write_text(self,filepath=None): + contents = '' + for sname,section in self.iteritems(): + contents+='&'+sname+'\n' + for name,value in section.iteritems(): + vtype = type(value) + contents += ' '+name+' = '+writeval[vtype](value)+'\n' + #end for + contents+='/\n' + #end for + return contents + #end def write_text + + + def __init__(self,filepath=None,**vars): + if filepath!=None: + self.read(filepath) + else: + inputpp = obj() + for name,value in vars.iteritems(): + inputpp[name] = value + #end for + self.inputpp = inputpp + #end if + #end def __init__ +#end class Pw2qmcpackInput + + +def generate_pw2qmcpack_input(prefix='pwscf',outdir='pwscf_output',write_psir=True): + pw = Pw2qmcpackInput( + prefix = prefix, + outdir = outdir, + write_psir = write_psir + ) + return pw +#end def generate_pw2qmcpack_input + + + +class Pw2qmcpackAnalyzer(SimulationAnalyzer): + def __init__(self,arg0): + if isinstance(arg0,Simulation): + sim = arg0 + self.infile = sim.infile + prefix,outdir = sim.input.inputpp.tuple('prefix','outdir') + self.dir = sim.locdir + self.h5file = os.path.join(sim.locdir,outdir,prefix+'.pwscf.h5') + else: + self.infile = arg0 + #end if + #end def __init__ + + def analyze(self): + if False: + import h5py + self.log('Fixing h5 file',n=5) + + path = os.path.split(self.h5file)[0] + print os.getcwd() + print os.listdir('./') + if os.path.exists(path): + print os.listdir(path) + #end if + print self.h5file + + h = h5py.File(self.h5file) + if 'electrons' in h: + elec = h['electrons'] + nkpoints = 0 + for name,val in elec.iteritems(): + if name.startswith('kpoint'): + nkpoints+=1 + #end for + #end if + nkold = elec['number_of_kpoints'][0] + self.log('Were',nkold,'kpoints, now',nkpoints,'kpoints',n=6) + elec['number_of_kpoints'][0] = nkpoints + #end for + #end if + #end def analyze + + def get_result(self,result_name): + self.not_implemented() + #end def get_result +#end class Pw2qmcpackAnalyzer + + +class Pw2qmcpack(Simulation): + input_type = Pw2qmcpackInput + analyzer_type = Pw2qmcpackAnalyzer + generic_identifier = 'pw2qmcpack' + application = 'pw2qmcpack.x' + application_properties = set(['serial']) + application_results = set(['orbitals']) + + def check_result(self,result_name,sim): + calculating_result = False + inputpp = self.input.inputpp + if result_name=='orbitals': + calculating_result = True + else: + calculating_result = False + self.error('ability to check for result '+result_name+' has not been implemented') + #end if + return calculating_result + #end def check_result + + def get_result(self,result_name,sim): + result = obj() + inputpp = self.input.inputpp + prefix = 'pwscf' + outdir = './' + if 'prefix' in inputpp: + prefix = inputpp.prefix + #end if + if 'outdir' in inputpp: + outdir = inputpp.outdir + #end if + if outdir.startswith('./'): + outdir = outdir[2:] + #end if + if result_name=='orbitals': + result.h5file = os.path.join(self.locdir,outdir,prefix+'.pwscf.h5') + result.ptcl_xml = os.path.join(self.locdir,outdir,prefix+'.ptcl.xml') + result.wfs_xml = os.path.join(self.locdir,outdir,prefix+'.wfs.xml') + else: + self.error('ability to get result '+result_name+' has not been implemented') + #end if + return result + #end def get_result + + def incorporate_result(self,result_name,result,sim): + if result_name=='orbitals': + pwin = sim.input.control + p2in = self.input.inputpp + pwprefix = 'pwscf' + p2prefix = 'pwscf' + pwoutdir = './' + p2outdir = './' + if 'prefix' in pwin: + pwprefix = pwin.prefix + if 'prefix' in p2in: + p2prefix = p2in.prefix + if 'outdir' in pwin: + pwoutdir = pwin.outdir + if 'outdir' in p2in: + p2outdir = p2in.outdir + if pwoutdir.startswith('./'): + pwoutdir = pwoutdir[2:] + if p2outdir.startswith('./'): + p2outdir = p2outdir[2:] + pwdir = os.path.abspath(os.path.join(sim.locdir ,pwoutdir)) + p2dir = os.path.abspath(os.path.join(self.locdir,p2outdir)) + errors = False + if pwdir!=p2dir: + self.error('to use orbitals, '+self.generic_identifier+' must have the same outdir as pwscf\n pwscf outdir: '+pwdir+'\n '+self.generic_identifier+' outdir: '+p2dir,exit=False) + errors = True + #end if + if pwprefix!=p2prefix: + self.error('to use orbitals, '+self.generic_identifier+' must have the same prefix as pwscf\n pwscf prefix: '+pwprefix+'\n '+self.generic_identifier+' prefix: '+p2prefix,exit=False) + errors = True + #end if + if errors: + self.error(self.generic_identifier+' cannot use orbitals from pwscf') + #end if + else: + self.error('ability to incorporate result '+result_name+' has not been implemented') + #end if + #end def incorporate_result + + def check_sim_status(self): + outfile = os.path.join(self.locdir,self.outfile) + fobj = open(outfile,'r') + output = fobj.read() + fobj.close() + inputpp = self.input.inputpp + prefix = 'pwscf' + outdir = './' + if 'prefix' in inputpp: + prefix = inputpp.prefix + #end if + if 'outdir' in inputpp: + outdir = inputpp.outdir + #end if + if outdir.startswith('./'): + outdir = outdir[2:] + #end if + h5file = os.path.join(self.locdir,outdir,prefix+'.pwscf.h5') + ptcl_xml = os.path.join(self.locdir,outdir,prefix+'.ptcl.xml') + wfs_xml = os.path.join(self.locdir,outdir,prefix+'.wfs.xml') + must_exist = [h5file,ptcl_xml,wfs_xml] + + files_exist = True + for file in must_exist: + files_exist = files_exist and os.path.exists(file) + #end for + outfin = True + #outfin = outfin and 'esh5 create' in output + #outfin = outfin and 'Creating electrons' in output + outfin = outfin and 'npw=' in output + outfin = outfin and 'ik=' in output + + outfin = outfin or 'JOB DONE' in output + + success = files_exist and outfin + + #self.finished = success and self.job.finished + + # pw2qmcpack has too many variants to assess completion based on log output + # assume (optimistically) that job completion indicates success + self.finished = files_exist and self.job.finished + #end def check_sim_status + + def get_output_files(self): + output_files = [] + return output_files + #end def get_output_files + + def app_command(self): + return self.app_name+'<'+self.infile + #end def app_command +#end class Pw2qmcpack + + + + +def generate_pw2qmcpack(**kwargs): + sim_args,inp_args = Simulation.separate_inputs(kwargs) + + if not 'input' in sim_args: + sim_args.input = generate_pw2qmcpack_input(**inp_args) + #end if + pw2qmcpack = Pw2qmcpack(**sim_args) + + return pw2qmcpack +#end def generate_pw2qmcpack + + + + + + + + + + + + + + + +class WfconvertInput(SimulationInput): + def __init__(self,app_name='wfconvert',h5in='MISSING.h5',h5out='wfconvert.h5',spline=False,format='eshdf',factor=None): + self.app_name = app_name + self.h5in = h5in + self.h5out= h5out + self.spline = spline + self.format = format + self.factor = factor + #end def __init__ + +#wfconvert --nospline --eshdf diamond.h5 out/diamond.pwscf.h5 >& diamond-wfconvert.out + def set_app_name(self,app_name): + self.app_name = app_name + #end def set_app_name + + def app_command(self): + c = self.app_name+' ' + if not self.spline: + c+= '--nospline ' + #end if + c+='--'+self.format+' '+self.h5out+' '+self.h5in + return c + #end def app_command + + + def read(self,filepath): + None + #end def read + + def write_text(self,filepath=None): + return self.app_command() + #end def write_text +#end class WfconvertInput + + +def generate_wfconvert_input(app_name='wfconvert',h5in='MISSING.h5',h5out='wfconvert.h5',spline=False,format='eshdf',factor=None): + wi = WfconvertInput( + app_name = app_name, + h5in = h5in, + h5out = h5out, + spline = spline, + format = format, + factor = factor + ) + return wi +#end def generate_wfconvert_input + + +class WfconvertAnalyzer(SimulationAnalyzer): + def __init__(self,arg0): + if isinstance(arg0,Simulation): + sim = arg0 + self.infile = sim.infile + self.dir = sim.locdir + self.h5file = os.path.join(sim.locdir,sim.input.h5out) + else: + self.infile = arg0 + #end if + #end def __init__ + + def analyze(self): + if False: + import h5py + self.log('Fixing h5 file',n=5) + h = h5py.File(self.h5file) + if 'electrons' in h: + elec = h['electrons'] + nkpoints = 0 + for name,val in elec.iteritems(): + if name.startswith('kpoint'): + nkpoints+=1 + #end for + #end if + nkold = elec['number_of_kpoints'][0] + self.log('Were',nkold,'kpoints, now',nkpoints,'kpoints',n=6) + elec['number_of_kpoints'][0] = nkpoints + #end for + #end if + #end def analyze +#end class WfconvertAnalyzer + + + +class Wfconvert(Simulation): + input_type = WfconvertInput + analyzer_type = WfconvertAnalyzer + generic_identifier = 'wfconvert' + application = 'wfconvert' + application_properties = set(['serial']) + application_results = set(['orbitals']) + + def set_app_name(self,app_name): + self.app_name = app_name + self.input.set_app_name(app_name) + #end def set_app_name + + def check_result(self,result_name,sim): + calculating_result = False + if result_name=='orbitals': + calculating_result = True + else: + calculating_result = False + self.error('ability to check for result '+result_name+' has not been implemented') + #end if + return calculating_result + #end def check_result + + def get_result(self,result_name,sim): + result = obj() + if result_name=='orbitals': + result.h5file = os.path.join(self.locdir,self.input.h5out) + result.outfile = os.path.join(self.locdir,self.outfile) + else: + self.error('ability to get result '+result_name+' has not been implemented') + #end if + return result + #end def get_result + + def incorporate_result(self,result_name,result,sim): + if result_name=='orbitals': + self.input.h5in = os.path.relpath(result.h5file,self.locdir) + self.job.app_command = self.input.app_command() + else: + self.error('ability to incorporate result '+result_name+' has not been implemented') + #end if + #end def incorporate_result + + def check_sim_status(self): + outfile = os.path.join(self.locdir,self.outfile) + errfile = os.path.join(self.locdir,self.errfile) + fobj = open(outfile,'r') + output = fobj.read() + fobj.close() + fobj = open(errfile,'r') + errors = fobj.read() + fobj.close() + h5file = os.path.join(self.locdir,self.input.h5out) + file_exists = os.path.exists(h5file) + outfin = 'Successfully read' in errors and 'numSpins' in errors + outfin = outfin and 'Writing laplacians' in output + + success = file_exists and outfin + + self.finished = success + #end def check_sim_status + + def get_output_files(self): + output_files = [] + return output_files + #end def get_output_files + + def app_command(self): + # app_name is passed along in post_init + return self.input.app_command() + #end def app_command +#end class Wfconvert + + + + +def generate_wfconvert(**kwargs): + sim_args,inp_args = Simulation.separate_inputs(kwargs) + + if not 'input' in sim_args: + sim_args.input = generate_wfconvert_input(**inp_args) + #end if + wfconvert = Wfconvert(**sim_args) + + return wfconvert +#end def generate_wfconvert + + + + + + + + + +class Convert4qmcInput(SimulationInput): + def __init__(self, + app_name = 'convert4qmc', + prefix = None, + gamess_ascii = None, + ci = None, + read_initial_guess = None, + natural_orbitals = None, + threshold = None, + zero_ci = False, + add_3body_J = False + ): + self.prefix = prefix + self.app_name = app_name + self.gamess_ascii = gamess_ascii + self.ci = ci + self.read_initial_guess = read_initial_guess + self.natural_orbitals = natural_orbitals + self.threshold = threshold + self.zero_ci = zero_ci + self.add_3body_J = add_3body_J + #end def __init__ + + def set_app_name(self,app_name): + self.app_name = app_name + #end def set_app_name + + def app_command(self): + c = self.app_name + if self.prefix!=None: + c += ' -prefix '+self.prefix + #end if + if self.gamess_ascii!=None: + c += ' -gamessAscii '+self.gamess_ascii + #end if + if self.ci!=None: + c += ' -ci '+self.ci + #end if + if self.threshold!=None: + c += ' -threshold '+str(self.threshold) + #end if + if self.zero_ci: + c += ' -zeroCi' + #end if + if self.read_initial_guess!=None: + c += ' -readInitialGuess '+str(self.read_initial_guess) + #end if + if self.natural_orbitals!=None: + c += ' -NaturalOrbitals '+str(self.natural_orbitals) + #end if + if self.add_3body_J: + c += ' -add3BodyJ' + #end if + return c + #end def app_command + + def read(self,filepath): + None + #end def read + + def write_text(self,filepath=None): + return self.app_command() + #end def write_text + + def output_files(self): + prefix = 'sample' + if self.prefix!=None: + prefix = self.prefix + #end if + wfn_file = prefix+'.Gaussian-G2.xml' + ptcl_file = prefix+'.Gaussian-G2.ptcl.xml' + return wfn_file,ptcl_file + #end def output_files +#end class Convert4qmcInput + + +def generate_convert4qmc_input(**kwargs): + return Convert4qmcInput(**kwargs) +#end def generate_convert4qmc_input + + +class Convert4qmcAnalyzer(SimulationAnalyzer): + def __init__(self,arg0): + if isinstance(arg0,Simulation): + self.infile = arg0.infile + else: + self.infile = arg0 + #end if + #end def __init__ + + def analyze(self): + None + #end def analyze +#end class Convert4qmcAnalyzer + + + +class Convert4qmc(Simulation): + input_type = Convert4qmcInput + analyzer_type = Convert4qmcAnalyzer + generic_identifier = 'convert4qmc' + application = 'convert4qmc' + application_properties = set(['serial']) + application_results = set(['orbitals']) + + def set_app_name(self,app_name): + self.app_name = app_name + self.input.set_app_name(app_name) + #end def set_app_name + + def propagate_identifier(self): + None + #self.input.prefix = self.identifier + #end def propagate_identifier + + def check_result(self,result_name,sim): + calculating_result = False + if result_name=='orbitals': + calculating_result = True + else: + calculating_result = False + self.error('ability to check for result '+result_name+' has not been implemented') + #end if + return calculating_result + #end def check_result + + def get_result(self,result_name,sim): + result = obj() + input = self.input + if result_name=='orbitals': + wfn_file,ptcl_file = input.output_files() + result.location = os.path.join(self.locdir,wfn_file) + else: + self.error('ability to get result '+result_name+' has not been implemented') + #end if + return result + #end def get_result + + def incorporate_result(self,result_name,result,sim): + if result_name=='orbitals': + orbpath = os.path.relpath(result.location,self.locdir) + if result.scftyp=='mcscf': + self.input.gamess_ascii = orbpath + self.input.ci = orbpath + elif result.scftyp=='none': # cisd, etc + self.input.gamess_ascii = orbpath + self.input.ci = orbpath + if result.mos>0: + self.input.read_initial_guess = result.mos + elif result.norbitals>0: + self.input.read_initial_guess = result.norbitals + #end if + else: + self.input.gamess_ascii = orbpath + #end if + self.job.app_command = self.input.app_command() + else: + self.error('ability to incorporate result '+result_name+' has not been implemented') + #end if + #end def incorporate_result + + def check_sim_status(self): + output = open(os.path.join(self.locdir,self.outfile),'r').read() + #errors = open(os.path.join(self.locdir,self.errfile),'r').read() + + success = 'QMCGaussianParserBase::dump' in output + for filename in self.input.output_files(): + success &= os.path.exists(os.path.join(self.locdir,filename)) + #end for + + self.failed = not success + self.finished = self.job.finished + #end def check_sim_status + + def get_output_files(self): + output_files = [] + return output_files + #end def get_output_files + + def app_command(self): + return self.input.app_command() + #end def app_command +#end class Convert4qmc + + + + + + + +def generate_convert4qmc(**kwargs): + sim_args,inp_args = Simulation.separate_inputs(kwargs) + if 'identifier' in sim_args and not 'prefix' in inp_args: + inp_args.prefix = sim_args.identifier + #end if + + if not 'input' in sim_args: + sim_args.input = generate_convert4qmc_input(**inp_args) + #end if + convert4qmc = Convert4qmc(**sim_args) + + return convert4qmc +#end def generate_convert4qmc diff --git a/nexus/library/qmcpack_input.py b/nexus/library/qmcpack_input.py index 70ff110d5..6898b7f1a 100644 --- a/nexus/library/qmcpack_input.py +++ b/nexus/library/qmcpack_input.py @@ -133,7 +133,7 @@ import os -import types as pytypes +import inspect import keyword from numpy import fromstring,empty,array,float64,\ loadtxt,ndarray,dtype,sqrt,pi,arange,exp,eye,\ @@ -142,12 +142,11 @@ from StringIO import StringIO from superstring import string2val from generic import obj,hidden from xmlreader import XMLreader,XMLelement -from project_base import Pobj +from developer import DevBase from structure import Structure,Jellium from physical_system import PhysicalSystem from simulation import SimulationInput,SimulationInputTemplate from pwscf_input import array_to_string as pwscf_array_string -from debug import * from debug import ci as interact @@ -238,7 +237,7 @@ bool_write_types = set([yesno,onezero,truefalse]) -class QIobj(Pobj): +class QIobj(DevBase): None #end class QIobj @@ -488,30 +487,25 @@ class QIxml(Names): @classmethod def init_class(cls): - vars = cls.__dict__.keys() - init_vars = dict(tag = cls.__name__, - identifier = None, - attributes = [], - elements = [], - text = None, - parameters = [], - attribs = [], - costs = [], - h5tags = [], - types = obj(), - write_types = obj(), - attr_types = None, - precision = None, - defaults = obj(), - collection_id = None - ) - for var,val in init_vars.iteritems(): - if not var in vars: - cls.__dict__[var] = val - #end if - #end for + cls.class_set_optional( + tag = cls.__name__, + identifier = None, + attributes = [], + elements = [], + text = None, + parameters = [], + attribs = [], + costs = [], + h5tags = [], + types = obj(), + write_types = obj(), + attr_types = None, + precision = None, + defaults = obj(), + collection_id = None + ) for v in ['attributes','elements','parameters','attribs','costs','h5tags']: - names = cls.__dict__[v] + names = cls.class_get(v) for i in range(len(names)): if names[i] in cls.escape_names: names[i]+='_' @@ -599,7 +593,7 @@ class QIxml(Names): if e in self: elem = self[e] if isinstance(elem,QIxml): - c += self[e].write(indent_level+1) + c += elem.write(indent_level+1) else: begin = '<'+e+'>' contents = param.write(elem) @@ -629,6 +623,7 @@ class QIxml(Names): c+=indent+'\n' #end if param.reset_precision() + return c #end def write @@ -797,7 +792,6 @@ class QIxml(Names): def incorporate_defaults(self,elements=False,overwrite=False,propagate=True): for name,value in self.defaults.iteritems(): - valtype = type(value) defval=None if isinstance(value,classcollection): if elements: @@ -809,11 +803,11 @@ class QIxml(Names): #end for defval = make_collection(coll) #end if - elif valtype==pytypes.ClassType: + elif inspect.isclass(value): if elements: defval = value() #end if - elif valtype==pytypes.FunctionType: + elif inspect.isfunction(value): defval = value() else: defval = value @@ -1393,7 +1387,7 @@ class QIxml(Names): #end def get_host def get_precision(self): - return self.__class__.__dict__['precision'] + return self.__class__.class_get('precision') #end def get_precision #end class QIxml @@ -2825,7 +2819,7 @@ class QmcpackInput(SimulationInput,Names): #end def read - def write_contents(self): + def write_text(self,filepath=None): c = '' header = ''' ''' @@ -2839,7 +2833,7 @@ class QmcpackInput(SimulationInput,Names): c+=base.write(first=True) Param.metadata = None return c - #end def write_contents + #end def write_text def unroll_calculations(self,modify=True): @@ -3757,6 +3751,8 @@ class QmcpackInput(SimulationInput,Names): +# base class for bundled qmcpack input +# not used on its own class BundledQmcpackInput(SimulationInput): def __init__(self,inputs,filenames): @@ -3799,8 +3795,8 @@ class BundledQmcpackInput(SimulationInput): #end def get_output_info - def generate_filenames(self): - None + def generate_filenames(self,infile): + self.not_implemented() #end def generate_filenames @@ -3845,6 +3841,7 @@ class TracedQmcpackInput(BundledQmcpackInput): self.quantities = obj() self.variables = obj() self.inputs = obj() + self.filenames = None if quantity!=None and values!=None and input!=None: self.bundle_inputs(quantity,values,input) #end if diff --git a/nexus/library/qmcpack_method_analyzers.py b/nexus/library/qmcpack_method_analyzers.py index df8deb1de..00d02b92f 100644 --- a/nexus/library/qmcpack_method_analyzers.py +++ b/nexus/library/qmcpack_method_analyzers.py @@ -21,8 +21,7 @@ import os import re from generic import obj from hdfreader import HDFreader -from qaobject import Checks -from qmcpack_analyzer_base import QAanalyzer,QAdata,QAHDFdata +from qmcpack_analyzer_base import Checks,QAanalyzer,QAdata,QAHDFdata from qmcpack_property_analyzers import WavefunctionAnalyzer from qmcpack_quantity_analyzers import HDFAnalyzer from debug import * diff --git a/nexus/library/qmcpack_property_analyzers.py b/nexus/library/qmcpack_property_analyzers.py index 18a4d498e..3ffc4e1c7 100644 --- a/nexus/library/qmcpack_property_analyzers.py +++ b/nexus/library/qmcpack_property_analyzers.py @@ -38,8 +38,7 @@ import os from numpy import loadtxt,array,ones,dot,floor,zeros from qmcpack_input import QmcpackInput -from qaobject import QAobject -from qmcpack_analyzer_base import QAanalyzer +from qmcpack_analyzer_base import QAobject,QAanalyzer from developer import unavailable from debug import * try: diff --git a/nexus/library/qmcpack_quantity_analyzers.py b/nexus/library/qmcpack_quantity_analyzers.py index 7a720c5ab..c10d1a153 100644 --- a/nexus/library/qmcpack_quantity_analyzers.py +++ b/nexus/library/qmcpack_quantity_analyzers.py @@ -58,6 +58,12 @@ # Can read multiple traces.h5 files and validate against # # data contained in scalars.dat and dmc.dat. # # # +# SpaceGrid # +# Specifically for energy density analysis # +# Represents a grid of data in 3-dimensional space. # +# Can represent rectilinear grids in Cartesian, cylindrical, or # +# or spherical coordinates as well as Voronoi grids. # +# # #====================================================================# @@ -69,11 +75,10 @@ try: except Exception: from numpy.linalg import eig,LinAlgError #end try -from extended_numpy import ndgrid,simstats,simplestats,equilibration_length +from numerics import ndgrid,simstats,simplestats,equilibration_length from generic import obj from hdfreader import HDFreader -from qaobject import QAobject -from qmcpack_analyzer_base import QAanalyzer,QAdata,QAHDFdata +from qmcpack_analyzer_base import QAobject,QAanalyzer,QAdata,QAHDFdata from fileio import XsfFile from debug import * @@ -423,8 +428,6 @@ class EnergyDensityAnalyzer(HDFAnalyzer): def analyze_local(self): - from spacegrid import SpaceGrid - nbe = QAanalyzer.method_info.nblocks_exclude self.info.nblocks_exclude = nbe data = self.data @@ -577,24 +580,24 @@ class EnergyDensityAnalyzer(HDFAnalyzer): #end def remove_data - def prev_init(self): - if data._contains_group("spacegrid1"): - self.points = data.spacegrid1.domain_centers - self.axinv = data.spacegrid1.axinv - val = data.spacegrid1.value - npoints,ndim = self.points.shape - self.E = zeros((npoints,)) - print 'p shape ',self.points.shape - print 'v shape ',val.shape - nblocks,nvpoints = val.shape - for b in range(nblocks): - for i in range(npoints): - ind = 6*i - self.E[i] += val[b,ind+1] + val[b,ind+2] - #end for - #end for - #end if - #end def prev_init + #def prev_init(self): + # if data._contains_group("spacegrid1"): + # self.points = data.spacegrid1.domain_centers + # self.axinv = data.spacegrid1.axinv + # val = data.spacegrid1.value + # npoints,ndim = self.points.shape + # self.E = zeros((npoints,)) + # print 'p shape ',self.points.shape + # print 'v shape ',val.shape + # nblocks,nvpoints = val.shape + # for b in range(nblocks): + # for i in range(npoints): + # ind = 6*i + # self.E[i] += val[b,ind+1] + val[b,ind+2] + # #end for + # #end for + # #end if + ##end def prev_init @@ -2032,4 +2035,1328 @@ class DensityAnalyzer(DensityAnalyzerBase): self.write_single_density('density',self.mean,self.error,format) #end def write_density #end class DensityAnalyzer + + + + + + + +# spacegrid code + +import re +import copy +from numpy import array,floor,sqrt,zeros,prod,dot,ones,empty,min,max +from numpy import pi,sin,cos,arccos as acos,arctan2 as atan2 +from numpy.linalg import inv,det +from numerics import simplestats,ndgrid,ogrid,arange,simstats +from hdfreader import HDFgroup + +#simple constants +o2pi = 1./(2.*pi) + +#simple functions +def is_integer(i): + return abs(floor(i)-i)<1e-6 +#end def is_integer + + +class SpaceGridInitializer(QAobject): + def __init__(self): + self.coord = None # string + return + #end def __init__ + + def check_complete(self,exit_on_fail=True): + succeeded = True + for k,v in self._iteritems(): + if v==None: + succeeded=False + if exit_on_fail: + self.error(' SpaceGridInitializer.'+k+' must be provided',exit=False) + #end if + #end if + #end if + if not succeeded and exit_on_fail: + self.error(' SpaceGridInitializer is incomplete') + #end if + return succeeded + #end def check_complete +#end class SpaceGridInitializer + + +class SpaceGridBase(QAobject): + cnames=['cartesian','cylindrical','spherical','voronoi'] + coord_s2n = dict() + coord_n2s = dict() + i=0 + for name in cnames: + exec name+'='+str(i) + coord_s2n[name]=i + coord_n2s[i]=name + i+=1 + #end for + + xlabel = 0 + ylabel = 1 + zlabel = 2 + rlabel = 3 + plabel = 4 + tlabel = 5 + axlabel_s2n = {'x':xlabel,'y':ylabel,'z':zlabel,'r':rlabel,'phi':plabel,'theta':tlabel} + axlabel_n2s = {xlabel:'x',ylabel:'y',zlabel:'z',rlabel:'r',plabel:'phi',tlabel:'theta'} + + axindex = {'x':0,'y':1,'z':2,'r':0,'phi':1,'theta':2} + + quantities=['D','T','V','E','P'] + + def __init__(self,initobj,options): + if options==None: + options = QAobject() + options.wasNone = True + options.points = None + options.exit_on_fail = True + options.nblocks_exclude = 0 + else: + if 'points' not in options: + options.points = None + if 'exit_on_fail' not in options: + options.exit_on_fail = True + if 'nblocks_exclude' not in options: + options.nblocks_exclude = 0 + #end if + + self.points = options.points + self.init_exit_fail = options.exit_on_fail + self.nblocks_exclude = options.nblocks_exclude + self.keep_data = True + delvars = ['init_exit_fail','keep_data'] + + self.coord = None # string + self.coordinate = None + self.ndomains = None + self.domain_volumes = None + self.domain_centers = None + self.nvalues_per_domain = -1 + self.nblocks = -1 + self.D = QAobject() #Number Density + self.T = QAobject() #Kinetic Energy Density + self.V = QAobject() #Potential Energy Density + self.E = QAobject() #Energy Density, T+V + self.P = QAobject() #Local Pressure, (Volume)*P=(2*T+V)/3 + + + self.init_special() + + if initobj==None: + return + #end if + + self.DIM=3 + + iname = initobj.__class__.__name__ + self.iname=iname + if iname==self.__class__.__name__+'Initializer': + self.init_from_initializer(initobj) + elif iname==self.__class__.__name__: + self.init_from_spacegrid(initobj) + elif iname=='HDFgroup': + self.init_from_hdfgroup(initobj) + elif iname=='XMLelement': + self.init_from_xmlelement(initobj) + else: + self.error('Spacegrid cannot be initialized from '+iname) + #end if + delvars.append('iname') + + self.check_complete() + + for dv in delvars: + del self[dv] + #end for + + self._reset_dynamic_methods() + self._register_dynamic_methods() + return + #end def __init__ + + def copy(self,other): + None + #end def copy + + def init_special(self): + None + #end def init_special + + def init_from_initializer(self,init): + None + #end def init_from_initializer + + def init_from_spacegrid(self,init): + None + #end def init_from_spacegrid + + def init_from_hdfgroup(self,init): + #copy all datasets from hdf group + value_pattern = re.compile('value') + gmap_pattern = re.compile(r'gmap\d*') + for k,v in init._iteritems(): + exclude = k[0]=='_' or gmap_pattern.match(k) or value_pattern.match(k) + if not exclude: + self[k]=v + #end if + #end for + + #convert 1x and 1x1 numpy arrays to just numbers + #convert Nx1 and 1xN numpy arrays to Nx arrays + array_type = type(array([])) + exclude = set(['value','value_squared']) + for k,v in self._iteritems(): + if k[0]!='_' and type(v)==array_type and k not in exclude: + sh=v.shape + ndim = len(sh) + if ndim==1 and sh[0]==1: + self[k]=v[0] + elif ndim==2: + if sh[0]==1 and sh[1]==1: + self[k]=v[0,0] + elif sh[0]==1 or sh[1]==1: + self[k]=v.reshape((sh[0]*sh[1],)) + #end if + #end if + #end if + #end for + + #set coord string + self.coord = SpaceGridBase.coord_n2s[self.coordinate] + + #determine if chempot grid + chempot = 'min_part' in init + self.chempot = chempot + if chempot: + npvalues = self.max_part-self.min_part+1 + self.npvalues = npvalues + #end if + + #process the data in hdf value,value_squared + nbe = self.nblocks_exclude + nquant = self.nvalues_per_domain + ndomains = self.ndomains + nblocks,ntmp = init.value.shape + self.nblocks = nblocks + + if not chempot: + value = init.value.reshape(nblocks,ndomains,nquant).transpose(2,1,0) + else: + value = init.value.reshape(nblocks,ndomains,npvalues,nquant).transpose(3,2,1,0) + #end if + value = value[...,nbe:] + + #(mean,error)=simplestats(value) + (mean,var,error,kappa)=simstats(value) + quants = ['D','T','V'] + for i in range(len(quants)): + q=quants[i] + self[q].mean = mean[i,...] + self[q].error = error[i,...] + exec 'i'+q+'='+str(i) + #end for + + E = value[iT,...]+value[iV,...] +# (mean,error)=simplestats(E) + (mean,var,error,kappa)=simstats(E) + self.E.mean = mean + self.E.error = error + + P = 2./3.*value[iT,...]+1./3.*value[iV,...] + #(mean,error)=simplestats(P) + (mean,var,error,kappa)=simstats(P) + self.P.mean = mean + self.P.error = error + + + #convert all quantities into true densities + ovol = 1./self.domain_volumes + sqovol = sqrt(ovol) + for q in SpaceGridBase.quantities: + self[q].mean *= ovol + self[q].error *= sqovol + #end for + + #keep original data, if requested + if self.keep_data: + self.data = QAobject() + for i in range(len(quants)): + q=quants[i] + self.data[q] = value[i,...] + #end for + self.data.E = E + self.data.P = P + #end if + + #print 'sg' + #import code + #code.interact(local=locals()) + + return + #end def init_from_hdfgroup + + def init_from_xmlelement(self,init): + None + #end def init_from_xmlelement + + def check_complete(self,exit_on_fail=True): + succeeded = True + for k,v in self._iteritems(): + if k[0]!='_' and v==None: + succeeded=False + if exit_on_fail: + self.error('SpaceGridBase.'+k+' must be provided',exit=False) + #end if + #end if + #end if + if not succeeded: + self.error('SpaceGrid attempted initialization from '+self.iname,exit=False) + self.error('SpaceGrid is incomplete',exit=False) + if exit_on_fail: + exit() + #end if + #end if + return succeeded + #end def check_complete + + def _reset_dynamic_methods(self): + None + #end def _reset_dynamic_methods + + def _unset_dynamic_methods(self): + None + #end def _unset_dynamic_methods + + def add_all_attributes(self,o): + for k,v in o.__dict__.iteritems(): + if not k.startswith('_'): + vc = copy.deepcopy(v) + self._add_attribute(k,vc) + #end if + #end for + return + #end def add_all_attributes + + + def reorder_atomic_data(self,imap): + None + #end if + + + def integrate(self,quantity,domain=None): + if quantity not in SpaceGridBase.quantities: + msg = 'requested integration of quantity '+quantity+'\n' + msg +=' '+quantity+' is not a valid SpaceGrid quantity\n' + msg +=' valid quantities are:\n' + msg +=' '+str(SpaceGridBase.quantities) + self.error(msg) + #end if + dv = self.domain_volumes + if domain==None: + mean = (self[quantity].mean*dv).sum() + error = sqrt((self[quantity].error**2*dv).sum()) + else: + mean = (self[quantity].mean[domain]*dv[domain]).sum() + error = sqrt((self[quantity].error[domain]**2*dv[domain]).sum()) + #end if + return mean,error + #end def integrate + + def integrate_data(self,quantity,*domains,**kwargs): + return_list = False + if 'domains' in kwargs: + domains = kwargs['domains'] + return_list = True + #end if + if 'return_list' in kwargs: + return_list = kwargs['return_list'] + #end if + if quantity not in SpaceGridBase.quantities: + msg = 'requested integration of quantity '+quantity+'\n' + msg +=' '+quantity+' is not a valid SpaceGrid quantity\n' + msg +=' valid quantities are:\n' + msg +=' '+str(SpaceGridBase.quantities) + self.error(msg) + #end if + q = self.data[quantity] + results = list() + nblocks = q.shape[-1] + qi = zeros((nblocks,)) + if len(domains)==0: + for b in xrange(nblocks): + qi[b] = q[...,b].sum() + #end for + (mean,var,error,kappa)=simstats(qi) + else: + for domain in domains: + for b in xrange(nblocks): + qb = q[...,b] + qi[b] = qb[domain].sum() + #end for + (mean,var,error,kappa)=simstats(qi) + res = QAobject() + res.mean = mean + res.error = error + res.data = qi.copy() + results.append(res) + #end for + #end for + if len(domains)<2: + return mean,error + else: + if not return_list: + return tuple(results) + else: + means = list() + errors = list() + for res in results: + means.append(res.mean) + errors.append(res.error) + #end for + return means,errors + #end if + #end if + #end def integrate_data + +#end class SpaceGridBase + + + + +class RectilinearGridInitializer(SpaceGridInitializer): + def __init__(self): + SpaceGridInitializer.__init__(self) + self.origin = None # 3x1 array + self.axes = None # 3x3 array + self.axlabel = None # 3x1 string list + self.axgrid = None # 3x1 string list + #end def __init__ +#end class RectilinearGridInitializer + + +class RectilinearGrid(SpaceGridBase): + def __init__(self,initobj=None,options=None): + SpaceGridBase.__init__(self,initobj,options) + return + #end def __init__ + + def init_special(self): + self.origin = None # 3x1 array + self.axes = None # 3x3 array + self.axlabel = None # 3x1 string list + self.axinv = None + self.volume = None + self.dimensions = None + self.gmap = None + self.umin = None + self.umax = None + self.odu = None + self.dm = None + self.domain_uwidths = None + return + #end def init_special + + def copy(self): + return RectilinearGrid(self) + #end def copy + + def _reset_dynamic_methods(self): + p2d=[self.points2domains_cartesian, \ + self.points2domains_cylindrical, \ + self.points2domains_spherical] + self.points2domains = p2d[self.coordinate] + + p2u=[self.point2unit_cartesian, \ + self.point2unit_cylindrical, \ + self.point2unit_spherical] + self.point2unit = p2u[self.coordinate] + return + #end def _reset_dynamic_methods + + def _unset_dynamic_methods(self): + self.points2domains = None + self.point2unit = None + return + #end def _unset_dynamic_methods + + def init_from_initializer(self,init): + init.check_complete() + for k,v in init._iteritems(): + if k[0]!='_': + self[k]=v + #end if + #end for + self.initialize() + return + #end def init_from_initializer + + def init_from_spacegrid(self,init): + for q in SpaceGridBase.quantities: + self[q].mean = init[q].mean.copy() + self[q].error = init[q].error.copy() + #end for + array_type = type(array([1])) + exclude = set(['point2unit','points2domains','points']) + for k,v in init._iteritems(): + if k[0]!='_': + vtype = type(v) + if k in SpaceGridBase.quantities: + self[k].mean = v.mean.copy() + self[k].error = v.error.copy() + elif vtype==array_type: + self[k] = v.copy() + elif vtype==HDFgroup: + self[k] = v + elif k in exclude: + None + else: + self[k] = vtype(v) + #end if + #end for + #end for + self.points = init.points + return + #end def init_from_spacegrid + + def init_from_hdfgroup(self,init): + SpaceGridBase.init_from_hdfgroup(self,init) + self.gmap=[init.gmap1,init.gmap2,init.gmap3] + #set axlabel strings + self.axlabel=list() + for d in range(self.DIM): + label = SpaceGridBase.axlabel_n2s[self.axtypes[d]] + self.axlabel.append(label) + #end for + del self.axtypes + for i in range(len(self.gmap)): + self.gmap[i]=self.gmap[i].reshape((len(self.gmap[i]),)) + #end for + return + #end def init_from_hdfgroup + + + def init_from_xmlelement(self,init): + DIM=self.DIM + self.axlabel=list() + self.axgrid =list() + #coord + self.coord = init.coord + #origin + p1 = self.points[init.origin.p1] + if 'p2' in init.origin: + p2 = self.points[init.origin.p2] + else: + p2 = self.points['zero'] + #end if + if 'fraction' in init.origin: + frac = eval(init.origin.fraction) + else: + frac = 0.0 + self.origin = p1 + frac*(p2-p1) + #axes + self.axes = zeros((DIM,DIM)) + for d in range(DIM): + exec 'axis=init.axis'+str(d+1) + p1 = self.points[axis.p1] + if 'p2' in axis: + p2 = self.points[axis.p2] + else: + p2 = self.points['zero'] + #end if + if 'scale' in axis: + scale = eval(axis.scale) + else: + scale = 1.0 + #end if + for dd in range(DIM): + self.axes[dd,d] = scale*(p1[dd]-p2[dd]) + #end for + self.axlabel.append(axis.label) + self.axgrid.append(axis.grid) + #end for + self.initialize() + return + #end def init_from_xmlelement + + def initialize(self): #like qmcpack SpaceGridBase.initialize + write=False + succeeded=True + + ndomains=-1 + + DIM = self.DIM + + coord = self.coord + origin = self.origin + axes = self.axes + axlabel = self.axlabel + axgrid = self.axgrid + del self.axgrid + + + + ax_cartesian = ["x" , "y" , "z" ] + ax_cylindrical = ["r" , "phi" , "z" ] + ax_spherical = ["r" , "phi" , "theta"] + + cmap = dict() + if(coord=="cartesian"): + for d in range(DIM): + cmap[ax_cartesian[d]]=d + axlabel[d]=ax_cartesian[d] + #end + elif(coord=="cylindrical"): + for d in range(DIM): + cmap[ax_cylindrical[d]]=d + axlabel[d]=ax_cylindrical[d] + #end + elif(coord=="spherical"): + for d in range(DIM): + cmap[ax_spherical[d]]=d + axlabel[d]=ax_spherical[d] + #end + else: + self.error(" Coordinate supplied to spacegrid must be cartesian, cylindrical, or spherical\n You provided "+coord,exit=False) + succeeded=False + #end + self.coordinate = SpaceGridBase.coord_s2n[self.coord] + coordinate = self.coordinate + + + #loop over spacegrid xml elements + naxes =DIM + # variables for loop + utol = 1e-5 + dimensions=zeros((DIM,),dtype=int) + umin=zeros((DIM,)) + umax=zeros((DIM,)) + odu=zeros((DIM,)) + ndu_per_interval=[None,None,None] + gmap=[None,None,None] + for dd in range(DIM): + iaxis = cmap[axlabel[dd]] + grid = axgrid[dd] + #read in the grid contents + # remove spaces inside of parentheses + inparen=False + gtmp='' + for gc in grid: + if(gc=='('): + inparen=True + gtmp+=' ' + #end + if(not(inparen and gc==' ')): + gtmp+=gc + if(gc==')'): + inparen=False + gtmp+=' ' + #end + #end + grid=gtmp + # break into tokens + tokens = grid.split() + if(write): + print " grid = ",grid + print " tokens = ",tokens + #end + # count the number of intervals + nintervals=0 + for t in tokens: + if t[0]!='(': + nintervals+=1 + #end + #end + nintervals-=1 + if(write): + print " nintervals = ",nintervals + # allocate temporary interval variables + ndom_int = zeros((nintervals,),dtype=int) + du_int = zeros((nintervals,)) + ndu_int = zeros((nintervals,),dtype=int) + # determine number of domains in each interval and the width of each domain + u1=1.0*eval(tokens[0]) + umin[iaxis]=u1 + if(abs(u1)>1.0000001): + self.error(" interval endpoints cannot be greater than 1\n endpoint provided: "+str(u1),exit=False) + succeeded=False + #end + is_int=False + has_paren_val=False + interval=-1 + for i in range(1,len(tokens)): + if not tokens[i].startswith('('): + u2=1.0*eval(tokens[i]) + umax[iaxis]=u2 + if(not has_paren_val): + du_i=u2-u1 + #end + has_paren_val=False + interval+=1 + if(write): + print " parsing interval ",interval," of ",nintervals + print " u1,u2 = ",u1,",",u2 + #end + if(u21.0000001): + self.error(" interval endpoints cannot be greater than 1\n endpoint provided: "+str(u2),exit=False) + succeeded=False + #end + if(is_int): + du_int[interval]=(u2-u1)/ndom_i + ndom_int[interval]=ndom_i + else: + du_int[interval]=du_i + ndom_int[interval]=floor((u2-u1)/du_i+.5) + if(abs(u2-u1-du_i*ndom_int[interval])>utol): + self.error(" interval ("+str(u1)+","+str(u2)+") not divisible by du="+str(du_i),exit=False) + succeeded=False + #end + #end + u1=u2 + else: + has_paren_val=True + paren_val=tokens[i][1:len(tokens[i])-1] + if(write): + print " interval spacer = ",paren_val + #end if + is_int=tokens[i].find(".")==-1 + if(is_int): + ndom_i = eval(paren_val) + du_i = -1.0 + else: + ndom_i = 0 + du_i = eval(paren_val) + #end + #end + #end + # find the smallest domain width + du_min=min(du_int) + odu[iaxis]=1.0/du_min + # make sure it divides into all other domain widths + for i in range(len(du_int)): + ndu_int[i]=floor(du_int[i]/du_min+.5) + if(abs(du_int[i]-ndu_int[i]*du_min)>utol): + self.error("interval {0} of axis {1} is not divisible by smallest subinterval {2}".format(i+1,iaxis+1,du_min),exit=False) + succeeded=False + #end + #end + + if(write): + print " interval breakdown" + print " interval,ndomains,nsubdomains_per_domain" + for i in range(len(ndom_int)): + print " ",i,",",ndom_int[i],",",ndu_int[i] + #end + #end + + # set up the interval map such that gmap[u/du]==domain index + gmap[iaxis] = zeros((floor((umax[iaxis]-umin[iaxis])*odu[iaxis]+.5),),dtype=int) + n=0 + nd=-1 + if(write): + print " i,j,k ax,n,nd " + #end if + for i in range(len(ndom_int)): + for j in range(ndom_int[i]): + nd+=1 + for k in range(ndu_int[i]): + gmap[iaxis][n]=nd + if(write): + print " ",i,",",j,",",k," ",iaxis,",",n,",",nd + #end + n+=1 + #end + #end + #end + dimensions[iaxis]=nd+1 + #end read in the grid contents + + #save interval width information + ndom_tot=sum(ndom_int) + ndu_per_interval[iaxis] = zeros((ndom_tot,),dtype=int) + idom=0 + for i in range(len(ndom_int)): + for ii in range(ndom_int[i]): + ndu_per_interval[iaxis][idom] = ndu_int[i] + idom+=1 + #end + #end + #end + + axinv = inv(axes) + + #check that all axis grid values fall in the allowed intervals + cartmap = dict() + for d in range(DIM): + cartmap[ax_cartesian[d]]=d + #end for + for d in range(DIM): + if axlabel[d] in cartmap: + if(umin[d]<-1.0 or umax[d]>1.0): + self.error(" grid values for {0} must fall in [-1,1]\n".format(axlabel[d])+" interval provided: [{0},{1}]".format(umin[d],umax[d]),exit=False) + succeeded=False + #end if + elif(axlabel[d]=="phi"): + if(abs(umin[d])+abs(umax[d])>1.0): + self.error(" phi interval cannot be longer than 1\n interval length provided: {0}".format(abs(umin[d])+abs(umax[d])),exit=False) + succeeded=False + #end if + else: + if(umin[d]<0.0 or umax[d]>1.0): + self.error(" grid values for {0} must fall in [0,1]\n".format(axlabel[d])+" interval provided: [{0},{1}]".format(umin[d],umax[d]),exit=False) + succeeded=False + #end if + #end if + #end for + + + #set grid dimensions + # C/Python style indexing + dm=array([0,0,0],dtype=int) + dm[0] = dimensions[1]*dimensions[2] + dm[1] = dimensions[2] + dm[2] = 1 + + ndomains=prod(dimensions) + + volume = abs(det(axes))*8.0#axes span only one octant + + #compute domain volumes, centers, and widths + domain_volumes = zeros((ndomains,)) + domain_centers = zeros((ndomains,DIM)) + domain_uwidths = zeros((ndomains,DIM)) + interval_centers = [None,None,None] + interval_widths = [None,None,None] + for d in range(DIM): + nintervals = len(ndu_per_interval[d]) + interval_centers[d] = zeros((nintervals)) + interval_widths[d] = zeros((nintervals)) + interval_widths[d][0]=ndu_per_interval[d][0]/odu[d] + interval_centers[d][0]=interval_widths[d][0]/2.0+umin[d] + for i in range(1,nintervals): + interval_widths[d][i] = ndu_per_interval[d][i]/odu[d] + interval_centers[d][i] = interval_centers[d][i-1] \ + +.5*(interval_widths[d][i]+interval_widths[d][i-1]) + #end for + #end for + du,uc,ubc,rc = zeros((DIM,)),zeros((DIM,)),zeros((DIM,)),zeros((DIM,)) + vol = -1e99 + vol_tot=0.0 + vscale = abs(det(axes)) + + for i in range(dimensions[0]): + for j in range(dimensions[1]): + for k in range(dimensions[2]): + idomain = dm[0]*i + dm[1]*j + dm[2]*k + du[0] = interval_widths[0][i] + du[1] = interval_widths[1][j] + du[2] = interval_widths[2][k] + uc[0] = interval_centers[0][i] + uc[1] = interval_centers[1][j] + uc[2] = interval_centers[2][k] + + if(coordinate==SpaceGridBase.cartesian): + vol=du[0]*du[1]*du[2] + ubc=uc + elif(coordinate==SpaceGridBase.cylindrical): + uc[1]=2.0*pi*uc[1]-pi + du[1]=2.0*pi*du[1] + vol=uc[0]*du[0]*du[1]*du[2] + ubc[0]=uc[0]*cos(uc[1]) + ubc[1]=uc[0]*sin(uc[1]) + ubc[2]=uc[2] + elif(coordinate==SpaceGridBase.spherical): + uc[1]=2.0*pi*uc[1]-pi + du[1]=2.0*pi*du[1] + uc[2]= pi*uc[2] + du[2]= pi*du[2] + vol=(uc[0]*uc[0]+du[0]*du[0]/12.0)*du[0] \ + *du[1] \ + *2.0*sin(uc[2])*sin(.5*du[2]) + ubc[0]=uc[0]*sin(uc[2])*cos(uc[1]) + ubc[1]=uc[0]*sin(uc[2])*sin(uc[1]) + ubc[2]=uc[0]*cos(uc[2]) + #end if + vol*=vscale + + vol_tot+=vol + + rc = dot(axes,ubc) + origin + + domain_volumes[idomain] = vol + for d in range(DIM): + domain_uwidths[idomain,d] = du[d] + domain_centers[idomain,d] = rc[d] + #end for + #end for + #end for + #end for + + #find the actual volume of the grid + du = umax-umin + uc = .5*(umax+umin) + if coordinate==SpaceGridBase.cartesian: + vol=du[0]*du[1]*du[2] + elif coordinate==SpaceGridBase.cylindrical: + uc[1]=2.0*pi*uc[1]-pi + du[1]=2.0*pi*du[1] + vol=uc[0]*du[0]*du[1]*du[2] + elif coordinate==SpaceGridBase.spherical: + uc[1]=2.0*pi*uc[1]-pi + du[1]=2.0*pi*du[1] + uc[2]= pi*uc[2] + du[2]= pi*du[2] + vol=(uc[0]*uc[0]+du[0]*du[0]/12.0)*du[0]*du[1]*2.0*sin(uc[2])*sin(.5*du[2]) + #end if + volume = vol*abs(det(axes)) + + for q in SpaceGridBase.quantities: + self[q].mean = zeros((ndomains,)) + self[q].error = zeros((ndomains,)) + #end for + + #save the results + self.axinv = axinv + self.volume = volume + self.gmap = gmap + self.umin = umin + self.umax = umax + self.odu = odu + self.dm = dm + self.dimensions = dimensions + self.ndomains = ndomains + self.domain_volumes = domain_volumes + self.domain_centers = domain_centers + self.domain_uwidths = domain_uwidths + + + #succeeded = succeeded and check_grid() + + if(self.init_exit_fail and not succeeded): + self.error(" in def initialize") + #end + + return succeeded + #end def initialize + + def point2unit_cartesian(point): + u = dot(self.axinv,(point-self.origin)) + return u + #end def point2unit_cartesian + + def point2unit_cylindrical(point): + ub = dot(self.axinv,(point-self.origin)) + u=zeros((self.DIM,)) + u[0] = sqrt(ub[0]*ub[0]+ub[1]*ub[1]) + u[1] = atan2(ub[1],ub[0])*o2pi+.5 + u[2] = ub[2] + return u + #end def point2unit_cylindrical + + def point2unit_spherical(point): + ub = dot(self.axinv,(point-self.origin)) + u=zeros((self.DIM,)) + u[0] = sqrt(ub[0]*ub[0]+ub[1]*ub[1]+ub[2]*ub[2]) + u[1] = atan2(ub[1],ub[0])*o2pi+.5 + u[2] = acos(ub[2]/u[0])*o2pi*2.0 + return u + #end def point2unit_spherical + + def points2domains_cartesian(self,points,domains,points_outside): + u = zeros((self.DIM,)) + iu = zeros((self.DIM,),dtype=int) + ndomains=-1 + npoints,ndim = points.shape + for p in xrange(npoints): + u = dot(self.axinv,(points[p]-self.origin)) + if (u>self.umin).all() and (uself.umin).all() and (uself.umin).all() and (u1e-6: + if warn: + self.warn('source origin must lie at interpolant r=0') + #end if + return False + #end if + #end if + # fine meshes must align + # origin must be an integer multiple of smallest dom width + if am_cylindrical: + mdims=[2] + elif am_cartesian: + mdims=[0,1,2] + else: + mdims=[] + #end if + for d in mdims: + if not is_integer(uo[d]*self.odu[d]): + if warn: + self.warn('source origin does not lie on interpolant fine mesh') + #end if + return False + #end if + #end for + # smallest dom width must be multiple of this smallest dom width + for d in range(self.DIM): + if not is_integer(self.odu[d]/s.odu[d]): + if warn: + self.warn('smallest source domain width must be a multiple of interpolants smallest domain width') + #end if + return False + #end if + #end for + # each interval along each direction for interpolant must map to only one source interval + # construct points at each fine interval center of interpolant, run them through source gmap to get interval indices + for d in range(self.DIM): + fine_interval_domains[d][:]=-2 + gmlen = len(s.gmap[d]) + for i in range(len(fine_interval_centers[d])): + uc = fine_interval_centers[d][i] + ind = floor((uc-s.umin[d])*s.odu[d]) + if ind < gmlen: + idom=s.gmap[d][ind] + else: + idom=-1 + #end if + fine_interval_domains[d][i]=idom + #end for + cind = self.gmap[d][0] + istart = 0 + iend = 0 + for i in range(len(self.gmap[d])): + if self.gmap[d][i]==cind: + iend+=1 + else: + source_ind = fine_interval_domains[istart] + for j in range(istart+1,iend): + if fine_interval_domains[j]!=source_ind: + if warn: + self.warn('an interpolant domain must not fall on multiple source domains') + #end if + return False + #end if + #end for + istart=iend + #end if + #end for + #end for + #end for + #end if + + + #get the list of domains points from this grid fall in + # and interpolate requested quantities on them + domain_centers = self.domain_centers + domind = zeros((self.ndomains,2),dtype=int) + domout = ones((self.ndomains,) ,dtype=int) + for s in spacegrids: + domind[:,:] = -1 + ndomin = s.points2domains(domain_centers,domind,domout) + for q in quantities: + self[q].mean[domind[0:ndomin,0]] = s[q].mean[domind[0:ndomin,1]].copy() + self[q].error[domind[0:ndomin,0]] = s[q].error[domind[0:ndomin,1]].copy() + #end for + #end for + for d in xrange(self.ndomains): + if domout[d]: + for q in quantities: + self[q].mean[d] = outside[q].mean + self[q].error[d] = outside[q].error + #end for + #end if + #end for + return True + #end def interpolate_across + + + def interpolate(self,points,quantities=None): + if quantities==None: + quantities=SpaceGridBase.quantities + #end if + npoints,ndim = points.shape + ind = empty((npoints,2),dtype=int) + out = ones((npoints,) ,dtype=int) + nin = self.points2domains(points,ind,out) + result = QAobject() + for q in quantities: + result._add_attribute(q,QAobject()) + result[q].mean = zeros((npoints,)) + result[q].error = zeros((npoints,)) + result[q].mean[ind[0:nin,0]] = self[q].mean[ind[0:nin,1]].copy() + result[q].error[ind[0:nin,0]] = self[q].error[ind[0:nin,1]].copy() + #end for + return result + #end def interpolate + + + def isosurface(self,quantity,contours=5,origin=None): + if quantity not in SpaceGridBase.quantities: + self.error() + #end if + dimensions = self.dimensions + if origin==None: + points = self.domain_centers + else: + npoints,ndim = self.domain_centers.shape + points = empty((npoints,ndim)) + for i in range(npoints): + points[i,:] = origin + self.domain_centers[i,:] + #end for + #end if + scalars = self[quantity].mean + name = quantity + self.plotter.isosurface(points,scalars,contours,dimensions,name) + return + #end def isosurface + + + def surface_slice(self,quantity,x,y,z,options=None): + if quantity not in SpaceGridBase.quantities: + self.error() + #end if + points = empty( (x.size,self.DIM) ) + points[:,0] = x.ravel() + points[:,1] = y.ravel() + points[:,2] = z.ravel() + val = self.interpolate(points,[quantity]) + scalars = val[quantity].mean + scalars.shape = x.shape + self.plotter.surface_slice(x,y,z,scalars,options) + return + #end def surface_slice + + + def plot_axes(self,color=None,radius=.025,origin=None): + if color is None: + color = (0.,0,0) + #end if + if origin is None: + origin = array([0.,0,0]) + #end if + colors=array([[1.,0,0],[0,1.,0],[0,0,1.]]) + for d in range(self.DIM): + a=self.axes[:,d]+origin + ax=array([-a[0],a[0]]) + ay=array([-a[1],a[1]]) + az=array([-a[2],a[2]]) + self.plotter.plot3d(ax,ay,az,tube_radius=radius,color=tuple(colors[:,d])) + #end for + return + #end def plot_axes + + def plot_box(self,color=None,radius=.025,origin=None): + if color is None: + color = (0.,0,0) + #end if + if origin is None: + origin = array([0.,0,0]) + #end if + p = self.points + p1=p.cmmm+origin + p2=p.cmpm+origin + p3=p.cpmm+origin + p4=p.cppm+origin + p5=p.cmmp+origin + p6=p.cmpp+origin + p7=p.cpmp+origin + p8=p.cppp+origin + bline = array([p1,p2,p4,p3,p1,p5,p6,p8,p7,p5,p7,p3,p4,p8,p6,p2]) + self.plotter.plot3d(bline[:,0],bline[:,1],bline[:,2],color=color) + return + #end def plot_box +#end class RectilinearGrid + + + + + +class VoronoiGridInitializer(SpaceGridInitializer): + def __init__(self): + SpaceGridInitializer.__init__(self) + #end def __init__ +#end class VoronoiGridInitializer + + +class VoronoiGrid(SpaceGridBase): + def __init__(self,initobj=None,options=None): + SpaceGridBase.__init__(self,initobj,options) + return + #end def __init__ + + def copy(self,other): + return VoronoiGrid(other) + #end def copy + + + def reorder_atomic_data(self,imap): + for q in self.quantities: + qv = self[q] + qv.mean = qv.mean[...,imap] + qv.error = qv.error[...,imap] + #end for + if 'data' in self: + data = self.data + for q in self.quantities: + data[q] = data[q][...,imap,:] + #end for + #end if + #end def reorder_atomic_data +#end class VoronoiGrid + + + + + + +def SpaceGrid(init,opts=None): + SpaceGrid.count+=1 + + iname = init.__class__.__name__ + if iname=='HDFgroup': + coordinate = init.coordinate[0] + #end if + coord = SpaceGrid.coord_n2s[coordinate] + + if coord in SpaceGrid.rect: + return RectilinearGrid(init,opts) + elif coord=='voronoi': + return VoronoiGrid(init,opts) + else: + print 'SpaceGrid '+coord+' has not been implemented, exiting...' + exit() + #end if + +#end def SpaceGrid +SpaceGrid.count = 0 +SpaceGrid.coord_n2s = SpaceGridBase.coord_n2s +SpaceGrid.rect = set(['cartesian','cylindrical','spherical']) diff --git a/nexus/library/qmcpack_result_analyzers.py b/nexus/library/qmcpack_result_analyzers.py index 520010a0a..1d3777691 100644 --- a/nexus/library/qmcpack_result_analyzers.py +++ b/nexus/library/qmcpack_result_analyzers.py @@ -26,12 +26,12 @@ #====================================================================# -from numpy import array,empty,zeros,sqrt +from numpy import array,empty,zeros,sqrt,arange from generic import obj from unit_converter import convert from qmcpack_input import QmcpackInput -from qaobject import QAobject -from qmcpack_analyzer_base import QAanalyzer +from qmcpack_analyzer_base import QAobject,QAanalyzer +from debug import * @@ -94,43 +94,75 @@ class OptimizationAnalyzer(ResultAnalyzer): vw = self.variance_weight Efail = 1e6 - EVratio_fail = 0.10 + Vfail = 1e3 + EVratio_fail = 0.30 + EVratio_soft_fail = 0.15 #save the energies and variances of opt iterations - nopt = len(opts) - en = zeros((nopt,))+1e99 - enerr = zeros((nopt,))+1e99 - va = zeros((nopt,))+1e99 - vaerr = zeros((nopt,))+1e99 + res = obj() variance_present = False any_complete = False all_complete = True unstable = False - for i in range(nopt): - o = opts[i] - complete = o.info.complete + any_stable = False + for s,opt in opts.iteritems(): + complete = opt.info.complete any_complete |= complete all_complete &= complete if complete: - le = o.scalars.LocalEnergy - en[i] = le.mean - enerr[i] = le.error - if 'LocalEnergyVariance' in o.scalars: + fail = False + le = opt.scalars.LocalEnergy + en = le.mean + enerr = le.error + fail |= abs(en)>Efail + if 'LocalEnergyVariance' in opt.scalars: variance_present = True - lev = o.scalars.LocalEnergyVariance - va[i] = lev.mean - vaerr[i] = lev.error + lev = opt.scalars.LocalEnergyVariance + va = lev.mean + vaerr = lev.error + fail |= abs(va)>Vfail or abs(va/en)>EVratio_fail #end if - unstable |= abs(le.mean)>Efail + if not fail: + any_stable = True + sres = obj() + sres.en = en + sres.enerr = enerr + if variance_present: + sres.va = va + sres.vaerr = vaerr + #end if + res[s] = sres + #end if + unstable|=fail #end if #end for unstable |= not any_complete + nseries = len(res) + en = zeros((nseries,),dtype=float) + enerr = zeros((nseries,),dtype=float) + va = zeros((nseries,),dtype=float) + vaerr = zeros((nseries,),dtype=float) + + series = array(sorted(res.keys()),dtype=int) + i = 0 + for s in series: + sres = res[s] + en[i] = sres.en + enerr[i] = sres.enerr + if variance_present: + va[i] = sres.va + vaerr[i] = sres.vaerr + #end if + i+=1 + #end for + self.set( any_complete = any_complete, all_complete = all_complete, unstable = unstable, + series = series, energy = en, energy_error = enerr, variance = va, @@ -146,44 +178,37 @@ class OptimizationAnalyzer(ResultAnalyzer): elif optimize=='energy': ew = 1.0 vw = 0.0 + elif optimize=='energy_within_variance_tol' or optimize=='ewvt': + None elif isinstance(optimize,(tuple,list)) and len(optimize)==2: ew,vw = optimize else: - self.error('selection for optimization is invalid\n optimize setting: {0}\n valid options are: energy, variance, or a length 2 tuple containing the cost of each, e.g. (.5,.5)'.format(optimize)) + self.error('selection for optimization is invalid\noptimize setting: {0}\nvalid options are: energy, variance, energy_within_variance_tol, or a length 2 tuple containing the cost of energy and variance, e.g. (.5,.5)'.format(optimize)) #end if self.failed = True self.optimal_series = None self.optimal_file = None self.optimal_wavefunction = None - if any_complete: - mincost = 1e99 - index = -1 - for i,opt in opts.iteritems(): - if opt.info.complete: - s = opt.scalars - e = s.LocalEnergy.mean - if 'LocalEnergyVariance' in s: - v = s.LocalEnergyVariance.mean - else: - v = 0 - #end if - cost = ew*e+vw*v - if costEfail or (va[index]<1e98 and abs(va[index]/en[index])>EVratio_fail) - - self.failed = failed - self.optimal_series = index - self.optimal_file = opts[index].info.files.opt - self.optimal_wavefunction = opts[index].wavefunction.info.wfn_xml.copy() + if any_stable: + if optimize=='energy_within_variance_tol' or optimize=='ewvt': + indices = arange(len(series),dtype=int) + vartol = 0.2 + vmin = va.min() + vind = indices[abs(va-vmin)/vminEfail or abs(va[index])>Vfail or abs(va[index]/en[index])>EVratio_soft_fail + + self.failed = failed + self.optimal_series = opt_series + self.optimal_file = opts[opt_series].info.files.opt + self.optimal_wavefunction = opts[opt_series].wavefunction.info.wfn_xml.copy() #end if #end def analyze_local diff --git a/nexus/library/simulation.py b/nexus/library/simulation.py index bfda2e0a6..8e0180379 100644 --- a/nexus/library/simulation.py +++ b/nexus/library/simulation.py @@ -68,59 +68,62 @@ import os import shutil import string +from subprocess import Popen,PIPE from generic import obj from periodic_table import is_element from physical_system import PhysicalSystem from machines import Job -from project_base import Pobj +from nexus_base import NexusCore,nexus_core -class SimulationInput(Pobj): - @classmethod - def templates(cls,template_name): - print 'Developer Error: templates function has not been implemented in '+cls.__name__ - exit() - template = None - return template - #end def - +class SimulationInput(NexusCore): def is_valid(self): self.not_implemented() #end def is_valid + def read_file_text(self,filepath): + if not os.path.exists(filepath): + self.error('file does not exist: '+filepath) + #end if + fobj = open(filepath,'r') + text = fobj.read() + fobj.close() + return text + #end def read_file_text + + def write_file_text(self,filepath,text): + fobj = open(filepath,'w') + fobj.write(text) + fobj.flush() + fobj.close() + #end def write_file_text + def read(self,filepath): tokens = filepath.split(None,1) if len(tokens)>1: - contents = filepath - self.read_contents(contents) + text = filepath + self.read_text(text) else: - if os.path.exists(filepath): - self.read_contents(open(filepath,'r').read()) - else: - self.error('failed read for filepath below\n '+filepath) - #end if + text = self.read_file_text(filepath) + self.read_text(text,filepath) #end if #end def read def write(self,filepath=None): - contents = self.write_contents() - if filepath is None: - return contents - else: - fobj = open(filepath,'w') - fobj.write(contents) - fobj.flush() - fobj.close() + text = self.write_text(filepath) + if filepath!=None: + self.write_file_text(filepath,text) #end if + return text #end def write - def read_contents(self,contents): + def read_text(self,text,filepath=None): self.not_implemented() - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self,filepath=None): self.not_implemented() - #end def write_contents + #end def write_text def incorporate_system(self,system): #take information from a physical system object and fill in input file @@ -147,7 +150,7 @@ class SimulationInput(Pobj): -class SimulationAnalyzer(Pobj): +class SimulationAnalyzer(NexusCore): def __init__(self,sim): self.not_implemented() #end def __init__ @@ -160,7 +163,7 @@ class SimulationAnalyzer(Pobj): -class SimulationEmulator(Pobj): +class SimulationEmulator(NexusCore): def run(self): self.not_implemented() #end def run @@ -168,11 +171,78 @@ class SimulationEmulator(Pobj): +class SimulationImage(NexusCore): + save_only_fields = set([ + # user block (temporary) of (sim+) subcascade + 'block', + 'block_subcascade', + # local/remote/results directories + 'locdir', + 'remdir', + 'resdir', + # image directories + 'imlocdir', + 'imremdir', + 'imresdir', + ]) + + load_fields = set([ + # important sim variables + 'identifier', + 'path', + 'process_id', + # properties of the executable + 'app_name', + 'app_props', + # names of in/out/err files + 'infile', + 'outfile', + 'errfile', + # directory and image file names for sim/input/analyzer + 'image_dir', + 'sim_image', + 'input_image', + 'analyzer_image', + # files copied in/out before/after run + 'files', + 'outputs', + # simulation status flags + 'setup', + 'sent_files', + 'submitted', + 'finished', + 'failed', + 'got_output', + 'analyzed', + # cascade status flag + 'subcascade_finished', + ]) + + save_fields = load_fields | save_only_fields + + def __init__(self): + None + #end def __init__ + + def save_image(self,sim,imagefile): + self.clear() + self.transfer_from(sim,SimulationImage.save_fields) + self.save(imagefile) + self.clear() + #end def save_image + + def load_image(self,sim,imagefile): + self.clear() + self.load(imagefile) + self.transfer_to(sim,SimulationImage.load_fields) + self.clear() + #end def load_image + +#end class SimulationImage - -class Simulation(Pobj): +class Simulation(NexusCore): input_type = SimulationInput analyzer_type = SimulationAnalyzer generic_identifier = 'sim' @@ -192,15 +262,8 @@ class Simulation(Pobj): analyzer_imagefile = 'analyzer.p' image_directory = 'sim' - updatable = set(['block','block_subcascade','force_write']) - preserve = set(['simid','got_dependencies','dependencies', - 'ordered_dependencies','dependents','dependency_ids', - 'wait_ids','input','locdir','remdir','resdir', - 'imlocdir','imremdir','imresdir', - 'skip_submit','job','system','temp']) sim_count = 0 - sim_directories = dict() @@ -234,7 +297,7 @@ class Simulation(Pobj): Simulation.class_error('system object must be of type PhysicalSystem') #end if species_labels,species = system.structure.species(symbol=True) - pseudopotentials = Simulation.pseudopotentials + pseudopotentials = nexus_core.pseudopotentials for ppfile in pseudos: if not ppfile in pseudopotentials: Simulation.class_error('pseudopotential file {0} cannot be found'.format(ppfile)) @@ -274,6 +337,7 @@ class Simulation(Pobj): self.input = self.input_type() self.system = None self.dependents = obj() + self.created_directories = False self.got_dependencies = False self.setup = False self.sent_files = False @@ -282,13 +346,12 @@ class Simulation(Pobj): self.failed = False self.got_output = False self.analyzed = False - self.succeeded = False self.subcascade_finished = False self.dependency_ids = set() self.wait_ids = set() self.block = False self.block_subcascade = False - self.skip_submit = self.skip_submission + self.skip_submit = nexus_core.skip_submit self.force_write = False self.loaded = False self.ordered_dependencies = [] @@ -301,8 +364,6 @@ class Simulation(Pobj): self.outputs = None #object representing output data # accessed by dependents when calling get_dependencies - self.temp = obj() # temporary storage, not saved - self.set(**kwargs) self.set_directories() self.set_files() @@ -320,9 +381,8 @@ class Simulation(Pobj): def init_job(self): if self.job==None: self.error('job not provided. Input field job must be set to a Job object.') - else: - self.job = self.job.copy() #end if + self.job = self.job.copy() self.job.initialize(self) #end def init_job @@ -349,7 +409,7 @@ class Simulation(Pobj): if p.startswith('./'): p = p[2:] #end if - ld = self.local_directory + ld = nexus_core.local_directory if p.startswith(ld): p = p.split(ld)[1].lstrip('/') #end if @@ -358,19 +418,21 @@ class Simulation(Pobj): if 'files' in allowed: self.files = set(self.files) #end if - if not isinstance(self.input,self.input_type): + if not isinstance(self.input,(self.input_type,GenericSimulationInput)): self.error('input must be of type {0}\nreceived {1}\nplease provide input appropriate to {2}'.format(self.input_type.__name__,self.input.__class__.__name__,self.__class__.__name__)) #end if if isinstance(self.system,PhysicalSystem): self.system = self.system.copy() + elif self.system!=None: + self.error('system must be a PhysicalSystem object\nyou provided an object of type: {0}'.format(self.system.__class__.__name__)) #end if #end def set def set_directories(self): - self.locdir = os.path.join(self.local_directory,self.runs,self.path) - self.remdir = os.path.join(self.remote_directory,self.runs,self.path) - self.resdir = os.path.join(self.local_directory,self.results,self.runs,self.path) + 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) if not self.locdir in self.sim_directories: self.sim_directories[self.locdir] = set([self.identifier]) @@ -379,7 +441,7 @@ class Simulation(Pobj): if not self.identifier in idset: idset.add(self.identifier) else: - self.error('multiple simulations in a single directory have the same identifier\n please assign unique identifiers to each simulation\n simulation directory: {0}\n repeated identifier: {1}\n other identifiers: {2}\n between the directory shown and the identifiers listed, it should be clear which simulations are involved\n most likely, you described two simulations with identifier {3}'.format(self.locdir,self.identifier,list(idset),self.identifier)) + self.error('multiple simulations in a single directory have the same identifier\nplease assign unique identifiers to each simulation\nsimulation directory: {0}\nrepeated identifier: {1}\nother identifiers: {2}\nbetween the directory shown and the identifiers listed, it should be clear which simulations are involved\nmost likely, you described two simulations with identifier {3}'.format(self.locdir,self.identifier,sorted(idset),self.identifier)) #end if #end if @@ -435,7 +497,7 @@ class Simulation(Pobj): self.not_implemented() #end def check_sim_status - def get_output_files(self): + def get_output_files(self): # returns list of output files to save self.not_implemented() #end def get_output_files @@ -474,6 +536,42 @@ class Simulation(Pobj): #end def condense_name + def has_generic_input(self): + return isinstance(self.input,GenericSimulationInput) + #end def has_generic_input + + def outfile_text(self): + return self._file_text('outfile') + #end def outfile_text + + def errfile_text(self): + return self._file_text('errfile') + #end def errfile_text + + def _file_text(self,filename): + filepath = os.path.join(self.locdir,self[filename]) + fobj = open(filepath,'r') + text = fobj.read() + fobj.close() + return text + #end def _file_text + + + def _create_dir(self,dir): + if not os.path.exists(dir): + os.makedirs(dir) + elif os.path.isfile(dir): + self.error('cannot create directory {0}\na file exists at this location'.format(dir)) + #end if + #end def _create_dir + + def create_directories(self): + self._create_dir(self.locdir) + self._create_dir(self.imlocdir) + self.created_directories = True + #end def create_directories + + def depends(self,*dependencies): if len(dependencies)==0: return @@ -524,9 +622,16 @@ class Simulation(Pobj): sim = dep.sim for result_name in dep.result_names: if result_name!='other': - calculating_result = sim.check_result(result_name,self) + if sim.has_generic_input(): + calculating_result = False + cls = self.__class__ + self.warn('a simulation result cannot be inferred from generic formatted or template input\nplease use {0} instead of {1}\nsee error below for information identifying this simulation instance'.format(cls.input_type.__class__.__name__,sim.input.__class__.__name__)) + else: + calculating_result = sim.check_result(result_name,self) + #end if if not calculating_result: self.error('simulation {0} id {1} is not calculating result {2}\nrequired by simulation {3} id {4}\n{5} {6} directory: {7}\n{8} {9} directory: {10}'.format(sim.identifier,sim.simid,result_name,self.identifier,self.simid,sim.identifier,sim.simid,sim.locdir,self.identifier,self.simid,self.locdir),exit=False) + #end if else: calculating_result = True #end if @@ -538,7 +643,7 @@ class Simulation(Pobj): def get_dependencies(self): - if self.generate_only or self.finished: + if nexus_core.generate_only or self.finished: for dep in self.dependencies: for result_name in dep.result_names: dep.results[result_name] = result_name @@ -549,6 +654,9 @@ class Simulation(Pobj): sim = dep.sim for result_name in dep.result_names: if result_name!='other': + if sim.has_generic_input(): + self.error('a simulation result cannot be inferred from generic formatted or template input\nplease use {0} instead of {1}\nsim id: {2}\ndirectory: {3}\nresult: {4}'.format(cls.input_type.__class__.__name__,sim.input.__class__.__name__,sim.id,sim.locdir,result_name)) + #end if dep.results[result_name] = sim.get_result(result_name,sim) else: dep.results['other'] = obj() @@ -560,6 +668,9 @@ class Simulation(Pobj): sim = dep.sim for result_name,result in dep.results.iteritems(): if result_name!='other': + if self.has_generic_input(): + self.error('a simulation result cannot be incorporated into generic formatted or template input\nplease use {0} instead of {1}\nsim id: {2}\ndirectory: {3}\nresult: {4}'.format(cls.input_type.__class__.__name__,self.input.__class__.__name__,self.id,self.locdir,result_name)) + #end if self.incorporate_result(result_name,result,sim) #end if #end for @@ -580,56 +691,33 @@ class Simulation(Pobj): def save_image(self,all=False): - self.tlog('save image',self.simid,n=5) imagefile = os.path.join(self.imlocdir,self.sim_image) if os.path.exists(imagefile): os.system('rm '+imagefile) #end if if not all: - pres = dict() - for v in self.preserve: - pres[v] = self[v] - del self[v] - #end for + sim_image = SimulationImage() + sim_image.save_image(self,imagefile) + else: + self.save(imagefile) #end if - self.save(imagefile) - if not all: - for k,v in pres.iteritems(): - self[k] = v - #end for - del pres - #end if - self.tlog('end save image',self.simid,n=5) #end def save_image def load_image(self,imagepath=None,all=False): - self.tlog('load image',self.simid,n=5) if imagepath==None: imagepath=os.path.join(self.imlocdir,self.sim_image) #end if if not all: - pres = dict() - for v in self.preserve: - pres[v] = self[v] - #end for - for v in self.updatable: - pres[v] = self[v] - #end for - #end if - self.load(imagepath) - if not all: - for k,v in pres.iteritems(): - self[k] = v - #end for - del pres + sim_image = SimulationImage() + sim_image.load_image(self,imagepath) + else: + self.load(imagepath) #end if # update process id for backwards compatibility - if not 'process_id' in self: + if 'process_id' not in self: self.process_id = self.job.system_id #end if - self.tlog('end load image',self.simid,n=5) - return #end def load_image @@ -649,16 +737,9 @@ class Simulation(Pobj): def write_inputs(self,save_image=True): - self.tlog('write inputs',self.simid,n=4) self.pre_write_inputs(save_image) self.enter(self.locdir,False,self.simid) self.log('writing input files'+self.idstr(),n=3) - if not os.path.exists(self.locdir): - os.makedirs(self.locdir) - #end if - if not os.path.exists(self.imlocdir): - os.makedirs(self.imlocdir) - #end if self.write_prep() if self.infile!=None: infile = os.path.join(self.locdir,self.infile) @@ -673,12 +754,10 @@ class Simulation(Pobj): self.save_image() self.input.save(os.path.join(self.imlocdir,self.input_image)) #end if - self.tlog('end write inputs',self.simid,n=4) #end def write_inputs def send_files(self,enter=True): - self.tlog('send files',self.simid,n=4) self.pre_send_files(enter) if enter: self.enter(self.locdir,False,self.simid) @@ -694,7 +773,7 @@ class Simulation(Pobj): self.files.add(self.infile) #end if send_files = self.files - file_locations = [self.locdir]+self.file_locations + file_locations = [self.locdir]+nexus_core.file_locations remote = self.remdir for file in send_files: found_file = False @@ -721,26 +800,27 @@ class Simulation(Pobj): self.copy_file(local,remote) #end if #end for - self.tlog('end send files',self.simid,n=4) #end def send_files def submit(self): - self.tlog('submit',self.simid,n=4) if not self.submitted: self.log('submitting job'+self.idstr(),n=3) if not self.skip_submit: - self.job.submit() + if not self.job.local: + self.job.submit() + else: + self.execute() # execute local job immediately + #end if #end if self.submitted = True - if (self.job.batch_mode or not self.monitor) and not self.generate_only: + if (self.job.batch_mode or not nexus_core.monitor) and not nexus_core.generate_only: self.save_image() #end if elif not self.finished: self.check_status() #end if self.post_submit() - self.tlog('end submit',self.simid,n=4) #end def submit @@ -754,8 +834,7 @@ class Simulation(Pobj): def check_status(self): self.pre_check_status() - self.tlog('check status',self.simid,n=5) - if self.generate_only: + if nexus_core.generate_only: self.finished = self.job.finished elif self.job.finished: should_check = True @@ -772,18 +851,18 @@ class Simulation(Pobj): #end if if self.failed: self.finished = True - self.block_dependents() + # commented out block dependents 15/09/30 + # try to rely on persistent failed flag instead + #self.block_dependents() #end if #end if if self.finished: self.save_image() #end if - self.tlog('end check status',self.simid,n=5) #end def check_status def get_output(self): - self.tlog('get output',self.simid,n=4) if not os.path.exists(self.resdir): os.makedirs(self.resdir) #end if @@ -804,7 +883,7 @@ class Simulation(Pobj): if self.finished: self.enter(self.locdir,False,self.simid) self.log('copying results'+self.idstr(),n=3) - if not self.generate_only: + if not nexus_core.generate_only: output_files = self.get_output_files() if self.infile!=None: output_files.append(self.infile) @@ -834,17 +913,15 @@ class Simulation(Pobj): self.got_output = True self.save_image() #end if - self.tlog('end get output',self.simid,n=4) #end def get_output def analyze(self): - self.tlog('analyze',self.simid,n=4) if self.finished: self.enter(self.locdir,False,self.simid) self.log('analyzing'+self.idstr(),n=3) analyzer = self.analyzer_type(self) - if not self.generate_only: + if not nexus_core.generate_only: analyzer.analyze() #end if analyzer.save(os.path.join(self.imresdir,self.analyzer_image)) @@ -852,13 +929,11 @@ class Simulation(Pobj): self.analyzed = True self.save_image() #end if - self.tlog('end analyze',self.simid,n=4) #end def analyze def reset_wait_ids(self): self.wait_ids = set(self.dependency_ids) - self.dlog(self.simid,'wids',self.wait_ids,n=2) for sim in self.dependents: sim.reset_wait_ids() #end for @@ -867,15 +942,9 @@ class Simulation(Pobj): def check_subcascade(self): finished = self.finished or self.block - if not finished: - self.dlog(self.simid,'is not finished',n=2) - else: - self.dlog(self.simid,'is finished',n=2) - #end if - if not self.block and not self.block_subcascade: + if not self.block and not self.block_subcascade and not self.failed: for sim in self.dependents: - dfin = sim.check_subcascade() - finished = finished and dfin + finished &= sim.check_subcascade() #end for #end if self.subcascade_finished = finished @@ -895,15 +964,12 @@ class Simulation(Pobj): def progress(self,dependency_id=None): - self.tlog('progress',self.simid,n=2) if dependency_id!=None: - self.dlog('wid',self.wait_ids,n=3) self.wait_ids.remove(dependency_id) #end if - if len(self.wait_ids)==0 and not self.block: - self.dlog('running',self.simid,n=3) - modes = self.modes - mode = self.mode + 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 @@ -921,29 +987,32 @@ class Simulation(Pobj): 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 self.stages: + if not self.setup and 'setup' in nexus_core.stages: self.write_inputs() #end if - if not self.sent_files and 'send_files' in self.stages: + if not self.sent_files and 'send_files' in nexus_core.stages: self.send_files() #end if - if not self.finished and 'submit' in self.stages: + if not self.finished and 'submit' in nexus_core.stages: self.submit() #end if - if self.dependent_modes <= self.stages_set: + 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 self.stages: + if not self.got_output and 'get_output' in nexus_core.stages: self.get_output() #end if - if not self.analyzed and 'analyze' in self.stages: + if not self.analyzed and 'analyze' in nexus_core.stages: self.analyze() #end if #end if @@ -965,40 +1034,31 @@ class Simulation(Pobj): #end if progress = self.finished #end if - self.dlog('progress sub',self.simid,n=4) - w,s,j,f,g,a=int(self.setup),int(self.submitted),int(self.job.finished),int(self.finished),int(self.got_output),int(self.analyzed) - self.dlog('w,s,j,f,g,a',w,s,j,f,g,a,n=4) - #self.dlog('f,jf,p,bs,nd',self.finished,self.job.finished,progress,self.block_subcascade,len(self.dependents),n=4) - if progress and not self.block_subcascade: + if progress and not self.block_subcascade and not self.failed: for sim in self.dependents: - self.dlog(self.simid,'is progressing',sim.simid,n=2) sim.progress(self.simid) #end for #end if elif len(self.wait_ids)==0 and self.force_write: - self.dlog('running',self.simid,n=3) - modes = self.modes - mode = self.mode + modes = nexus_core.modes + mode = nexus_core.mode if mode==modes.stages: if not self.got_dependencies: self.get_dependencies() #end if - if 'setup' in self.stages: + if 'setup' in nexus_core.stages: self.write_inputs() #end if - if not self.sent_files and 'send_files' in self.stages: + if not self.sent_files and 'send_files' in nexus_core.stages: self.send_files() #end if #end if #end if - self.tlog('end progress',self.simid,n=2) #end def progress def reconstruct_cascade(self): imagefile = os.path.join(self.imlocdir,self.sim_image) - self.dlog(self.simid,'reconstructing, dids',self.dependency_ids,n=2) - self.dlog(os.path.exists(imagefile),self.loaded,n=3) if os.path.exists(imagefile) and not self.loaded: self.load_image() # continue from interruption @@ -1008,7 +1068,6 @@ class Simulation(Pobj): #end if self.loaded = True #end if - self.dlog(self.simid,'reconstructed, dids',self.dependency_ids,n=3) for sim in self.dependents: sim.reconstruct_cascade() #end for @@ -1043,29 +1102,65 @@ class Simulation(Pobj): # #end for # #end def write_dependents - def write_dependents(self,n=0,location=False): - if not location: - self.log(self.__class__.__name__,self.identifier,self.simid,list(self.dependency_ids),n=n) - else: - self.log(self.__class__.__name__,self.identifier,self.simid,self.locdir,list(self.dependency_ids),n=n) + def write_dependents(self,n=0,location=False,block_status=False): + outs = [self.__class__.__name__,self.identifier,self.simid] + if location: + outs.append(self.locdir) #end if + if block_status: + if self.block: + outs.append('blocked') + else: + outs.append('unblocked') + #end if + #end if + outs.append(list(self.dependency_ids)) + self.log(*outs,n=n) n+=1 for sim in self.dependents: - sim.write_dependents(n=n,location=location) + sim.write_dependents(n=n,location=location,block_status=block_status) #end for #end def write_dependents -#end class Simulation -Simulation.set_user_interface( - member_variables=['path','infile','outfile','input','job','files','dependencies','app_name'], - member_functions=['set','depends','progress'] - ) -Simulation.set_dev_instruction( - 'writing derived class', - class_variables=['input_type','analyzer_type','infile_name'], - member_functions=['check_result','get_result','app_command','check_sim_status','get_output_files'] - ) + def execute(self,run_command=None): + pad = self.enter(self.locdir) + if run_command is None: + job = self.job + command = 'export OMP_NUM_THREADS='+str(job.threads)+'\n' + if len(job.presub)>0: + command += job.presub+'\n' + #end if + machine = job.get_machine() + command += job.run_command(machine.app_launcher) + if len(job.postsub)>0: + command += job.postsub+'\n' + #end if + command = ('\n'+command).replace('\n','\n '+pad) + run_command = command + #end if + if self.job is None: + env = os.environ.copy() + else: + env = job.env + #end if + if nexus_core.generate_only: + self.log(pad+'Would have executed: '+command) + else: + self.log(pad+'Executing: '+command) + fout = open(self.outfile,'w') + ferr = open(self.errfile,'w') + out,err = Popen(command,env=env,stdout=fout,stderr=ferr,shell=True,close_fds=True).communicate() + #end if + self.leave() + self.submitted = True + if self.job!=None: + job.status = job.states.finished + self.job.finished = True + #end if + #end def execute + +#end class Simulation @@ -1078,12 +1173,6 @@ Simulation.set_dev_instruction( class NullSimulationInput(SimulationInput): - @classmethod - def templates(cls,template_name): - print 'Developer Error: templates function has not been implemented in '+cls.__name__ - exit() - #end def - def is_valid(self): return True #end def is_valid @@ -1096,13 +1185,13 @@ class NullSimulationInput(SimulationInput): None #end def write - def read_contents(self,contents): + def read_text(self,text,filepath=None): None - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self,filepath=None): None - #end def write_contents + #end def write_text def incorporate_system(self,system): None @@ -1135,10 +1224,12 @@ class NullSimulationAnalyzer(SimulationAnalyzer): #end class NullSimulationAnalyzer +class GenericSimulationInput: # marker class for generic user input + None +#end class GenericSimulationInput + class GenericSimulation(Simulation): - preserve = set(list(Simulation.preserve)+['input_type','analyzer_type']) - def __init__(self,**kwargs): self.input_type = NullSimulationInput self.analyzer_type = NullSimulationAnalyzer @@ -1170,246 +1261,78 @@ class GenericSimulation(Simulation): -class SimulationInputTemplate(SimulationInput): - name_chars = string.ascii_letters+string.digits+'_' - name_characters = set(name_chars) - - comparators = '== != <= >= < >'.split() - - def __init__(self,filepath=None,delimiter='|',conditionals=None,defaults=None): - self.delimiter = delimiter - self.keywords = obj() - self.values = obj() - self.use_default_value = obj() - self.template = '' - if defaults is None: - self.default_values = obj() - else: - self.default_values = obj(**defaults) - #end if - if conditionals is None: - self.conditional_variables = obj() - else: - self.conditional_variables = obj(**conditionals) - #end if +from string import Template +class SimulationInputTemplateDev(SimulationInput): + def __init__(self,filepath=None,text=None): + self.reset() if filepath!=None: self.read(filepath) + elif text!=None: + self.read_text(text) #end if #end def __init__ - - - def set_delimiter(self,delimiter): - if not isinstance(delimiter,str): - self.error('delimiter must be a character, received '+str(delimiter)) - elif len(delimiter)!=1: - self.error('delimiter must be a single character, received'+str([delimiter])) - #end if - self.delimiter = delimiter - #end def set_delimiter - - - def read(self,filepath): - tokens = filepath.split(None,1) - if len(tokens)>1: - contents = filepath - self.read_contents(contents) - else: - if os.path.exists(filepath): - self.read_contents(open(filepath,'r').read(),filepath) - else: - self.error('failed read for filepath below\n '+filepath) - #end if - #end if - #end def read - - - def preprocess(self,contents,filepath=None): - return contents - #end def preprocess - - def read_contents(self,contents,filepath=None): - contents = self.preprocess(contents,filepath) - delimiter = self.delimiter - dlocs = [] - i=0 - for c in contents: - if c==delimiter: - dlocs.append(i) - #end if - i+=1 - #end for - klocs=[] - keywords = [] - nconditionals = len(self.conditional_variables) - conditional_expressions = obj() - conditional_words = [] - for i in range(len(dlocs)-1): - d1 = dlocs[i] - d2 = dlocs[i+1] - word = contents[d1+1:d2] - expressions = None - if nconditionals>0 and ':' in word: - old_word = word - word,expressions = word.split(':') - conditional_words.append((old_word,word)) - #end if - if set(word)<=self.name_characters: - keywords.append(word) - klocs.append(i) - if expressions!=None: - self.screen_conditional_expressions(word,expressions) - conditional_expressions[word] = expressions - #end if - #end if - #end for - for i in range(len(klocs)-1): - if klocs[i+1]-klocs[i]==1: - self.error('keywords cannot be adjacent\n offending text: {0}{1}{0}{2}{0}'.format(delimiter,keywords[i],keywords[i+1])) - #end if - #end for - keywords = set(keywords) - for keyword in keywords: - self.use_default_value[keyword] = False - #end for - for keyword in keywords: - kw = keyword.lower() - self.keywords[kw] = keyword - #end for - defaults = self.default_values - for keyword in list(defaults.keys()): - kw = keyword.lower() - if kw in self.keywords: - value = defaults[keyword] - del defaults[keyword] - defaults[self.keywords[kw]] = value - else: - self.error('default value provided for non-existent template keyword\n non-existent keyword: {0}\n default value provided: {1}\n valid keywords are:\n {2}'.format(keyword,value,self.keywords.keys())) - #end if - #end for - self.evaluate_conditional_expressions(conditional_expressions) - for old_word,word in conditional_words: - old_word = delimiter+old_word+delimiter - word = delimiter+word+delimiter - contents = contents.replace(old_word,word) - #end for - self.template = contents - #end def read_contents - - - def write_contents(self): - kw_rem = self.required_keywords_remaining() - if len(kw_rem)>0: - kw_rem = list(kw_rem) - kw_rem.sort() - self.error('not all keywords for this template have been assigned\n keywords remaining:\n '+str(kw_rem)) - #end if - contents = self.fillout() - return contents - #end def write_contents - - - def read_text(self,*args,**kwargs): - return self.read_contents(*args,**kwargs) - #end def read_text - - - def write_text(self,*args,**kwargs): - return self.write_contents(*args,**kwargs) - #end def write_text - - - def keywords_remaining(self): - return set(self.keywords.values())-set(self.values.keys()) - #end def keywords_remaining - - - def required_keywords_remaining(self): - return self.keywords_remaining()-set(self.default_values.keys()) - #end def required_keywords_remaining - + + def reset(self): + self.template = None + self.keywords = set() + self.values = obj() + #end def reset + + def clear(self): + self.values.clear() + #end def clear def assign(self,**values): - for keyword,value in values.iteritems(): - kw = keyword.lower() - if not kw in self.keywords: - self.error('cannot assign {0} because it is not a valid keyword for this template\n valid options are: {1}'.format(kw,self.keywords.keys())) -#end class SimulationInputTemplate - #end if - kw = self.keywords[kw] - self.values[kw] = value - #end for + if self.template is None: + self.error('cannot assign values prior to reading template') + #end if + invalid = set(values.keys()) - self.keywords + if len(invalid)>0: + self.error('attempted to assign invalid keywords\ninvalid keywords: {0}\nvalid options are: {1}'.format(sorted(invalid),sorted(self.keywords))) + #end if + self.values.set(**values) #end def assign - - def fillout(self): - d = self.delimiter - template = str(self.template) - for keyword in self.values.keys(): - if self.use_default_value[keyword]: - value = self.default_values[keyword] - else: - value = self.values[keyword] + def read_text(self,text,filepath=None): + text = self.preprocess(text,filepath) # for derived class intervention + try: + template = Template(text) + key_tuples = Template.pattern.findall(text) + except Exception,e: + self.error('exception encountered during read\nfile: {0}\nexception: {1}'.format(filepath,e)) + #end try + for ktup in key_tuples: + if len(ktup[1])>0: # normal keyword, e.g. $key + self.keywords.add(ktup[1]) + elif len(ktup[2])>0: # braced keyword, e.g. ${key} + self.keywords.add(ktup[2]) #end if - template = template.replace(d+keyword+d,str(value)) #end for - for keyword,value in self.default_values.iteritems(): - template = template.replace(d+keyword+d,str(value)) - #end for - return template - #end def fillout + self.template = template + #end def read_text + def write_text(self,filepath=None): + kw_rem = self.keywords-set(self.values.keys()) + if len(kw_rem)>0: + self.error('not all keywords for this template have been assigned\nkeywords remaining: {0}'.format(sorted(kw_rem))) + #end if + try: + text = self.template.substitute(**self.values) + except Exception,e: + self.error('exception encountered during write:\n'+str(e)) + #end try + return text + #end def write_text - def screen_conditional_expressions(self,word,expressions): - es = str(expressions) - for comp in self.comparators: - es = es.replace(comp,'@') - #end for - es = es.replace('not ','').replace(' or ',':').replace(' and ',':') - es = es.split(':') - for e in es: - tokens = e.split('@') - if not len(tokens)==2: - self.error('invalid sentinel expression encountered for template keyword {0}\n invalid expression: {1}\n this expression must be of the form "name [comparator] value" or a boolean combination of them "expr1 and expr2 or expr3 ..."'.format(word,expressions)) - #end if - name,value = tokens - if not name.strip() in self.conditional_variables: - self.error('conditional variable {0} has not been provided\n valid options are: {1}'.format(name,self.conditional_variables.keys())) - #end if - #if not comparator in self.comparators: - # self.error('invalid comparator encountered in conditional expression for template keyword {0}\n invalid comparator encountered: {1}\n valid options are: {2}'.format(word,comparator,list(self.comparators))) - ##end if - #end for - #end def screen_conditional_expressions - - - def evaluate_conditional_expressions(self,conditional_expressions): - if len(conditional_expressions)>0: - for _name,_value in self.conditional_variables.iteritems(): - try: - exec('{0}=_value'.format(_name,_value)) - except Exception,e: - self.error('assignment of conditional variable failed\n conditional variable: {0}\n error message: {1}'.format(_name,e)) - #end try - #end for - for _keyword,_expression in conditional_expressions.iteritems(): - if not _keyword in self.default_values: - self.error('a default value must be provided for template keyword {0} because it has a conditional expression:\n {1}'.format(_keyword,_expression)) - #end if - try: - exec('_passes = '+_expression) - except Exception,e: - self.error('evaluation of conditional expression for template keyword failed\n template_keyword: {0}\n conditional expression: {1}\n error message: {2}'.format(_keyword,_expression,e)) - #end try - self.use_default_value[_keyword] = not _passes - #end for - #end for - #end if -#end class SimulationInputTemplate + def preprocess(self,text,filepath): + return text # derived classes can modify text prior to template creation + #end def preprocess +#end class SimulationInputTemplateDev -class SimulationInputMultiTemplate(SimulationInput): +class SimulationInputMultiTemplateDev(SimulationInput): def __init__(self,delimiter='|',conditionals=None,defaults=None,**file_templates): self.filenames = obj() if len(file_templates)>0: @@ -1476,10 +1399,37 @@ class SimulationInputMultiTemplate(SimulationInput): #end for #end if #end def write +#end class SimulationInputMultiTemplateDev + + +# these are for user access, *Dev are for development +class SimulationInputTemplate(SimulationInputTemplateDev,GenericSimulationInput): + None +#end class SimulationInputTemplate + +class SimulationInputMultiTemplate(SimulationInputMultiTemplateDev,GenericSimulationInput): + None #end class SimulationInputMultiTemplate +# developer functions + +def input_template_dev(*args,**kwargs): + return SimulationInputTemplateDev(*args,**kwargs) +#end def input_template_dev + + +def multi_input_template_dev(*args,**kwargs): + return SimulationInputMultiTemplateDev(*args,**kwargs) +#end def multi_input_template_dev + + + + + + +# user functions def input_template(*args,**kwargs): return SimulationInputTemplate(*args,**kwargs) diff --git a/nexus/library/spacegrid.py b/nexus/library/spacegrid.py deleted file mode 100644 index a9f3bdd9a..000000000 --- a/nexus/library/spacegrid.py +++ /dev/null @@ -1,1335 +0,0 @@ -################################################################## -## (c) Copyright 2015- by Jaron T. Krogel ## -################################################################## - - -#====================================================================# -# spacegrid.py # -# Component of QmcpackAnalyzer used specifically for energy # -# density analysis. # -# # -# Content summary: # -# SpaceGrid # -# Represents a grid of data in 3-dimensional space. # -# Can represent rectilinear grids in Cartesian, cylindrical, or # -# or spherical coordinates as well as Voronoi grids. # -# # -#====================================================================# - - -import re -import copy -from numpy import array,floor,sqrt,zeros,prod,dot,ones,empty,min,max -from numpy import pi,sin,cos,arccos as acos,arctan2 as atan2 -from numpy.linalg import inv,det -from extended_numpy import simplestats,ndgrid,ogrid,arange,simstats -from hdfreader import HDFgroup -from qaobject import QAobject - -#simple constants -o2pi = 1./(2.*pi) - -#simple functions -def is_integer(i): - return abs(floor(i)-i)<1e-6 -#end def is_integer - - -class SpaceGridInitializer(QAobject): - def __init__(self): - self.coord = None # string - return - #end def __init__ - - def check_complete(self,exit_on_fail=True): - succeeded = True - for k,v in self._iteritems(): - if v==None: - succeeded=False - if exit_on_fail: - self.error(' SpaceGridInitializer.'+k+' must be provided',exit=False) - #end if - #end if - #end if - if not succeeded and exit_on_fail: - self.error(' SpaceGridInitializer is incomplete') - #end if - return succeeded - #end def check_complete -#end class SpaceGridInitializer - - -class SpaceGridBase(QAobject): - cnames=['cartesian','cylindrical','spherical','voronoi'] - coord_s2n = dict() - coord_n2s = dict() - i=0 - for name in cnames: - exec name+'='+str(i) - coord_s2n[name]=i - coord_n2s[i]=name - i+=1 - #end for - - xlabel = 0 - ylabel = 1 - zlabel = 2 - rlabel = 3 - plabel = 4 - tlabel = 5 - axlabel_s2n = {'x':xlabel,'y':ylabel,'z':zlabel,'r':rlabel,'phi':plabel,'theta':tlabel} - axlabel_n2s = {xlabel:'x',ylabel:'y',zlabel:'z',rlabel:'r',plabel:'phi',tlabel:'theta'} - - axindex = {'x':0,'y':1,'z':2,'r':0,'phi':1,'theta':2} - - quantities=['D','T','V','E','P'] - - def __init__(self,initobj,options): - if options==None: - options = QAobject() - options.wasNone = True - options.points = None - options.exit_on_fail = True - options.nblocks_exclude = 0 - else: - if 'points' not in options: - options.points = None - if 'exit_on_fail' not in options: - options.exit_on_fail = True - if 'nblocks_exclude' not in options: - options.nblocks_exclude = 0 - #end if - - self.points = options.points - self.init_exit_fail = options.exit_on_fail - self.nblocks_exclude = options.nblocks_exclude - self.keep_data = True - delvars = ['init_exit_fail','keep_data'] - - self.coord = None # string - self.coordinate = None - self.ndomains = None - self.domain_volumes = None - self.domain_centers = None - self.nvalues_per_domain = -1 - self.nblocks = -1 - self.D = QAobject() #Number Density - self.T = QAobject() #Kinetic Energy Density - self.V = QAobject() #Potential Energy Density - self.E = QAobject() #Energy Density, T+V - self.P = QAobject() #Local Pressure, (Volume)*P=(2*T+V)/3 - - - self.init_special() - - if initobj==None: - return - #end if - - self.DIM=3 - - iname = initobj.__class__.__name__ - self.iname=iname - if iname==self.__class__.__name__+'Initializer': - self.init_from_initializer(initobj) - elif iname==self.__class__.__name__: - self.init_from_spacegrid(initobj) - elif iname=='HDFgroup': - self.init_from_hdfgroup(initobj) - elif iname=='XMLelement': - self.init_from_xmlelement(initobj) - else: - self.error('Spacegrid cannot be initialized from '+iname) - #end if - delvars.append('iname') - - self.check_complete() - - for dv in delvars: - del self[dv] - #end for - - self._reset_dynamic_methods() - self._register_dynamic_methods() - return - #end def __init__ - - def copy(self,other): - None - #end def copy - - def init_special(self): - None - #end def init_special - - def init_from_initializer(self,init): - None - #end def init_from_initializer - - def init_from_spacegrid(self,init): - None - #end def init_from_spacegrid - - def init_from_hdfgroup(self,init): - #copy all datasets from hdf group - value_pattern = re.compile('value') - gmap_pattern = re.compile(r'gmap\d*') - for k,v in init._iteritems(): - exclude = k[0]=='_' or gmap_pattern.match(k) or value_pattern.match(k) - if not exclude: - self.__dict__[k]=v - #end if - #end for - - #convert 1x and 1x1 numpy arrays to just numbers - #convert Nx1 and 1xN numpy arrays to Nx arrays - array_type = type(array([])) - exclude = set(['value','value_squared']) - for k,v in self._iteritems(): - if k[0]!='_' and type(v)==array_type and k not in exclude: - sh=v.shape - ndim = len(sh) - if ndim==1 and sh[0]==1: - self.__dict__[k]=v[0] - elif ndim==2: - if sh[0]==1 and sh[1]==1: - self.__dict__[k]=v[0,0] - elif sh[0]==1 or sh[1]==1: - self.__dict__[k]=v.reshape((sh[0]*sh[1],)) - #end if - #end if - #end if - #end for - - #set coord string - self.coord = SpaceGridBase.coord_n2s[self.coordinate] - - #determine if chempot grid - chempot = 'min_part' in init - self.chempot = chempot - if chempot: - npvalues = self.max_part-self.min_part+1 - self.npvalues = npvalues - #end if - - #process the data in hdf value,value_squared - nbe = self.nblocks_exclude - nquant = self.nvalues_per_domain - ndomains = self.ndomains - nblocks,ntmp = init.value.shape - self.nblocks = nblocks - - if not chempot: - value = init.value.reshape(nblocks,ndomains,nquant).transpose(2,1,0) - else: - value = init.value.reshape(nblocks,ndomains,npvalues,nquant).transpose(3,2,1,0) - #end if - value = value[...,nbe:] - - #(mean,error)=simplestats(value) - (mean,var,error,kappa)=simstats(value) - quants = ['D','T','V'] - for i in range(len(quants)): - q=quants[i] - self[q].mean = mean[i,...] - self[q].error = error[i,...] - exec 'i'+q+'='+str(i) - #end for - - E = value[iT,...]+value[iV,...] -# (mean,error)=simplestats(E) - (mean,var,error,kappa)=simstats(E) - self.E.mean = mean - self.E.error = error - - P = 2./3.*value[iT,...]+1./3.*value[iV,...] - #(mean,error)=simplestats(P) - (mean,var,error,kappa)=simstats(P) - self.P.mean = mean - self.P.error = error - - - #convert all quantities into true densities - ovol = 1./self.domain_volumes - sqovol = sqrt(ovol) - for q in SpaceGridBase.quantities: - self[q].mean *= ovol - self[q].error *= sqovol - #end for - - #keep original data, if requested - if self.keep_data: - self.data = QAobject() - for i in range(len(quants)): - q=quants[i] - self.data[q] = value[i,...] - #end for - self.data.E = E - self.data.P = P - #end if - - #print 'sg' - #import code - #code.interact(local=locals()) - - return - #end def init_from_hdfgroup - - def init_from_xmlelement(self,init): - None - #end def init_from_xmlelement - - def check_complete(self,exit_on_fail=True): - succeeded = True - for k,v in self._iteritems(): - if k[0]!='_' and v==None: - succeeded=False - if exit_on_fail: - self.error('SpaceGridBase.'+k+' must be provided',exit=False) - #end if - #end if - #end if - if not succeeded: - self.error('SpaceGrid attempted initialization from '+self.iname,exit=False) - self.error('SpaceGrid is incomplete',exit=False) - if exit_on_fail: - exit() - #end if - #end if - return succeeded - #end def check_complete - - def _reset_dynamic_methods(self): - None - #end def _reset_dynamic_methods - - def _unset_dynamic_methods(self): - None - #end def _unset_dynamic_methods - - def add_all_attributes(self,o): - for k,v in o.__dict__.iteritems(): - if not k.startswith('_'): - vc = copy.deepcopy(v) - self._add_attribute(k,vc) - #end if - #end for - return - #end def add_all_attributes - - - def reorder_atomic_data(self,imap): - None - #end if - - - def integrate(self,quantity,domain=None): - if quantity not in SpaceGridBase.quantities: - msg = 'requested integration of quantity '+quantity+'\n' - msg +=' '+quantity+' is not a valid SpaceGrid quantity\n' - msg +=' valid quantities are:\n' - msg +=' '+str(SpaceGridBase.quantities) - self.error(msg) - #end if - dv = self.domain_volumes - if domain==None: - mean = (self[quantity].mean*dv).sum() - error = sqrt((self[quantity].error**2*dv).sum()) - else: - mean = (self[quantity].mean[domain]*dv[domain]).sum() - error = sqrt((self[quantity].error[domain]**2*dv[domain]).sum()) - #end if - return mean,error - #end def integrate - - def integrate_data(self,quantity,*domains,**kwargs): - return_list = False - if 'domains' in kwargs: - domains = kwargs['domains'] - return_list = True - #end if - if 'return_list' in kwargs: - return_list = kwargs['return_list'] - #end if - if quantity not in SpaceGridBase.quantities: - msg = 'requested integration of quantity '+quantity+'\n' - msg +=' '+quantity+' is not a valid SpaceGrid quantity\n' - msg +=' valid quantities are:\n' - msg +=' '+str(SpaceGridBase.quantities) - self.error(msg) - #end if - q = self.data[quantity] - results = list() - nblocks = q.shape[-1] - qi = zeros((nblocks,)) - if len(domains)==0: - for b in xrange(nblocks): - qi[b] = q[...,b].sum() - #end for - (mean,var,error,kappa)=simstats(qi) - else: - for domain in domains: - for b in xrange(nblocks): - qb = q[...,b] - qi[b] = qb[domain].sum() - #end for - (mean,var,error,kappa)=simstats(qi) - res = QAobject() - res.mean = mean - res.error = error - res.data = qi.copy() - results.append(res) - #end for - #end for - if len(domains)<2: - return mean,error - else: - if not return_list: - return tuple(results) - else: - means = list() - errors = list() - for res in results: - means.append(res.mean) - errors.append(res.error) - #end for - return means,errors - #end if - #end if - #end def integrate_data - -#end class SpaceGridBase - - - - -class RectilinearGridInitializer(SpaceGridInitializer): - def __init__(self): - SpaceGridInitializer.__init__(self) - self.origin = None # 3x1 array - self.axes = None # 3x3 array - self.axlabel = None # 3x1 string list - self.axgrid = None # 3x1 string list - #end def __init__ -#end class RectilinearGridInitializer - - -class RectilinearGrid(SpaceGridBase): - def __init__(self,initobj=None,options=None): - SpaceGridBase.__init__(self,initobj,options) - return - #end def __init__ - - def init_special(self): - self.origin = None # 3x1 array - self.axes = None # 3x3 array - self.axlabel = None # 3x1 string list - self.axinv = None - self.volume = None - self.dimensions = None - self.gmap = None - self.umin = None - self.umax = None - self.odu = None - self.dm = None - self.domain_uwidths = None - return - #end def init_special - - def copy(self): - return RectilinearGrid(self) - #end def copy - - def _reset_dynamic_methods(self): - p2d=[self.points2domains_cartesian, \ - self.points2domains_cylindrical, \ - self.points2domains_spherical] - self.points2domains = p2d[self.coordinate] - - p2u=[self.point2unit_cartesian, \ - self.point2unit_cylindrical, \ - self.point2unit_spherical] - self.point2unit = p2u[self.coordinate] - return - #end def _reset_dynamic_methods - - def _unset_dynamic_methods(self): - self.points2domains = None - self.point2unit = None - return - #end def _unset_dynamic_methods - - def init_from_initializer(self,init): - init.check_complete() - for k,v in init._iteritems(): - if k[0]!='_': - self.__dict__[k]=v - #end if - #end for - self.initialize() - return - #end def init_from_initializer - - def init_from_spacegrid(self,init): - for q in SpaceGridBase.quantities: - self[q].mean = init[q].mean.copy() - self[q].error = init[q].error.copy() - #end for - array_type = type(array([1])) - exclude = set(['point2unit','points2domains','points']) - for k,v in init._iteritems(): - if k[0]!='_': - vtype = type(v) - if k in SpaceGridBase.quantities: - self[k].mean = v.mean.copy() - self[k].error = v.error.copy() - elif vtype==array_type: - self[k] = v.copy() - elif vtype==HDFgroup: - self[k] = v - elif k in exclude: - None - else: - self[k] = vtype(v) - #end if - #end for - #end for - self.points = init.points - return - #end def init_from_spacegrid - - def init_from_hdfgroup(self,init): - SpaceGridBase.init_from_hdfgroup(self,init) - self.gmap=[init.gmap1,init.gmap2,init.gmap3] - #set axlabel strings - self.axlabel=list() - for d in range(self.DIM): - label = SpaceGridBase.axlabel_n2s[self.axtypes[d]] - self.axlabel.append(label) - #end for - del self.axtypes - for i in range(len(self.gmap)): - self.gmap[i]=self.gmap[i].reshape((len(self.gmap[i]),)) - #end for - return - #end def init_from_hdfgroup - - - def init_from_xmlelement(self,init): - DIM=self.DIM - self.axlabel=list() - self.axgrid =list() - #coord - self.coord = init.coord - #origin - p1 = self.points[init.origin.p1] - if 'p2' in init.origin: - p2 = self.points[init.origin.p2] - else: - p2 = self.points['zero'] - #end if - if 'fraction' in init.origin: - frac = eval(init.origin.fraction) - else: - frac = 0.0 - self.origin = p1 + frac*(p2-p1) - #axes - self.axes = zeros((DIM,DIM)) - for d in range(DIM): - exec 'axis=init.axis'+str(d+1) - p1 = self.points[axis.p1] - if 'p2' in axis: - p2 = self.points[axis.p2] - else: - p2 = self.points['zero'] - #end if - if 'scale' in axis: - scale = eval(axis.scale) - else: - scale = 1.0 - #end if - for dd in range(DIM): - self.axes[dd,d] = scale*(p1[dd]-p2[dd]) - #end for - self.axlabel.append(axis.label) - self.axgrid.append(axis.grid) - #end for - self.initialize() - return - #end def init_from_xmlelement - - def initialize(self): #like qmcpack SpaceGridBase.initialize - write=False - succeeded=True - - ndomains=-1 - - DIM = self.DIM - - coord = self.coord - origin = self.origin - axes = self.axes - axlabel = self.axlabel - axgrid = self.axgrid - del self.axgrid - - - - ax_cartesian = ["x" , "y" , "z" ] - ax_cylindrical = ["r" , "phi" , "z" ] - ax_spherical = ["r" , "phi" , "theta"] - - cmap = dict() - if(coord=="cartesian"): - for d in range(DIM): - cmap[ax_cartesian[d]]=d - axlabel[d]=ax_cartesian[d] - #end - elif(coord=="cylindrical"): - for d in range(DIM): - cmap[ax_cylindrical[d]]=d - axlabel[d]=ax_cylindrical[d] - #end - elif(coord=="spherical"): - for d in range(DIM): - cmap[ax_spherical[d]]=d - axlabel[d]=ax_spherical[d] - #end - else: - self.error(" Coordinate supplied to spacegrid must be cartesian, cylindrical, or spherical\n You provided "+coord,exit=False) - succeeded=False - #end - self.coordinate = SpaceGridBase.coord_s2n[self.coord] - coordinate = self.coordinate - - - #loop over spacegrid xml elements - naxes =DIM - # variables for loop - utol = 1e-5 - dimensions=zeros((DIM,),dtype=int) - umin=zeros((DIM,)) - umax=zeros((DIM,)) - odu=zeros((DIM,)) - ndu_per_interval=[None,None,None] - gmap=[None,None,None] - for dd in range(DIM): - iaxis = cmap[axlabel[dd]] - grid = axgrid[dd] - #read in the grid contents - # remove spaces inside of parentheses - inparen=False - gtmp='' - for gc in grid: - if(gc=='('): - inparen=True - gtmp+=' ' - #end - if(not(inparen and gc==' ')): - gtmp+=gc - if(gc==')'): - inparen=False - gtmp+=' ' - #end - #end - grid=gtmp - # break into tokens - tokens = grid.split() - if(write): - print " grid = ",grid - print " tokens = ",tokens - #end - # count the number of intervals - nintervals=0 - for t in tokens: - if t[0]!='(': - nintervals+=1 - #end - #end - nintervals-=1 - if(write): - print " nintervals = ",nintervals - # allocate temporary interval variables - ndom_int = zeros((nintervals,),dtype=int) - du_int = zeros((nintervals,)) - ndu_int = zeros((nintervals,),dtype=int) - # determine number of domains in each interval and the width of each domain - u1=1.0*eval(tokens[0]) - umin[iaxis]=u1 - if(abs(u1)>1.0000001): - self.error(" interval endpoints cannot be greater than 1\n endpoint provided: "+str(u1),exit=False) - succeeded=False - #end - is_int=False - has_paren_val=False - interval=-1 - for i in range(1,len(tokens)): - if not tokens[i].startswith('('): - u2=1.0*eval(tokens[i]) - umax[iaxis]=u2 - if(not has_paren_val): - du_i=u2-u1 - #end - has_paren_val=False - interval+=1 - if(write): - print " parsing interval ",interval," of ",nintervals - print " u1,u2 = ",u1,",",u2 - #end - if(u21.0000001): - self.error(" interval endpoints cannot be greater than 1\n endpoint provided: "+str(u2),exit=False) - succeeded=False - #end - if(is_int): - du_int[interval]=(u2-u1)/ndom_i - ndom_int[interval]=ndom_i - else: - du_int[interval]=du_i - ndom_int[interval]=floor((u2-u1)/du_i+.5) - if(abs(u2-u1-du_i*ndom_int[interval])>utol): - self.error(" interval ("+str(u1)+","+str(u2)+") not divisible by du="+str(du_i),exit=False) - succeeded=False - #end - #end - u1=u2 - else: - has_paren_val=True - paren_val=tokens[i][1:len(tokens[i])-1] - if(write): - print " interval spacer = ",paren_val - #end if - is_int=tokens[i].find(".")==-1 - if(is_int): - ndom_i = eval(paren_val) - du_i = -1.0 - else: - ndom_i = 0 - du_i = eval(paren_val) - #end - #end - #end - # find the smallest domain width - du_min=min(du_int) - odu[iaxis]=1.0/du_min - # make sure it divides into all other domain widths - for i in range(len(du_int)): - ndu_int[i]=floor(du_int[i]/du_min+.5) - if(abs(du_int[i]-ndu_int[i]*du_min)>utol): - self.error("interval {0} of axis {1} is not divisible by smallest subinterval {2}".format(i+1,iaxis+1,du_min),exit=False) - succeeded=False - #end - #end - - if(write): - print " interval breakdown" - print " interval,ndomains,nsubdomains_per_domain" - for i in range(len(ndom_int)): - print " ",i,",",ndom_int[i],",",ndu_int[i] - #end - #end - - # set up the interval map such that gmap[u/du]==domain index - gmap[iaxis] = zeros((floor((umax[iaxis]-umin[iaxis])*odu[iaxis]+.5),),dtype=int) - n=0 - nd=-1 - if(write): - print " i,j,k ax,n,nd " - #end if - for i in range(len(ndom_int)): - for j in range(ndom_int[i]): - nd+=1 - for k in range(ndu_int[i]): - gmap[iaxis][n]=nd - if(write): - print " ",i,",",j,",",k," ",iaxis,",",n,",",nd - #end - n+=1 - #end - #end - #end - dimensions[iaxis]=nd+1 - #end read in the grid contents - - #save interval width information - ndom_tot=sum(ndom_int) - ndu_per_interval[iaxis] = zeros((ndom_tot,),dtype=int) - idom=0 - for i in range(len(ndom_int)): - for ii in range(ndom_int[i]): - ndu_per_interval[iaxis][idom] = ndu_int[i] - idom+=1 - #end - #end - #end - - axinv = inv(axes) - - #check that all axis grid values fall in the allowed intervals - cartmap = dict() - for d in range(DIM): - cartmap[ax_cartesian[d]]=d - #end for - for d in range(DIM): - if axlabel[d] in cartmap: - if(umin[d]<-1.0 or umax[d]>1.0): - self.error(" grid values for {0} must fall in [-1,1]\n".format(axlabel[d])+" interval provided: [{0},{1}]".format(umin[d],umax[d]),exit=False) - succeeded=False - #end if - elif(axlabel[d]=="phi"): - if(abs(umin[d])+abs(umax[d])>1.0): - self.error(" phi interval cannot be longer than 1\n interval length provided: {0}".format(abs(umin[d])+abs(umax[d])),exit=False) - succeeded=False - #end if - else: - if(umin[d]<0.0 or umax[d]>1.0): - self.error(" grid values for {0} must fall in [0,1]\n".format(axlabel[d])+" interval provided: [{0},{1}]".format(umin[d],umax[d]),exit=False) - succeeded=False - #end if - #end if - #end for - - - #set grid dimensions - # C/Python style indexing - dm=array([0,0,0],dtype=int) - dm[0] = dimensions[1]*dimensions[2] - dm[1] = dimensions[2] - dm[2] = 1 - - ndomains=prod(dimensions) - - volume = abs(det(axes))*8.0#axes span only one octant - - #compute domain volumes, centers, and widths - domain_volumes = zeros((ndomains,)) - domain_centers = zeros((ndomains,DIM)) - domain_uwidths = zeros((ndomains,DIM)) - interval_centers = [None,None,None] - interval_widths = [None,None,None] - for d in range(DIM): - nintervals = len(ndu_per_interval[d]) - interval_centers[d] = zeros((nintervals)) - interval_widths[d] = zeros((nintervals)) - interval_widths[d][0]=ndu_per_interval[d][0]/odu[d] - interval_centers[d][0]=interval_widths[d][0]/2.0+umin[d] - for i in range(1,nintervals): - interval_widths[d][i] = ndu_per_interval[d][i]/odu[d] - interval_centers[d][i] = interval_centers[d][i-1] \ - +.5*(interval_widths[d][i]+interval_widths[d][i-1]) - #end for - #end for - du,uc,ubc,rc = zeros((DIM,)),zeros((DIM,)),zeros((DIM,)),zeros((DIM,)) - vol = -1e99 - vol_tot=0.0 - vscale = abs(det(axes)) - - for i in range(dimensions[0]): - for j in range(dimensions[1]): - for k in range(dimensions[2]): - idomain = dm[0]*i + dm[1]*j + dm[2]*k - du[0] = interval_widths[0][i] - du[1] = interval_widths[1][j] - du[2] = interval_widths[2][k] - uc[0] = interval_centers[0][i] - uc[1] = interval_centers[1][j] - uc[2] = interval_centers[2][k] - - if(coordinate==SpaceGridBase.cartesian): - vol=du[0]*du[1]*du[2] - ubc=uc - elif(coordinate==SpaceGridBase.cylindrical): - uc[1]=2.0*pi*uc[1]-pi - du[1]=2.0*pi*du[1] - vol=uc[0]*du[0]*du[1]*du[2] - ubc[0]=uc[0]*cos(uc[1]) - ubc[1]=uc[0]*sin(uc[1]) - ubc[2]=uc[2] - elif(coordinate==SpaceGridBase.spherical): - uc[1]=2.0*pi*uc[1]-pi - du[1]=2.0*pi*du[1] - uc[2]= pi*uc[2] - du[2]= pi*du[2] - vol=(uc[0]*uc[0]+du[0]*du[0]/12.0)*du[0] \ - *du[1] \ - *2.0*sin(uc[2])*sin(.5*du[2]) - ubc[0]=uc[0]*sin(uc[2])*cos(uc[1]) - ubc[1]=uc[0]*sin(uc[2])*sin(uc[1]) - ubc[2]=uc[0]*cos(uc[2]) - #end if - vol*=vscale - - vol_tot+=vol - - rc = dot(axes,ubc) + origin - - domain_volumes[idomain] = vol - for d in range(DIM): - domain_uwidths[idomain,d] = du[d] - domain_centers[idomain,d] = rc[d] - #end for - #end for - #end for - #end for - - #find the actual volume of the grid - du = umax-umin - uc = .5*(umax+umin) - if coordinate==SpaceGridBase.cartesian: - vol=du[0]*du[1]*du[2] - elif coordinate==SpaceGridBase.cylindrical: - uc[1]=2.0*pi*uc[1]-pi - du[1]=2.0*pi*du[1] - vol=uc[0]*du[0]*du[1]*du[2] - elif coordinate==SpaceGridBase.spherical: - uc[1]=2.0*pi*uc[1]-pi - du[1]=2.0*pi*du[1] - uc[2]= pi*uc[2] - du[2]= pi*du[2] - vol=(uc[0]*uc[0]+du[0]*du[0]/12.0)*du[0]*du[1]*2.0*sin(uc[2])*sin(.5*du[2]) - #end if - volume = vol*abs(det(axes)) - - for q in SpaceGridBase.quantities: - self[q].mean = zeros((ndomains,)) - self[q].error = zeros((ndomains,)) - #end for - - #save the results - self.axinv = axinv - self.volume = volume - self.gmap = gmap - self.umin = umin - self.umax = umax - self.odu = odu - self.dm = dm - self.dimensions = dimensions - self.ndomains = ndomains - self.domain_volumes = domain_volumes - self.domain_centers = domain_centers - self.domain_uwidths = domain_uwidths - - - #succeeded = succeeded and check_grid() - - if(self.init_exit_fail and not succeeded): - self.error(" in def initialize") - #end - - return succeeded - #end def initialize - - def point2unit_cartesian(point): - u = dot(self.axinv,(point-self.origin)) - return u - #end def point2unit_cartesian - - def point2unit_cylindrical(point): - ub = dot(self.axinv,(point-self.origin)) - u=zeros((self.DIM,)) - u[0] = sqrt(ub[0]*ub[0]+ub[1]*ub[1]) - u[1] = atan2(ub[1],ub[0])*o2pi+.5 - u[2] = ub[2] - return u - #end def point2unit_cylindrical - - def point2unit_spherical(point): - ub = dot(self.axinv,(point-self.origin)) - u=zeros((self.DIM,)) - u[0] = sqrt(ub[0]*ub[0]+ub[1]*ub[1]+ub[2]*ub[2]) - u[1] = atan2(ub[1],ub[0])*o2pi+.5 - u[2] = acos(ub[2]/u[0])*o2pi*2.0 - return u - #end def point2unit_spherical - - def points2domains_cartesian(self,points,domains,points_outside): - u = zeros((self.DIM,)) - iu = zeros((self.DIM,),dtype=int) - ndomains=-1 - npoints,ndim = points.shape - for p in xrange(npoints): - u = dot(self.axinv,(points[p]-self.origin)) - if (u>self.umin).all() and (uself.umin).all() and (uself.umin).all() and (u1e-6: - if warn: - self.warn('source origin must lie at interpolant r=0') - #end if - return False - #end if - #end if - # fine meshes must align - # origin must be an integer multiple of smallest dom width - if am_cylindrical: - mdims=[2] - elif am_cartesian: - mdims=[0,1,2] - else: - mdims=[] - #end if - for d in mdims: - if not is_integer(uo[d]*self.odu[d]): - if warn: - self.warn('source origin does not lie on interpolant fine mesh') - #end if - return False - #end if - #end for - # smallest dom width must be multiple of this smallest dom width - for d in range(self.DIM): - if not is_integer(self.odu[d]/s.odu[d]): - if warn: - self.warn('smallest source domain width must be a multiple of interpolants smallest domain width') - #end if - return False - #end if - #end for - # each interval along each direction for interpolant must map to only one source interval - # construct points at each fine interval center of interpolant, run them through source gmap to get interval indices - for d in range(self.DIM): - fine_interval_domains[d][:]=-2 - gmlen = len(s.gmap[d]) - for i in range(len(fine_interval_centers[d])): - uc = fine_interval_centers[d][i] - ind = floor((uc-s.umin[d])*s.odu[d]) - if ind < gmlen: - idom=s.gmap[d][ind] - else: - idom=-1 - #end if - fine_interval_domains[d][i]=idom - #end for - cind = self.gmap[d][0] - istart = 0 - iend = 0 - for i in range(len(self.gmap[d])): - if self.gmap[d][i]==cind: - iend+=1 - else: - source_ind = fine_interval_domains[istart] - for j in range(istart+1,iend): - if fine_interval_domains[j]!=source_ind: - if warn: - self.warn('an interpolant domain must not fall on multiple source domains') - #end if - return False - #end if - #end for - istart=iend - #end if - #end for - #end for - #end for - #end if - - - #get the list of domains points from this grid fall in - # and interpolate requested quantities on them - domain_centers = self.domain_centers - domind = zeros((self.ndomains,2),dtype=int) - domout = ones((self.ndomains,) ,dtype=int) - for s in spacegrids: - domind[:,:] = -1 - ndomin = s.points2domains(domain_centers,domind,domout) - for q in quantities: - self[q].mean[domind[0:ndomin,0]] = s[q].mean[domind[0:ndomin,1]].copy() - self[q].error[domind[0:ndomin,0]] = s[q].error[domind[0:ndomin,1]].copy() - #end for - #end for - for d in xrange(self.ndomains): - if domout[d]: - for q in quantities: - self[q].mean[d] = outside[q].mean - self[q].error[d] = outside[q].error - #end for - #end if - #end for - return True - #end def interpolate_across - - - def interpolate(self,points,quantities=None): - if quantities==None: - quantities=SpaceGridBase.quantities - #end if - npoints,ndim = points.shape - ind = empty((npoints,2),dtype=int) - out = ones((npoints,) ,dtype=int) - nin = self.points2domains(points,ind,out) - result = QAobject() - for q in quantities: - result._add_attribute(q,QAobject()) - result[q].mean = zeros((npoints,)) - result[q].error = zeros((npoints,)) - result[q].mean[ind[0:nin,0]] = self[q].mean[ind[0:nin,1]].copy() - result[q].error[ind[0:nin,0]] = self[q].error[ind[0:nin,1]].copy() - #end for - return result - #end def interpolate - - - def isosurface(self,quantity,contours=5,origin=None): - if quantity not in SpaceGridBase.quantities: - self.error() - #end if - dimensions = self.dimensions - if origin==None: - points = self.domain_centers - else: - npoints,ndim = self.domain_centers.shape - points = empty((npoints,ndim)) - for i in range(npoints): - points[i,:] = origin + self.domain_centers[i,:] - #end for - #end if - scalars = self[quantity].mean - name = quantity - self.plotter.isosurface(points,scalars,contours,dimensions,name) - return - #end def isosurface - - - def surface_slice(self,quantity,x,y,z,options=None): - if quantity not in SpaceGridBase.quantities: - self.error() - #end if - points = empty( (x.size,self.DIM) ) - points[:,0] = x.ravel() - points[:,1] = y.ravel() - points[:,2] = z.ravel() - val = self.interpolate(points,[quantity]) - scalars = val[quantity].mean - scalars.shape = x.shape - self.plotter.surface_slice(x,y,z,scalars,options) - return - #end def surface_slice - - - def plot_axes(self,color=None,radius=.025,origin=None): - if color is None: - color = (0.,0,0) - #end if - if origin is None: - origin = array([0.,0,0]) - #end if - colors=array([[1.,0,0],[0,1.,0],[0,0,1.]]) - for d in range(self.DIM): - a=self.axes[:,d]+origin - ax=array([-a[0],a[0]]) - ay=array([-a[1],a[1]]) - az=array([-a[2],a[2]]) - self.plotter.plot3d(ax,ay,az,tube_radius=radius,color=tuple(colors[:,d])) - #end for - return - #end def plot_axes - - def plot_box(self,color=None,radius=.025,origin=None): - if color is None: - color = (0.,0,0) - #end if - if origin is None: - origin = array([0.,0,0]) - #end if - p = self.points - p1=p.cmmm+origin - p2=p.cmpm+origin - p3=p.cpmm+origin - p4=p.cppm+origin - p5=p.cmmp+origin - p6=p.cmpp+origin - p7=p.cpmp+origin - p8=p.cppp+origin - bline = array([p1,p2,p4,p3,p1,p5,p6,p8,p7,p5,p7,p3,p4,p8,p6,p2]) - self.plotter.plot3d(bline[:,0],bline[:,1],bline[:,2],color=color) - return - #end def plot_box -#end class RectilinearGrid - - - - - -class VoronoiGridInitializer(SpaceGridInitializer): - def __init__(self): - SpaceGridInitializer.__init__(self) - #end def __init__ -#end class VoronoiGridInitializer - - -class VoronoiGrid(SpaceGridBase): - def __init__(self,initobj=None,options=None): - SpaceGridBase.__init__(self,initobj,options) - return - #end def __init__ - - def copy(self,other): - return VoronoiGrid(other) - #end def copy - - - def reorder_atomic_data(self,imap): - for q in self.quantities: - qv = self[q] - qv.mean = qv.mean[...,imap] - qv.error = qv.error[...,imap] - #end for - if 'data' in self: - data = self.data - for q in self.quantities: - data[q] = data[q][...,imap,:] - #end for - #end if - #end def reorder_atomic_data -#end class VoronoiGrid - - - - - - -def SpaceGrid(init,opts=None): - SpaceGrid.count+=1 - - iname = init.__class__.__name__ - if iname=='HDFgroup': - coordinate = init.coordinate[0] - #end if - coord = SpaceGrid.coord_n2s[coordinate] - - if coord in SpaceGrid.rect: - return RectilinearGrid(init,opts) - elif coord=='voronoi': - return VoronoiGrid(init,opts) - else: - print 'SpaceGrid '+coord+' has not been implemented, exiting...' - exit() - #end if - -#end def SpaceGrid -SpaceGrid.count = 0 -SpaceGrid.coord_n2s = SpaceGridBase.coord_n2s -SpaceGrid.rect = set(['cartesian','cylindrical','spherical']) diff --git a/nexus/library/sqd_input.py b/nexus/library/sqd_input.py index decfe7531..1424386fa 100644 --- a/nexus/library/sqd_input.py +++ b/nexus/library/sqd_input.py @@ -23,7 +23,7 @@ import os -import types as pytypes +import inspect import keyword from numpy import fromstring,empty,array,float64,\ loadtxt,ndarray,dtype,sqrt,pi,arange,exp,eye,ceil,mod @@ -32,7 +32,7 @@ from superstring import string2val from generic import obj from xmlreader import XMLreader,XMLelement from periodic_table import pt as periodic_table -from project_base import Pobj +from developer import DevBase from structure import Structure from physical_system import PhysicalSystem from simulation import SimulationInput @@ -127,7 +127,7 @@ def string_to_val(s): #end def string_to_val -class SQDobj(Pobj): +class SQDobj(DevBase): None #end class SQDobj @@ -312,24 +312,19 @@ class SQDxml(Names): @classmethod def init_class(cls): - vars = cls.__dict__.keys() - init_vars = dict(tag = cls.__name__, - attributes = [], - elements = [], - text = None, - parameters = [], - attribs = [], - costs = [], - h5tags = [], - defaults = obj() - ) - for var,val in init_vars.iteritems(): - if not var in vars: - cls.__dict__[var] = val - #end if - #end for + cls.class_set_optional( + tag = cls.__name__, + attributes = [], + elements = [], + text = None, + parameters = [], + attribs = [], + costs = [], + h5tags = [], + defaults = obj() + ) for v in ['attributes','elements','parameters','attribs','costs','h5tags']: - names = cls.__dict__[v] + names = cls.class_get(v) for i in range(len(names)): if names[i] in cls.escape_names: names[i]+='_' @@ -600,7 +595,6 @@ class SQDxml(Names): def incorporate_defaults(self,elements=False,overwrite=False,propagate=True): for name,value in self.defaults.iteritems(): - valtype = type(value) defval=None if isinstance(value,classcollection): if elements: @@ -612,11 +606,11 @@ class SQDxml(Names): #end for defval = make_collection(coll) #end if - elif valtype==pytypes.ClassType: + elif inspect.isclass(value): if elements: defval = value() #end if - elif valtype==pytypes.FunctionType: + elif inspect.isfunction(value): defval = value() else: defval = value @@ -1483,7 +1477,7 @@ class SqdInput(SimulationInput,Names): #end def read - def write_contents(self): + def write_text(self,filepath=None): c = '' header = ''' ''' @@ -1497,7 +1491,7 @@ class SqdInput(SimulationInput,Names): c+=base.write(first=True) Param.metadata = None return c - #end def write_contents + #end def write_text def unroll_calculations(self,modify=True): qmc = [] @@ -1705,7 +1699,7 @@ class SqdInput(SimulationInput,Names): -class Shells(Pobj): +class Shells(DevBase): channel_names = tuple('spdfghik') channels = obj() for l in range(len(channel_names)): @@ -1898,7 +1892,7 @@ class Shells(Pobj): self.error('unexpected key values for shells\n expected values: '+str(shells.keys())+'\n you provided '+str(self.all_shells.keys())) #end if else: - self.error('must provide a string, dict, or obj describing atomic shells\n you provided '+str(shell_str)) + self.error('must provide a string, dict, or obj describing atomic shells\n you provided '+str(shells)) #end if self.check_shells() #end def __init__ @@ -1958,7 +1952,7 @@ class Shells(Pobj): m=v1 ma = abs(array(m)) if ma.max()>self.channel_indices[l]: - self.error('maximum |m| for {0} channel is {1}\n you requested {2}: {3}'.format(l,channel_indices[l],ma.max(),m)) + self.error('maximum |m| for {0} channel is {1}\n you requested {2}: {3}'.format(l,self.channel_indices[l],ma.max(),m)) #end if channel = m m=None @@ -2082,11 +2076,6 @@ class Shells(Pobj): #end for return orbitals #end def orbitals - - - def error(self,msg,exit=True): - Pobj.error(self,msg,self.location,exit=exit) - #end def error #end class Shells hunds_rule_filling = Shells.hunds_rule_filling diff --git a/nexus/library/structure.py b/nexus/library/structure.py index 5a3b95ff7..210d12ae3 100755 --- a/nexus/library/structure.py +++ b/nexus/library/structure.py @@ -32,7 +32,7 @@ from numpy import array,floor,empty,dot,diag,sqrt,pi,mgrid,exp,append,arange,cei from numpy.linalg import inv,det,norm from types import NoneType from unit_converter import convert -from extended_numpy import nearest_neighbors,convex_hull,voronoi_neighbors +from numerics import nearest_neighbors,convex_hull,voronoi_neighbors from periodic_table import pt,is_element from generic import obj from developer import DevBase,unavailable,error,warn @@ -603,9 +603,12 @@ class Structure(Sobj): # while remaining periodically correct # note that the unshearing procedure is not unique # it depends on the order of unshearing operations - def unsheared_axes(self,distances=False): + def unsheared_axes(self,axes=None,distances=False): if self.dim!=3: - self.error('rinscribe is currently only implemented for 3 dimensions') + self.error('unsheared_axes is currently only implemented for 3 dimensions') + #end if + if axes is None: + axes = self.axes #end if dim=3 axbar = identity(dim) @@ -654,11 +657,6 @@ class Structure(Sobj): return self.face_vectors(distances=True)[1] #end def face_distances - - def set_orig(self): - self.orig_pos = pos.copy() - #end def set_orig - def rescale(self,scale): self.scale *= scale @@ -2957,19 +2955,19 @@ class Structure(Sobj): #end if #end if c = open(filepath,'r').read() - self.read_contents(c,format,elem=elem) + self.read_text(c,format,elem=elem) return c #end def read - def read_contents(self,contents,format,elem=None): + def read_text(self,contents,format,elem=None): format = format.lower() if format=='poscar': self.read_poscar(contents,elem=elem,contents=True) else: self.error('unrecognized file format: {0}'.format(format)) #end if - #end def read_contents + #end def read_text def read_poscar(self,filepath,elem=None,contents=False): @@ -4182,7 +4180,7 @@ def generate_crystal_structure(lattice=None,cell=None,centering=None, basis_vectors=None,tiling=None,cscale=None, axes=None,units=None,angular_units='degrees', magnetization=None,magnetic_order=None,magnetic_prim=True, - kpoints=None,kgrid=None,kshift=(0,0,0),permute=None, + kpoints=None,kweights=None,kgrid=None,kshift=(0,0,0),permute=None, structure=None,shape=None,element=None,scale=None, #legacy inputs operations=None, struct_type=Crystal,elem=None,pos=None,frozen=None, diff --git a/nexus/library/template_simulation.py b/nexus/library/template_simulation.py index 8bc306419..fddc5b8f7 100644 --- a/nexus/library/template_simulation.py +++ b/nexus/library/template_simulation.py @@ -54,7 +54,7 @@ from simulation import Simulation,SimulationInput,SimulationAnalyzer # in a form TemplateSimulationInput understands (this depends on your implementation) # # required functions to be implemented: -# TemplateSimulationInput: read_contents, write_contents +# TemplateSimulationInput: read_text, write_text # TemplateSimulation: app_command, check_sim_status # # 2) generated standalone simulation @@ -64,7 +64,7 @@ from simulation import Simulation,SimulationInput,SimulationAnalyzer # a standard PhysicalSystem object # # required functions to be implemented: -# TemplateSimulationInput: read_contents, write_contents, incorporate_system +# TemplateSimulationInput: read_text, write_text, incorporate_system # TemplateSimulation: app_command, check_sim_status # generate_template_simulation_input # @@ -76,7 +76,7 @@ from simulation import Simulation,SimulationInput,SimulationAnalyzer # this information is used by the others to populate input files # # required functions to be implemented: -# TemplateSimulationInput: read_contents, write_contents +# TemplateSimulationInput: read_text, write_text # TemplateSimulation: app_command,check_sim_status, # check_result, get_result # @@ -89,7 +89,7 @@ from simulation import Simulation,SimulationInput,SimulationAnalyzer # info is used to populate own input file # # required functions to be implemented: -# TemplateSimulationInput: read_contents, write_contents +# TemplateSimulationInput: read_text, write_text # TemplateSimulation: app_command,check_sim_status, # check_result, get_result, # incorporate_result @@ -111,10 +111,10 @@ class TemplateSimulationInput(SimulationInput): #end def __init__ - def read_contents(self,contents): + def read_text(self,text,filepath=None): # required - # the string 'contents' contains the text of an input file - # translate contents into an internal representation of the input + # the string 'text' contains the text of an input file + # translate text into an internal representation of the input # for example, an input file looking like: # section_a # var_a 1 @@ -132,7 +132,7 @@ class TemplateSimulationInput(SimulationInput): # sec['var_d'] = True # self['section_b'] = sec # with some line parsing: - # for line in contents.splitlines(): + # for line in text.splitlines(): # # parse lines here # #end for # the resulting input object can then be worked with in a simple way: @@ -153,23 +153,23 @@ class TemplateSimulationInput(SimulationInput): # # >>> input.section_b.var_c = 25.0 None - #end def read_contents + #end def read_text - def write_contents(self): + def write_text(self,filepath=None): # required # translate the internal representation of input into a string # for the above example, this might look like: - # contents = '' + # text = '' # for secname,sec in self.iteritems(): - # contents += secname+'\n' + # text += secname+'\n' # for val,val in sec.iteritems(): - # contents += ' '+var+' = '+val2str(val) + # text += ' '+var+' = '+val2str(val) # #end for # #end for - contents = '' - return contents - #end def write_contents + text = '' + return text + #end def write_text def incorporate_system(self,system): diff --git a/nexus/library/unit_converter.py b/nexus/library/unit_converter.py index 41df34b3e..982f61669 100644 --- a/nexus/library/unit_converter.py +++ b/nexus/library/unit_converter.py @@ -20,31 +20,44 @@ #====================================================================# -from abilities import Callable +from numpy import dot,zeros +from numpy.linalg import inv +from generic import obj +from developer import DevBase -class Unit: - def __init__(self,name,symbol,type,value,shift=0): - self.name = name +class Unit(DevBase): + + unit_dicts = obj(all=obj()) + + def __init__(self,type,name,symbol,value,shift=0): + self.type = type + self.name = name self.symbol = symbol - self.type = type - self.value = value - self.shift = shift + self.value = value + self.shift = shift + + ud = Unit.unit_dicts + if type not in ud: + ud[type] = obj() + #end if + td = ud[type] + td[symbol] = self + ud.all[symbol] = self #end def __init__ #end class Unit -class UnitConverter: +class UnitConverter(DevBase): unassigned = None - kb = 1.3806503e-23 #J/K - count_set = set(['mol']) + # count mol = 6.0221415e23 - distance_set = set(['m','A','B','nm','pm','fm','a','b','c']) + # distance m = 1.e0 A = 1.e-10*m B = .52917720859e-10*m @@ -52,21 +65,21 @@ class UnitConverter: pm = 1.e-12*m fm = 1.e-15*m - time_set = set(['s','ms','ns','ps','fs']) + # time s = 1.e0 ms = 1.e-3*s ns = 1.e-9*s ps = 1.e-12*s fs = 1.e-15*s - mass_set = set(['kg','me','mp','amu','Da']) + # mass kg = 1.e0 me = 9.10938291e-31*kg mp = 1.672621777e-27*kg amu = 1.660538921e-27*kg Da = amu - energy_set = set(['J','eV','Ry','Ha','kJ_mol','K','degC','degF','kcal_mol']) + # energy J = 1.e0 eV = 1.60217646e-19*J Ry = 13.6056923*eV @@ -80,166 +93,85 @@ class UnitConverter: degC_shift = -273.15 degF_shift = -459.67 - charge_set = set(['C','e']) + # charge C = 1.e0 e = 1.60217646e-19*C - pressure_set = set(['Pa','bar','Mbar','GPa','atm']) + # pressure Pa = 1.e0 bar = 1.e5*Pa Mbar = 1.e6*bar GPa = 1.e9*Pa atm = 1.01325e5*Pa - force_set = set(['N','pN']) + # force N = 1.e0 pN = 1e-12*N - therm_cond_set = set(['W_mK']) + # thermal conductivity W_mK = 1.0 - alatt = unassigned - blatt = unassigned - clatt = unassigned - meter = Unit('meter' ,'m' ,'distance',m) - angstrom = Unit('Angstrom' ,'A' ,'distance',A) - bohr = Unit('Bohr' ,'B' ,'distance',B) - nanometer = Unit('nanometer' ,'nm','distance',nm) - picometer = Unit('picometer' ,'pm','distance',pm) - femtometer = Unit('femtometer','pm','distance',fm) - a = Unit('a' ,'a' ,'distance',alatt) - b = Unit('b' ,'b' ,'distance',blatt) - c = Unit('c' ,'c' ,'distance',clatt) - - second = Unit('second' ,'s' ,'time',s ) - millisecond = Unit('millisecond','ms','time',ms) - nanosecond = Unit('nanosecond' ,'ns','time',ns) - picosecond = Unit('picosecond' ,'ps','time',ps) - femtosecond = Unit('femtosecond','fs','time',fs) - - kilogram = Unit('kilogram' ,'kg' ,'mass',kg) - electron_mass = Unit('electron mass' ,'me' ,'mass',me) - proton_mass = Unit('proton mass' ,'mp' ,'mass',mp) - atomic_mass_unit = Unit('atomic mass unit','amu','mass',amu) - dalton = Unit('Dalton' ,'Da' ,'mass',Da) + meter = Unit('distance' ,'meter' ,'m' ,m ) + angstrom = Unit('distance' ,'Angstrom' ,'A' ,A ) + bohr = Unit('distance' ,'Bohr' ,'B' ,B ) + nanometer = Unit('distance' ,'nanometer' ,'nm' ,nm ) + picometer = Unit('distance' ,'picometer' ,'pm' ,pm ) + femtometer = Unit('distance' ,'femtometer' ,'pm' ,fm ) + + second = Unit('time' ,'second' ,'s' ,s ) + millisecond = Unit('time' ,'millisecond' ,'ms' ,ms ) + nanosecond = Unit('time' ,'nanosecond' ,'ns' ,ns ) + picosecond = Unit('time' ,'picosecond' ,'ps' ,ps ) + femtosecond = Unit('time' ,'femtosecond' ,'fs' ,fs ) + + kilogram = Unit('mass' ,'kilogram' ,'kg' ,kg ) + electron_mass = Unit('mass' ,'electron mass' ,'me' ,me ) + proton_mass = Unit('mass' ,'proton mass' ,'mp' ,mp ) + atomic_mass_unit = Unit('mass' ,'atomic mass unit','amu' ,amu ) + dalton = Unit('mass' ,'Dalton' ,'Da' ,Da ) - joule = Unit('Joule' ,'J' ,'energy',J) - electron_volt = Unit('electron Volt','eV' ,'energy',eV) - rydberg = Unit('Rydberg' ,'Ry' ,'energy',Ry) - hartree = Unit('Hartree' ,'Ha' ,'energy',Ha) - kJ_mole = Unit('kJ_mole' ,'kJ_mol','energy',kJ_mol) - kcal_mole = Unit('kcal_mole' ,'kcal_mol','energy',kcal_mol) - kelvin = Unit('Kelvin' ,'K' ,'energy',K) - celcius = Unit('Celcius' ,'degC' ,'energy',degC,degC_shift) - fahrenheit = Unit('Fahrenheit' ,'degF' ,'energy',degF,degF_shift) + joule = Unit('energy' ,'Joule' ,'J' ,J ) + electron_volt = Unit('energy' ,'electron Volt' ,'eV' ,eV ) + rydberg = Unit('energy' ,'Rydberg' ,'Ry' ,Ry ) + hartree = Unit('energy' ,'Hartree' ,'Ha' ,Ha ) + kJ_mole = Unit('energy' ,'kJ_mole' ,'kJ_mol' ,kJ_mol ) + kcal_mole = Unit('energy' ,'kcal_mole' ,'kcal_mol',kcal_mol ) + kelvin = Unit('energy' ,'Kelvin' ,'K' ,K ) + celcius = Unit('energy' ,'Celcius' ,'degC' ,degC,degC_shift) + fahrenheit = Unit('energy' ,'Fahrenheit' ,'degF' ,degF,degF_shift) + + coulomb = Unit('charge' ,'Coulomb' ,'C' ,C ) + electron_charge = Unit('charge' ,'electron charge' ,'e' ,e ) - coulomb = Unit('Coulomb' ,'C','charge',C) - electron_charge = Unit('electron charge','e','charge',e) - - pascal = Unit('Pascal' ,'Pa' ,'pressure',Pa) - bar = Unit('bar' ,'bar' ,'pressure',bar) - megabar = Unit('megabar' ,'Mbar','pressure',Mbar) - gigapascal = Unit('gigaPascal','Gpa' ,'pressure',GPa) - atmosphere = Unit('atmosphere','atm' ,'pressure',atm) - - newton = Unit('Newton' ,'N' ,'force',N) - piconewton = Unit('picoNewton','pN','force',pN) - - W_per_mK = Unit('W/(m*K)','W_mK','thermal_cond',W_mK) + pascal = Unit('pressure' ,'Pascal' ,'Pa' ,Pa ) + bar = Unit('pressure' ,'bar' ,'bar' ,bar ) + megabar = Unit('pressure' ,'megabar' ,'Mbar' ,Mbar ) + gigapascal = Unit('pressure' ,'gigaPascal' ,'Gpa' ,GPa ) + atmosphere = Unit('pressure' ,'atmosphere' ,'atm' ,atm ) + + newton = Unit('force' ,'Newton' ,'N' ,N ) + piconewton = Unit('force' ,'picoNewton' ,'pN' ,pN ) + + W_per_mK = Unit('therm_cond','W/(m*K)' ,'W_mK' ,W_mK ) - distance_dict = dict([('A',angstrom),\ - ('B',bohr),\ - ('a',a),\ - ('b',b),\ - ('c',c),\ - ('m',meter),\ - ('nm',nanometer),\ - ('pm',picometer),\ - ('fm',femtometer),\ - ]) + distance_dict = Unit.unit_dicts.distance + mass_dict = Unit.unit_dicts.mass + energy_dict = Unit.unit_dicts.energy + charge_dict = Unit.unit_dicts.charge + pressure_dict = Unit.unit_dicts.pressure + force_dict = Unit.unit_dicts.force + therm_cond_dict = Unit.unit_dicts.therm_cond - mass_dict = dict([ ('kg',kilogram),\ - ('me',electron_mass),\ - ('mp',proton_mass),\ - ('amu',atomic_mass_unit),\ - ('Da',dalton),\ - ]) - energy_dict = dict([\ - ('J',joule),\ - ('eV',electron_volt),\ - ('Ry',rydberg),\ - ('Ha',hartree),\ - ('kJ_mol',kJ_mole),\ - ('kcal_mol',kcal_mole),\ - ('K',kelvin),\ - ('degC',celcius),\ - ('degF',fahrenheit),\ - ]) - - charge_dict = dict([\ - ('C',coulomb),\ - ('e',electron_charge),\ - ]) - - pressure_dict = dict([\ - ('Pa',pascal),\ - ('bar',bar),\ - ('Mbar',megabar),\ - ('GPa',gigapascal),\ - ('atm',atmosphere),\ - ]) - - force_dict = dict([\ - ('N',newton),\ - ('pN',piconewton),\ - ]) - - therm_cond_dict = dict([\ - ('W_mK',W_per_mK),\ - ]) - - - unit_dict = dict([ ('A',angstrom),\ - ('B',bohr),\ - ('a',a),\ - ('b',b),\ - ('c',c),\ - ('m',meter),\ - ('nm',nanometer),\ - ('pm',picometer),\ - ('fm',femtometer),\ - ('kg',kilogram),\ - ('me',electron_mass),\ - ('mp',proton_mass),\ - ('amu',atomic_mass_unit),\ - ('J',joule),\ - ('eV',electron_volt),\ - ('Ry',rydberg),\ - ('Ha',hartree),\ - ('kJ_mol',kJ_mole),\ - ('kcal_mol',kcal_mole),\ - ('K',kelvin),\ - ('degC',celcius),\ - ('degF',fahrenheit),\ - ('C',coulomb),\ - ('e',electron_charge),\ - ('Pa',pascal),\ - ('bar',bar),\ - ('Mbar',megabar),\ - ('GPa',gigapascal),\ - ('atm',atmosphere),\ - ('N',newton),\ - ('pN',piconewton),\ - ('W_mK',W_per_mK),\ - ]) + unit_dict = Unit.unit_dicts.all def __init(self): - None + self.error('UnitConverter should not be instantiated') #def __init__ + @staticmethod def convert(value,source_unit,target_unit): ui = UnitConverter.unit_dict[source_unit] uo = UnitConverter.unit_dict[target_unit] @@ -253,11 +185,9 @@ class UnitConverter: #end if return (value_out,target_unit) - #end def convert - convert = Callable(convert) - + @staticmethod def convert_scalar_to_all(units,value_orig): unit_type = UnitConverter.unit_dict[units].type @@ -272,11 +202,10 @@ class UnitConverter: return value #end def convert_scalar_to_all - convert_scalar_to_all = Callable(convert_scalar_to_all) + @staticmethod def convert_array_to_all(units,arr,vectors=None): - A = dict() A['orig'] = arr.copy() @@ -293,7 +222,7 @@ class UnitConverter: arr_use = arr ui = UnitConverter.unit_dict[units] if(vectors!=None): - A['lattice'] = dot(arr,linalg.inv(vectors.A[units])) + A['lattice'] = dot(arr,inv(vectors.A[units])) #end if #end if @@ -311,12 +240,6 @@ class UnitConverter: return A #end def convert_array_to_all - convert_array_to_all = Callable(convert_array_to_all) - - def submit_unit(uo): - UnitConverter.unit_dict[uo.symbol] = uo - #end def submit_unit - submit_unit = Callable(submit_unit) #end class UnitConverter diff --git a/nexus/library/vasp.py b/nexus/library/vasp.py index d38f79924..0d9edc26e 100644 --- a/nexus/library/vasp.py +++ b/nexus/library/vasp.py @@ -28,7 +28,7 @@ import os from generic import obj from simulation import Simulation,SimulationInput,SimulationAnalyzer from vasp_input import VaspInput,generate_vasp_input,generate_poscar,Poscar -from vasp_analyzer import VaspAnalyzer +from vasp_analyzer import VaspAnalyzer,read_vxml from structure import Structure from debug import * @@ -114,10 +114,10 @@ class Vasp(Simulation): input = self.input if result_name=='structure': if input.performing_neb(): - if 'neb_structures' not in self.temp: - self.temp.neb_structures = [] + if 'neb_structures' not in self: + self.neb_structures = [] #end if - neb_structures = self.temp.neb_structures + neb_structures = self.neb_structures if len(neb_structures)>1: self.error('NEB simulation at {0} depends on more than two structures\n please check your inputs'.format(self.locdir)) #end if diff --git a/nexus/library/vasp_input.py b/nexus/library/vasp_input.py index 52ae46b8c..92ef2b3e2 100644 --- a/nexus/library/vasp_input.py +++ b/nexus/library/vasp_input.py @@ -41,6 +41,7 @@ import os from numpy import array,abs,empty,ndarray from generic import obj from periodic_table import is_element +from nexus_base import nexus_noncore from simulation import SimulationInput from structure import interpolate_structures,Structure from physical_system import PhysicalSystem @@ -339,18 +340,18 @@ class VKeywordFile(VFile): @classmethod def class_init(cls): for kw_field in cls.kw_fields: - if not kw_field in cls.__dict__: - cls.__dict__[kw_field] = set() + if not cls.class_has(kw_field): + cls.class_set_single(kw_field,set()) #end if #end for #cls.check_consistency() cls.scalar_keywords = set() for scalar_field in cls.kw_scalars: - cls.scalar_keywords |= cls.__dict__[scalar_field] + cls.scalar_keywords |= cls.class_get(scalar_field) #end for cls.array_keywords = set() for array_field in cls.kw_arrays: - cls.array_keywords |= cls.__dict__[array_field] + cls.array_keywords |= cls.class_get(array_field) #end for cls.keywords = cls.scalar_keywords | cls.array_keywords cls.type = obj() @@ -358,7 +359,7 @@ class VKeywordFile(VFile): cls.write_value = obj() cls.assign_value = obj() for type in cls.kw_scalars + cls.kw_arrays: - for name in cls.__dict__[type]: + for name in cls.class_get(type): cls.type[name] = type cls.read_value[name] = read_value_functions[type] cls.write_value[name] = write_value_functions[type] @@ -374,14 +375,14 @@ class VKeywordFile(VFile): types = cls.kw_scalars+cls.kw_arrays untyped = cls.keywords for type in types: - untyped -= cls.__dict__[type] + untyped -= cls.class_get(type) #end for if len(untyped)>0: fail = True msg += 'variables without a type: {0}\n'.format(sorted(untyped)) #end if for type in types: - unknown = cls.__dict__[type]-cls.keywords + unknown = cls.class_get(type)-cls.keywords if len(unknown)>0: fail = True msg += 'unknown {0}: {1}\n'.format(type,sorted(unknown)) @@ -1348,7 +1349,7 @@ class VaspInput(SimulationInput,Vobj): ordered_pseudos.append(pseudo_map[symbol]) #end for #end if - self.potcar = Potcar(VaspInput.pseudo_dir,ordered_pseudos) + self.potcar = Potcar(nexus_noncore.pseudo_dir,ordered_pseudos) #end def set_potcar diff --git a/nexus/library/wfconvert.py b/nexus/library/wfconvert.py deleted file mode 100644 index 1205a7eb5..000000000 --- a/nexus/library/wfconvert.py +++ /dev/null @@ -1,206 +0,0 @@ -################################################################## -## (c) Copyright 2015- by Jaron T. Krogel ## -################################################################## - - -#====================================================================# -# wfconvert.py # -# Nexus interface to the wfconvert tool packaged with QMCPACK. # -# # -# Content summary: # -# WfconvertInput # -# SimulationInput class for wfconvert. # -# # -# WfconvertAnalyzer # -# SimulationAnalyzer class for wfconvert. # -# # -# Wfconvert # -# Simulation class for wfconvert. # -# # -# generate_wfconvert # -# User-facing function to generate wfconvert simulation objects.# -# # -#====================================================================# - - - -import os -from generic import obj -from simulation import Simulation,SimulationInput,SimulationAnalyzer - - -class WfconvertInput(SimulationInput): - def __init__(self,app_name='wfconvert',h5in='MISSING.h5',h5out='wfconvert.h5',spline=False,format='eshdf',factor=None): - self.app_name = app_name - self.h5in = h5in - self.h5out= h5out - self.spline = spline - self.format = format - self.factor = factor - #end def __init__ - -#wfconvert --nospline --eshdf diamond.h5 out/diamond.pwscf.h5 >& diamond-wfconvert.out - def set_app_name(self,app_name): - self.app_name = app_name - #end def set_app_name - - def app_command(self): - c = self.app_name+' ' - if not self.spline: - c+= '--nospline ' - #end if - c+='--'+self.format+' '+self.h5out+' '+self.h5in - return c - #end def app_command - - - def read(self,filepath): - None - #end def read - - def write_contents(self): - return self.app_command() - #end def write_contents -#end class WfconvertInput - - -def generate_wfconvert_input(app_name='wfconvert',h5in='MISSING.h5',h5out='wfconvert.h5',spline=False,format='eshdf',factor=None): - wi = WfconvertInput( - app_name = app_name, - h5in = h5in, - h5out = h5out, - spline = spline, - format = format, - factor = factor - ) - return wi -#end def generate_wfconvert_input - - -class WfconvertAnalyzer(SimulationAnalyzer): - def __init__(self,arg0): - if isinstance(arg0,Simulation): - sim = arg0 - self.infile = sim.infile - self.dir = sim.locdir - self.h5file = os.path.join(sim.locdir,sim.input.h5out) - else: - self.infile = arg0 - #end if - #end def __init__ - - def analyze(self): - if False: - import h5py - self.log('Fixing h5 file',n=5) - h = h5py.File(self.h5file) - if 'electrons' in h: - elec = h['electrons'] - nkpoints = 0 - for name,val in elec.iteritems(): - if name.startswith('kpoint'): - nkpoints+=1 - #end for - #end if - nkold = elec['number_of_kpoints'][0] - self.log('Were',nkold,'kpoints, now',nkpoints,'kpoints',n=6) - elec['number_of_kpoints'][0] = nkpoints - #end for - #end if - #end def analyze -#end class WfconvertAnalyzer - - - -class Wfconvert(Simulation): - input_type = WfconvertInput - analyzer_type = WfconvertAnalyzer - generic_identifier = 'wfconvert' - application = 'wfconvert' - application_properties = set(['serial']) - application_results = set(['orbitals']) - - def set_app_name(self,app_name): - self.app_name = app_name - self.input.set_app_name(app_name) - #end def set_app_name - - def check_result(self,result_name,sim): - calculating_result = False - if result_name=='orbitals': - calculating_result = True - else: - calculating_result = False - self.error('ability to check for result '+result_name+' has not been implemented') - #end if - return calculating_result - #end def check_result - - def get_result(self,result_name,sim): - result = obj() - if result_name=='orbitals': - result.h5file = os.path.join(self.locdir,self.input.h5out) - result.outfile = os.path.join(self.locdir,self.outfile) - else: - self.error('ability to get result '+result_name+' has not been implemented') - #end if - return result - #end def get_result - - def incorporate_result(self,result_name,result,sim): - if result_name=='orbitals': - self.input.h5in = os.path.relpath(result.h5file,self.locdir) - self.job.app_command = self.input.app_command() - else: - self.error('ability to incorporate result '+result_name+' has not been implemented') - #end if - #end def incorporate_result - - def check_sim_status(self): - outfile = os.path.join(self.locdir,self.outfile) - errfile = os.path.join(self.locdir,self.errfile) - fobj = open(outfile,'r') - output = fobj.read() - fobj.close() - fobj = open(errfile,'r') - errors = fobj.read() - fobj.close() - h5file = os.path.join(self.locdir,self.input.h5out) - file_exists = os.path.exists(h5file) - outfin = 'Successfully read' in errors and 'numSpins' in errors - outfin = outfin and 'Writing laplacians' in output - - success = file_exists and outfin - - self.finished = success - #end def check_sim_status - - def get_output_files(self): - output_files = [] - return output_files - #end def get_output_files - - def app_command(self): - # app_name is passed along in post_init - return self.input.app_command() - #end def app_command -#end class Wfconvert - - - - - - - - - -def generate_wfconvert(**kwargs): - sim_args,inp_args = Simulation.separate_inputs(kwargs) - - if not 'input' in sim_args: - sim_args.input = generate_wfconvert_input(**inp_args) - #end if - wfconvert = Wfconvert(**sim_args) - - return wfconvert -#end def generate_wfconvert diff --git a/nexus/library/xmlreader.py b/nexus/library/xmlreader.py index 705f5a6bc..a7ca8eb99 100644 --- a/nexus/library/xmlreader.py +++ b/nexus/library/xmlreader.py @@ -38,11 +38,11 @@ from superstring import \ valid_variable_name,\ string2val -#from abilities import AllAbilities from generic import obj +from developer import DevBase -class XMLelement(obj): +class XMLelement(DevBase): def _escape_name(self,name): if name in self._escape_names: name=name+'_' @@ -214,7 +214,7 @@ class XMLelement(obj): class XMLReader reads an xml file and creates a dynamic object out of its contents ''' -class XMLreader(obj): +class XMLreader(DevBase): def __init__(self,fpath=None,element_joins=None,element_aliases=None,contract_names=False,strip_prefix=None,warn=True,xml=None): if element_joins is None: element_joins = []