diff --git a/.gitignore b/.gitignore index 6b3e9d5..2074dd2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,12 @@ Tpc156.5_pseudo-muS_muB_r0.4QMHRG2020_BI HRG_LCP* P_div* s_div* -testing/base/test.d +*.d +*.redmine +*.tex examples/chi2B.txt + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/applications/main_getBeta.py b/applications/main_getBeta.py index 2c53128..fb4eb6a 100755 --- a/applications/main_getBeta.py +++ b/applications/main_getBeta.py @@ -9,7 +9,8 @@ # import argparse -from latqcdtools.physics.referenceScales import r0_div_a, r0_hQCD_2014, a_times_fk, fk_phys, ignoreBetaRange, CY_FK_PHYS, CY_A_TIMES_FK, CY_A_DIV_R0 +from latqcdtools.physics.referenceScales import r0_div_a, a_times_fk, ignoreBetaRange, CY_phys, CY_param +from latqcdtools.physics.constants import fk_phys, r0_phys from latqcdtools.base.utilities import getArgs from latqcdtools.math.optimize import persistentSolve import latqcdtools.base.logger as logger @@ -32,19 +33,18 @@ Nt = args.Nt scaleYear = args.scaleYear paramYear = args.paramYear -beta_guess = 6 +beta_guess = 6.0 + +if paramYear is None: + paramYear = CY_param[scale] +if scaleYear is None: + scaleYear = CY_phys[scale] # Implement target_T - T as the LHS of the solver. if scale == 'r0': - if paramYear is None: - paramYear = CY_A_DIV_R0 def LHS(beta): - return r0_div_a(beta,paramYear)/r0_hQCD_2014("MeVinv")/Nt - T + return r0_div_a(beta,paramYear)/r0_phys(scaleYear,units="MeVinv")/Nt - T elif scale == 'fk': - if scaleYear is None: - scaleYear = CY_FK_PHYS - if paramYear is None: - paramYear = CY_A_TIMES_FK def LHS(beta): return fk_phys(scaleYear,units="MeV")/a_times_fk(beta,paramYear)/Nt - T else: diff --git a/applications/main_getTempAndSpacing.py b/applications/main_getTempAndSpacing.py index 10e963b..daad352 100755 --- a/applications/main_getTempAndSpacing.py +++ b/applications/main_getTempAndSpacing.py @@ -11,7 +11,7 @@ import argparse from latqcdtools.physics.lattice_params import latticeParams from latqcdtools.base.utilities import getArgs -from latqcdtools.physics.referenceScales import CY_A_DIV_R0, CY_FK_PHYS, CY_A_TIMES_FK +from latqcdtools.physics.referenceScales import CY_param, CY_phys import latqcdtools.base.logger as logger logger.set_log_level('INFO') @@ -38,16 +38,10 @@ else: Ns = args.Ns -if scale == 'r0': - if paramYear is None: - paramYear = CY_A_DIV_R0 -elif scale == 'fk': - if scaleYear is None: - scaleYear = CY_FK_PHYS - if paramYear is None: - paramYear = CY_A_TIMES_FK -else: - logger.TBError('Beta extraction not yet implemented for scale',scale) +if paramYear is None: + paramYear = CY_param[scale] +if scaleYear is None: + scaleYear = CY_phys[scale] lp = latticeParams(Ns, Nt, beta, mass1=None, mass2=None, scaleType=scale, paramYear=paramYear, scaleYear=scaleYear) diff --git a/latqcdtools/interfaces/interfaces.py b/latqcdtools/interfaces/interfaces.py index af8a4e1..40c4f71 100644 --- a/latqcdtools/interfaces/interfaces.py +++ b/latqcdtools/interfaces/interfaces.py @@ -6,6 +6,8 @@ # Some common classes and functions that may be shared among multiple interfaces modules. # +import re +from sys import set_coroutine_origin_tracking_depth import yaml import numpy as np from latqcdtools.physics.lattice_params import latticeParams @@ -83,4 +85,97 @@ def loadYAML(filename): try: return yaml.safe_load(stream) except yaml.YAMLError as exc: - logger.TBError('Encountered exception:',exc) \ No newline at end of file + logger.TBError('Encountered exception:',exc) + + +class genericTable(list): + + def __init__(self,delimiter=None,pre='',post=''): + """ genericTable objects are to streamline output tables in an arbitrary format. A genericTable + is implemented as a list of lists. + + Args: + delimiter (str, optional) + pre (str, optional): String to appear at beginning of every line table. Defaults to ''. + post (str, optional): String to appear at end of every line of table. Defaults to ''. + """ + if delimiter is None: + logger.TBError('Please set a delimiter.') + checkType(delimiter,str) + checkType(pre,str) + checkType(post,str) + self.delimiter=delimiter + self.pre=pre + self.post=post + + def append(self, item): + checkType(item, list) + super(genericTable, self).append(item) + + def outputTable(self,filename=None): + """ Lets you output a table. + + Args: + filename (str, optional): If set, will output to file. Otherwise output to screen. + """ + if filename is not None: + outFile = open(filename,'w') + for row in self: + line = self.pre + ' ' + str(row[0]) + for col in range(1,len(row)): + line += ' ' + self.delimiter + ' ' + str(row[col]) + line += ' ' + self.post + if filename is None: + logger.info(line) + else: + outFile.write(line+'\n') + if filename is not None: + outFile.close() + + +class latexTable(genericTable): + def __init__(self): + super().__init__(delimiter='&', pre='', post='\\\\') + + +class redmineTable(genericTable): + def __init__(self): + super().__init__(delimiter='|', pre='|', post='|') + + +def convertTable(source,target): + """ Convert a source table into a target table. The assumption for the source file is that + is that the only lines are table lines, i.e. there's no intervening \hline or something like that. + The table type is determined by the file extensions of source and target. + + Args: + source (str): source filename + target (str): target filename + """ + checkType(source,str) + checkType(target,str) + sourceType = source.split('.')[-1] + targetType = target.split('.')[-1] + inFile = open(source,'r') + if sourceType == 'tex': + sourceTable = latexTable() + elif sourceType == 'redmine': + sourceTable = redmineTable() + else: + logger.TBError('Unknown source file type',sourceType) + if targetType == 'tex': + targetTable = latexTable() + elif targetType == 'redmine': + targetTable = redmineTable() + else: + logger.TBError('Unknown target file type',targetType) + for row in inFile: + start = len(sourceTable.pre) + end = len(sourceTable.post) + if end==2: # This is for LaTeX + end=3 + items = row[start:-end] + items = items.split(sourceTable.delimiter) + targetTable.append(items) + targetTable.outputTable(target) + inFile.close() \ No newline at end of file diff --git a/latqcdtools/math/optimize.py b/latqcdtools/math/optimize.py index 4ce1648..868b2fe 100644 --- a/latqcdtools/math/optimize.py +++ b/latqcdtools/math/optimize.py @@ -10,32 +10,37 @@ from scipy.optimize import newton_krylov, fsolve, root from scipy.optimize.nonlin import NoConvergence import latqcdtools.base.logger as logger -from latqcdtools.base.check import DivideByZeroError, InvalidValueError +from latqcdtools.base.check import DivideByZeroError, InvalidValueError, checkType from latqcdtools.base.utilities import unvector, envector # This is the base list of exceptions. If encountered, we treat the solve as unreliable. opt_exceptions = (NoConvergence, FloatingPointError, ValueError, RuntimeWarning, DivideByZeroError, InvalidValueError) +root_methods =['hybr','lm','broyden1','broyden2','anderson','diagbroyden','krylov'] -def persistentSolve(LHS, guess, tol=1e-8, maxiter=200): + +def persistentSolve(LHS, guess, tol=1e-8, maxiter=300): """ Attempt to solve LHS==0 using, in this order, SciPy's newton_krylov, fsolve, and root. """ + checkType(tol,float) + checkType(maxiter,int) try: logger.debug("Trying newton_krylov.") - solution = unvector( newton_krylov(LHS, guess, f_tol=tol, inner_maxiter=maxiter) ) + return newton_krylov(LHS, guess, f_tol=tol, inner_maxiter=maxiter) except opt_exceptions: try: logger.debug("Trying fsolve.") - solution = unvector( fsolve(LHS, guess, xtol=tol, maxfev=maxiter) ) + return fsolve(LHS, guess, xtol=tol, maxfev=maxiter) except opt_exceptions: try: logger.debug("Trying root.") - solution = unvector( root(LHS, guess, tol=tol) ) - if type(solution).__name__ == "OptimizeResult": - raise RuntimeWarning('RuntimeWarning: Bad progress on root solve.') - except Exception as e: - raise e - return unvector(solution) + for method in root_methods: + try: + return root(LHS, guess, tol=tol, method=method).x + except: + continue + except: + raise NoConvergence def minimize(func, jack=None, hess=None, start_params=None, tol=1e-12, maxiter=10000, algorithm=None): diff --git a/testing/interfaces/testInterfaces.py b/testing/interfaces/testInterfaces.py new file mode 100644 index 0000000..33749fb --- /dev/null +++ b/testing/interfaces/testInterfaces.py @@ -0,0 +1,28 @@ +# +# testInterfaces.py +# +# D. Clarke +# +# Testing of some generic interfacing tools. +# + +from latqcdtools.interfaces.interfaces import latexTable, redmineTable +import latqcdtools.base.logger as logger + +logger.set_log_level('INFO') + +def testInterfaces(): + test = latexTable() + test.append([1,2,3]) + test.append([1,2,3]) + test.append([1,2,3]) + test.outputTable('testInterface.tex') + test = redmineTable() + test.append([1,2,3]) + test.append([1,2,3]) + test.append([1,2,3]) + test.outputTable('testInterface.redmine') + logger.TBPass('No problems encountered.') + +if __name__ == '__main__': + testInterfaces() \ No newline at end of file diff --git a/testing/runTests.bash b/testing/runTests.bash index e4d7153..be568e6 100755 --- a/testing/runTests.bash +++ b/testing/runTests.bash @@ -35,6 +35,7 @@ cd .. cd interfaces runTestRoutine testReadWriteConf.py +runTestRoutine testInterfaces.py cd ..