From 847d527f8bc05d3bfb5ffd8ef868349df4e7c066 Mon Sep 17 00:00:00 2001 From: drewejohnson <1drew.e.johnson@gmail.com> Date: Thu, 30 Mar 2017 15:22:50 -0400 Subject: [PATCH 1/8] Setup; Shuffled files around Started setting up a package-style directory, compete with a setup.py feature. This will allow easy installation, plus double checking if the required packages are installed (currently pandas and python>=3.4) Signed-off-by: drewejohnson <1drew.e.johnson@gmail.com> --- CritOpS/__init__.py | 5 ++ CritOpS.py => CritOpS/__main__.py | 11 ++-- globalparams.py => CritOpS/globalparams.py | 0 iterator.py => CritOpS/iterator.py | 6 +-- outputs.py => CritOpS/outputs.py | 5 +- readinputs.py => CritOpS/readinputs.py | 6 ++- utils.py => CritOpS/utils.py | 2 +- setup.py | 61 ++++++++++++++++++++++ 8 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 CritOpS/__init__.py rename CritOpS.py => CritOpS/__main__.py (68%) rename globalparams.py => CritOpS/globalparams.py (100%) rename iterator.py => CritOpS/iterator.py (96%) rename outputs.py => CritOpS/outputs.py (97%) rename readinputs.py => CritOpS/readinputs.py (98%) rename utils.py => CritOpS/utils.py (97%) create mode 100644 setup.py diff --git a/CritOpS/__init__.py b/CritOpS/__init__.py new file mode 100644 index 0000000..8715373 --- /dev/null +++ b/CritOpS/__init__.py @@ -0,0 +1,5 @@ +from CritOpS.iterator import * +from CritOpS.readinputs import * +from CritOpS.utils import * +from CritOpS.globalparams import * +from CritOpS.outputs import * diff --git a/CritOpS.py b/CritOpS/__main__.py similarity index 68% rename from CritOpS.py rename to CritOpS/__main__.py index 471d9ac..2ef3195 100644 --- a/CritOpS.py +++ b/CritOpS/__main__.py @@ -13,9 +13,14 @@ Classes: """ -import globalparams as gp -from iterator import itermain -from readinputs import readmain +import sys + +import CritOpS.globalparams as gp +from CritOpS.readinputs import readmain +from CritOpS.iterator import itermain + +if sys.version_info[0] < 3: + raise SystemError('Need python 3 >') gp.args = gp.parser.parse_args() if gp.args.output is None: diff --git a/globalparams.py b/CritOpS/globalparams.py similarity index 100% rename from globalparams.py rename to CritOpS/globalparams.py diff --git a/iterator.py b/CritOpS/iterator.py similarity index 96% rename from iterator.py rename to CritOpS/iterator.py index 6ed9f40..bf8d78f 100644 --- a/iterator.py +++ b/CritOpS/iterator.py @@ -16,9 +16,9 @@ """ import subprocess -import globalparams as gp -import utils -from outputs import parse_scale_out_eig, output_landing +import CritOpS.globalparams as gp +import CritOpS.utils as utils +from CritOpS.outputs import parse_scale_out_eig, output_landing def makefile(_tfile, _iter): diff --git a/outputs.py b/CritOpS/outputs.py similarity index 97% rename from outputs.py rename to CritOpS/outputs.py index a1b1c7f..a6934f6 100644 --- a/outputs.py +++ b/CritOpS/outputs.py @@ -15,8 +15,9 @@ """ import pandas as pd -import globalparams as gp -import utils +import CritOpS.utils as utils + +from CritOpS import globalparams as gp def parse_scale_out_eig(_ofile): diff --git a/readinputs.py b/CritOpS/readinputs.py similarity index 98% rename from readinputs.py rename to CritOpS/readinputs.py index 2b41bbf..06c8609 100644 --- a/readinputs.py +++ b/CritOpS/readinputs.py @@ -17,8 +17,10 @@ """ import os.path -import globalparams as gp -import utils + +import CritOpS.utils as utils + +from CritOpS import globalparams as gp def read_param(_pfile): diff --git a/utils.py b/CritOpS/utils.py similarity index 97% rename from utils.py rename to CritOpS/utils.py index 0eb4d37..3b259b9 100644 --- a/utils.py +++ b/CritOpS/utils.py @@ -16,7 +16,7 @@ Classes: """ -import globalparams as gp +import CritOpS.globalparams as gp lineBreakShort = '-' * 10 + '\n' diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..615ff19 --- /dev/null +++ b/setup.py @@ -0,0 +1,61 @@ +""" + +Setup + - Properly install CritOpS + +A. Johnson + +Install with python setup.py install + +""" + +from setuptools import setup + +shortDesc = 'A Critical Optimization Search Tool for NEWT' +longDesc = r""" + ______ _ __ ____ _____ _ _________ ________ + / ____/____(_) /_/ __ \____ / ___/ / | / / ____/ | / /_ __/ + / / / ___/ / __/ / / / __ \\__ \_____/ |/ / __/ | | /| / / / / +/ /___/ / / / /_/ /_/ / /_/ /__/ /____/ /| / /___ | |/ |/ / / / +\____/_/ /_/\__/\____/ .___/____/ /_/ |_/_____/ |__/|__/ /_/ + /_/ + +""" + """ + CritOpS +A Critical Optimization Search tool for NEWT[1] +A. Johnson + +Objective: Iteratively update a parameter in a template NEWT file in +order to obtain a critical system. + +[1]: M. D. DeHart, and S. Bowman, "Reactor Physics Methods and Analysis +\tCapabilities in SCALE," Nuclear Technology, Technical Paper +\tvol. 174, no.2, pp. 196-213, 2011.""" + +vRelease = 2 +vMacro = 0 +vMicro = 0 + +vDevel = 'dev' +vDevelMicro = '1' + +if vDevel: + version = "{}.{}.{}.{}{}".format(vRelease, vMacro, vMicro, vDevel, vDevelMicro) +else: + version = "{}.{}.{}".format(vRelease, vMacro, vMicro) + +installReqs = ['pandas>=0.19'] + +if __name__ == '__main__': + setup( + name='CritOpS', + version=version, + description=shortDesc, + long_description=longDesc, + maintainer='A. Johnson', + maintainer_email='1drew.e.johnson@gmail.com', + url='https://github.com/drewejohnson/CritOpS', + install_requires=installReqs, + python_requires='>=3.4', + packages=['CritOpS'] + ) From ab6ff2380fdbdc8f62f728d3740b5be9633678e8 Mon Sep 17 00:00:00 2001 From: drewejohnson <1drew.e.johnson@gmail.com> Date: Mon, 10 Apr 2017 18:44:51 -0400 Subject: [PATCH 2/8] Major change: Removed global parameters, Updated README and LICENSE Removed the global parameter file. Everything is encompassed inside a dictionary that is passed between functions. The code as a whole seems more streamlined and connected (the output parser is contained in the iterator file). The code just feels better. Did test the code and it appears to be working quite well. Will undergo more testing tomorrow. Tests should include some import tests. Signed-off-by: drewejohnson <1drew.e.johnson@gmail.com> --- CritOpS/__init__.py | 4 +- CritOpS/__main__.py | 81 ++++++++++++++------ CritOpS/constants.py | 43 +++++++++++ CritOpS/globalparams.py | 72 ------------------ CritOpS/iterator.py | 136 ++++++++++++++++++++++------------ CritOpS/outputs.py | 54 ++++---------- CritOpS/readinputs.py | 159 ++++++++++++++++++++++------------------ CritOpS/utils.py | 44 +++++------ LICENSE | 2 +- README.md | 75 +++++++++++++++++-- linux/linux_param.txt | 4 - linux/linux_tester.inp | 112 ---------------------------- linux/linux_tester.txt | 4 - 13 files changed, 383 insertions(+), 407 deletions(-) create mode 100644 CritOpS/constants.py delete mode 100644 CritOpS/globalparams.py delete mode 100644 linux/linux_param.txt delete mode 100644 linux/linux_tester.inp delete mode 100644 linux/linux_tester.txt diff --git a/CritOpS/__init__.py b/CritOpS/__init__.py index 8715373..563d881 100644 --- a/CritOpS/__init__.py +++ b/CritOpS/__init__.py @@ -1,5 +1,5 @@ +from CritOpS.constants import * from CritOpS.iterator import * +from CritOpS.outputs import * from CritOpS.readinputs import * from CritOpS.utils import * -from CritOpS.globalparams import * -from CritOpS.outputs import * diff --git a/CritOpS/__main__.py b/CritOpS/__main__.py index 2ef3195..7dce7b5 100644 --- a/CritOpS/__main__.py +++ b/CritOpS/__main__.py @@ -1,36 +1,71 @@ """ + ______ _ __ ____ _____ _ _________ ________ + / ____/____(_) /_/ __ \____ / ___/ / | / / ____/ | / /_ __/ + / / / ___/ / __/ / / / __ \\__ \_____/ |/ / __/ | | /| / / / / +/ /___/ / / / /_/ /_/ / /_/ /__/ /____/ /| / /___ | |/ |/ / / / +\____/_/ /_/\__/\____/ .___/____/ /_/ |_/_____/ |__/|__/ /_/ + /_/ -NRE6401 - Molten Salt Reactor -msr-refl-iter -A. Johnson - -refl_iter -Objective: Main file for reading the input, and driving control of the operation - -Functions: + CritOpS +A Critical Optimization Search tool for NEWT[1] +A. Johnson -Classes: +Objective: Iteratively update a parameter in a template NEWT file in +order to obtain a critical system. +[1]: M. D. DeHart, and S. Bowman, "Reactor Physics Methods and Analysis + Capabilities in SCALE," Nuclear Technology, Technical Paper + vol. 174, no.2, pp. 196-213, 2011. """ + +import argparse +import os import sys -import CritOpS.globalparams as gp -from CritOpS.readinputs import readmain +from CritOpS import utils +from CritOpS.constants import header, default_params from CritOpS.iterator import itermain +from CritOpS.outputs import output_landing +from CritOpS.readinputs import readmain + +# Input parameters +parser = argparse.ArgumentParser(description=header, formatter_class=argparse.RawDescriptionHelpFormatter) +parser.add_argument('inp_file', type=str, help='template SCALE input file') +parser.add_argument('param_file', type=str, help='file containing parameters for operation') +parser.add_argument('-v', '--verbose', help='reveal more of the mystery behind the operation', action='store_true') +parser.add_argument('-o', '--output', help="write status to output file", type=str) + +if __name__ == '__main__': + + if int(sys.version_info[0]) < 3: + raise SystemError('Need python 3 >') + + kwargs = {} + for key in default_params: + kwargs[key] = default_params[key] + + args = vars(parser.parse_args()) + kwargs['verbose'] = args.pop('verbose') + kwargs['output'] = args.pop('output') + + if kwargs['output'] is None: + print(header) + else: + with open(kwargs['output'], 'w') as outobj: + outobj.write(header) -if sys.version_info[0] < 3: - raise SystemError('Need python 3 >') + # Update files to be absolute references + for file in ('inp_file', 'param_file'): + args[file] = os.path.join(os.getcwd(), args[file]) + if not os.path.exists(args[file]): + utils.error('File {} does not exist'.format(args[file]), 'CritOps __main__', args) -gp.args = gp.parser.parse_args() -if gp.args.output is None: - print(gp.header) -else: - with open(gp.args.output, 'w') as outobj: - outobj.write(gp.header) + # Read the input files + template, iter_vars = readmain(args['inp_file'], args['param_file'], kwargs) -# Read the input files -readmain() + # Start the iteration + iter_vecs, k_vec, conv_type = itermain(template, args['inp_file'], iter_vars, kwargs) -# Start the iteration -itermain() + # Output + output_landing(iter_vecs, k_vec, conv_type, **kwargs) diff --git a/CritOpS/constants.py b/CritOpS/constants.py new file mode 100644 index 0000000..5435bb4 --- /dev/null +++ b/CritOpS/constants.py @@ -0,0 +1,43 @@ +""" + +NRE6401 - Molten Salt Reactor +CritOpS +A. Johnson + +constants + +Objective: Header file for some useful constants + +""" +lineBreakShort = '-' * 10 + '\n' +lineBreakLong = "*" * 70 + '\n' + +default_params = { + 'eps_k': 1E-4, 'k_target': 1.0, 'iter_lim': 50, + 'inf': 1E30, 'tiny': 1E-16, 'var_char': '$', 'exe_str': 'C:\\SCALE-6.2.1\\bin\\scalerte.exe' +} + +pName = "CritOpS-NEWT" +asciiHeader = r""" + ______ _ __ ____ _____ _ _________ ________ + / ____/____(_) /_/ __ \____ / ___/ / | / / ____/ | / /_ __/ + / / / ___/ / __/ / / / __ \\__ \_____/ |/ / __/ | | /| / / / / +/ /___/ / / / /_/ /_/ / /_/ /__/ /____/ /| / /___ | |/ |/ / / / +\____/_/ /_/\__/\____/ .___/____/ /_/ |_/_____/ |__/|__/ /_/ + /_/ +""" # http://patorjk.com/software/taag/#p=display&f=Slant&t=CritOpS-NEWT + +header = lineBreakLong + asciiHeader + pName.center(len(lineBreakLong)) + """ +A Critical Optimization Search tool for NEWT[1] +A. Johnson + +Objective: Iteratively update a parameter in a template NEWT file in +order to obtain a critical system. + +[1]: M. D. DeHart, and S. Bowman, "Reactor Physics Methods and Analysis +\tCapabilities in SCALE," Nuclear Technology, Technical Paper +\tvol. 174, no.2, pp. 196-213, 2011. + +""" + lineBreakLong + +supVarChars = ('$',) diff --git a/CritOpS/globalparams.py b/CritOpS/globalparams.py deleted file mode 100644 index 6070d8b..0000000 --- a/CritOpS/globalparams.py +++ /dev/null @@ -1,72 +0,0 @@ -""" - -NRE6401 - Molten Salt Reactor -msr-refl-iter -A. Johnson - -globalparams - -Objective: Contain the default parameters for operation, and be common place to refer to global variables - -Functions: - -Classes: - -""" - -import argparse - -# Header -lineBreakLong = "*" * 70 + '\n' -pName = "CritOpS-NEWT" -asciiHeader = r""" - ______ _ __ ____ _____ _ _________ ________ - / ____/____(_) /_/ __ \____ / ___/ / | / / ____/ | / /_ __/ - / / / ___/ / __/ / / / __ \\__ \_____/ |/ / __/ | | /| / / / / -/ /___/ / / / /_/ /_/ / /_/ /__/ /____/ /| / /___ | |/ |/ / / / -\____/_/ /_/\__/\____/ .___/____/ /_/ |_/_____/ |__/|__/ /_/ - /_/ -""" # http://patorjk.com/software/taag/#p=display&f=Slant&t=CritOpS-NEWT - -header = lineBreakLong + asciiHeader + pName.center(len(lineBreakLong)) + """ -A Critical Optimization Search tool for NEWT[1] -A. Johnson - -Objective: Iteratively update a parameter in a template NEWT file in -order to obtain a critical system. - -[1]: M. D. DeHart, and S. Bowman, "Reactor Physics Methods and Analysis -\tCapabilities in SCALE," Nuclear Technology, Technical Paper -\tvol. 174, no.2, pp. 196-213, 2011. - -""" + lineBreakLong - -# Input parameters -parser = argparse.ArgumentParser(description=header, formatter_class=argparse.RawDescriptionHelpFormatter) -parser.add_argument('inp_file', type=argparse.FileType('r'), help='template SCALE input file') -parser.add_argument('param_file', type=argparse.FileType('r'), - help='file containing parameters for operation') -parser.add_argument('-v', '--verbose', help='reveal more of the mystery behind the operation', - action='store_true') -parser.add_argument('-o', '--output', help="write status to output file", type=str) -args = None -supVarChars = ('$',) # will add more later - -# Iteration parameters -iter_vars = {} # syntax: iter_vars['param'] = [initial_value, minimum_value, maximium_value] -eps_k = 1E-6 -k_target = 1.0 -inf = 1E30 -tiny = 1E-16 -iter_lim = 50 -iter_ints = ('iter_lim',) -iter_floats = ('eps_k', 'inf', 'tiny', "k_target") -iter_vecs = {} -k_vec = [] - -# SCALE parameters -var_char = '$' -exe_str = r'C:\SCALE-6.2.1\bin\scalerte.exe' -template_file = None - -# Outputs diff --git a/CritOpS/iterator.py b/CritOpS/iterator.py index bf8d78f..82177a2 100644 --- a/CritOpS/iterator.py +++ b/CritOpS/iterator.py @@ -1,7 +1,7 @@ """ NRE6401 - Molten Salt Reactor -msr-refl-iter +CritOpS A. Johnson iterator @@ -16,41 +16,42 @@ """ import subprocess -import CritOpS.globalparams as gp import CritOpS.utils as utils -from CritOpS.outputs import parse_scale_out_eig, output_landing -def makefile(_tfile, _iter): +def makefile(_tfile: (list, tuple), _name: str, _iter: int, _varchar: str, _vars: dict): """ Write the new output file using the value from iteration _iter :param _tfile: Template output file with variables to be replaced + :param _name: Name of original file :param _iter: Iteration number + :param _varchar: Variable character to update with new_val + :param _vars: Dictionary with iteration variables as keys and their new values as keys + i.e. {del_z: 10.21, del_r: 3.4} :return: Name of input file """ - _ofile = _tfile.name[:_tfile.name.rfind('.')] + "_" + str(_iter).zfill(len(str(gp.iter_lim))) + ".inp" + _ofile = _name[:_name.rfind('.')] + "_" + str(_iter) + ".inp" with open(_ofile, 'w') as _outObj: - for _line in gp.template_file: - if gp.var_char not in _line: + for _line in _tfile: + if _varchar not in _line: _outObj.write(_line) else: - _var = _line[_line.index(gp.var_char):].split()[0][1:] + _var = _line[_line.index(_varchar):].split()[0][1:] # assumes that iteration variable will be followed by a space - _outObj.write(_line.replace(gp.var_char + _var, "{:7.5f}".format(gp.iter_vecs[_var][-1]))) + _outObj.write(_line.replace(_varchar + _var, "{:7.5f}".format(_vars[_var]))) return _ofile -def update_itervar(): - """ - Simple function to adjust the updating of the iteration variables - - Operates according to the following logic: - An increase in a reflector parameter (thickness) will introduce more reflectance, increasing the eigenvalue - Therefore, if the current eigenvalue is larger than the desired value, decrease the reflector thickness - z_{n+1} = z_n \frac{k_{target}}{k_n} - +def update_itervar(iter_vars: dict, iter_vec: dict, kcur: float, ktarg: float): + """Simple function to update the iteration variables. + Currently set up for a positive feedback on the variables. + I.e. increasing each iteration variable will increase k + :param iter_vars: Dictionary of iteration variables and their minima/maxima + :param iter_vec: Dictionary of iteration variables and their values through the iteratio procedure + :param kcur: Current eigenvalue + :param ktarg: Target eigenvalue :return: status status = 0 if the updated value is inside the intended range status = 1 if the desired updated value is greater than the specified maximum of the parameter @@ -60,55 +61,95 @@ def update_itervar(): """ # Assumes only one iteration variable for now - _var = list(gp.iter_vars.keys())[0] - _des = gp.iter_vecs[_var][-1] * (gp.k_target / gp.k_vec[-1]) ** 2 - # may square the ratio of k for small convergence + _var = list(iter_vars.keys())[0] + _des = iter_vec[_var][-1] * (ktarg / kcur) ** 2 - if _des > gp.iter_vars[_var][2]: - gp.iter_vecs[_var].append(gp.iter_vars[_var][2]) + if _des > iter_vars[_var][2]: + iter_vec[_var].append(iter_vars[_var][2]) return 1 - elif _des < gp.iter_vars[_var][1]: - gp.iter_vecs[_var].append(gp.iter_vars[_var][1]) + elif _des < iter_vars[_var][1]: + iter_vec[_var].append(iter_vars[_var][1]) return -1 else: - gp.iter_vecs[_var].append(_des) + iter_vec[_var].append(_des) return 0 -def itermain(): - """Main function for controlling the iteration""" +def parse_scale_out_eig(_ofile: str, **kwargs): + """ + Read through the SCALE output file specified by _ofile and return status and eigenvalue (if present) + :param _ofile: SCALE .out file + :return: Status, eigenvalue + status = True if output file exists and eigenvalue was extracted + status = False if output file exists but no eigenvalue was found (possible error in input file syntax) + exit operation if no output file found + """ + try: + open(_ofile, 'r').close() + except IOError: + utils.error("SCALE output file {} not found".format(_ofile), 'parse_scale_out_eig()', **kwargs) + + _rK = None + _stat = False + utils.vprint('\n Parsing output file {}'.format(_ofile), **kwargs) + with open(_ofile, 'r') as _outObj: + _line = _outObj.readline() + while _line != "": + if "k-eff = " in _line: + _rK = float(_line.split()[-1]) + _stat = True + break + _line = _outObj.readline() + utils.vprint(' done', **kwargs) + return _stat, _rK + + +def itermain(tmp_list: (list, tuple), file_name: str, iter_vars: dict, kwargs: dict): + """Main function for controlling the iteration + :param tmp_list: List of lines from template file + :param file_name: Name of template file + :param iter_vars: Dictionary of iteration variables and their starting, minima, and maximum values + :param kwargs: Additional keyword arguments + :return: k_vec: List of progression of eigenvalue through iteration procedure + :return: iter_vecs: Dictionary of iteration and their values through iteration procedure + """ + # Make sure all the required keywords are present. If not, set to defaults from constants.py + utils.check_defaults(kwargs) - for _var in gp.iter_vars.keys(): - gp.iter_vecs[_var] = [gp.iter_vars[_var][0], ] + iter_vecs = {} - # gp.k_vec.append(gp.k_guess) + for _var in iter_vars: + iter_vecs[_var] = [iter_vars[_var][0], ] - utils.oprint("Starting the iteration procedure....\n") + utils.oprint("Starting the iteration procedure....\n", **kwargs) conv_flag = False conv_type = None _n = 0 - while _n < gp.iter_lim: + k_vec = [] + + while _n < kwargs['iter_lim']: _n += 1 - _iter_file = makefile(gp.args.inp_file, _n) - utils.vprint('Running SCALE iteration number {}...'.format(_n)) - subprocess.call([gp.exe_str, _iter_file]) - utils.vprint(' done') - stat, _k = parse_scale_out_eig(_iter_file.replace('.inp', '.out')) + _iterfile = makefile(tmp_list, file_name, _n, kwargs['var_char'], + {_var: iter_vecs[_var][-1] for _var in iter_vars}) + utils.vprint('Running SCALE iteration number {}...'.format(_n), **kwargs) + subprocess.call([kwargs['exe_str'], _iterfile]) + utils.vprint(' done', **kwargs) + stat, _k = parse_scale_out_eig(_iterfile.replace('.inp', '.out'), **kwargs) if stat: # successful operation - utils.oprint(" {0:<3}: {1}".format(_n, _k)) - gp.k_vec.append(_k) + utils.oprint(" {0:<3}: {1}".format(_n, _k), **kwargs) + k_vec.insert(_n - 1, _k) else: utils.error('Could not find value of k-eff for iteration file {0}.inp\n' - 'Check {0}.out for error message'.format(_iter_file.split('.')[0]), - 'itermain() of iteration {}'.format(_n)) + 'Check {0}.out for error message'.format(file_name), + 'itermain() of iteration {}'.format(_n), **kwargs) # check for convergance based on updated eigenvalue, and then a termination based on exceeding the specified # input range from the parameter file - if abs(_k - gp.k_target) < gp.eps_k: + if abs(_k - kwargs['k_target']) < kwargs['eps_k']: conv_type = 0 break - stat = update_itervar() + stat = update_itervar(iter_vars, iter_vecs, _k, kwargs['k_target']) if stat == 0: conv_flag = False else: @@ -116,9 +157,8 @@ def itermain(): if conv_flag: break - if _n == gp.iter_lim and conv_type is None: + if _n == kwargs['iter_lim'] and conv_type is None: conv_type = 2 - utils.oprint(' done') - - output_landing(conv_type) + utils.oprint(' done', **kwargs) + return iter_vecs, k_vec, conv_type diff --git a/CritOpS/outputs.py b/CritOpS/outputs.py index a6934f6..0bbe8b3 100644 --- a/CritOpS/outputs.py +++ b/CritOpS/outputs.py @@ -1,7 +1,7 @@ """ NRE6401 - Molten Salt Reactor -msr-refl-iter +CritOpS A. Johnson outputs @@ -11,62 +11,34 @@ Functions: parse_scale_output: Parse through the SCALE output file and return status -Classes: """ import pandas as pd -import CritOpS.utils as utils - -from CritOpS import globalparams as gp - -def parse_scale_out_eig(_ofile): - """ - Read through the SCALE output file specified by _ofile and return status and eigenvalue (if present) - :param _ofile: SCALE .out file - :return: Status, eigenvalue - status = True if output file exists and eigenvalue was extracted - status = False if output file exists but no eigenvalue was found (possible error in input file syntax) - exit operation if no output file found - """ - try: - open(_ofile, 'r').close() - except IOError: - utils.error("SCALE output file {} not found".format(_ofile), 'parse_scale_out_eig()') - - _rK = None - _stat = False - utils.vprint('\n Parsing output file {}'.format(_ofile)) - with open(_ofile, 'r') as _outObj: - _line = _outObj.readline() - while _line != "": - if "k-eff = " in _line: - _rK = float(_line.split()[-1]) - _stat = True - break - _line = _outObj.readline() - utils.vprint(' done') - return _stat, _rK +import CritOpS.utils as utils -def output_landing(_out_type): +def output_landing(iter_vecs: dict, k_vec: (list, tuple), _outtype: int, **kwargs): """ Write the output file according to the type of output - :param _out_type: Flag indicating the reason the program terminated + :param iter_vecs: Dictionary with iteration variables and their values through the procedure + :param k_vec: Vector of eigenvalues + :param _outtype: Flag indicating the reason the program terminated 0: Nothing went wrong 1: Desired update value for iteration parameter twice exceeded the maximum value from the parameter file -1: Desired update value for iteration parameter twice exceeded the minimum value from the parameter file 2: Exceeded the total number of iterations allotted :return: """ + utils.check_defaults(kwargs) out_messages = {0: " Completed successfullly", 1: "Terminated due to iteration parameter {} twice exceeding max value {}".format( - list(gp.iter_vars.keys())[0], gp.iter_vars[list(gp.iter_vars.keys())[0]][2]), + list(iter_vecs.keys())[0], iter_vecs[list(iter_vecs.keys())[0]][2]), -1: "Terminated due to iteration parameter {} twice exceeding minimum value {}".format( - list(gp.iter_vars.keys())[0], gp.iter_vars[list(gp.iter_vars.keys())[0]][2], ), - 2: "Terminated due to exceeding the iteration limit {}".format(gp.iter_lim) + list(iter_vecs.keys())[0], iter_vecs[list(iter_vecs.keys())[0]][1]), + 2: "Terminated due to exceeding the iteration limit {}".format(kwargs['iter_lim']) } - utils.oprint('End of operation. Status: {}'.format(out_messages[_out_type])) - var_df = pd.DataFrame({_var: gp.iter_vecs[_var] for _var in gp.iter_vars}) - var_df['k-eff'] = gp.k_vec + utils.oprint('End of operation. Status: {}'.format(out_messages[_outtype])) + var_df = pd.DataFrame({_var: iter_vecs[_var] for _var in iter_vecs}) + var_df['k-eff'] = k_vec utils.oprint(var_df.to_string()) diff --git a/CritOpS/readinputs.py b/CritOpS/readinputs.py index 06c8609..1560845 100644 --- a/CritOpS/readinputs.py +++ b/CritOpS/readinputs.py @@ -1,7 +1,7 @@ """ NRE6401 - Molten Salt Reactor -msr-refl-iter +CritOps A. Johnson readinputs @@ -13,107 +13,122 @@ read_param: Read the parameter file and update values in globalparams readMain: Main driver for reading and processing the input files -Classes: - """ import os.path import CritOpS.utils as utils +from CritOpS import constants -from CritOpS import globalparams as gp +iter_ints = ('iter_lim',) +iter_floats = ('eps_k', 'inf', 'tiny', "k_target") -def read_param(_pfile): +def read_param(_pfile, **kwargs): """ Read the parameter file and update values in globalparams :param _pfile: Parameter file - :return: None + :return: iter_vars: Dictionary of iteration variables and their starting, minima, and maximum values """ - utils.vprint('Reading from parameter file {}'.format(_pfile.name)) - _rLine = _pfile.readline - _line = _rLine() - _count = 1 - _locStr = 'read_param() for parameter file {} - line {}' - - while _line != "": - _lSplit = _line.split() - if _lSplit[0] == 'iter_var': - if len(_lSplit) == 5: - gp.iter_vars[_lSplit[1]] = [float(_v) for _v in _lSplit[2:]] - else: - utils.error('Need starting, minimum, and maximum value for parameter {}'.format(_lSplit[1]), - _locStr.format(_pfile.name, _count)) - elif _lSplit[0] == 'var_char': - if _lSplit[1] in gp.supVarChars: - gp.var_char = _lSplit[1] - else: - utils.error('Variable character {} not supported at this moment.'.format(_lSplit[1]), - _locStr.format(_pfile.name, _count)) - elif _lSplit[0] in gp.iter_floats: - gp.__dict__[_lSplit[0]] = float(_lSplit[1]) - elif _lSplit[0] in gp.iter_ints: - gp.__dict__[_lSplit[0]] = int(_lSplit[1]) - elif _lSplit[0] == 'exe_str': - gp.exe_str = _lSplit[1] - _line = _rLine() - _count += 1 - utils.vprint(' done') - - -def check_inputs(): + + iter_vars = {} + + utils.vprint('Reading from parameter file {}'.format(_pfile), **kwargs) + with open(_pfile, 'r') as pobj: + _line = pobj.readline() + _count = 1 + _locStr = 'read_param() for parameter file {} - line {}' + + while _line != "": + _lSplit = _line.split() + if _lSplit[0] == 'iter_var': + if len(_lSplit) == 5: + iter_vars[_lSplit[1]] = [float(_v) for _v in _lSplit[2:]] + else: + utils.error('Need starting, minimum, and maximum value for parameter {}'.format(_lSplit[1]), + _locStr.format(_pfile.name, _count), **kwargs) + elif _lSplit[0] == 'var_char': + if _lSplit[1] in constants.supVarChars: + kwargs['var_char'] = _lSplit[1] + else: + utils.error('Variable character {} not supported at this moment.'.format(_lSplit[1]), + _locStr.format(_pfile.name, _count), **kwargs) + elif _lSplit[0] in iter_floats: + kwargs[_lSplit[0]] = float(_lSplit[1]) + elif _lSplit[0] in iter_ints: + kwargs[_lSplit[0]] = int(_lSplit[1]) + elif _lSplit[0] == 'exe_str': + kwargs['exe_str'] = _lSplit[1] + _line = pobj.readline() + _count += 1 + utils.vprint(' done', **kwargs) + return iter_vars + + +def check_inputs(temp_lines: list, iter_vars: dict, **kwargs): """Run over the inputs and make sure things are good for operation""" - utils.vprint('Checking run parameters') - for _int in gp.iter_ints: + utils.vprint('Checking run parameters', **kwargs) + for _int in iter_ints: try: - assert gp.__dict__[_int] % 1 == 0 + assert kwargs[_int] % 1 == 0 except AssertionError: - utils.error('Variable {} must be integer, not {}'.format(_int, gp.__dict__[_int]), - 'check_inputs()') + utils.error('Variable {} must be integer, not {}'.format(_int, kwargs[_int]), + 'check_inputs()', **kwargs) try: - assert gp.__dict__[_int] > 0 + assert kwargs[_int] > 0 except AssertionError: - utils.error('Variable {} must be positive, not {}'.format(_int, gp.__dict__[_int]), - 'check_inputs()') - for _flt in gp.iter_floats: + utils.error('Variable {} must be positive, not {}'.format(_int, kwargs[_int]), + 'check_inputs()', **kwargs) + for _flt in iter_floats: try: - assert gp.__dict__[_flt] > 0 + assert kwargs[_flt] > 0 except AssertionError: - utils.error('Variable {} must be positive, not {}'.format(_flt, gp.__dict__[_flt]), - 'check_inputs()') + utils.error('Variable {} must be positive, not {}'.format(_flt, kwargs[_flt]), + 'check_inputs()', **kwargs) - if len(gp.iter_vars) > 1: + if len(iter_vars) > 1: utils.error('Only one value can be modified as iter_var at this moment. Variables indicated:\n' + - "\n".join(gp.iter_vars.keys()), "check_inputs()") - elif len(gp.iter_vars) == 0: + "\n".join(iter_vars.keys()), "check_inputs()", **kwargs) + elif len(iter_vars) == 0: utils.error('No iteration variable to update. Use the following syntax in input file:\n' - 'iter_var var start min max', 'check_inputs()') + 'iter_var ', 'check_inputs()', **kwargs) l_count = 1 _instance_count = 0 - for _line in gp.template_file: - if gp.var_char in _line: - if _line.split(gp.var_char)[1].split()[0] in gp.iter_vars: + for _line in temp_lines: + if kwargs['var_char'] in _line: + if _line.split(kwargs['var_char'])[1].split()[0] in iter_vars: _instance_count += 1 utils.vprint(' {} at line {} in input file'. - format(_line.split(gp.var_char)[1].split()[0], l_count)) + format(_line.split(kwargs['var_char'])[1].split()[0], l_count), **kwargs) l_count += 1 if _instance_count == 0: - utils.error('No instances of iteration variable {} found in input file {}'.format(gp.iter_vars.keys(), - gp.args.inp_file.name), - 'check_inputs()') + utils.error('No instances of iteration variables {} found in input file'.format(', '.join(iter_vars.keys())), + 'check_inputs()', **kwargs) - if not os.path.isfile(gp.exe_str): - utils.error('Execution file {} does not exist'.format(gp.exe_str), 'check_inputs()') + if not os.path.isfile(kwargs['exe_str']): + utils.error('Execution file {} does not exist'.format(kwargs['exe_str']), 'check_inputs()', **kwargs) - utils.vprint(' done') + utils.vprint(' done', **kwargs) -def readmain(): - """Main driver for reading and processing input files""" - utils.vprint('Reading from input file {}'.format(gp.args.inp_file.name)) - gp.template_file = gp.args.inp_file.readlines() - utils.vprint(' done') - gp.args.inp_file.close() - read_param(gp.args.param_file) - check_inputs() +def readmain(tmp_file, param_file, kwargs: dict): + """Main driver for reading and processing input files. + :param tmp_file: Template input file + :param param_file: Parameter file + :param kwargs: Additional arguments + - verbose (True) - status updates + - output (None) - print to screen + Plus additional iteration parameters + :return List of valid template file lines and dictionary of interation variables + Updates kwargs based on values in param_file + """ + utils.check_defaults(kwargs) + utils.vprint('Reading from input file {}'.format(tmp_file), **kwargs) + with open(tmp_file, 'r') as file: + tmp_lines = file.readlines() + utils.vprint(' done', **kwargs) + iter_vars = read_param(param_file, **kwargs) + check_inputs(tmp_lines, iter_vars, **kwargs) + + return tmp_lines, iter_vars diff --git a/CritOpS/utils.py b/CritOpS/utils.py index 3b259b9..803c142 100644 --- a/CritOpS/utils.py +++ b/CritOpS/utils.py @@ -1,7 +1,7 @@ """ NRE6401 - Molten Salt Reactor -msr-refl-iter +CritOpS A. Johnson utils.py @@ -13,48 +13,48 @@ error: produce a fatal error message show_license: print the license vprint: verbose print shortcut + oprint: Print to screen or append to file, depending on verbosity + check_defaults: Update any missing keys from parameter dictionary Classes: """ -import CritOpS.globalparams as gp +from CritOpS.constants import lineBreakShort, default_params -lineBreakShort = '-' * 10 + '\n' +def check_defaults(params: dict): + """Update missing keys with default values""" + for key in default_params: + if key not in params: + params[key] = default_params[key] -def oprint(_msg): + +def oprint(_msg, **kwargs): """ Print message to stdout if output argument not chosen. Else, append message to output file" """ - if gp.args.output is None: + if 'output' not in kwargs or kwargs['output'] is None: print(_msg) else: - with open(gp.args.output, 'a') as outobj: - outobj.write(_msg + '\n') + with open(kwargs['output'], 'a') as outobj: + outobj.write(_msg) -def warning(_msg, _loc=None): +def warning(_msg, _loc=None, **kwargs): """Produce a non-fatal warning message""" oprint(lineBreakShort + _msg) if _loc is not None: - oprint(" in " + _loc) - oprint(lineBreakShort[::-1]) + oprint(" in " + _loc, **kwargs) + oprint(lineBreakShort[::-1], **kwargs) -def error(_msg, _loc): +def error(_msg, _loc, **kwargs): """Produce a fatal error message""" - oprint(lineBreakShort + "Fatal error: " + _msg + "\nin " + _loc) - raise SystemExit - - -def show_license(): - """Print the contents of LICENSE to stdout""" - with("LICENSE", 'r') as _license: - print(_license.read()) + oprint(lineBreakShort + "Fatal error: " + _msg + "\nin " + _loc, **kwargs) raise SystemExit -def vprint(_msg): +def vprint(_msg, **kwargs): """Print a chatty message""" - if gp.args.verbose: - oprint(_msg) + if 'verbose' in kwargs and kwargs['verbose']: + oprint(_msg, **kwargs) diff --git a/LICENSE b/LICENSE index 7eb3c91..2e72e6c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Drew Johnson +Copyright (c) 2017 Andrew Johnson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a8bae0d..2b710d4 100644 --- a/README.md +++ b/README.md @@ -13,15 +13,17 @@ A. Johnson **Objective**: Iteratively update a parameter in a template NEWT file in order to obtain a critical system. - -[1]: M. D. DeHart, and S. Bowman, "Reactor Physics Methods and Analysis Capabilities in SCALE," Nuclear Technology, Technical Paper -vol. 174, no.2, pp. 196-213, 2011. - -ASCII Art generated from [http://patorjk.com/software/taag](http://patorjk.com/software/taag/#p=display&f=Slant&t=CritOpS-NEWT) +## Setup +``` +git clone https://github.com/drewejohnson/CritOpS.git +cd CritOpS +python setup.py install +``` +The code currently requires `python3` due to some formatting calls, and `pandas` for some better data output. ## Input Syntax ``` -python3 CritOpS.py [-h] [-v] [-o OUTPUT] inp_file param_file +python3 CritOpS.py inp_file param_file [-v] [-o OUTPUT] positional arguments: inp_file template SCALE input file @@ -33,4 +35,65 @@ optional arguments: -o OUTPUT, --output OUTPUT write status to output file ``` +The parameter file controls iteration procedure and `SCALE` execution. +Parameters that can be updated with the parameter file include +1. `k_target`: Desired value of k-eff to be obtained from the `SCALE` runs +1. `eps_k`: Acceptable accuracy between `k_target` and each value of k-eff +1. `iter_lim`: Maximum number of times to run `SCALE` +1. `exe_str`: Absolute path to your `SCALE` executable. +1. `var_char`: Whatever character you want to use as a designator for the variables + +Currently, `CritOpS` only supports one iteration variable, which is declared in the parameter file with +``` +iter_var +``` + +The input file should be a valid `NEWT` input file, with some minor modifications. +There should exist certain values defined as variables preceeded by the `var_char`, +``` +cuboid 20 5 0 0 -$del_z +``` + +Given some input and parameter files, the code will create and execute successive input files, +parse the outputs for the update k-eff, and then update the iteration variables. + +## Caveats/Future Work +This code was designed to optimize the thickness of a reflector, and assumes that each parameter +has a positive effect on criticality. +Increasing the value of an iteration variable is assumed to increase the criticality. +Technically this code could work on any `SCALE` input file, and so long as the output file contains the k-eff string, the iteration procedure should work. +This was not the intent, nor has this been tested. + +Future work will include +1. The ability to specify positive/negative feedbacks +1. The ability to specify and iterate upon multiple variables +1. The ability to define some variables as functions of iteration variables + +## License +MIT License + +Copyright (c) 2017 Andrew Johnson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +## References +[1]: M. D. DeHart, and S. Bowman, "Reactor Physics Methods and Analysis Capabilities in SCALE," Nuclear Technology, Technical Paper +vol. 174, no.2, pp. 196-213, 2011. http://dx.doi.org/10.13182/NT174-196 +ASCII Art generated from [http://patorjk.com/software/taag](http://patorjk.com/software/taag/#p=display&f=Slant&t=CritOpS-NEWT) \ No newline at end of file diff --git a/linux/linux_param.txt b/linux/linux_param.txt deleted file mode 100644 index e49f800..0000000 --- a/linux/linux_param.txt +++ /dev/null @@ -1,4 +0,0 @@ -var_char $ -iter_var del_z 10 5.0 15.0 -iter_lim 30 -exe_str /nv/hp22/ajohnson400/data/Codes/Scale/SCALE-6.2.1/bin/scalerte diff --git a/linux/linux_tester.inp b/linux/linux_tester.inp deleted file mode 100644 index 99cb53c..0000000 --- a/linux/linux_tester.inp +++ /dev/null @@ -1,112 +0,0 @@ -=t-newt parm=(centrm) -MSR iterative reflector optimization procedure -v7-252 - -read comp - -' --- NaCl-UCl3-PuCl3' -' --- 50/25/25 dens=3.60' -' --- 19.75 wt% eniched uranium' - Na-23 1 0 5.3767E-03 900 end - Cl-35 1 0 1.5991E-02 900 end - Cl-37 1 0 5.5155E-03 900 end - U-235 1 0 5.2556E-04 900 end - U-238 1 0 2.1355E-03 900 end - Pu-239 1 0 2.4994E-03 900 end - Pu-240 1 0 1.8892E-04 900 end - -' --- NaCl-UCl3-PuCl3' -' --- 50/25/25 dens=3.60' -' --- 19.75 wt% eniched uranium' - Na-23 10 0 5.3767E-03 900 end - Cl-35 10 0 1.5991E-02 900 end - Cl-37 10 0 5.5155E-03 900 end - U-235 10 0 5.2556E-04 900 end - U-238 10 0 2.1355E-03 900 end - Pu-239 10 0 2.4994E-03 900 end - Pu-240 10 0 1.8892E-04 900 end -' --- Heat exchanger fluid -' -- Nitrogen gas a.t.m. - n-14 2 1.0 293.0 end -' --- Piping -' -- Stainless steel - ss304 3 1.0 end -' --- Piping -' -- Stainless steel - ss304 30 1.0 end -' -- Reflector - ss304 4 1.0 600.0 end - -end comp - - -read celldata - - multiregion slab right_bdy=vacuum left_bdy=reflected origin=0.0 end - 1 55 - 3 60 - 2 70 - 30 75 - 10 100 - 4 120 end zone - -end celldata - -read model -Preliminary model - -read parameters - -drawit=no -sn=6 -echo=yes -prtflux=no - -end parameters - -read materials - - mix=1 com="in fuel" end - mix=10 com="out fuel" end - mix=2 pn=2 com="HX" end - mix=3 com="pipe" end - mix=4 com="refl" pn=2 end - -end materials - -read geometry - -global unit 1 - cuboid 99 120 0 20 -$del_z - cuboid 10 70 0.0 20 0.0 - cuboid 11 72 70 20 0 - cuboid 12 83 72 20 0 - cuboid 13 85 83 20 0 - cuboid 14 120 85 20 0 - media 1 1 10 - media 3 1 11 - media 2 1 12 - media 3 1 13 - media 10 1 14 - cuboid 20 5 0 0 -$del_z - cuboid 21 70 5 0 -$del_z - cuboid 22 72 70 0 -$del_z - cuboid 23 83 72 0 -$del_z - cuboid 24 85 83 0 -$del_z - cuboid 25 120 85 0 -$del_z - media 3 1 20 - media 4 1 21 - media 3 1 22 - media 2 1 23 - media 3 1 24 - media 4 1 25 - boundary 99 4 4 -end geometry - -read bounds - +x=vac +y=refl -x=refl -y=vac -end bounds -end model - - -end diff --git a/linux/linux_tester.txt b/linux/linux_tester.txt deleted file mode 100644 index 4cca18a..0000000 --- a/linux/linux_tester.txt +++ /dev/null @@ -1,4 +0,0 @@ -var_char $ -iter_var del_z 10 5.0 15.0 -iter_lim 5 -exe_str /nv/hp22/ajohnson400/Codes/Scale/SCALE-6.2.1/bin/scaletre From a3757f444fc44091ae56a3aaac06baac1b635561 Mon Sep 17 00:00:00 2001 From: drewejohnson <1drew.e.johnson@gmail.com> Date: Tue, 11 Apr 2017 13:56:35 -0400 Subject: [PATCH 3/8] rename module to lowercaps critops Signed-off-by: drewejohnson <1drew.e.johnson@gmail.com> --- .gitignore | 3 --- CritOpS/__init__.py | 5 ----- critops/__init__.py | 5 +++++ {CritOpS => critops}/__main__.py | 10 +++++----- {CritOpS => critops}/constants.py | 0 {CritOpS => critops}/iterator.py | 2 +- {CritOpS => critops}/outputs.py | 2 +- {CritOpS => critops}/readinputs.py | 4 ++-- {CritOpS => critops}/utils.py | 2 +- setup.py | 8 ++++---- 10 files changed, 19 insertions(+), 22 deletions(-) delete mode 100644 CritOpS/__init__.py create mode 100644 critops/__init__.py rename {CritOpS => critops}/__main__.py (92%) rename {CritOpS => critops}/constants.py (100%) rename {CritOpS => critops}/iterator.py (99%) rename {CritOpS => critops}/outputs.py (98%) rename {CritOpS => critops}/readinputs.py (98%) rename {CritOpS => critops}/utils.py (96%) diff --git a/.gitignore b/.gitignore index a985ff0..b63d7af 100644 --- a/.gitignore +++ b/.gitignore @@ -97,9 +97,6 @@ ENV/ # SCALE stuff applet_resources/ -*.ps -*.msg -*.tempdir.path # Scheduler *.pbs diff --git a/CritOpS/__init__.py b/CritOpS/__init__.py deleted file mode 100644 index 563d881..0000000 --- a/CritOpS/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from CritOpS.constants import * -from CritOpS.iterator import * -from CritOpS.outputs import * -from CritOpS.readinputs import * -from CritOpS.utils import * diff --git a/critops/__init__.py b/critops/__init__.py new file mode 100644 index 0000000..26cc78a --- /dev/null +++ b/critops/__init__.py @@ -0,0 +1,5 @@ +from critops.constants import * +from critops.iterator import * +from critops.outputs import * +from critops.readinputs import * +from critops.utils import * diff --git a/CritOpS/__main__.py b/critops/__main__.py similarity index 92% rename from CritOpS/__main__.py rename to critops/__main__.py index 7dce7b5..cf43ee0 100644 --- a/CritOpS/__main__.py +++ b/critops/__main__.py @@ -23,11 +23,11 @@ import os import sys -from CritOpS import utils -from CritOpS.constants import header, default_params -from CritOpS.iterator import itermain -from CritOpS.outputs import output_landing -from CritOpS.readinputs import readmain +from critops import utils +from critops.constants import header, default_params +from critops.iterator import itermain +from critops.outputs import output_landing +from critops.readinputs import readmain # Input parameters parser = argparse.ArgumentParser(description=header, formatter_class=argparse.RawDescriptionHelpFormatter) diff --git a/CritOpS/constants.py b/critops/constants.py similarity index 100% rename from CritOpS/constants.py rename to critops/constants.py diff --git a/CritOpS/iterator.py b/critops/iterator.py similarity index 99% rename from CritOpS/iterator.py rename to critops/iterator.py index 82177a2..b4a377c 100644 --- a/CritOpS/iterator.py +++ b/critops/iterator.py @@ -16,7 +16,7 @@ """ import subprocess -import CritOpS.utils as utils +import critops.utils as utils def makefile(_tfile: (list, tuple), _name: str, _iter: int, _varchar: str, _vars: dict): diff --git a/CritOpS/outputs.py b/critops/outputs.py similarity index 98% rename from CritOpS/outputs.py rename to critops/outputs.py index 0bbe8b3..e161ca5 100644 --- a/CritOpS/outputs.py +++ b/critops/outputs.py @@ -15,7 +15,7 @@ """ import pandas as pd -import CritOpS.utils as utils +import critops.utils as utils def output_landing(iter_vecs: dict, k_vec: (list, tuple), _outtype: int, **kwargs): diff --git a/CritOpS/readinputs.py b/critops/readinputs.py similarity index 98% rename from CritOpS/readinputs.py rename to critops/readinputs.py index 1560845..4b0aab4 100644 --- a/CritOpS/readinputs.py +++ b/critops/readinputs.py @@ -16,8 +16,8 @@ """ import os.path -import CritOpS.utils as utils -from CritOpS import constants +import critops.utils as utils +from critops import constants iter_ints = ('iter_lim',) iter_floats = ('eps_k', 'inf', 'tiny', "k_target") diff --git a/CritOpS/utils.py b/critops/utils.py similarity index 96% rename from CritOpS/utils.py rename to critops/utils.py index 803c142..eff9687 100644 --- a/CritOpS/utils.py +++ b/critops/utils.py @@ -18,7 +18,7 @@ Classes: """ -from CritOpS.constants import lineBreakShort, default_params +from critops.constants import lineBreakShort, default_params def check_defaults(params: dict): diff --git a/setup.py b/setup.py index 615ff19..28f93ba 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ /_/ """ + """ - CritOpS + critops A Critical Optimization Search tool for NEWT[1] A. Johnson @@ -48,14 +48,14 @@ if __name__ == '__main__': setup( - name='CritOpS', + name='critops', version=version, description=shortDesc, long_description=longDesc, maintainer='A. Johnson', maintainer_email='1drew.e.johnson@gmail.com', - url='https://github.com/drewejohnson/CritOpS', + url='https://github.com/drewejohnson/critops', install_requires=installReqs, python_requires='>=3.4', - packages=['CritOpS'] + packages=['critops'] ) From 5b94cae443683bd9f5e1614569cbfaf0f4019d27 Mon Sep 17 00:00:00 2001 From: drewejohnson <1drew.e.johnson@gmail.com> Date: Tue, 11 Apr 2017 16:20:51 -0400 Subject: [PATCH 4/8] Updated iteration procedure Iteration variables are now updated based on a linear fit of the previous two values and delta k (k_targ - k_i). This slightly improves iteration, and also takes into account directly/conversely proportional relationships between variables and the eigenvalue Signed-off-by: drewejohnson <1drew.e.johnson@gmail.com> --- .gitignore | 1 - critops/__main__.py | 3 ++- critops/constants.py | 2 +- critops/iterator.py | 32 +++++++++++++++++++++++++------- critops/outputs.py | 13 +++++++++---- critops/readinputs.py | 3 ++- setup.py | 7 ++++--- 7 files changed, 43 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index b63d7af..bb919de 100644 --- a/.gitignore +++ b/.gitignore @@ -93,7 +93,6 @@ ENV/ # Backup garbage *.ini -*.bak # SCALE stuff applet_resources/ diff --git a/critops/__main__.py b/critops/__main__.py index cf43ee0..39a6a84 100644 --- a/critops/__main__.py +++ b/critops/__main__.py @@ -30,7 +30,8 @@ from critops.readinputs import readmain # Input parameters -parser = argparse.ArgumentParser(description=header, formatter_class=argparse.RawDescriptionHelpFormatter) +parser = argparse.ArgumentParser(description=header, formatter_class=argparse.RawDescriptionHelpFormatter, + usage='critops inp_file param_file [-v] [-o OUTPUT]') parser.add_argument('inp_file', type=str, help='template SCALE input file') parser.add_argument('param_file', type=str, help='file containing parameters for operation') parser.add_argument('-v', '--verbose', help='reveal more of the mystery behind the operation', action='store_true') diff --git a/critops/constants.py b/critops/constants.py index 5435bb4..6228d71 100644 --- a/critops/constants.py +++ b/critops/constants.py @@ -17,7 +17,7 @@ 'inf': 1E30, 'tiny': 1E-16, 'var_char': '$', 'exe_str': 'C:\\SCALE-6.2.1\\bin\\scalerte.exe' } -pName = "CritOpS-NEWT" +pName = "CritOpS-NEWT v2.0.0dev5" asciiHeader = r""" ______ _ __ ____ _____ _ _________ ________ / ____/____(_) /_/ __ \____ / ___/ / | / / ____/ | / /_ __/ diff --git a/critops/iterator.py b/critops/iterator.py index b4a377c..0995bb6 100644 --- a/critops/iterator.py +++ b/critops/iterator.py @@ -44,13 +44,13 @@ def makefile(_tfile: (list, tuple), _name: str, _iter: int, _varchar: str, _vars return _ofile -def update_itervar(iter_vars: dict, iter_vec: dict, kcur: float, ktarg: float): +def update_itervar(iter_vars: dict, iter_vec: dict, kvec: (list, tuple), ktarg: float): """Simple function to update the iteration variables. Currently set up for a positive feedback on the variables. I.e. increasing each iteration variable will increase k :param iter_vars: Dictionary of iteration variables and their minima/maxima :param iter_vec: Dictionary of iteration variables and their values through the iteratio procedure - :param kcur: Current eigenvalue + :param kvec: Vector of eigenvalues :param ktarg: Target eigenvalue :return: status status = 0 if the updated value is inside the intended range @@ -62,7 +62,12 @@ def update_itervar(iter_vars: dict, iter_vec: dict, kcur: float, ktarg: float): # Assumes only one iteration variable for now _var = list(iter_vars.keys())[0] - _des = iter_vec[_var][-1] * (ktarg / kcur) ** 2 + _delk = [ktarg - kv for kv in kvec] + + if len(kvec) <= 1: + _des = iter_vec[_var][-1] * (ktarg / kvec[-1]) ** 2 + else: + _des = iter_vec[_var][-1] - _delk[-1] * (iter_vec[_var][-2] - iter_vec[_var][-1]) / (_delk[-2] - _delk[-1]) if _des > iter_vars[_var][2]: iter_vec[_var].append(iter_vars[_var][2]) @@ -112,6 +117,12 @@ def itermain(tmp_list: (list, tuple), file_name: str, iter_vars: dict, kwargs: d :param kwargs: Additional keyword arguments :return: k_vec: List of progression of eigenvalue through iteration procedure :return: iter_vecs: Dictionary of iteration and their values through iteration procedure + :return: conv_type - reason for exiting iter_main + 0: Accurately converged to target eigenvalue in specified iterations + 1: iter_var exceeded specified maximum twice + -1: iter_var exceeded specified minimum twice + 2: Reached iteration limit without reaching target eigenvalue + -2: Previous two k are close to similar """ # Make sure all the required keywords are present. If not, set to defaults from constants.py utils.check_defaults(kwargs) @@ -147,15 +158,22 @@ def itermain(tmp_list: (list, tuple), file_name: str, iter_vars: dict, kwargs: d # check for convergance based on updated eigenvalue, and then a termination based on exceeding the specified # input range from the parameter file if abs(_k - kwargs['k_target']) < kwargs['eps_k']: - conv_type = 0 - break - stat = update_itervar(iter_vars, iter_vecs, _k, kwargs['k_target']) + utils.oprint(' done', **kwargs) + return iter_vecs, k_vec, 0 + if len(k_vec) > 1 and abs(_k - k_vec[-2]) < kwargs['eps_k']: + utils.oprint(' done', **kwargs) + return iter_vecs, k_vec, -2 + stat = update_itervar(iter_vars, iter_vecs, k_vec, kwargs['k_target']) if stat == 0: conv_flag = False else: conv_type = stat if conv_flag: - break + utils.oprint(' done', **kwargs) + for var in iter_vecs: + iter_vecs[var].pop() + return iter_vecs, k_vec, conv_type + conv_flag = True if _n == kwargs['iter_lim'] and conv_type is None: conv_type = 2 diff --git a/critops/outputs.py b/critops/outputs.py index e161ca5..7f3c67f 100644 --- a/critops/outputs.py +++ b/critops/outputs.py @@ -33,12 +33,17 @@ def output_landing(iter_vecs: dict, k_vec: (list, tuple), _outtype: int, **kwarg utils.check_defaults(kwargs) out_messages = {0: " Completed successfullly", 1: "Terminated due to iteration parameter {} twice exceeding max value {}".format( - list(iter_vecs.keys())[0], iter_vecs[list(iter_vecs.keys())[0]][2]), + list(iter_vecs.keys())[0], iter_vecs[list(iter_vecs.keys())[0]][-1]), -1: "Terminated due to iteration parameter {} twice exceeding minimum value {}".format( - list(iter_vecs.keys())[0], iter_vecs[list(iter_vecs.keys())[0]][1]), - 2: "Terminated due to exceeding the iteration limit {}".format(kwargs['iter_lim']) + list(iter_vecs.keys())[0], iter_vecs[list(iter_vecs.keys())[0]][-1]), + 2: "Terminated due to exceeding the iteration limit {}".format(kwargs['iter_lim']), + -2: "Terminated due to static eigenvalue {}".format(k_vec[-1]) } - utils.oprint('End of operation. Status: {}'.format(out_messages[_outtype])) + if _outtype in out_messages: + outmessage = out_messages[_outtype] + else: + outmessage = _outtype + utils.oprint('End of operation. Status: {}'.format(outmessage)) var_df = pd.DataFrame({_var: iter_vecs[_var] for _var in iter_vecs}) var_df['k-eff'] = k_vec utils.oprint(var_df.to_string()) diff --git a/critops/readinputs.py b/critops/readinputs.py index 4b0aab4..ece718f 100644 --- a/critops/readinputs.py +++ b/critops/readinputs.py @@ -103,7 +103,8 @@ def check_inputs(temp_lines: list, iter_vars: dict, **kwargs): l_count += 1 if _instance_count == 0: - utils.error('No instances of iteration variables {} found in input file'.format(', '.join(iter_vars.keys())), + utils.error('No instances of iteration variables {}{} found in input file'.format(kwargs['var_char'], + ', '.join(iter_vars.keys())), 'check_inputs()', **kwargs) if not os.path.isfile(kwargs['exe_str']): diff --git a/setup.py b/setup.py index 28f93ba..8f4c11f 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ vMicro = 0 vDevel = 'dev' -vDevelMicro = '1' +vDevelMicro = '5' if vDevel: version = "{}.{}.{}.{}{}".format(vRelease, vMacro, vMicro, vDevel, vDevelMicro) @@ -53,9 +53,10 @@ description=shortDesc, long_description=longDesc, maintainer='A. Johnson', - maintainer_email='1drew.e.johnson@gmail.com', + maintainer_email='1drew.e.johnson [at] gmail.com', url='https://github.com/drewejohnson/critops', install_requires=installReqs, python_requires='>=3.4', - packages=['critops'] + packages=['critops'], + license='MIT License' ) From 695a76a3dbde7e7e7fbf832f136946b5aa385b0d Mon Sep 17 00:00:00 2001 From: drewejohnson <1drew.e.johnson@gmail.com> Date: Tue, 11 Apr 2017 16:38:41 -0400 Subject: [PATCH 5/8] promoted to v2.0.0dev6 Signed-off-by: drewejohnson <1drew.e.johnson@gmail.com> --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8f4c11f..87330d1 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ vMicro = 0 vDevel = 'dev' -vDevelMicro = '5' +vDevelMicro = '6' if vDevel: version = "{}.{}.{}.{}{}".format(vRelease, vMacro, vMicro, vDevel, vDevelMicro) From 406be9dbe50c45a6866a3c838ec4328ad5eaea68 Mon Sep 17 00:00:00 2001 From: drewejohnson <1drew.e.johnson@gmail.com> Date: Tue, 11 Apr 2017 18:06:57 -0400 Subject: [PATCH 6/8] Started building documentation with sphinx Still have to perfect the art of lists in docstrings and add some more explanations, but its a start Signed-off-by: drewejohnson <1drew.e.johnson@gmail.com> --- critops/iterator.py | 32 +- critops/outputs.py | 16 +- critops/readinputs.py | 15 +- docs/conf.py | 158 + docs/html/.buildinfo | 4 + docs/html/.doctrees/environment.pickle | Bin 0 -> 7510 bytes docs/html/.doctrees/index.doctree | Bin 0 -> 4861 bytes docs/html/.doctrees/intro.doctree | Bin 0 -> 2197 bytes docs/html/.doctrees/iterator.doctree | Bin 0 -> 20542 bytes docs/html/.doctrees/outputs.doctree | Bin 0 -> 9129 bytes docs/html/.doctrees/readinput.doctree | Bin 0 -> 13237 bytes docs/html/.doctrees/readinputs.doctree | Bin 0 -> 12775 bytes docs/html/_sources/index.rst.txt | 24 + docs/html/_sources/intro.rst.txt | 3 + docs/html/_sources/iterator.rst.txt | 7 + docs/html/_sources/outputs.rst.txt | 4 + docs/html/_sources/readinput.rst.txt | 6 + docs/html/_sources/readinputs.rst.txt | 6 + docs/html/_static/ajax-loader.gif | Bin 0 -> 673 bytes docs/html/_static/alabaster.css | 693 ++ docs/html/_static/basic.css | 632 ++ docs/html/_static/comment-bright.png | Bin 0 -> 756 bytes docs/html/_static/comment-close.png | Bin 0 -> 829 bytes docs/html/_static/comment.png | Bin 0 -> 641 bytes docs/html/_static/custom.css | 1 + docs/html/_static/doctools.js | 287 + docs/html/_static/down-pressed.png | Bin 0 -> 222 bytes docs/html/_static/down.png | Bin 0 -> 202 bytes docs/html/_static/file.png | Bin 0 -> 286 bytes docs/html/_static/jquery-3.1.0.js | 10074 +++++++++++++++++++++++ docs/html/_static/jquery.js | 4 + docs/html/_static/minus.png | Bin 0 -> 90 bytes docs/html/_static/plus.png | Bin 0 -> 90 bytes docs/html/_static/pygments.css | 65 + docs/html/_static/searchtools.js | 758 ++ docs/html/_static/underscore-1.3.1.js | 999 +++ docs/html/_static/underscore.js | 31 + docs/html/_static/up-pressed.png | Bin 0 -> 214 bytes docs/html/_static/up.png | Bin 0 -> 203 bytes docs/html/_static/websupport.js | 808 ++ docs/html/genindex.html | 161 + docs/html/index.html | 123 + docs/html/intro.html | 102 + docs/html/iterator.html | 199 + docs/html/objects.inv | 5 + docs/html/outputs.html | 137 + docs/html/py-modindex.html | 121 + docs/html/readinputs.html | 162 + docs/html/search.html | 105 + docs/html/searchindex.js | 1 + docs/index.rst | 24 + docs/intro.rst | 3 + docs/iterator.rst | 7 + docs/outputs.rst | 4 + docs/readinputs.rst | 6 + 55 files changed, 15767 insertions(+), 20 deletions(-) create mode 100644 docs/conf.py create mode 100644 docs/html/.buildinfo create mode 100644 docs/html/.doctrees/environment.pickle create mode 100644 docs/html/.doctrees/index.doctree create mode 100644 docs/html/.doctrees/intro.doctree create mode 100644 docs/html/.doctrees/iterator.doctree create mode 100644 docs/html/.doctrees/outputs.doctree create mode 100644 docs/html/.doctrees/readinput.doctree create mode 100644 docs/html/.doctrees/readinputs.doctree create mode 100644 docs/html/_sources/index.rst.txt create mode 100644 docs/html/_sources/intro.rst.txt create mode 100644 docs/html/_sources/iterator.rst.txt create mode 100644 docs/html/_sources/outputs.rst.txt create mode 100644 docs/html/_sources/readinput.rst.txt create mode 100644 docs/html/_sources/readinputs.rst.txt create mode 100644 docs/html/_static/ajax-loader.gif create mode 100644 docs/html/_static/alabaster.css create mode 100644 docs/html/_static/basic.css create mode 100644 docs/html/_static/comment-bright.png create mode 100644 docs/html/_static/comment-close.png create mode 100644 docs/html/_static/comment.png create mode 100644 docs/html/_static/custom.css create mode 100644 docs/html/_static/doctools.js create mode 100644 docs/html/_static/down-pressed.png create mode 100644 docs/html/_static/down.png create mode 100644 docs/html/_static/file.png create mode 100644 docs/html/_static/jquery-3.1.0.js create mode 100644 docs/html/_static/jquery.js create mode 100644 docs/html/_static/minus.png create mode 100644 docs/html/_static/plus.png create mode 100644 docs/html/_static/pygments.css create mode 100644 docs/html/_static/searchtools.js create mode 100644 docs/html/_static/underscore-1.3.1.js create mode 100644 docs/html/_static/underscore.js create mode 100644 docs/html/_static/up-pressed.png create mode 100644 docs/html/_static/up.png create mode 100644 docs/html/_static/websupport.js create mode 100644 docs/html/genindex.html create mode 100644 docs/html/index.html create mode 100644 docs/html/intro.html create mode 100644 docs/html/iterator.html create mode 100644 docs/html/objects.inv create mode 100644 docs/html/outputs.html create mode 100644 docs/html/py-modindex.html create mode 100644 docs/html/readinputs.html create mode 100644 docs/html/search.html create mode 100644 docs/html/searchindex.js create mode 100644 docs/index.rst create mode 100644 docs/intro.rst create mode 100644 docs/iterator.rst create mode 100644 docs/outputs.rst create mode 100644 docs/readinputs.rst diff --git a/critops/iterator.py b/critops/iterator.py index 0995bb6..0ac47d8 100644 --- a/critops/iterator.py +++ b/critops/iterator.py @@ -1,17 +1,18 @@ """ NRE6401 - Molten Salt Reactor + CritOpS -A. Johnson -iterator +A. Johnson Objective: Main file for controlling the iteration scheme Functions: iter_main: Landing function that drives the iteration - -Classes: + makefile: Write the new output file using the value from iteration _iter + update_itervar: Simple function to update the iteration variables. + parse_scale_out_eig: Read through the SCALE output file specified by _ofile and return status and eigenvalue (if present) """ import subprocess @@ -22,12 +23,14 @@ def makefile(_tfile: (list, tuple), _name: str, _iter: int, _varchar: str, _vars: dict): """ Write the new output file using the value from iteration _iter + :param _tfile: Template output file with variables to be replaced :param _name: Name of original file :param _iter: Iteration number :param _varchar: Variable character to update with new_val :param _vars: Dictionary with iteration variables as keys and their new values as keys i.e. {del_z: 10.21, del_r: 3.4} + :return: Name of input file """ _ofile = _name[:_name.rfind('.')] + "_" + str(_iter) + ".inp" @@ -48,16 +51,18 @@ def update_itervar(iter_vars: dict, iter_vec: dict, kvec: (list, tuple), ktarg: """Simple function to update the iteration variables. Currently set up for a positive feedback on the variables. I.e. increasing each iteration variable will increase k + :param iter_vars: Dictionary of iteration variables and their minima/maxima :param iter_vec: Dictionary of iteration variables and their values through the iteratio procedure :param kvec: Vector of eigenvalues :param ktarg: Target eigenvalue + :return: status status = 0 if the updated value is inside the intended range status = 1 if the desired updated value is greater than the specified maximum of the parameter - and the max value is used as the updated value + and the max value is used as the updated value status = -1 if the desired updated value is less than the specified maximum of the parameter - and the minimum value is used as the updated value + and the minimum value is used as the updated value """ # Assumes only one iteration variable for now @@ -83,8 +88,11 @@ def update_itervar(iter_vars: dict, iter_vec: dict, kvec: (list, tuple), ktarg: def parse_scale_out_eig(_ofile: str, **kwargs): """ Read through the SCALE output file specified by _ofile and return status and eigenvalue (if present) + :param _ofile: SCALE .out file + :return: Status, eigenvalue + status = True if output file exists and eigenvalue was extracted status = False if output file exists but no eigenvalue was found (possible error in input file syntax) exit operation if no output file found @@ -111,18 +119,26 @@ def parse_scale_out_eig(_ofile: str, **kwargs): def itermain(tmp_list: (list, tuple), file_name: str, iter_vars: dict, kwargs: dict): """Main function for controlling the iteration + :param tmp_list: List of lines from template file :param file_name: Name of template file :param iter_vars: Dictionary of iteration variables and their starting, minima, and maximum values :param kwargs: Additional keyword arguments + :return: k_vec: List of progression of eigenvalue through iteration procedure :return: iter_vecs: Dictionary of iteration and their values through iteration procedure :return: conv_type - reason for exiting iter_main + 0: Accurately converged to target eigenvalue in specified iterations + 1: iter_var exceeded specified maximum twice - -1: iter_var exceeded specified minimum twice + + -1: iter_var exceeded specified minimum twice + 2: Reached iteration limit without reaching target eigenvalue - -2: Previous two k are close to similar + + -2: Previous two k are close to similar + """ # Make sure all the required keywords are present. If not, set to defaults from constants.py utils.check_defaults(kwargs) diff --git a/critops/outputs.py b/critops/outputs.py index 7f3c67f..f417557 100644 --- a/critops/outputs.py +++ b/critops/outputs.py @@ -1,17 +1,16 @@ """ NRE6401 - Molten Salt Reactor + CritOpS -A. Johnson -outputs +A. Johnson Objective: Functions for reading SCALE output files and writing output files Functions: parse_scale_output: Parse through the SCALE output file and return status - """ import pandas as pd @@ -21,13 +20,16 @@ def output_landing(iter_vecs: dict, k_vec: (list, tuple), _outtype: int, **kwargs): """ Write the output file according to the type of output + :param iter_vecs: Dictionary with iteration variables and their values through the procedure :param k_vec: Vector of eigenvalues :param _outtype: Flag indicating the reason the program terminated - 0: Nothing went wrong - 1: Desired update value for iteration parameter twice exceeded the maximum value from the parameter file - -1: Desired update value for iteration parameter twice exceeded the minimum value from the parameter file - 2: Exceeded the total number of iterations allotted + - 0 Nothing went wrong + - 1 Desired update value for iteration parameter twice exceeded the maximum value from the parameter file + - -1 Desired update value for iteration parameter twice exceeded the minimum value from the parameter file + - 2 Exceeded the total number of iterations allotted + - -2 No excessive change in eigenvalue + :return: """ utils.check_defaults(kwargs) diff --git a/critops/readinputs.py b/critops/readinputs.py index ece718f..503396c 100644 --- a/critops/readinputs.py +++ b/critops/readinputs.py @@ -1,17 +1,18 @@ """ NRE6401 - Molten Salt Reactor + CritOps + A. Johnson -readinputs Objective: Read the inputs, update global variables, and check for proper variable usage Functions: check_inputs: make sure values in global_parameters are good for running read_param: Read the parameter file and update values in globalparams - readMain: Main driver for reading and processing the input files + readmain: Main driver for reading and processing the input files """ import os.path @@ -25,8 +26,10 @@ def read_param(_pfile, **kwargs): """ - Read the parameter file and update values in globalparams + Read the parameter file and update values in kwargs + :param _pfile: Parameter file + :return: iter_vars: Dictionary of iteration variables and their starting, minima, and maximum values """ @@ -115,13 +118,15 @@ def check_inputs(temp_lines: list, iter_vars: dict, **kwargs): def readmain(tmp_file, param_file, kwargs: dict): """Main driver for reading and processing input files. + :param tmp_file: Template input file :param param_file: Parameter file :param kwargs: Additional arguments - verbose (True) - status updates - output (None) - print to screen - Plus additional iteration parameters - :return List of valid template file lines and dictionary of interation variables + - Plus additional iteration parameters + + :return: List of valid template file lines and dictionary of interation variables Updates kwargs based on values in param_file """ utils.check_defaults(kwargs) diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..68b612c --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# CritOpS documentation build configuration file, created by +# sphinx-quickstart on Tue Apr 11 17:09:52 2017. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['sphinx.ext.autodoc', + 'sphinx.ext.mathjax'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = 'CritOpS' +copyright = '2017, Andrew Johnson' +author = 'Andrew Johnson' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '2.0.0' +# The full version, including alpha/beta/rc tags. +release = '2.0.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'CritOpSdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'CritOpS.tex', 'CritOpS Documentation', + 'Andrew Johnson', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'critops', 'CritOpS Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'CritOpS', 'CritOpS Documentation', + author, 'CritOpS', 'One line description of project.', + 'Miscellaneous'), +] + + + diff --git a/docs/html/.buildinfo b/docs/html/.buildinfo new file mode 100644 index 0000000..c2ef904 --- /dev/null +++ b/docs/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 6e56c55a3315425c276faea4bc80cf11 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/html/.doctrees/environment.pickle b/docs/html/.doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..430fa49e2755c4a9fe76d8c4c7bffa083c5fd9dc GIT binary patch literal 7510 zcmcgxO^h5z752}1XJ^Obu}yvz3N36>trr-8iZWMTE%ISc!uI2i16w>RI74d*YUO+FH)#aPis(5jfPKo7o z&x_rz(e=zwy#m%LGf~S3L{&6im9>EP4AXNXz8MjZz0CL3iku306j^Sc#LdV%dX~ct z%ME!DS)OZfmvtQ8RWD+J+>FAw6Il^vZ1%ihpl-+mT2)LlJ!sumvKmLd*-y`g7TO1( z(&+Sqe9+-tBaDU)4+ZBDSnT(?Z**A5jW}?WY>FuI!{hDt#>Pg=A4bA+TVBv_clp&e zW`=EO4v>}DD;s^Nj@4jQ1D}}@v^)|8*1+g_UgUZaH?U+LKsj!Nn7|=zS}-Rv9DbEM zYH6Rm-E=&5#oz;GIR@)?10IGv1f%^y&n#*6;Y_Q@^PI3{@u;V@64AhcMh7-n;9~t) z8SFPu@=)pyab!6y*Xx3(tY1ndttNAFSJ(?RmE1#rru0%^0`;1b53JA3ESx&=^yzD7 zSDrY3?b7^(m9s0SubsMZ;rxYbtEbjZT{v~L{mk6#!7y@Y4O?rM^mvVj*D|*S*$>hr$%;Ps)JY)Ux4uPzDzWz zjc6dA0fWnU3_J{vd0E9{+>6az@V)}xMSsG%KEhc}y+3cMtM`XZY}A-S7Nbr7F;%EHgnBz7Ni=VaXucCn@<>+5d>JzHZp{~tjKI~Sm{LzS zR`x!5G8xEyxawWyL1592Ly$Y*5Bs#RFo`)zPA2rkNPD9Z#=V}kN$xz+3c^S+c?dDZ za(f;{RE-KbyAG=qePtzuP08ESR&${YAB4`kaP5ueq9@$YbCvj!Y@T;{)3NXeikX4s z6VOes*YpF=Mqq70p=B#Hx#KXGdvT~plj#8q5&uaMC0>`)*d*KyL78ZjpE;XRi^Y*g z(~5%#odXsLn?dI)a~MJ_cquOTA>zjr`l|!x8b0gm-8=&U6=)WDeyGHc;lXdPrQM`O z)%5&fVD$w~wA+r&ed1FOHpdnyr=WE|1}AW>1l-{W=h)20T63*A9D{t*bmA_DEX3;| z)qc|G(CG-}E{b^230vI`+O36EV-@EehoTi&l2)t4FXaJ;!7K(?YjbMbMttB?cSwu{ znQ+?3`=Iziiq0@RyxPpCRMHNNS5olFK!<3q;7)QBC9!KdwXeptktl$6;S+$Ymd*2twAK9v=TpyJMuu}nFdZ$7c0i%Xc-Oa!aEL81m7g`iptV%QN>fk zQ(xL68cVxlS*67pY0@C~>ug|z2u7>IRcGMkIE-+L$a_+Ywu-c(IWzFOvBQrld3Vy9 zy?K%n%PWzZ5r36Oi4w=7J9D%-W4XZo#+ABH_$MjQ|A>cW3jnjI4y?onts=Qwr_wr>^Z$%m~OP z<8oRVX~Ata_TdG{)4=p93$|WuiD$mntgki7px}HAWL3`8EvJhxUdr2?!U857kSB~P`B<$*Nj zm;wZx!BjFC$nVp;%56{i5FJysc{j?RGi972jlhb+~5eUiTG=7jra?N4>-E&x{ z$h6){xq#t8tdbaF2kBrq#}l82=bXT^faeK3XLN=&N|9$e zkIE{spe-^e_)w-t`QmoGN;G24zHj%gU6dHgM!FVU5Yk-!P^UO5 zm7Fce%bMrcmNL`Nj4%ZNFbFPlfs3=|MLEq}Q+RlxlV+K4l9ON)2bKb^fQn#4LW)E@ zyA!Eg}nqXb}wXV5&%2I?i(4+`+!}Iu=`dapoCp<>nXhMyUEPWG34quA$JXSdk)X@ zc)p6~Yqy96GiCqFBfvHsMkBzRqz|B+DPy^2|D3w@{@#YmE%tZWE!XT{k8r|D%HBEV zk+k5#E9F-_X@7?;B%X)gQ39H*h+2IB*J51lgaOuDu z5*Mo|JdSfUshD`KGgLQn7X#Ed^Vmj4V*eXl1&l8zbAEZPqD~%(0w3G#av%4Sr9E;g z$sJHgTiQj5yFOu)gOZ$!bk~a8q_s^db2-s>ypFm-=FNeW6Lg1EOH~--FQh^mCbh|U z+<6zCZvTqt*X+#2M?Ji{=hhx>|F$H3)TIxPklxCr<%jNtO)Zm$vq<7*BPuoG?zyd- z+kY+zMf5#-T)9&1!AH;avpg zM>3lCAuu;6Fn_KPPzua>?WMr-OfvD?CE$QvET@>`B!y>6sw$`F|Mb|!#S?=iQPs`w z{Ba!@sHFM(J10e5H=lax7k?Lxr1uYRUyH?WmL8I~jU>#lD-}qnUh8;nzg)#cDX@x) zTuodNbuknT@p3HpW214@#$7YJKi8-b?zdX){Qtb~FQDAsKIh?X)21D7xp6#b&$|q@ zq%M1??O2_5hZmZw#_AcB_N92KLzU4f^!EiMlMgco3Jt1CKybhJx@P;j#B_~&t(d@#7dz@$LyTpo|MlBVarDvgdxFXh8M2HXq=t(F$r> zX&vrKD(RqyVw|jXIX(~I+ZF9&e2kFkcY|k@J%s8@yP#nhb+v|7(@ILugt44Nt&%&5 zfhR-G0#hjad$io;y!`9XE=GOpka00!Ziw0(#5@^zn?ocU_V+Ov)y-l0eF$B$wyGI5 zpQIw?b$nj1e~3x;>-h5m-aB8X6Pvza=^Ag%AI|1)V%h!y%_Rc4e_0#3iK7Pvzk<`FMJcU z_D{4typiBk`gH|w*liNhDW_CUEce)nS0@(9yZ2Hde2eK5R8Zbx00%*u({yR;)+uvA hIMDS3y_qMi0R>cLAHnv)?UC;Nhq9cgJTvaJ{s-gbIAs6; literal 0 HcmV?d00001 diff --git a/docs/html/.doctrees/index.doctree b/docs/html/.doctrees/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..aa2bdadbd8e92721585d87f42a64db5397e05622 GIT binary patch literal 4861 zcmds5TW=&s6}H!xneqC*7m(PXCJ|bLGPXA?ELgmtjkw6t@IW9z@upqVT{Bg7-_liW z&pc!W+D)`8)e~uu@`4aT;t%8%@dJQ&f_Ma8xjZ5Se5d*{)3Nb-Us-9^-8FSN=X~G! z&Z+sq{Ez>!Ib;8sRX_GJEd#Y3#XeWLY12T+Bb~pWf9{9*JNcGbmys`1?rB%EbjY>J zALOQ`*)U=u&&8}+@uX&2#*v%yfx;RwE9OjFajj)E#HJhdDT6eQG>`n;EPjs#8BVN^ zc_Gepl4+MmUhHF?%hNPYUBMzh;3*a;ok~yVrXzhf!AWwIo0;4!sW?kL?q+F__e^KV zBc3uHr+8UWusX^@cQlC8FyEgwtF%etdT~fTD$H5uqa;?`m9Q&~SU_X9WORWgV#BQY zS(vywWs#ztY0c^>OCvHHCvX;GE5<=m{YOvmn2V6I5Sc(v&VLT9IUl^o{gYRXO# zY}OCBZ$kr+wA2AFqxIA**jMtz6D(yO0^|n#ga@!WkP&x7mL6vbJh|ZoF*|m7$YkI$ z-%q)<_=(xzBdHM*rZZKn&G#38OMyb|*v)~&xiV5bwLGfKdSY5`0dH=;dVlZWyO^L3 z*ikGZ6-Re>cMo1I>8cLCA@w)2{=xlJ>Tf6CIe<6n0LnRl#U zkVttF5I$x(;fdR4;0964I6~`0?d|NGo}O+eV=dxnJ5Gl?K0n#POtpjXf)O64o$@DU zm6q3_6MQQ=_OPLMjNlz3Efzq*bex+TG}A@^2f3PuFhIkAHpaW3-MtGWuOa{9)OUTJ zAba41w1ik!<4CiSE96iF_`uKkAdZ0Ul3;4kqprQgy@-N z1wgg?b_TjCpt@OecVaYhXvNaD&Th~WqM-RmQ(A%A8qRk#>w~?%7WsbLET;oDyYj>`e!a&ic z6<~yn2H2nygLNMExes=Z1Fi(;8a^-hyq{4pRst3cGd867_yFSyj{vX_V8G@u!Hi`v zB}Tk#O62=j%xaTj0N6|Je&JqjHc5w6)^DcQGSE~|NGqLrFYB8QQnIAGxMo_UuhJ($ z-7=db!X8%+>_TI2;(zLsq92CQ6S8p+(xh%#hotCA}ei3Re2z!49aaPj9Y zX4=FhpldN}`&m-W$xPc5GJtkOSg|E$#OPB-P{&HxS5&7guyVK3&6-kOWa1HK?3vrmUtvQTksYu=(e*y z&T3OO#2ISc#0_z+Hqop>4Nxk0_cUcmf(pmZwc4zyM965g4OuN~bgNu>&c@{TBeP(2 zFE=YP@`B9gLi*4Qu)7_y5hR4N@``DZ{E&_y+C5sM(>Q+*#BNI{y)B{iwuEwqdW?do z?6<9=2+<1%+AOi0FrE9hvTL;m;X=*rqu8OY%$UXc^d-xG2zM}sE%U=5?&nV}T!4t+ zGRvjGB!<>5@l)|L@pJJD4l~$kb(r`i0b79D67P%0`yHV0M7%2ydP3(t@wivvQjBtp zGE5}6<_NB0SR9Cc(dH1DYj7+QZx)+iL_c^HotW?DVuwo;o!q_7fqP0_kvS7qhm9 z)Z9Bn6J;rMm_NfE?1RK$Lr_>u?IZs9jCDVv>Wbi@UmD@Wix=QyMLrRFJT80s*j-yVmiCKv-OZh-N6HDJN` zB*NaKnA9pyV9@BRjnT7UkoNzkOr$9>tx5uE>{Lm}OsDF5ZI7~2y;Zkcv~yV>jhn{B z8F${Ie|ZOjQ}lzVrs>e}B$l?x6L0p! zgI;Df8iDZ3%RgEzDlo0`l07A)=C@_*)@(fE{G+_|^6`<1;fzT&*Hd*|Nv()Z)c@mSCm!SH0w<8is68(`=vy7B9VOx{@ExX|fWww0+#xhd3-;hniVM7RShie;PVrNS zJmK4C!809PPWFoHJ#KHf1@rU-KarG}77fe8|FbAGllUi9&K~8Im5=uqn%RY3`9p3x w)h|Xi!>-nxv$=EqjwS)w~~w+Q@v}aWzigH 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 N^;BGlgqx}s{|}M@kaGY4 literal 0 HcmV?d00001 diff --git a/docs/html/.doctrees/outputs.doctree b/docs/html/.doctrees/outputs.doctree new file mode 100644 index 0000000000000000000000000000000000000000..610b3b581dfdfed80fe8e79f0bd4c38287d44709 GIT binary patch literal 9129 zcmeHN+ix958Ml+zK0fg!NgJzzq}r;KI3;${Hry;!36d6Q(o>YsCL)ejdv@oX+0CBa z?ar+2qXH_CA|=uwg4lq#Kk&l!4=6nHQ1QqEDm+(xMXGp1Lgn|(Ue7wdf&11d$M(+7 ze3##Motg9Ip$ETsa!mhIb53X{()Go15IRhxszn0>7RdAm>FMvJ-%1zNbT15L5K6qh znW`gh;J7ifr75kr&!irlj9Jfh1g5K&U{bn4AGD5^#CvfVNESG$ntaXj6HqFt&zRtg z1(tNfAnmA`m_=bMO`okXKfQE7P0QG_S=X{}rFYe=0OueXm>az?9;BDX)wJuF5wYJ$ z)mW-#O*;&FZr|*=ekSlyw&6-sNJ}Q7pgN(B6-t>z*>{6mf~d_28M_f^3#pRcU3%{kHs~@3figrY;EYMAGcBzy<~fq5ms;vLfv%atlBQ$>1cF2$v@pK()VcGB z^m)^91;Ldk7KnLb)G!SP*wvZ>XvK6>?7TSE7zlrYZvm29G6K__!Djx}jf%RQ_fRpe9|U zUWoz#ut@}+!H5VU_DQWd-LCVKf+o2dK^7rA=_((Dx)ymSj{`=?% zKZgjTU?3z$8~pqo&| zq5{^UOjqb}kYK)v(SnWMn}^neu~t z9G?Nm@-cqBsBK*ECwKx0_&O*J@%bh`-^S<7n`r`>uXB0n0Kd&&*UO#Cm_!O{ANo3S zBXq7_+(~s!#+p0O`@2ckg7?geh`YhYGBQ|R#V1gt*+z*L7wQDn7@!jLjj(5I(mBKM zhmdEylvqtsA)$mva7_xV^${D7H5MC-8IY&bts!0L$kZw{FOWz|&7p15g}&3k)9S}o z#P=e)I@!7M!e`E(d&XEYUJiZq8OBwldE*L0UJK(CK>vC~u|j}Cpbg2{i+VaN+vWiNOiEJ59gce%3S@)o%KDdRGx<{7#ls=-KXzKd3&=4{}s zL*Z>`JE1wkYDrJGM&rw=_QKrz;JOG1^h{WgJEm$8X*rBw<8~57VB$yIf}<7=nmOe( zu{B*J%TeCjIr=+Xc0lGYxu3UQ%9^5fsvW(7UH-DbF4N@UA#|JnLsPh~rixV+Ztnt) z_cU$@68vx2=<+LFkFv@dTQOct0-axkfvRPoucAb2T)ptc%P$yNf;DtMX&?m~>#(hk zBi*oNFA8C&c5UeWWnXFiKD7Q<=`BdIZUAwS-?#FX56CuK8*kM3k2VNC#19Tx zWw}@#LSxhLQ%AKc`H1MkZivq0M3Elq%S+t7$7q7%eGI<}^idcK^s7+OA?kgSW^V(! zSMnPTj<4<;o`uJ5kL6;e_CB(%PnV@h+3xHF>C%s7WWpP68Xj1JO{| z_%gLl1z}c^@1c};y)4PLdU@8NwgPPQsP_$mqMmXW`2*~n@ZLn@k8N@ivzkEaQ`;5x zyoD@aNl}`*4Wy9BV{?t!V#RQHv|=Q_kG5-;k16{FGR1ms!706R4HBzj=KH+t2H;c|XHbo{t>0@bC!P zEAy?$R5JW-YZ;C-qj9g?HxsD%zO^;q*^!vvE7Qj6isRc`b8Ho9Wv|Stg%zK_)%l>% z;6Ji!mM3t4f~`Znq0WPWdTQ@oT3Ju{o3?Y!{8JY0J*VhTUqgpU4HBz2pN3`AQ51Ea zGSn|A_tI`IOQ67K=Y5X%9_f+iNJPN@$f`p0pBho`ef%oho}SD6O}mq#a{gx*K-PuC zj+*j6DApoho1}GMhe-c`SmljiI}>U&@uC$(FPbGnlqTjqvJ=TRO~{f*eQAZqahiZ0 zuK`9kbcRj&pWHRGF?G0$ddYBfIkM&3F3mla3j(c{bDyP5lW)Af; z+I6=U>bCd!QUx?azUJi92{;{{mWAEHWkAu*kToyUqLOO9^DXK*PC{`26*1fGxpsP& z`iC#&Ob{0}LX~YhIVzcL@2f+ELR!7o>$UAc;iY|qr^#YpiI*Ms|LGi$>#|6YyoPNx zw$aE;%*BmCX8E0M+$(JCy^O!gayy~v?r2Z%8Ww3YhB+M=AzxeJH>7uEcy2bKUR#*( z_`?;csAaR&7W4KA*z0$Y#)`5_@V@9-1a$V&rf3C;3_lX)8E#Z#6V@bX2-e}zp>Fck# zNV>tvwnybpOHJD@PGZsV=^MJ)`Yj=il!+0S4%ycraQoG0x)Swh)4|gG{}c^19u}kw0Q%& ziOKAXD^=ep_)oGkM(^JQK>ZGEM1eQ-fs~qX1&*O~%b4HXp-aX_@+N;hQL_a|nPRx# ioGq_pwW=7Ivy+(a4U4afbZA4SW{OdLjfq>~<^KW#7~DYs literal 0 HcmV?d00001 diff --git a/docs/html/.doctrees/readinput.doctree b/docs/html/.doctrees/readinput.doctree new file mode 100644 index 0000000000000000000000000000000000000000..d83fdbc2598b9fd07bb6518891f04676649532f7 GIT binary patch literal 13237 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 literal 0 HcmV?d00001 diff --git a/docs/html/.doctrees/readinputs.doctree b/docs/html/.doctrees/readinputs.doctree new file mode 100644 index 0000000000000000000000000000000000000000..039a0bbee102e51c7b49cdc946bf05ce740388ea GIT binary patch literal 12775 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 literal 0 HcmV?d00001 diff --git a/docs/html/_static/alabaster.css b/docs/html/_static/alabaster.css new file mode 100644 index 0000000..a88ce29 --- /dev/null +++ b/docs/html/_static/alabaster.css @@ -0,0 +1,693 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif; + font-size: 17px; + background-color: #fff; + color: #000; + margin: 0; + padding: 0; +} + + +div.document { + width: 940px; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 220px; +} + +div.sphinxsidebar { + width: 220px; + font-size: 14px; + line-height: 1.5; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #fff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +div.body > .section { + text-align: left; +} + +div.footer { + width: 940px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + +div.relations { + display: none; +} + + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: left; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: 'Garamond', 'Georgia', serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif; + font-size: 1em; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: 'Garamond', 'Georgia', serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: ; + border-bottom: 1px solid #fafafa; +} + +dd div.admonition { + margin-left: -60px; + padding-left: 60px; +} + +div.admonition p.admonition-title { + font-family: 'Garamond', 'Georgia', serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: #fff; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #EEE; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +dl dl pre { + margin-left: -90px; + padding-left: 90px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + + +@media screen and (max-width: 870px) { + + div.sphinxsidebar { + display: none; + } + + div.document { + width: 100%; + + } + + div.documentwrapper { + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.bodywrapper { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 0; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .bodywrapper { + margin: 0; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + + +} + + + +@media screen and (max-width: 875px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + } + + div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + padding: 0; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Make nested-list/multi-paragraph items look better in Releases changelog + * pages. Without this, docutils' magical list fuckery causes inconsistent + * formatting between different release sub-lists. + */ +div#changelog > div.section > ul > li > p:only-child { + margin-bottom: 0; +} + +/* Hide fugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} \ No newline at end of file diff --git a/docs/html/_static/basic.css b/docs/html/_static/basic.css new file mode 100644 index 0000000..7ed0e58 --- /dev/null +++ b/docs/html/_static/basic.css @@ -0,0 +1,632 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox input[type="text"] { + width: 170px; +} + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dl { + margin-bottom: 15px; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, .highlighted { + background-color: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +div.code-block-caption { + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +div.code-block-caption + div > div.highlight > pre { + margin-top: 0; +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + padding: 1em 1em 0; +} + +div.literal-block-wrapper div.highlight { + margin: 0; +} + +code.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +code.descclassname { + background-color: transparent; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: relative; + left: 0px; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs/html/_static/comment-bright.png b/docs/html/_static/comment-bright.png new file mode 100644 index 0000000000000000000000000000000000000000..15e27edb12ac25701ac0ac21b97b52bb4e45415e GIT binary patch literal 756 zcmVgfIX78 z$8Pzv({A~p%??+>KickCb#0FM1rYN=mBmQ&Nwp<#JXUhU;{|)}%&s>suq6lXw*~s{ zvHx}3C%<;wE5CH!BR{p5@ml9ws}y)=QN-kL2?#`S5d*6j zk`h<}j1>tD$b?4D^N9w}-k)bxXxFg>+#kme^xx#qg6FI-%iv2U{0h(Y)cs%5a|m%Pn_K3X_bDJ>EH#(Fb73Z zfUt2Q3B>N+ot3qb*DqbTZpFIn4a!#_R-}{?-~Hs=xSS6p&$sZ-k1zDdtqU`Y@`#qL z&zv-~)Q#JCU(dI)Hf;$CEnK=6CK50}q7~wdbI->?E07bJ0R;!GSQTs5Am`#;*WHjvHRvY?&$Lm-vq1a_BzocI^ULXV!lbMd%|^B#fY;XX)n<&R^L z=84u1e_3ziq;Hz-*k5~zwY3*oDKt0;bM@M@@89;@m*4RFgvvM_4;5LB!@OB@^WbVT zjl{t;a8_>od-~P4 m{5|DvB&z#xT;*OnJqG}gk~_7HcNkCr0000W zanA~u9RIXo;n7c96&U)YLgs-FGlx~*_c{Jgvesu1E5(8YEf&5wF=YFPcRe@1=MJmi zag(L*xc2r0(slpcN!vC5CUju;vHJkHc*&70_n2OZsK%O~A=!+YIw z7zLLl7~Z+~RgWOQ=MI6$#0pvpu$Q43 zP@36QAmu6!_9NPM?o<1_!+stoVRRZbW9#SPe!n;#A_6m8f}|xN1;H{`0RoXQ2LM47 zt(g;iZ6|pCb@h2xk&(}S3=EVBUO0e90m2Lp5CB<(SPIaB;n4))3JB87Or#XPOPcum z?<^(g+m9}VNn4Y&B`g8h{t_$+RB1%HKRY6fjtd-<7&EsU;vs0GM(Lmbhi%Gwcfs0FTF}T zL{_M6Go&E0Eg8FuB*(Yn+Z*RVTBE@10eIOb3El^MhO`GabDll(V0&FlJi2k^;q8af zkENdk2}x2)_KVp`5OAwXZM;dG0?M-S)xE1IKDi6BY@5%Or?#aZ9$gcX)dPZ&wA1a< z$rFXHPn|TBf`e?>Are8sKtKrKcjF$i^lp!zkL?C|y^vlHr1HXeVJd;1I~g&Ob-q)& z(fn7s-KI}G{wnKzg_U5G(V%bX6uk zIa+<@>rdmZYd!9Y=C0cuchrbIjuRB_Wq{-RXlic?flu1*_ux}x%(HDH&nT`k^xCeC ziHi1!ChH*sQ6|UqJpTTzX$aw8e(UfcS^f;6yBWd+(1-70zU(rtxtqR%j z-lsH|CKQJXqD{+F7V0OTv8@{~(wp(`oIP^ZykMWgR>&|RsklFMCnOo&Bd{le} zV5F6424Qzl;o2G%oVvmHgRDP9!=rK8fy^!yV8y*4p=??uIRrrr0?>O!(z*g5AvL2!4z0{sq%vhG*Po}`a<6%kTK5TNhtC8}rXNu&h^QH4A&Sk~Autm*s~45(H7+0bi^MraaRVzr05hQ3iK?j` zR#U@^i0WhkIHTg29u~|ypU?sXCQEQgXfObPW;+0YAF;|5XyaMAEM0sQ@4-xCZe=0e z7r$ofiAxn@O5#RodD8rh5D@nKQ;?lcf@tg4o+Wp44aMl~c47azN_(im0N)7OqdPBC zGw;353_o$DqGRDhuhU$Eaj!@m000000NkvXXu0mjfjZ7Z_ literal 0 HcmV?d00001 diff --git a/docs/html/_static/custom.css b/docs/html/_static/custom.css new file mode 100644 index 0000000..2a924f1 --- /dev/null +++ b/docs/html/_static/custom.css @@ -0,0 +1 @@ +/* This file intentionally left blank. */ diff --git a/docs/html/_static/doctools.js b/docs/html/_static/doctools.js new file mode 100644 index 0000000..8163495 --- /dev/null +++ b/docs/html/_static/doctools.js @@ -0,0 +1,287 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + */ +jQuery.urldecode = function(x) { + return decodeURIComponent(x).replace(/\+/g, ' '); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s == 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node) { + if (node.nodeType == 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { + var span = document.createElement("span"); + span.className = className; + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this); + }); + } + } + return this.each(function() { + highlight(this); + }); +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated == 'undefined') + return string; + return (typeof translated == 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated == 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) == 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this == '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keyup(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box or textarea + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); \ No newline at end of file diff --git a/docs/html/_static/down-pressed.png b/docs/html/_static/down-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..5756c8cad8854722893dc70b9eb4bb0400343a39 GIT binary patch literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`OFdm2Ln;`PZ^+1>KjR?B@S0W7 z%OS_REiHONoJ6{+Ks@6k3590|7k9F+ddB6!zw3#&!aw#S`x}3V3&=A(a#84O-&F7T z^k3tZB;&iR9siw0|F|E|DAL<8r-F4!1H-;1{e*~yAKZN5f0|Ei6yUmR#Is)EM(Po_ zi`qJR6|P<~+)N+kSDgL7AjdIC_!O7Q?eGb+L+qOjm{~LLinM4NHn7U%HcK%uoMYO5 VJ~8zD2B3o(JYD@<);T3K0RV0%P>BEl literal 0 HcmV?d00001 diff --git a/docs/html/_static/down.png b/docs/html/_static/down.png new file mode 100644 index 0000000000000000000000000000000000000000..1b3bdad2ceffae91cee61b32f3295f9bbe646e48 GIT binary patch literal 202 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6CVIL!hEy=F?b*7pIY7kW{q%Rg zx!yQ<9v8bmJwa`TQk7YSw}WVQ()mRdQ;TC;* literal 0 HcmV?d00001 diff --git a/docs/html/_static/file.png b/docs/html/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/docs/html/_static/jquery-3.1.0.js b/docs/html/_static/jquery-3.1.0.js new file mode 100644 index 0000000..f2fc274 --- /dev/null +++ b/docs/html/_static/jquery-3.1.0.js @@ -0,0 +1,10074 @@ +/*eslint-disable no-unused-vars*/ +/*! + * jQuery JavaScript Library v3.1.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2016-07-07T21:44Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + + + + function DOMEval( code, doc ) { + doc = doc || document; + + var script = doc.createElement( "script" ); + + script.text = code; + doc.head.appendChild( script ).parentNode.removeChild( script ); + } +/* global Symbol */ +// Defining this global in .eslintrc would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.1.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? + + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + + // Return all the elements in a clean array + slice.call( this ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = jQuery.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isFunction: function( obj ) { + return jQuery.type( obj ) === "function"; + }, + + isArray: Array.isArray, + + isWindow: function( obj ) { + return obj != null && obj === obj.window; + }, + + isNumeric: function( obj ) { + + // As of jQuery 3.0, isNumeric is limited to + // strings and numbers (primitives or objects) + // that can be coerced to finite numbers (gh-2662) + var type = jQuery.type( obj ); + return ( type === "number" || type === "string" ) && + + // parseFloat NaNs numeric-cast false positives ("") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + !isNaN( obj - parseFloat( obj ) ); + }, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + // Convert dashed to camelCase; used by the css and data modules + // Support: IE <=9 - 11, Edge 12 - 13 + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: Date.now, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.0 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-01-04 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + // Known :disabled false positives: + // IE: *[disabled]:not(button, input, select, textarea, optgroup, option, menuitem, fieldset) + // not IE: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Check form elements and option elements for explicit disabling + return "label" in elem && elem.disabled === disabled || + "form" in elem && elem.disabled === disabled || + + // Check non-disabled form elements for fieldset[disabled] ancestors + "form" in elem && elem.disabled === false && ( + // Support: IE6-11+ + // Ancestry is covered for us + elem.isDisabled === disabled || + + // Otherwise, assume any non-